#45 · Advise users when a timeline outgrows its platform
- timeline-app
- pull request
Fixes #39. A notice under the header suggests another platform for the open timeline. It never blocks editing, and dismissing it holds for that timeline (remembered in local storage, keyed by timeline and the kind of advice). ## Rules (`src/capacity.ts`, thresholds from the capacity benchmarks in #41) | Where | Shown when | Actions | |---|---|---| | **Browser** (guest, offline HTML, signed-in browser-only timeline) | This device measured the timeline as slow: opening (reading, indexing, first draw) over 1.5 s, a median of recent redraws over 150 ms, or a median draft save over 100 ms. Without measurements, from 20,000 moments. | **Save to server** (signed in) or **Sign in** (server available); **Export**; *Get the desktop app*; offline only, *Open the platform* | | **Desktop app** | The median of recent whole-view queries is over 1 s on this computer. | **Save to server**, or **Server connection** when not connected | | **Every platform** | 150,000 or more moments, durations or relationships. In the browser it counts all three; on the desktop and the platform, moments. | none; the message suggests splitting the timeline | The limit warning comes first when several apply. The platform is never told to move elsewhere. Redraw, draft and view rules need at least 2–3 recent samples, so a single slow frame doesn't trigger them. ## Measurements in the editor - **Opening:** - For imports, it runs from reading the file to the first drawn view; for other opens, from `loadDocument`. - It is discarded if the first draw is deferred because the editor isn't visible (for example, opened behind the dashboard). That deferral would time the wait, not the device. - **Redraws:** the duration of each full in-memory render. - **Draft save:** the synchronous part of `persistDraft` (`model.document()` plus the IndexedDB put, which structured-clones on the main thread). - **Desktop views:** from issuing each overview query to its result. Measurements reset when another timeline opens. The moment count used by the header is now `momentCount()`, which the advice reuses. ## Tests - **`test/capacity.test.mjs` (unit):** every threshold and its boundary; medians needing consistent samples; the limit warning ordering for all three entity kinds; no advice for the platform; the sample window. - **`test/capacity-browser.mjs`** (served app and offline HTML, Chromium and Firefox): - a 20,000-moment import shows the advice with Export and the desktop link, plus the platform link offline only; - dismissal holds after reopening; - small timelines show nothing; - in Chromium, the CPU throttled 30× makes a 3,000-moment import show the measured "took … s to open" advice. - **`test/remote-cache-browser.mjs`:** an ordinary server timeline shows nothing. Reporting 160,000 moments shows the limit warning with no actions. - **`test/desktop-cache-browser.mjs`:** fast views show nothing. Four slow (1.1 s) views show the desktop advice with **Server connection**. - `browser.mjs` and `offline-browser.mjs` pass locally in Chromium and Firefox; 184 unit tests and the typecheck pass. The docs (`docs/capacity.md`) gain an "Advice in the app" section.
Sources
Open #45 · Advise users when a timeline outgrows its platform in the timeline