Deep-review of the quickfix batch surfaced two data/preference-loss bugs plus
smaller items; all fixed with tests.
- watch_sync _pull_apply: don't let the Plex-authoritative pull overwrite a DIRTY
local row (a change whose immediate push failed) — that stranded the value
forever since _repush_dirty only retries dirty rows. Leave it dirty for re-push.
- PlexProvider / ChannelsProvider: a partial shared link opened in a fresh tab
persisted mount-time DEFAULTS over the account's stored scope/sort/filters
(base read before the account was pinned). Persist/keep only URL-present dims;
re-hydrate the omitted ones from storage.
- playback resume write-back: guard against out-of-order delivery (a superseded
older push now drops) and evict the throttle map so it can't grow unbounded.
- PlexPlayer: announce mid-playback buffering to assistive tech (role=status +
sr-only label); new plex.player.buffering (HU+EN).
- columnSort: hoist the shared key:dir sort codec used by both URL-state modules.
- Tests: dirty-guard + flag-settle + per-key throttle scoping + superseded-push
(backend); hold-repeat/suppress-click/unmount + partial-link no-clobber +
refetch-doesn't-clobber-undo (frontend). Backend pytest 475, FE vitest 519.
Mirror the Plex-browse content state into the address bar so a browse view is
bookmarkable/shareable, the Plex analogue of the feed's urlState. Keys are
NAMESPACED (pscope/psort/pshow/pf) rather than reusing the feed's bare
scope/sort/show: FeedFiltersProvider actively strips its own KEYS from the URL
whenever off the feed page, so a shared key would be deleted out from under the
Plex page. The namespaced keys are Plex-unique (like ?v=/?pl), so no other
provider ever reads or clears them.
- New lib/plexUrlState.ts: plexParamUpdates / plexParamsToState / hasPlexParams.
The pf filter blob reuses the SAME appendPlexFilters wire serializer (new
public plexFiltersToParams + inverse parsePlexFilters, kept next to each other
so a new wire key can't be added on one side only).
- PlexProvider: URL-seed wins over localStorage at mount; the account-pin
rehydrate persists the seed instead of clobbering it (mirrors feed's
initialHadUrlFilters); useUrlMirror mirrors/clears the 4 keys, gated on
page===plex. q/field stay out of the shareable contract.
- NavigationProvider: a page switch now also nulls the 4 plex keys.
Tests: 8 new round-trip cases in plexUrlState.dom.test.ts (FE vitest 483→491).