fix: telemetry live updates, input validation, connection race in UI

pull/3/head
lambda 1 week ago
parent 7cd6674bdd
commit 66f7e82887
No known key found for this signature in database
GPG Key ID: CF45A8EE158BBCB6

@ -13,6 +13,7 @@ const groups = {
const deviceCards = new Map(); // device_id -> li const deviceCards = new Map(); // device_id -> li
const selected = {}; // category -> { btn, card } подключённого датчика const selected = {}; // category -> { btn, card } подключённого датчика
const pendingStatus = {}; // category -> status (пришёл до установки selected)
function el(tag, className, text) { function el(tag, className, text) {
const node = document.createElement(tag); const node = document.createElement(tag);
@ -108,6 +109,10 @@ async function connect(deviceId, btn, category, card) {
btn.textContent = "✓"; btn.textContent = "✓";
btn.classList.add("device__connect--done"); btn.classList.add("device__connect--done");
selected[category] = { btn, card }; selected[category] = { btn, card };
if (pendingStatus[category]) {
applyStatus(selected[category], category, pendingStatus[category]);
delete pendingStatus[category];
}
if (category === "trainer") startBtn.disabled = false; if (category === "trainer") startBtn.disabled = false;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -140,17 +145,14 @@ once("battery", (event) => {
if (card) card.querySelector(".device__head").append(batteryIcon(percent)); if (card) card.querySelector(".device__head").append(batteryIcon(percent));
}); });
once("telemetry", (event) => { listen("telemetry", (event) => {
const t = event.payload.telemetry; const t = event.payload.telemetry;
if (t.Power) setMetric("power-value", t.Power.watts); if (t.Power) setMetric("power-value", t.Power.watts);
else if (t.Cadence) setMetric("cadence-value", Math.round(t.Cadence.rpm)); else if (t.Cadence) setMetric("cadence-value", Math.round(t.Cadence.rpm));
else if (t.HeartRate) setMetric("hr-value", t.HeartRate.bpm); else if (t.HeartRate) setMetric("hr-value", t.HeartRate.bpm);
}); });
listen("connection", (event) => { function applyStatus(sel, category, status) {
const { category, status } = event.payload;
const sel = selected[category];
if (!sel) return;
const { btn } = sel; const { btn } = sel;
if (status === "reconnecting") { if (status === "reconnecting") {
btn.textContent = "переподключение…"; btn.textContent = "переподключение…";
@ -165,6 +167,16 @@ listen("connection", (event) => {
btn.disabled = false; btn.disabled = false;
selected[category] = null; selected[category] = null;
} }
}
listen("connection", (event) => {
const { category, status } = event.payload;
const sel = selected[category];
if (!sel) {
pendingStatus[category] = status;
return;
}
applyStatus(sel, category, status);
}); });
// --- Таймер --- // --- Таймер ---
@ -212,8 +224,12 @@ timerBtn.addEventListener("click", async () => {
// --- Целевая мощность/каденс --- // --- Целевая мощность/каденс ---
document.querySelector("#apply-btn").addEventListener("click", async () => { document.querySelector("#apply-btn").addEventListener("click", async () => {
const watts = Number(document.querySelector("#power-input").value); const powerRaw = document.querySelector("#power-input").value.trim();
const rpm = Number(document.querySelector("#cadence-input").value); const cadenceRaw = document.querySelector("#cadence-input").value.trim();
if (powerRaw === "" || cadenceRaw === "") return;
const watts = Number(powerRaw);
const rpm = Number(cadenceRaw);
if (!Number.isFinite(watts) || !Number.isFinite(rpm)) return;
try { try {
await invoke("set_target_power", { watts }); await invoke("set_target_power", { watts });
await invoke("set_target_cadence", { rpm }); await invoke("set_target_cadence", { rpm });

Loading…
Cancel
Save