feat(ui): add global query refresh indicator to board header#5811
Draft
ajnart wants to merge 15 commits into
Draft
feat(ui): add global query refresh indicator to board header#5811ajnart wants to merge 15 commits into
ajnart wants to merge 15 commits into
Conversation
a83bc66 to
c209fd9
Compare
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.
6aeaa49 to
a266874
Compare
Use Mantine Indicator with processing animation instead of custom CSS. Switch from HoverCard to Menu with grouped sections. Remove beep, position dot next to board logo, hide in 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.
…-mode guard - 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
…scope indicator - Add isFetched guard in media-requests/list to avoid throwing before data loads - Scope refresh indicator to only track widget and integration queries
Member
Author
|
i believe this change will be nice, I'd much rather see the calendar and then 500-800ms later see the entries popping up rather than the loading circle, that's probably the case for a bunch of other integrations that could have fallback states in place of the loading spinner. The issue is I'm not sure where to indicate the freshness of the queries |
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.
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.
Call setActiveQueryCacheBoardId when board context initializes so the client-side persister knows which board to scope cache reads/writes to.
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.
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 QueryCacheHydration async server component inside <Suspense> that reads all persisted queries from Redis via HGETALL and streams a HydrationBoundary to the client. Builds DehydratedState directly with original dataUpdatedAt timestamps so fresh prefetch data is never overwritten by stale cache. Make client persister write-only (getItem returns null) since reads are handled server-side.
Filter out widget.app.ping from the indicator. Show colored status dots (green/orange/red) per query alongside integration icons with name tooltips. Use lookup maps and resolver functions instead of ternaries. Display relative timestamps for last data update.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
widget.*,docker.*,app.*,integration.*)fromNow)AudioContext)<Loader>Continues the work from #5768 with a broader scope.
Test plan