From a042dc2850e5429787d73582fe83e420a91ba5bb Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 19 Jul 2026 17:48:50 +0200 Subject: [PATCH] fix(client/windows): settings combos render blank until touched The section-switch key was moved onto the scroll_view's direct child during the parity restructure, which silently disabled it: ScrollView::children() is Children::PositionalSingle, reconciled positionally with keys ignored. The column was therefore reused across section switches, diffing one section's controls into another's -- which re-sets a reused ComboBox's items (clearing WinUI's selection) but skips selected_index whenever the two sections' values compare equal, so every combo rendered empty until changed. Put the keyed column back inside a panel's child list, where the keyed diff path actually runs and the switch remounts. This is the same bug the original code carried a comment about; the comment now names the PositionalSingle trap that makes the key placement load-bearing. Co-Authored-By: Claude Fable 5 --- clients/windows/src/app/settings.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/clients/windows/src/app/settings.rs b/clients/windows/src/app/settings.rs index 75955046..57d727d1 100644 --- a/clients/windows/src/app/settings.rs +++ b/clients/windows/src/app/settings.rs @@ -690,11 +690,17 @@ pub(crate) fn settings_page( ) .chain(groups) .collect(); + // The keyed column MUST sit inside a panel's child list, not directly under the + // scroll_view: `ScrollView::children()` is `Children::PositionalSingle`, which + // reconciles its one child POSITIONALLY and ignores keys outright. Keyed straight onto + // the scroll_view's child, the section switch silently diffs one section's controls into + // another's — which re-sets each reused ComboBox's items (clearing WinUI's selection) + // but skips `selected_index` whenever the two sections' values compare equal, so the + // combos render blank until touched. A panel (vstack) takes the keyed path, so the key + // remounts the whole column and every prop is applied fresh. let content = scroll_view( - vstack(titled) - .spacing(10.0) - .margin(edges(24.0, 20.0, 28.0, 40.0)) - .with_key(section), + vstack(vec![vstack(titled).spacing(10.0).with_key(section).into()]) + .margin(edges(24.0, 20.0, 28.0, 40.0)), ) .opacity(progress) .margin(edges(0.0, (1.0 - progress) * 22.0, 0.0, 0.0));