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) <noreply@anthropic.com>
This commit is contained in:
Mae PUGIN 2026-04-07 13:16:26 +02:00
parent b4ab9af18b
commit 61c3afc344
3 changed files with 58 additions and 6 deletions

View file

@ -555,6 +555,57 @@ fn main() {
window.global::<ConnectionBridge>().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::<AppState>().on_tab_changed(move |tab_idx| {
let Some(w) = window_weak.upgrade() else { return };
if w.global::<AppState>().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();

View file

@ -34,6 +34,7 @@ export enum ActiveTab { keymap, advanced, macros, stats, settings }
export global AppState {
in-out property <ConnectionState> connection: ConnectionState.disconnected;
in-out property <ActiveTab> active-tab: ActiveTab.keymap;
callback tab-changed(int);
in-out property <string> status-text: "Disconnected";
in-out property <bool> spinner-visible: false;
in-out property <string> firmware-version: "";

View file

@ -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); } }
}
}