Convert Uptime Kuma, Paperless-ngx, audio-stats, and UPS widgets
to use useQuery with WidgetEmptyState fallback, consistent with the
query cache persistence pattern from PR #5811.
Convert all 4 Beszel widget components to use useQuery with staleTime
instead of useSuspenseQuery with refetchOnMount, matching the query
cache persistence pattern from PR #5811.
* chore(integrations): add ws dependency for the truenas client
* feat(definitions): allow api key authentication for truenas
* fix(integrations): connect to truenas over trusted-certificate websocket with protocol autodetection
* test(integrations): cover truenas protocol detection and authentication
* refactor(integrations): avoid shorthand index variable in truenas mapping
* feat(integrations): add a websocket url helper to the integration base
* refactor(integrations): extract truenas connection handling into a client
Remove WidgetEmptyState guard from downloads (widget renders fine with
empty data). Fix columnsSort filter logic from .some() to .every() so
non-sortable columns are correctly excluded. Add server-side prefetch
via tRPC caller so download data is available immediately on page load.
Add WidgetEmptyState component for widgets that need a loading fallback.
Disable refetch-on-mount/focus/reconnect and retry for integration widgets
so cached data is preserved. Ensure hooks are never called conditionally.
Replace individual Redis keys (queryCache:sha256(...)) with a Hash per
user+board (qc:{userId}:{boardId}). This enables HGETALL to read all
cached entries in a single call for server-side hydration. Remove unused
SHA256 hashKey function and createHash import.
Add tRPC router (queryCache.getItem/setItem/removeItem) for persisting
TanStack Query cache entries to Redis, scoped per user and board.
Includes isPersistableWidgetQueryKey filter that excludes widget.app.ping,
and comprehensive tests covering access control, TTL expiry, and size limits.
- Add isFetched guard in media-requests/list to avoid throwing before data loads
- Scope refresh indicator to only track widget and integration queries
- Move hooks above early returns in system-disks, immich-carousel, media-transcoding
- Add enabled flag to immich-carousel query when albumId is absent
- Replace disconnected local state in ping-indicator with query cache setData
- Stabilize docker timestamp with useMemo to prevent useTimeAgo flicker
- Wrap releases results in useMemo with proper type narrowing
- Hide refresh indicator during edit mode
Non-blocking data fetching for all 38 widget components. Widgets now
render immediately and show data when available, with loading state
delegated to the global refresh indicator in the board header.
Replace per-widget loading spinners with a shared header indicator that
shows live TanStack Query cache status for all widget-related queries.
Includes orange/green dot, completion beep, and hover card with
per-query staleness and error details.