AbleSet 1.0.1: a remounted tile asks for the state instead of waiting
Every gear change remounts the tile, and the remounted tile joins the page's shared stream mid-flow, so it heard nothing until AbleSet next changed — with the transport stopped, never. Tiles went blank until a reload. The tile now fetches /state when it starts and whenever the stream (re)opens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
41fd76817c
commit
9192eed318
@@ -647,6 +647,27 @@ export default function create({ root, moduleApi }) {
|
||||
return moduleApi.setStatus('ok', state.setlist.name ? `AbleSet · ${state.setlist.name}` : 'AbleSet');
|
||||
}
|
||||
|
||||
function applyState(next) {
|
||||
if (!next || typeof next !== 'object') return;
|
||||
takePos(next.pos);
|
||||
state = next;
|
||||
reportStatus();
|
||||
render();
|
||||
}
|
||||
|
||||
/* The page's one stream is shared, so a tile mounted onto it (a gear
|
||||
change remounts the tile) joins mid-flow and hears nothing until
|
||||
AbleSet next changes — which, stopped, may be never. Ask for the state. */
|
||||
let stopped = false;
|
||||
async function backfill() {
|
||||
try {
|
||||
const res = await moduleApi.fetch('/state');
|
||||
if (!res.ok) return;
|
||||
const body = await res.json();
|
||||
if (!stopped) applyState(body.state);
|
||||
} catch { /* the stream's error handler reports the outage */ }
|
||||
}
|
||||
|
||||
function takePos(p) {
|
||||
if (!p) return;
|
||||
pos = p;
|
||||
@@ -666,19 +687,15 @@ export default function create({ root, moduleApi }) {
|
||||
sectionsView.syncButton();
|
||||
}
|
||||
stream = moduleApi.sse('/stream', {
|
||||
open() {},
|
||||
open() { backfill(); },
|
||||
error() {
|
||||
moduleApi.setStatus('error', 'Lost the ProdDash stream — reconnecting');
|
||||
},
|
||||
events: {
|
||||
state(e) {
|
||||
try {
|
||||
const next = JSON.parse(e.data);
|
||||
takePos(next.pos);
|
||||
state = next;
|
||||
} catch { return; }
|
||||
reportStatus();
|
||||
render();
|
||||
let next;
|
||||
try { next = JSON.parse(e.data); } catch { return; }
|
||||
applyState(next);
|
||||
},
|
||||
pos(e) {
|
||||
try { takePos(JSON.parse(e.data)); } catch { return; }
|
||||
@@ -687,6 +704,7 @@ export default function create({ root, moduleApi }) {
|
||||
},
|
||||
},
|
||||
});
|
||||
backfill();
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
fitAll();
|
||||
if (view === 'sections' && state) sectionsView.place();
|
||||
@@ -696,6 +714,7 @@ export default function create({ root, moduleApi }) {
|
||||
tickTimer = setInterval(() => { if (state && !moving()) impl.frame(); }, 1000);
|
||||
},
|
||||
stop() {
|
||||
stopped = true;
|
||||
if (stream) stream.close();
|
||||
stream = null;
|
||||
cancelAnimationFrame(raf);
|
||||
|
||||
Reference in New Issue
Block a user