diff --git a/apps/client/src/features/user/user-provider.tsx b/apps/client/src/features/user/user-provider.tsx index 4e7c726c..5720f29e 100644 --- a/apps/client/src/features/user/user-provider.tsx +++ b/apps/client/src/features/user/user-provider.tsx @@ -11,6 +11,7 @@ import { useTreeSocket } from "@/features/websocket/use-tree-socket.ts"; import { useNotificationSocket } from "@/features/notification/hooks/use-notification-socket.ts"; import { useCollabToken } from "@/features/auth/queries/auth-query.tsx"; import { Error404 } from "@/components/ui/error-404.tsx"; +import { queryClient } from "@/main.tsx"; export function UserProvider({ children }: React.PropsWithChildren) { const [, setCurrentUser] = useAtom(currentUserAtom); @@ -33,8 +34,19 @@ export function UserProvider({ children }: React.PropsWithChildren) { // @ts-ignore setSocket(newSocket); + // Distinguish the first connect from a reconnect so we only resync after a gap. + let firstConnect = true; newSocket.on("connect", () => { console.log("ws connected"); + if (!firstConnect) { + // On RECONNECT (not the first connect) refetch the sidebar tree through the + // authorized API so the view re-converges after a gap where ws events were + // missed (wifi blip, laptop sleep). Invalidate both the root level and the + // nested-page levels of every space tree. + queryClient.invalidateQueries({ queryKey: ["root-sidebar-pages"] }); + queryClient.invalidateQueries({ queryKey: ["sidebar-pages"] }); + } + firstConnect = false; }); return () => {