aboutsummaryrefslogtreecommitdiffstats
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.js62
1 files changed, 62 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 30df80e..a5312e1 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/platform.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/platform.js
@@ -266,6 +266,68 @@ export const node = {
};
/**
+ * Poll a group's initial-scan progress on the local node (loopback), until
+ * it reports it is no longer scanning. For "add a directory" in Settings,
+ * where the group is already hosted — index-status is meaningful the whole
+ * time. NOT for a brand-new group the wizard just attached: see
+ * waitForGroupHosted below for why that needs a different exit condition.
+ *
+ * `onUpdate` is called with each {scanning, scanned_bytes, total_bytes,
+ * current_dir} snapshot, including the final one where scanning is false.
+ */
+export async function watchIndexProgress(groupId, onUpdate, { intervalMs = 500 } = {}) {
+ for (;;) {
+ let status;
+ try {
+ status = await node.call('GET', `/api/groups/${groupId}/index-status`);
+ } catch {
+ // The node went away mid-poll — stop rather than spin forever; the
+ // caller's own connection-status handling already covers that case.
+ return;
+ }
+ onUpdate(status);
+ if (!status.scanning) return;
+ await new Promise(resolve => setTimeout(resolve, intervalMs));
+ }
+}
+
+/**
+ * Create Group wizard only: wait for a brand-new group to actually become
+ * usable on the node, showing index-status along the way.
+ *
+ * Not the same wait as watchIndexProgress above. `/api/reload` returns as
+ * soon as the reload is scheduled (ops.start_reload) — before the node has
+ * even created an indexer for the group, let alone started scanning. A
+ * naive "poll index-status until scanning is false" would see the default
+ * idle answer on that very first poll and return immediately, and every
+ * group-scoped call after it (add a root, init the GEK) would still 404
+ * with "not configured"/"not hosted" for as long as the real scan actually
+ * takes. The only answer that means "safe to proceed" is the group
+ * genuinely appearing in /api/groups (groups_ctx, daemon.py) — index-status
+ * is read purely for the progress bar.
+ */
+export async function waitForGroupHosted(groupId, onProgress,
+ { intervalMs = 500, timeoutMs = 30 * 60 * 1000 } = {}) {
+ const deadline = Date.now() + timeoutMs;
+ for (;;) {
+ try {
+ const status = await node.call('GET', `/api/groups/${groupId}/index-status`);
+ if (onProgress) onProgress(status);
+ } catch { /* keep waiting — the loopback API can be momentarily busy */ }
+
+ try {
+ const list = await node.call('GET', '/api/groups');
+ if (Array.isArray(list.groups) && list.groups.some((g) => g.id === groupId)) return;
+ } catch { /* keep waiting */ }
+
+ if (Date.now() > deadline) {
+ throw new Error('The node did not finish attaching this group in time');
+ }
+ 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.
*