2026-04-06 18:40:34 +00:00
|
|
|
import { Theme } from "../theme.slint";
|
2026-04-07 11:45:12 +00:00
|
|
|
import { DarkButton } from "../components/dark_button.slint";
|
|
|
|
|
import { SettingsBridge, AppState, ConnectionState } from "../globals.slint";
|
2026-04-06 18:40:34 +00:00
|
|
|
|
|
|
|
|
export component TabSettings inherits Rectangle {
|
|
|
|
|
background: Theme.bg-primary;
|
|
|
|
|
|
|
|
|
|
VerticalLayout {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
spacing: 16px;
|
|
|
|
|
alignment: start;
|
|
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
text: "Settings";
|
|
|
|
|
color: Theme.fg-primary;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 11:45:12 +00:00
|
|
|
// OTA Firmware Update
|
2026-04-06 18:40:34 +00:00
|
|
|
Rectangle {
|
|
|
|
|
background: Theme.bg-secondary;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
|
|
VerticalLayout {
|
|
|
|
|
padding: 16px;
|
2026-04-07 11:45:12 +00:00
|
|
|
spacing: 10px;
|
2026-04-06 18:40:34 +00:00
|
|
|
|
2026-04-07 11:45:12 +00:00
|
|
|
Text { text: "OTA Firmware Update"; color: Theme.accent-cyan; font-size: 14px; font-weight: 600; }
|
|
|
|
|
Text { text: "Update firmware via USB (no programming cable needed)"; color: Theme.fg-secondary; font-size: 11px; }
|
|
|
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
|
spacing: 8px;
|
|
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
horizontal-stretch: 1;
|
|
|
|
|
text: SettingsBridge.ota-path != "" ? SettingsBridge.ota-path : "No firmware file selected";
|
|
|
|
|
color: SettingsBridge.ota-path != "" ? Theme.fg-primary : Theme.fg-secondary;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
vertical-alignment: center;
|
|
|
|
|
overflow: elide;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DarkButton {
|
|
|
|
|
text: "Browse...";
|
|
|
|
|
clicked => { SettingsBridge.ota-browse(); }
|
|
|
|
|
}
|
2026-04-06 18:40:34 +00:00
|
|
|
}
|
2026-04-07 11:45:12 +00:00
|
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
|
spacing: 12px;
|
|
|
|
|
|
|
|
|
|
DarkButton {
|
|
|
|
|
text: SettingsBridge.ota-flashing ? "Flashing..." : "Flash OTA";
|
|
|
|
|
primary: true;
|
|
|
|
|
enabled: !SettingsBridge.ota-flashing
|
|
|
|
|
&& SettingsBridge.ota-path != ""
|
|
|
|
|
&& AppState.connection == ConnectionState.connected;
|
|
|
|
|
clicked => { SettingsBridge.ota-start(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
text: SettingsBridge.ota-status;
|
|
|
|
|
color: Theme.fg-primary;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
vertical-alignment: center;
|
|
|
|
|
horizontal-stretch: 1;
|
|
|
|
|
}
|
2026-04-06 18:40:34 +00:00
|
|
|
}
|
2026-04-07 11:45:12 +00:00
|
|
|
|
|
|
|
|
if SettingsBridge.ota-flashing || SettingsBridge.ota-progress > 0 : Rectangle {
|
|
|
|
|
height: 20px;
|
|
|
|
|
background: Theme.bg-primary;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
|
x: 0;
|
|
|
|
|
width: parent.width * clamp(SettingsBridge.ota-progress, 0, 1);
|
|
|
|
|
height: 100%;
|
|
|
|
|
background: SettingsBridge.ota-progress >= 1.0 ? Theme.accent-green : Theme.accent-purple;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
text: round(SettingsBridge.ota-progress * 100) + "%";
|
|
|
|
|
color: Theme.fg-primary;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
horizontal-alignment: center;
|
|
|
|
|
vertical-alignment: center;
|
|
|
|
|
}
|
2026-04-06 18:40:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
feat: Binary protocol v2, config import/export, Tools tab, new layout format
- Migrate all serial commands from ASCII text to binary KS/KR frame protocol
(SETLAYER, TD_LIST, COMBO_LIST, LEADER_LIST, KO_LIST, etc.)
- Add config import/export as JSON (keymaps, tap dances, combos, KO, leaders, macros)
- Merge Flash + Layout Preview into single Tools tab
- Replace WPF tree layout JSON format with flat groups+keys format:
- Top-level "keys" for absolute positioning (thumbs, isolated keys)
- "groups" with x/y/r transform, keys inside use local coordinates
- Coordinates in units (1u = 50px), w/h default 1u, r default 0
- Layout auto-refresh (5s timer) for live preview while editing externally
- Pretty-print JSON in layout preview and export
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:30:04 +00:00
|
|
|
// Config backup / restore
|
|
|
|
|
Rectangle {
|
|
|
|
|
background: Theme.bg-secondary;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
|
|
VerticalLayout {
|
|
|
|
|
padding: 16px;
|
|
|
|
|
spacing: 10px;
|
|
|
|
|
|
|
|
|
|
Text { text: "Configuration Backup"; color: Theme.accent-cyan; font-size: 14px; font-weight: 600; }
|
|
|
|
|
Text { text: "Export or import your full keyboard configuration (keymaps, macros, combos, etc.)"; color: Theme.fg-secondary; font-size: 11px; }
|
|
|
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
|
spacing: 12px;
|
|
|
|
|
|
|
|
|
|
DarkButton {
|
|
|
|
|
text: SettingsBridge.config-busy ? "Working..." : "Export Config";
|
|
|
|
|
primary: true;
|
|
|
|
|
enabled: !SettingsBridge.config-busy
|
|
|
|
|
&& AppState.connection == ConnectionState.connected;
|
|
|
|
|
clicked => { SettingsBridge.config-export(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DarkButton {
|
|
|
|
|
text: SettingsBridge.config-busy ? "Working..." : "Import Config";
|
|
|
|
|
enabled: !SettingsBridge.config-busy
|
|
|
|
|
&& AppState.connection == ConnectionState.connected;
|
|
|
|
|
clicked => { SettingsBridge.config-import(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
text: SettingsBridge.config-status;
|
|
|
|
|
color: Theme.fg-primary;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
vertical-alignment: center;
|
|
|
|
|
horizontal-stretch: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if SettingsBridge.config-busy : Rectangle {
|
|
|
|
|
height: 20px;
|
|
|
|
|
background: Theme.bg-primary;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
|
x: 0;
|
|
|
|
|
width: parent.width * clamp(SettingsBridge.config-progress, 0, 1);
|
|
|
|
|
height: 100%;
|
|
|
|
|
background: SettingsBridge.config-progress >= 1.0 ? Theme.accent-green : Theme.accent-purple;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Text {
|
|
|
|
|
text: round(SettingsBridge.config-progress * 100) + "%";
|
|
|
|
|
color: Theme.fg-primary;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
horizontal-alignment: center;
|
|
|
|
|
vertical-alignment: center;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 11:45:12 +00:00
|
|
|
// About
|
|
|
|
|
Rectangle {
|
|
|
|
|
background: Theme.bg-secondary;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
|
|
VerticalLayout {
|
|
|
|
|
padding: 16px;
|
|
|
|
|
spacing: 8px;
|
|
|
|
|
|
|
|
|
|
Text { text: "About"; color: Theme.fg-primary; font-size: 14px; font-weight: 600; }
|
2026-04-07 14:23:12 +00:00
|
|
|
Text { text: "KeSp Controller v1.0.0"; color: Theme.fg-secondary; font-size: 12px; }
|
2026-04-07 11:45:12 +00:00
|
|
|
Text { text: "Split keyboard configurator"; color: Theme.fg-secondary; font-size: 12px; }
|
|
|
|
|
Text { text: "Made with Slint"; color: Theme.accent-purple; font-size: 11px; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-06 18:40:34 +00:00
|
|
|
Rectangle { vertical-stretch: 1; }
|
|
|
|
|
}
|
|
|
|
|
}
|