From f1e915c379a8e137937461c37e095fb6c58674b9 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Thu, 21 May 2026 00:30:57 +0200 Subject: [PATCH] docs: document download peer count chip Update the launcher design reference so active downloads show how many LAN peers are currently seeding the transfer. The reference now places the peer chip between speed and ETA, describes the singular/plural copy, and records how the ETA and peer count collapse in narrow modal layouts. Test Plan: - git diff --cached --check --- design/README.md | 13 ++++++++----- design/design_reference/components.jsx | 9 +++++++++ design/design_reference/data.jsx | 4 ++-- design/design_reference/styles.css | 11 +++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/design/README.md b/design/README.md index 184ba2f..6d75ebf 100644 --- a/design/README.md +++ b/design/README.md @@ -251,20 +251,22 @@ grid-template-areas: ``` - **Primary row** (`.dl-lg-primary`, top-left) — pulse dot + the uppercase live label `DOWNLOADING` in `color-mix(in srgb, var(--accent) 80%, white)`, 13px / 600, `letter-spacing: 0.02em`. This is the only place the word "Downloading" appears in the component. -- **Secondary row** (`.dl-lg-secondary`, bottom-left) — the live stats. 12px, three groups separated by `·` (0.45 opacity): +- **Secondary row** (`.dl-lg-secondary`, bottom-left) — the live stats. 12px, four groups separated by `·` (0.45 opacity): 1. `11.4 GB / 35 GB` (`var(--t-1)` strong + `var(--t-2)` rest) 2. `47.6 MB/s` (`var(--t-1)`) - 3. `8 min left` (`var(--t-2)`) + 3. `[users-icon] from 5 peers` — `.dl-peers`, inline-flex with 5px gap, icon at 0.7 opacity, count bold + tabular-nums in `var(--t-1)`, rest in `var(--t-2)`. Singular/plural switches on `peers === 1`. Hidden entirely when `game.peers` is falsy. Communicates that this is a LAN swarm transfer, not a single-source pull. + 4. `8 min left` (`var(--t-2)`) - **pct column** — large percentage, 20px / 700, `letter-spacing: -0.01em`, `var(--t-1)`. `%` glyph at 12px / 600 / 0.55 opacity. - **cancel column** — 28×28 square, `1px solid var(--bd-2)`, `border-radius: 6px`, X icon. Hover: bg `rgba(239,68,68,0.12)`, border `rgba(239,68,68,0.40)`, text `#fca5a5`. Cancelling reverts the game to its prior state (`local` if any data was kept, `none` otherwise) — dev decides the underlying behavior. **Graceful degradation in narrow modals:** ```css -@container (max-width: 380px) { .dl-lg-secondary .dl-eta, .dl-lg-secondary .dl-sep-eta { display: none; } } +@container (max-width: 380px) { .dl-lg-secondary .dl-eta, .dl-lg-secondary .dl-sep-eta { display: none; } } +@container (max-width: 300px) { .dl-lg-secondary .dl-peers, .dl-lg-secondary .dl-sep-peers { display: none; } } ``` -The ETA drops first if the modal narrows; bytes + speed stay (they're the actionable numbers). The pct/cancel column never collapses. +ETA drops first, then peers; bytes + speed always stay (they're the actionable numbers). The pct/cancel column never collapses. ### Number formatting @@ -287,10 +289,11 @@ type Game = { state: 'installed' | 'local' | 'downloading' | 'none'; progress?: number; // 0–1, only when state === 'downloading' speed?: number; // current throughput in MB/s + peers?: number; // number of LAN peers currently seeding }; ``` -In the real app, `progress` and `speed` come from the download worker (Tauri command emitting events). The mock's `useLiveDownload(game)` hook (in `components.jsx`) is just a placeholder — 600ms `setInterval` advancing `progress` proportional to `speed`, with `speed` smoothed via a low-pass filter and small random drift so the number doesn't look fake. Replace with a `useEffect` that subscribes to your real progress events; the rendering layer needs nothing else. +In the real app, `progress`, `speed`, and `peers` come from the download worker (Tauri command emitting events). The mock's `useLiveDownload(game)` hook (in `components.jsx`) is just a placeholder — 600ms `setInterval` advancing `progress` proportional to `speed`, with `speed` smoothed via a low-pass filter and small random drift so the number doesn't look fake. `peers` is read straight off the game object (static in the mock); in production, push updates as peers join/leave the swarm — the `.dl-peers` chip re-renders silently. Replace the hook with a `useEffect` that subscribes to your real progress events; the rendering layer needs nothing else. Filter changes: - `Local` filter includes `installed` + `local` + `downloading` (in-flight downloads belong on the Local tab — you're managing them). diff --git a/design/design_reference/components.jsx b/design/design_reference/components.jsx index 64e6cb8..647426b 100644 --- a/design/design_reference/components.jsx +++ b/design/design_reference/components.jsx @@ -159,6 +159,15 @@ function DownloadProgress({ game, accent, size = 'md', full = false }) { · {fmtSpeed(speed)} + {game.peers > 0 && ( + + · + + + from {game.peers} {game.peers === 1 ? 'peer' : 'peers'} + + + )} · {fmtEta(etaSec)} left diff --git a/design/design_reference/data.jsx b/design/design_reference/data.jsx index 15032ee..9d95a5d 100644 --- a/design/design_reference/data.jsx +++ b/design/design_reference/data.jsx @@ -18,7 +18,7 @@ const GAMES = [ { id: 'avp', title: 'Aliens vs. Predator', size: 35.0, version: '2019.10.01', desc: "Three campaigns, three nightmares. Be the alien stalking the dark, the predator hunting both, or the marine just trying to make it home with a working flashlight.", - state: 'downloading', progress: 0.32, speed: 49.4, players: '2–16', tags: ['FPS', 'Horror', 'Multiplayer'], + state: 'downloading', progress: 0.32, speed: 49.4, peers: 5, players: '2–16', tags: ['FPS', 'Horror', 'Multiplayer'], cover: { c1: '#064e3b', c2: '#020617', accent: '#34d399', mood: 'dark' }, }, { @@ -120,7 +120,7 @@ const GAMES = [ { id: 'quake3', title: 'Quake III Arena', size: 0.5, version: '2010.08.15', desc: "Arena FPS in its most distilled form. Rocket jumps, rail-gun duels, and a netcode that's still the benchmark.", - state: 'downloading', progress: 0.71, speed: 12.8, players: '2–16', tags: ['FPS', 'Arena', 'LAN'], + state: 'downloading', progress: 0.71, speed: 12.8, peers: 3, players: '2–16', tags: ['FPS', 'Arena', 'LAN'], cover: { c1: '#7f1d1d', c2: '#0a0a0a', accent: '#fbbf24', mood: 'dark' }, }, { diff --git a/design/design_reference/styles.css b/design/design_reference/styles.css index 6c98a32..059d97b 100644 --- a/design/design_reference/styles.css +++ b/design/design_reference/styles.css @@ -784,6 +784,12 @@ } .dl-lg-secondary .dl-bytes .dl-of { color: var(--t-2); font-weight: 500; } .dl-lg-secondary .dl-speed { color: var(--t-1); font-weight: 600; white-space: nowrap; } +.dl-lg-secondary .dl-peers { + display: inline-flex; align-items: center; gap: 5px; + color: var(--t-2); white-space: nowrap; +} +.dl-lg-secondary .dl-peers strong { color: var(--t-1); font-weight: 600; font-variant-numeric: tabular-nums; } +.dl-lg-secondary .dl-peers svg { opacity: 0.7; } .dl-lg-secondary .dl-eta { white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; } .dl-sep { opacity: 0.45; } @@ -792,6 +798,11 @@ .dl-lg-secondary .dl-eta, .dl-lg-secondary .dl-sep-eta { display: none; } } +/* Even narrower: drop peers too, keep size + speed */ +@container (max-width: 300px) { + .dl-lg-secondary .dl-peers, + .dl-lg-secondary .dl-sep-peers { display: none; } +} .dl-lg-pct { grid-area: pct;