fix(offline): stop offline white-screen and replay paused structural mutations
Fixes the offline-sync defects QA found on PR #120 (#237/#238/#220). Blank-shell / white-screen on offline reload (HIGH): - auth-query.tsx: the useCollabToken retry predicate read `error.response.status` unguarded. Offline the collab-token POST rejects as an axios NETWORK error (isAxiosError true, response undefined), so `.status` threw an uncaught TypeError in the React Query retryer BEFORE React mounted, white-screening every route. Extracted the predicate as `collabTokenRetry` and guarded it with optional chaining (`error.response?.status === 404`). - user-provider.tsx: gated the whole <Layout> on useCurrentUser() and returned a bare `<></>` on any error, blanking every authenticated route offline even when cached data existed. Now renders the cached app when a (stale) user is present and an explicit OfflineFallback when there is no user to fall back on. - query-persister.ts / make-offline.ts: persist and warm the ['currentUser'] query so the auth gate can hydrate offline (pinned pages now survive relaunch). Offline structural create/move/comment silently lost on reload (HIGH): - offline-mutations.ts: register setMutationDefaults (default mutationFns) for stable mutation keys and tag useCreatePageMutation / useMovePageMutation / useCreateCommentMutation with those keys. A paused mutation dehydrated to IndexedDB while offline now has a mutationFn after reload, so resumePausedMutations() replays it on reconnect instead of no-op'ing. Tests (client vitest): collabTokenRetry no longer throws on a no-response network error; UserProvider renders cached children / the offline fallback (not a blank fragment) on a network error; a rehydrated paused create/move is replayable via resumePausedMutations; currentUser persist-root coverage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import { notifications } from "@mantine/notifications";
|
||||
import { IPagination } from "@/lib/types.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { offlineMutationKeys } from "@/features/offline/offline-mutations";
|
||||
|
||||
export const RQ_KEY = (pageId: string) => ["comments", pageId];
|
||||
|
||||
@@ -60,6 +61,9 @@ export function useCreateCommentMutation() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return useMutation<IComment, Error, Partial<IComment>>({
|
||||
// Stable key so a paused comment-create restored from IndexedDB after an
|
||||
// offline reload finds its default mutationFn and is replayed on reconnect.
|
||||
mutationKey: offlineMutationKeys.createComment,
|
||||
mutationFn: (data) => createComment(data),
|
||||
onSuccess: (newComment) => {
|
||||
const cache = queryClient.getQueryData(
|
||||
|
||||
Reference in New Issue
Block a user