summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/platform.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/platform.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/platform.js40
1 files changed, 40 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/platform.js b/packages/meshbay-hub/src/meshbay_hub/static/platform.js
index a5312e1..78e27eb 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/platform.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/platform.js
@@ -328,6 +328,46 @@ export async function waitForGroupHosted(groupId, onProgress,
}
/**
+ * Create Group wizard only: after adding extra roots (step 5), wait for
+ * whatever scanning that triggers to actually finish, showing progress along
+ * the way. `POST /api/groups/{id}/roots` (ui/app.py) schedules its rescan as
+ * a detached background task and returns as soon as the config write is
+ * done — "every add-root call resolved" is not "the node is done indexing".
+ * Found live (2026-08-25): a multi-root group's later, larger roots kept
+ * scanning for minutes after the wizard had already moved on to GEK init and
+ * pairing, with no progress shown anywhere — the disk was working, the UI
+ * just never asked again.
+ *
+ * Same race as waitForGroupHosted above, one level down: the very first
+ * poll can land in the gap between "the last add-root call returned" and
+ * "its background reload actually started scanning", which reads as "not
+ * scanning" for the wrong reason (nothing left to do) rather than the right
+ * one (hasn't started yet). Waits up to `graceMs` for scanning to be
+ * observed at least once before trusting a "not scanning" answer — after
+ * that, the first "not scanning" really does mean finished, because the
+ * node scans one root at a time (indexer.py's single-worker executor) and
+ * nothing here adds more roots once this call starts.
+ */
+export async function waitForRootsIndexed(groupId, onProgress,
+ { intervalMs = 500, graceMs = 5000 } = {}) {
+ const graceDeadline = Date.now() + graceMs;
+ let sawScanning = false;
+ for (;;) {
+ let status;
+ try {
+ status = await node.call('GET', `/api/groups/${groupId}/index-status`);
+ } catch {
+ return; // the node went away mid-poll — same stance as watchIndexProgress
+ }
+ if (onProgress) onProgress(status);
+ if (status.scanning) sawScanning = true;
+ if (sawScanning && !status.scanning) return;
+ if (!sawScanning && Date.now() > graceDeadline) return;
+ await new Promise((r) => setTimeout(r, intervalMs));
+ }
+}
+
+/**
* LAN cast relay — re-serve decrypted video segments over HTTP so a
* Chromecast or Smart TV on the same Wi-Fi can play the stream.
*