diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/platform.js | 31 | ||||
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/video-player.js | 31 |
2 files changed, 47 insertions, 15 deletions
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; diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js index fa10d15..2a4d2ea 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js @@ -1433,6 +1433,19 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { } }, [phase]); + // The scan lives as long as the picker is open: closing it, or picking a + // receiver, stops the updates. Receivers are listed as they answer, and the + // spinner sits below them so one landing never moves the row being aimed at. + useEffect(() => { + if (!castPickerOpen) return undefined; + setCastDevices([]); + setCastScanning(true); + return platform.cast.discover((devices, scanning) => { + setCastDevices(devices || []); + setCastScanning(scanning); + }); + }, [castPickerOpen]); + useEffect(() => { return () => { if (blobUrlRef.current) { @@ -1685,12 +1698,6 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { setCastPickerOpen(false); } else { setCastPickerOpen(true); - setCastScanning(true); - setCastDevices([]); - platform.cast.discover().then((devices) => { - setCastDevices(devices || []); - setCastScanning(false); - }).catch(() => setCastScanning(false)); } } }} @@ -1698,12 +1705,6 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { <${Icon} name="cast" /></button> ${castPickerOpen && html` <div class="cast-picker"> - ${castScanning && html` - <div class="cast-picker-item cast-picker-scanning"> - <span class="spinner" style="width:14px;height:14px"></span> - ${t('cast.scanning')} - </div> - `} ${castDevices.map(d => html` <button class="cast-picker-item" onClick=${() => { setCastPickerOpen(false); @@ -1718,6 +1719,12 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { <${Icon} name="cast" /> ${d.name} </button> `)} + ${castScanning && html` + <div class="cast-picker-item cast-picker-scanning"> + <span class="spinner" style="width:14px;height:14px"></span> + ${t('cast.scanning')} + </div> + `} ${!castScanning && castDevices.length === 0 && html` <div class="cast-picker-item cast-picker-empty"> ${t('cast.no_devices')} |