From 61c3afc34408867a36b5f40c3a6bb09742687321 Mon Sep 17 00:00:00 2001 From: Mae PUGIN <48982737+mornepousse@users.noreply.github.com> Date: Tue, 7 Apr 2026 13:16:26 +0200 Subject: [PATCH] feat: Auto-refresh data on tab change - Advanced tab: auto-loads TD, combos, leaders, KO, BT - Macros tab: auto-loads macro list via binary protocol - Stats tab: auto-loads heatmap + bigrams - Only refreshes when connected - 50ms delays between serial queries Co-Authored-By: Claude Opus 4.6 (1M context) --- src/main.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ ui/globals.slint | 1 + ui/main.slint | 12 ++++++------ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index baa0d7a..8fb798a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -555,6 +555,57 @@ fn main() { window.global::().on_refresh_ports(|| {}); + // --- Auto-refresh on tab change --- + { + let serial = serial.clone(); + let tx = bg_tx.clone(); + let window_weak = window.as_weak(); + + window.global::().on_tab_changed(move |tab_idx| { + let Some(w) = window_weak.upgrade() else { return }; + if w.global::().get_connection() != ConnectionState::Connected { return; } + + let serial = serial.clone(); + let tx = tx.clone(); + match tab_idx { + 1 => { + // Advanced: refresh TD, combo, leader, KO, BT + std::thread::spawn(move || { + let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner()); + for (tag, cmd) in [("td", "TD?"), ("combo", "COMBO?"), ("leader", "LEADER?"), ("ko", "KO?"), ("bt", "BT?")] { + std::thread::sleep(std::time::Duration::from_millis(50)); + let lines = ser.query_command(cmd).unwrap_or_default(); + let _ = tx.send(BgMsg::TextLines(tag.into(), lines)); + } + }); + } + 2 => { + // Macros: refresh via binary + std::thread::spawn(move || { + let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner()); + if let Ok(resp) = ser.send_binary(logic::binary_protocol::cmd::LIST_MACROS, &[]) { + let macros = logic::parsers::parse_macros_binary(&resp.payload); + let _ = tx.send(BgMsg::MacroList(macros)); + } + }); + } + 3 => { + // Stats: refresh heatmap + bigrams + std::thread::spawn(move || { + let mut ser = serial.lock().unwrap_or_else(|e| e.into_inner()); + let lines = ser.query_command("KEYSTATS?").unwrap_or_default(); + let (data, max) = logic::parsers::parse_heatmap_lines(&lines); + let _ = tx.send(BgMsg::HeatmapData(data, max)); + std::thread::sleep(std::time::Duration::from_millis(50)); + let bigram_lines = ser.query_command("BIGRAMS?").unwrap_or_default(); + let _ = tx.send(BgMsg::BigramLines(bigram_lines)); + }); + } + _ => {} + } + }); + } + // --- Settings: change layout --- { let keyboard_layout = keyboard_layout.clone(); diff --git a/ui/globals.slint b/ui/globals.slint index 6e78ca1..3a2fe71 100644 --- a/ui/globals.slint +++ b/ui/globals.slint @@ -34,6 +34,7 @@ export enum ActiveTab { keymap, advanced, macros, stats, settings } export global AppState { in-out property connection: ConnectionState.disconnected; in-out property active-tab: ActiveTab.keymap; + callback tab-changed(int); in-out property status-text: "Disconnected"; in-out property spinner-visible: false; in-out property firmware-version: ""; diff --git a/ui/main.slint b/ui/main.slint index 75fee68..55ba6ce 100644 --- a/ui/main.slint +++ b/ui/main.slint @@ -67,12 +67,12 @@ export component MainWindow inherits Window { padding-right: 8px; spacing: 2px; - DarkTab { title: "Keymap"; active: root.current-tab == 0; clicked => { root.current-tab = 0; } } - DarkTab { title: "Advanced"; active: root.current-tab == 1; clicked => { root.current-tab = 1; } } - DarkTab { title: "Macros"; active: root.current-tab == 2; clicked => { root.current-tab = 2; } } - DarkTab { title: "Stats"; active: root.current-tab == 3; clicked => { root.current-tab = 3; } } - DarkTab { title: "Settings"; active: root.current-tab == 4; clicked => { root.current-tab = 4; } } - DarkTab { title: "Flash"; active: root.current-tab == 5; clicked => { root.current-tab = 5; } } + DarkTab { title: "Keymap"; active: root.current-tab == 0; clicked => { root.current-tab = 0; AppState.tab-changed(0); } } + DarkTab { title: "Advanced"; active: root.current-tab == 1; clicked => { root.current-tab = 1; AppState.tab-changed(1); } } + DarkTab { title: "Macros"; active: root.current-tab == 2; clicked => { root.current-tab = 2; AppState.tab-changed(2); } } + DarkTab { title: "Stats"; active: root.current-tab == 3; clicked => { root.current-tab = 3; AppState.tab-changed(3); } } + DarkTab { title: "Settings"; active: root.current-tab == 4; clicked => { root.current-tab = 4; AppState.tab-changed(4); } } + DarkTab { title: "Flash"; active: root.current-tab == 5; clicked => { root.current-tab = 5; AppState.tab-changed(5); } } } }