app: debounce channel tree and cache render width

This commit is contained in:
Username
2026-02-24 15:32:57 +01:00
parent 57f4559a38
commit be6574ae79

View File

@@ -25,6 +25,7 @@ VOLUME_STEPS = (0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0)
RECONNECT_INITIAL = 2 # seconds before first retry
RECONNECT_MAX = 30 # maximum backoff delay
RECONNECT_RETRIES = 10 # attempts before giving up
TREE_DEBOUNCE = 0.1 # seconds to coalesce state changes
def _next_volume(current: float) -> float:
@@ -186,8 +187,7 @@ class ChannelTree(Static):
for child in children:
self._collect_order(child.channel_id, order)
@property
def _available_width(self) -> int:
def _get_width(self) -> int:
"""Usable character width (content area, excludes padding/border)."""
w = self.content_size.width
if w <= 0:
@@ -218,9 +218,10 @@ class ChannelTree(Static):
if not self._channels:
return " Channels\n [dim]\u2514\u2500 (not connected)[/]"
w = self._get_width()
lines = [" [bold]Channels[/]"]
root_id = self._find_root()
self._render_tree(root_id, lines, indent=1, is_last=True)
self._render_tree(root_id, lines, indent=1, is_last=True, w=w)
return "\n".join(lines)
def _find_root(self) -> int:
@@ -235,12 +236,11 @@ class ChannelTree(Static):
lines: list[str],
indent: int,
is_last: bool,
w: int,
) -> None:
ch = self._channels.get(channel_id)
if ch is None:
return
w = self._available_width
prefix = " " * indent
branch = "\u2514\u2500" if is_last else "\u251c\u2500"
@@ -294,6 +294,7 @@ class ChannelTree(Static):
lines,
indent + 2,
is_last=i == len(children) - 1,
w=w,
)
def on_key(self, event: events.Key) -> None:
@@ -412,6 +413,7 @@ class TuimbleApp(App):
self._audio.input_gain = acfg.input_gain
self._audio.output_gain = acfg.output_gain
self._pending_reload: Config | None = None
self._tree_refresh_timer = None
self._reconnecting: bool = False
self._reconnect_attempt: int = 0
self._intentional_disconnect: bool = False
@@ -620,7 +622,11 @@ class TuimbleApp(App):
chatlog.write(f"[#7aa2f7]{msg.sender}[/] {clean}")
def on_server_state_changed(self, _msg: ServerStateChanged) -> None:
self._refresh_channel_tree()
if self._tree_refresh_timer is not None:
self._tree_refresh_timer.stop()
self._tree_refresh_timer = self.set_timer(
TREE_DEBOUNCE, self._refresh_channel_tree,
)
def on_channel_selected(self, msg: ChannelSelected) -> None:
if not self._client.connected: