2fa5c8c39470acc3d06d087f0c66dc8822aa0790
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f569b19c49 |
fix: review round 2 — a signed-out tab acts as nobody, honest share-page failures
Deep-review round 2 over main..improvement/watch-background-audio. Account resolution (server) - A request naming an account that is no longer signed in to this browser (X-Siftlode-Account or ?account=) now acts as nobody instead of the session's default account. A tab still pinned to an account signed out in another tab went on acting as the default: its player checkpoints and preference saves landed in that account, the messages socket and Plex playback ran as it, and its Sign out signed THAT account out. A hidden tab never polls /api/me, so a tab playing in the background kept doing it. The /api/me bootstrap probe alone keeps the fallback, which is how such a tab learns who it now is: the app's 401 handler reloads, and BootGate re-pins the tab. BootGate - On an identity change the tab reloads without moving its pin first. The tree being torn down still runs its unmount saves before the page goes, and with the pin already moved they wrote into the new account's local keys (a player volume still pending). The reloaded page corrects the pin. Share page (/watch) - Only a 404 says the link is gone. A 5xx, a dropped connection, and the unlock's own rate limit all rendered "no longer available ... expired or revoked" to a viewer with a valid link, with no way to try again. A load failure now offers Retry; too many password tries says so and keeps the form; an unlock that gets no answer says so instead of doing nothing. Strings in en/hu/de. Downloads - A cookie-authed asset is recognised under the current signature version and the one before it, so a job queued before a deploy that bumps the version still downloads with its cookie instead of failing on the login wall with an error that says no cookie was used. The app chunk is preloaded through lazyWithPreload, so a failed fetch no longer leaves an unhandled rejection beside the ErrorBoundary. The panel layout seed is one helper (seedLayout). Tests: the stale-tab refusal, its harmless Sign out and the probe fallback; the pre-bump authed asset; BootGate keeping the pin on reload and staying mounted through a same-account change; the reveal clock's later-commit hand-off; the prefs, panel layout and demo-scope seeds from the me cache; the share page's failure states. Each mutation-checked RED for its own reason. |
||
|
|
e795d191c5 |
fix(boot): review round 1 — reconcile the tab pin, one loading clock, honest probe failures
Deep-review round 1 over main..improvement/watch-background-audio. BootGate - The tab's account pin is corrected to the account the server answered as. The server honours the pin only for an account still signed in to this browser and otherwise answers as the default, so a tab pinned to an account signed out in another tab ran as the default on the server while reading and writing the gone account's local state. - A mounted tab whose identity changes (its session ended, or the case above) reloads instead of rebuilding the tree in place, like every account switch; that also drops the previous account's query cache. The account key on the tree goes: the readyFor gate already unmounted it on every change. - An unanswered setup probe shows the error with Retry, like an unanswered account probe, instead of the signed-out landing to a signed-in user. - Comments: /api/me never 401s; the ended-session path is identity → nobody. Loading states - LoadingState's reveal delay is one clock across loading states that hand over to each other (boot screen → page-chunk fallback → the page's own fetching state), instead of a CSS delay restarted by each, which blanked a visible spinner for another 300 ms at every hand-off. BootScreen is now the shared loading visual, full screen, counting from navigation start. Plex shared link - Persists only the dimensions the link carries again. Writing the default filters for an omitted `pf` created the stored-filters key, which is what tells SavedViewsProvider the account picked filters, so the account's default Plex saved view was never applied again. Watch page - The Repeat toggle uses the shared pressed-pill paint (a solid fill when on) instead of Button variants that differ only in colour, and its flag goes through storage.ts readJSON/writeJSON. - The actions wrap under the title when the row is too narrow, instead of squeezing the title into a column a word wide on a phone; the title breaks long words. Comments that still justified code by the removed adopt effects (usePref, PrefsProvider, FeedViewProvider) are rewritten against the seed-once model. Tests: BootGate error/retry for both probes, setup mode, a failed background refetch keeping the app, the pin correction and the reload on an identity change; the shared reveal clock; the Plex link persist; the audio signature actually moved off version 4; a video download (av and v) still remuxed to an mp4. Each mutation-checked RED for its own reason. |
||
|
|
5346efcd10 |
fix(boot): a new tab knows its account before anything renders
With Settings -> Appearance -> Startup turned off, every NEW tab or window still opened on Home; only a same-tab reload honoured it. The provider tree mounted before /api/me answered, so NavigationProvider's initializer could not read the per-account opt-out, landed on Home and mirrored ?page=home into the address bar. When App pinned the account a moment later, the re-hydrate re-read that mirror and stayed on Home. The same mount-then-patch shape made a new tab start on default filters, the default theme and the browser language, and correct each after the first paint. BootGate (main.tsx, above the providers) now owns the setup-status and /api/me queries and mounts the tree only once the identity is settled: it pins the tab's account and adopts the account's language in a layout effect, so the first frame of the app is already right. The tree is keyed on the account id, which makes "per-account state is read once, for this account" a structural guarantee. With that, the whole re-hydrate machinery is gone: useAccountRehydrate, the reactive active-account store, the markDirty guards, the pin-deferred saved-view seed and the present-dimension bookkeeping of the shared Channels/Plex links. PrefsProvider, FeedFiltersProvider, usePref and App's panel layouts seed from the me cache instead of adopting it in an effect; the theme is applied in layout effects. The app chunk is fetched in parallel with the probe, and the boot screen only fades its label in after 400 ms, on one clock across the gate and the Suspense fallback. Module switches no longer flash a placeholder either. Measured frame by frame in Chromium and WebKit, every first visit to a module showed "Loading..." for 17-70 ms: the lazy chunk's Suspense fallback, then often the first fetch's LoadingState. Pages are now lazyWithPreload components, and App fetches the chunks of every module the account can reach (plus the channel page) once the first page is idle; a preloaded page renders synchronously and never suspends. LoadingState, the one shared loading visual, fades in only after 300 ms, so a fast load shows nothing in between and a slow one still gets its spinner. |