From eb99f89a9141185cf71e263662cb2fa9fdb1cb30 Mon Sep 17 00:00:00 2001 From: Mollusk Date: Sun, 14 Jun 2026 15:33:42 -0400 Subject: [PATCH] fix(ui): stop the participant mute button shifting when a peer speaks (A10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The participant row right-anchors [name | space | share | mute | indicator], with the status indicator ([Idle]/[Speaking]/[Muted]/[Connecting…]) as the rightmost element. Those labels differ in width, so when a peer started speaking the indicator grew and pushed the whole right cluster — including the mute button — leftward, making the mute icon visibly jump. Fix: render the indicator in a fixed-width (124px), right-aligned slot sized for the longest label, so its left edge (and the mute button beside it) stays put across state changes. Build + clippy clean. Layout-only; visual confirmation wants a 2-machine call. Co-Authored-By: Claude Opus 4.8 --- src/app/mod.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index 9722277..edd3fb2 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1608,20 +1608,26 @@ fn view(state: &AppState) -> Element<'_, AppMessage> { let is_connecting = state.connecting.contains(peer_id); let is_speaking = !is_connecting && level > 0.01; - let indicator = if is_connecting { + let (ind_label, ind_color): (&str, Color) = if is_connecting { let label = if state.ever_connected.contains(peer_id) { "[Reconnecting…]" } else { "[Connecting…]" }; - text(label).size(14).color(color_yellow) + (label, color_yellow) } else if peer.is_muted { - text("[Muted]").size(14).color(color_red) + ("[Muted]", color_red) } else if is_speaking { - text("[Speaking]").size(14).color(color_green) + ("[Speaking]", color_green) } else { - text("[Idle]").size(14).color(color_subtext) + ("[Idle]", color_subtext) }; + // Fixed-width, right-aligned slot so the label changing (e.g. Idle→ + // Speaking) doesn't reflow the row and shift the mute button (A10). + // Width covers the longest label, "[Reconnecting…]". + let indicator = container(text(ind_label).size(14).color(ind_color)) + .width(iced::Length::Fixed(124.0)) + .align_x(iced::alignment::Horizontal::Right); let peer_id_clone = *peer_id; let is_locally_muted = state.locally_muted.contains(peer_id);