From 5ed83b12261733c2a79ad6597258933481d8e79b Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Mon, 11 May 2026 20:59:12 -0400 Subject: [PATCH] fix(client): show app with connecting banner instead of splash on reconnect Remove the loading state from the render gate so the app renders as soon as the MatrixClient is available (mx != null), rather than waiting for the first sync to complete. SyncStatus already renders a green 'Connecting...' banner during the initial PREPARED/SYNCING/CATCHUP phase, so there's no need for the full splash screen. The 'petting cats' splash now only appears before any MatrixClient exists (e.g. during very first load). Returning users no longer see the loading screen if the client needs to reconnect after being backgrounded. --- src/app/pages/client/ClientRoot.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/pages/client/ClientRoot.tsx b/src/app/pages/client/ClientRoot.tsx index 70ba9221e..32e1b21c4 100644 --- a/src/app/pages/client/ClientRoot.tsx +++ b/src/app/pages/client/ClientRoot.tsx @@ -175,7 +175,6 @@ type ClientRootProps = { children: ReactNode; }; export function ClientRoot({ children }: ClientRootProps) { - const [loading, setLoading] = useState(true); const navigate = useNavigate(); const clientConfig = useClientConfig(); const sessions = useAtomValue(sessionsAtom); @@ -191,6 +190,8 @@ export function ClientRoot({ children }: ClientRootProps) { const syncStartTimeRef = useRef(performance.now()); const firstSyncReadyRef = useRef(false); + const [loading, setLoading] = useState(true); + const [loadState, loadMatrix, setLoadState] = useAsyncCallback( useCallback(async () => { if (!activeSession) { @@ -238,8 +239,8 @@ export function ClientRoot({ children }: ClientRootProps) { if (mx?.clientRunning) { stopClient(mx); } - setLoading(true); loadedUserIdRef.current = undefined; + setLoading(true); setLoadState({ status: AsyncStatus.Idle }); navigate(getHomePath(), { replace: true }); } @@ -292,6 +293,7 @@ export function ClientRoot({ children }: ClientRootProps) { mx, useCallback((state: string) => { if (isClientReady(state)) { + setLoading(false); if (!firstSyncReadyRef.current) { firstSyncReadyRef.current = true; Sentry.metrics.distribution( @@ -299,7 +301,6 @@ export function ClientRoot({ children }: ClientRootProps) { performance.now() - syncStartTimeRef.current ); } - setLoading(false); } }, []) ); @@ -358,7 +359,7 @@ export function ClientRoot({ children }: ClientRootProps) { {mx && } - {loading && } + {(loading || !mx) && } {(loadState.status === AsyncStatus.Error || startState.status === AsyncStatus.Error) && (