fix(nav): a page settling keeps a reload's overlay entry; an old entry's sub-view goes to its own (review round 4)

- useUrlMirror: a change before the user has done anything since the load is the page settling (the
  rail stepping off a playlist deleted since, Files off a folder gone), not another view: the reload
  mark stays, and the player that reopens takes its entry over — one Back closes it, as before.
- useHistorySubview: an entry an older build wrote is a module's only when its _sub is the view the
  address names under that module's key (the card's push kept the season's `v` beside its `m`).
- Playlists: the rail's default selection and the page's "the rail moved there" read one helper.
- moduleUrl contract: writer literals in a choice's branches are scanned too; the sub-view census
  walks type arguments of any depth and refuses an aliased import.
- A stale comment on the nav press over a live search.
This commit is contained in:
2026-10-28 01:39:26 +01:00
parent 99a33e7fd1
commit 5686759bca
10 changed files with 137 additions and 29 deletions
+6 -2
View File
@@ -164,12 +164,16 @@ export function useHistorySubview<T>(
// The entry's _sub is this module's only when it says so (`_subOf`): one entry can carry another
// module's — the sign-in card mounts on the entry a Plex season stood on when signed out there, and
// took that season for one of its modes (a card with no button for it). An entry an older build
// wrote says nothing: its _sub is this module's when its address names one of this module's views.
// wrote says nothing: its _sub is this module's when it is the view the address names under this
// module's key. The key alone is not enough: the card's push kept the season's `v` beside its `m`.
const readView = (): T => {
const st = window.history.state;
const raw = url ? new URLSearchParams(window.location.search).get(url.key) : null;
const decoded = url && raw != null ? url.decode(raw) : null;
const owned = st?._subOf === undefined ? decoded != null : st._subOf === subOwner(url);
const owned =
st?._subOf === undefined
? decoded != null && st?._sub != null && url?.encode(st._sub as T) === raw
: st._subOf === subOwner(url);
const fromState = owned ? (st?._sub as T | undefined) : undefined;
if (fromState != null) return fromState;
if (decoded != null) return decoded;