From e941cc4c39c38a12220153ea572bd4c7bb92fde0 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 2 Oct 2026 08:39:56 +0200 Subject: feat(client): list cast receivers as they answer The scan still runs six seconds, but the picker polls what it has found and shows each receiver immediately. A rescan no longer has its timer cut short by the scan it replaced. Co-Authored-By: Claude Opus 5.5 --- .../meshbay-hub/src/meshbay_hub/static/platform.js | 31 +++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/platform.js') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/platform.js b/packages/meshbay-hub/src/meshbay_hub/static/platform.js index 19f12a6..749f93e 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/platform.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/platform.js @@ -430,6 +430,8 @@ export async function waitForRootsIndexed(groupId, onProgress, * Absent in a browser, where the relay cannot run: there is no main process * to bind a server socket in, and a page cannot open one. */ +const CAST_POLL_MS = 250; + export const cast = { available: Boolean(bridge && bridge.cast), async start(opts) { @@ -456,9 +458,32 @@ export const cast = { if (!bridge || !bridge.cast) return null; return bridge.cast.status(); }, - async discover() { - if (!bridge || !bridge.cast) return []; - return bridge.cast.discover(); + // Lists receivers as they answer rather than at the end of the scan: most + // answer within two seconds, and the scan runs on for the ones coming back + // from a reset. `onUpdate(devices, scanning)` is called on each poll until + // the scan ends; the returned function stops it being called at all. + discover(onUpdate) { + if (!bridge || !bridge.cast) { + onUpdate([], false); + return () => {}; + } + let stopped = false; + let timer = null; + const poll = async () => { + const snap = await bridge.cast.devices().catch(() => null); + if (stopped) return; + if (!snap) { + onUpdate([], false); + return; + } + onUpdate(snap.devices, snap.scanning); + if (snap.scanning) timer = setTimeout(poll, CAST_POLL_MS); + }; + bridge.cast.scan().then(poll, () => { if (!stopped) onUpdate([], false); }); + return () => { + stopped = true; + clearTimeout(timer); + }; }, async chromecastConnect(opts) { if (!bridge || !bridge.cast) return null; -- cgit v1.2.3