The WidgetTimeProvider plumbed a server timestamp and the container's
timezone down to useWidgetNow so clock widgets would paint a real time in
the SSR HTML instead of "--:--". That traded a cosmetic first-paint win for
a wrong clock: the seeded timezone is the server's, so anyone whose timezone
differs from the container's saw an incorrect time for the whole hydration
window. Fixing that properly needs a client-set timezone cookie read during
RSC render, which is far more plumbing than the problem warrants.
Revert the clock to release/v2 behaviour ("--:--" until hydration) and drop
the provider, the @homarr/widgets/time export and their tests. The e2e clock
assertions now wait on hydration explicitly instead of the seeded paint.
Also restore the widget.beszel.getSystemStats persistence exclusion. #6289
added it deliberately to keep those large time-series payloads out of the
persisted cache, and this branch had removed it with no stated rationale.
Query-cache persistence and the background-refresh indicator are unchanged.
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.