aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/app.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-08 23:43:46 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-08 23:43:46 +0200
commit77615ddb5fead3e74751a94847d3bcc99fc0a96d (patch)
tree72e596fdc56567925100b18460793a978bb29c63 /packages/meshbay-hub/src/meshbay_hub/static/app.js
parent1ba91bb4f38f6338d1c86678ebcd19195db2a120 (diff)
downloadmeshbay-77615ddb5fead3e74751a94847d3bcc99fc0a96d.tar.gz
fix(hub): the transfers row exists from the click
Clicking Download produced nothing — no row, no icon, no panel — for as long as it took to open somewhere to write, and then several rows at once. The streamed path waits for the worker twice; a Save As dialog waits for a person. The row was created after that, so the slowest part of a download happened with nothing on screen to say it had begun. The store gains a `prepare` step, distinct from `run`, and the order is now: row, then target, then slot. That last part is why the obvious fix was wrong. Taking the slot first would let the row appear immediately, and it was tried this morning: a granted slot has to be taken up within the node's deadline, opening a target can outlast it, and three downloads became one. (The diagnosis at the time blamed that ordering for revocations which were in fact a missing `touch()` call — the revert was right for the wrong reason.) `makeLease` is called after `prepare` succeeds, never before. Three behaviours fall out, each with a test: - a dismissed dialog leaves nothing behind. `prepare` returning false drops the row: nothing started, so nothing should remain on screen to explain it; - the row takes the name the file was actually saved under, once known; - a refusal above the memory ceiling fails the row that is already there, rather than creating one to kill it. `preparing` counts as live everywhere — badge, cancel, clearFinished, and `_busy`, since closing a transport under a preparing transfer strands it exactly as under a queued one. Six places asked "is this finished?" and were drifting apart; there is one definition now. Two mistakes in the tests, worth the note: one counted positions in an output array by hand and was one out, which reads exactly like a failing assertion about the code — the values are tagged now, not indexed. And test_zip_size_limit.py's stub did not run `prepare`, so it no longer reached the size check the file is about; it now behaves like the real store. 819 hub, 1169 node, 0 failed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HCGdheDLxGReuKHga3BtST
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/app.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/app.js23
1 files changed, 19 insertions, 4 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js
index ff066cf..6f4bb92 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js
@@ -157,9 +157,11 @@ function TransferWidget() {
}, [open]);
const running = items.filter(i => i.status === 'running');
- const waiting = items.filter(i => i.status === 'queued');
+ const waiting = items.filter(
+ i => i.status === 'queued' || i.status === 'preparing');
const finished = items.filter(
- i => i.status !== 'running' && i.status !== 'queued');
+ i => i.status !== 'running' && i.status !== 'queued'
+ && i.status !== 'preparing');
const active = running.length + waiting.length;
// Grouped, and in this order: what is moving, what is waiting, what is over.
@@ -240,7 +242,8 @@ function TransferRow({ it }) {
? html`<a class="transfer-name" href="#" title=${it.name}
onClick=${(e) => { e.preventDefault(); transfers.open(it.id); }}>${it.name}</a>`
: html`<span class="transfer-name" title=${it.name}>${it.name}</span>`}
- ${(it.status === 'running' || it.status === 'queued') && html`
+ ${(it.status === 'running' || it.status === 'queued'
+ || it.status === 'preparing') && html`
<button class="transfer-cancel"
aria-label=${t('transfers.cancel_one', { name: it.name })}
title=${t('transfers.cancel')}
@@ -249,7 +252,19 @@ function TransferRow({ it }) {
</button>
`}
</div>
- ${it.status === 'queued'
+ ${it.status === 'preparing'
+ ? html`
+ ${/* Not a progress bar at 0%: nothing is wrong and nothing is
+ stalled, the download is still finding somewhere to write. The
+ row exists from the click precisely so this state is visible
+ instead of being an empty panel. */''}
+ <div class="dl-progress dl-waiting"></div>
+ <div class="transfer-meta">
+ <span>${t('transfers.preparing')}</span>
+ <span>${formatSize(it.total)}</span>
+ </div>
+ `
+ : it.status === 'queued'
? html`
<div class="dl-progress dl-waiting"></div>
<div class="transfer-meta">