AbleSet 1.0.0: follow AbleSet's setlist over OSC #17

Merged
michael merged 3 commits from claude/proddash-ableset-module-6c2556 into main 2026-09-27 09:02:27 -04:00
2 changed files with 28 additions and 9 deletions
Showing only changes of commit 9192eed318 - Show all commits
+27 -8
View File
@@ -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);
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "ableset",
"name": "AbleSet",
"version": "1.0.0",
"version": "1.0.1",
"proddash": ">=1.5.0",
"description": "The song AbleSet is playing — tempo, time left, sections, setlist and status",
"permissions": [