Review follow-ups on the session query cache:
- Cache the per-payload size verdict and reuse a single TextEncoder. The
persist subscription re-dehydrates the whole cache on every cache event,
so every widget payload was being superjson-serialized several times per
refresh cycle just to measure it.
- Skip the size measurement on the restore path. It runs before any query is
allowed to fetch and the payload was already budgeted when it was written.
- Reject stored queries whose dataUpdatedAt is not a positive finite number;
`undefined <= 0` is false, so those were hydrating with a NaN timestamp.
- Add `stop()` and tear the persister down before `queryClient.clear()`, so
the clear cannot overwrite the saved snapshot with an empty cache.
- Remove every other scope's cache when a persister is created: signing out
navigates away before the scope guard can react, which left the previous
account's dashboard data in the tab.
- Remove the entry instead of storing an empty cache.
Refresh indicator:
- Make it decorative instead of an aria-live region; every widget refreshes
on a timer, so it made assistive technology repeat "loading" forever.
Also broadens the e2e hydration-error matcher to production React's minified
error codes, hoists the single WidgetTimeProvider in ClientBoard, memoizes the
resolved local time zone, and drops the exports this branch made dead.
- Classify IPv4/IPv6 link-local addresses (169.254.0.0/16, fe80::/10) as
LAN in Jellyfin location parsing - they can't traverse a router, so a
false WAN reading was possible for common autoconfig/link-local sessions.
- Fix portrait video resolution mislabeling - a 1080x1920 clip was
classified off its long-axis height (1920) and showed as 1440p. Classify
by the short axis instead so orientation doesn't flip the result.
- Raise the compact-mode status column breakpoint from 420 to 540px - at
420 the fixed-width user (200px) and status (190px) columns left almost
no room for the currentlyPlaying column, the widget's primary content.
- Document the new resolution indicator in the media-server widget docs.
Rebuild the integration marquee on Mantine's Marquee, SimpleGrid and
ThemeIcon instead of the hand-rolled grid, track and keyframes, and
reduce the stylesheet to the mask and reduced-motion rule.
Drop the useMounted guards from the login form and let the buttons rely
on the pending state alone, and use Group for the restore flow's file
summary.