aboutsummaryrefslogtreecommitdiffstats
path: root/docs/desktop-client-v1.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-18 13:40:15 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-18 13:40:15 +0200
commitcf418a095b07c8127042390c748e721d1433879b (patch)
tree6ede268b8354127764da4a97d726e1bc680bb1c4 /docs/desktop-client-v1.md
parentae7099edefbff5cd6ac0e2329f0684b6caff0b73 (diff)
downloadmeshbay-cf418a095b07c8127042390c748e721d1433879b.tar.gz
fix(client): downloads stream to disk, and two rough edges on first run
**Downloads were going through RAM.** `_openDownloadTarget` tries a granted folder, then a service worker, then its floor: collect the whole file in the page and hand the browser a blob. Both of the first two are absent in the desktop application — `showDirectoryPicker` does not exist, and Chromium refuses a service worker on a custom scheme — so every download under 512 MB took the floor. A gigabyte of film meant a gigabyte of RAM, and the only visible symptom was a Save As dialog at the *end* rather than the start, which is what the operator noticed and asked about. The main process now streams to disk: it honours "save automatically" with a folder chosen once and no dialog, never overwrites (a colliding name gets a suffix), awaits each write so the renderer cannot outrun the disk and queue the file in memory anyway, and unlinks a cancelled download rather than leaving a truncated file that looks complete to whoever opens it next. Settings now offers the native folder picker instead of saying downloads are unsupported. Measured in the running application: the file on disk grows 256 KB → 512 KB → 768 KB → 1 MB as the chunks arrive, and an aborted download leaves nothing behind. **A permanent scrollbar on sign-in.** `.layout` and `.page-center` each reserved `100vh - 52px`, and `.page-center` sits inside `main`'s 24px vertical padding — so the page overflowed by exactly 48px at every window size. Found by measuring in the app rather than reading the stylesheet: `scrollHeight` 819 against a 771 viewport, then the bottom edge of every element. The centring page brings its own padding, so main's is dropped for it and the duplicated arithmetic goes rather than growing a third term. Now `scrollHeight == innerHeight`, no overflowing elements. **The first-run screen was unstyled.** It used a class name I invented (`auth-page`) that appears nowhere in the stylesheet, so it had no card and the button sat against the input. It now uses the same `page-center` + `login-card` markup as sign-in, which is where the 12px gap comes from. The sign-in link in the nav is hidden until a hub is chosen — it led to a page that could not work. 809 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs/desktop-client-v1.md')
-rw-r--r--docs/desktop-client-v1.md2
1 files changed, 1 insertions, 1 deletions
diff --git a/docs/desktop-client-v1.md b/docs/desktop-client-v1.md
index 0989f52..23287dd 100644
--- a/docs/desktop-client-v1.md
+++ b/docs/desktop-client-v1.md
@@ -1061,7 +1061,7 @@ build existing.
| D4 | ✅ **DONE 2026-08-18, verified against a hub running this code** — first-run hub prompt (no default, on purpose), passphrase sign-in registers this device, later launches sign in with the device key and no passphrase. **The renderer never holds that key**: it is generated, stored and used entirely in the main process, which signs on request — the same rule as the save dialog, because the renderer is the part that parses hostile input. Measured: register 201 → passphrase login 200 → device register 201 → **device sign-in 200 with a real session** → a stranger's key 401. **Verified end to end on a real desktop** (Ubuntu 24.04 GNOME, 2026-08-18): the application was quit and relaunched, and signed in **without asking for the passphrase**. safeStorage really uses the keyring — `secrets.bin` carries Chromium's `v11` prefix, the marker for keyring-backed encryption | 1 |
| D5 | Node management panel over the Stage-B ops, root selection included | 2 |
| D6 | First-run wizard — detect, enable the unit, link, group, `gek-init`, pair (§7.4) | 2 |
-| D7 | Native save dialog, streamed write from the main process | 2 |
+| D7 | ✅ **DONE 2026-08-18, and it was not optional** — the two browser paths are both absent in the application (`showDirectoryPicker` does not exist, and Chromium refuses a service worker on a custom scheme), so the chain fell through to its floor: **the whole file collected in the page and handed over as a blob**. A gigabyte of film meant a gigabyte of RAM, and a Save As dialog at the *end* — which is how the operator noticed. The main process now streams to disk, honours "save automatically" with a remembered folder and no dialog, never overwrites, applies backpressure, and unlinks a cancelled download rather than leaving a truncated file. Measured: the file on disk grows 256 KB → 512 KB → 768 KB → 1 MB as chunks arrive |
| D8 | ◐ **PARTIAL** — `electron-builder` configured for deb and rpm, and `meshbay-node-user.service` added. **Found doing it:** the spec installed the *system* template (`User=%i`) into the user unit directory, where systemd refuses the file — the packaged unit could never have started. Fixed, with `test_packaging_units.py`. Nothing has been built: no npm, no rpmbuild here | 1 |
| D9 | Python sidecar — `group://` over QUIC | 2 |
| D10 | Video thumbnails, own bounded pool (§6.10) | 2 |