- Refactor groupDispatchers to accept userId as a parameter instead of closing over nullable userId
- Replace mutationGroup! with a guard clause
- Use optional chaining for preferenceChildrenOptionsByKey lookup with fallback
- Clear optimistic store on user/session change to prevent stale values leaking across logins
- Move dispatcher lookup before setOptimistic to avoid permanent ghost entries when no dispatcher exists
- Inline dayjs.weekdays() calls to reflect runtime locale changes instead of caching at module load
- Remove unused UserPreferenceKey import
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.
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.
Replace 5 per-preference children files with a single
preference-registry.tsx that auto-generates CMDK children via factory
functions. Rewrite useUserPreferences from ~347 lines to ~160 lines by
deriving mutation dispatch, pending state, and optimistic values from
preference definitions.
Simplify settings-children.tsx and groups.tsx to iterate over
visiblePreferenceDefinitions instead of maintaining manual mappings.
Deleted: board.tsx, color-scheme.tsx, first-day-of-week.tsx,
search-engine.tsx, registry.ts
Net reduction: ~261 lines across 9 files.
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.
Enrich userPreferenceDefinitions with mutationGroup field to express
which tRPC mutation handles each preference key. Move
visiblePreferenceDefinitions helper from spotlight registry to the
shared settings package.
This enables data-driven mutation dispatch in the CMDK hook and
eliminates manual key-to-group mappings.
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.