From 5ee69940a60f3b438fcf2fcb7b17c6f0f2322dcd Mon Sep 17 00:00:00 2001 From: xan.lol Date: Mon, 04 May 2026 06:51:52 +0000 Subject: [PATCH] fix: native app regressions - switching accounts on mobile losing navigation history 🙂‍↔️ - now able to sign in on mobile again --- src/Navigation.tsx | 12 +++++++++--- src/state/session/oauth-web-return-url.ts | 34 +++++++++++++++++++++++----------- 2 file(s) changed, 32 insertion(s)(+), 14 deletion(s)(-) diff --git a/src/Navigation.tsx b/src/Navigation.tsx --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -1,4 +1,4 @@ -import {type JSX, useCallback, useRef} from 'react' +import {type JSX, useCallback, useRef, useState} from 'react' import * as Linking from 'expo-linking' import * as Notifications from 'expo-notifications' import {i18n, type MessageDescriptor} from '@lingui/core' @@ -1047,8 +1047,14 @@ const linkingUrl = Linking.useLinkingURL() const disableVerifyEmailReminder = useDisableVerifyEmailReminder() - // Consume stored navigation state from account switch (native only) - const initialState = IS_NATIVE ? consumeStoredNavigationState() : undefined + // Consume stored navigation state exactly once for this mount. + // Account switches trigger session updates before the keyed shell subtree + // remounts, so consuming during render can clear the stored back stack too + // early and leave React Navigation to reconstruct only the active route. + const [initialState, setInitialState] = useState(() => + IS_NATIVE ? consumeStoredNavigationState() : undefined, + ) + void setInitialState /** * Handle navigation to a conversation, or prepares for account switch. diff --git a/src/state/session/oauth-web-return-url.ts b/src/state/session/oauth-web-return-url.ts --- a/src/state/session/oauth-web-return-url.ts +++ b/src/state/session/oauth-web-return-url.ts @@ -1,17 +1,27 @@ const OAUTH_RETURN_URL_KEY = 'oauth_return_url' const OAUTH_CALLBACK_ERROR_KEY = 'oauth_callback_error' -export function saveOAuthReturnUrl(url = window.location.href) { - if (typeof window === 'undefined') return +function getSessionStorage() { + if (typeof window === 'undefined') return undefined + + return window.sessionStorage +} + +export function saveOAuthReturnUrl(url?: string) { + const sessionStorage = getSessionStorage() + if (!sessionStorage) return - window.sessionStorage.setItem(OAUTH_RETURN_URL_KEY, url) + const returnUrl = url ?? window.location.href + + sessionStorage.setItem(OAUTH_RETURN_URL_KEY, returnUrl) } export function consumeOAuthReturnUrl() { - if (typeof window === 'undefined') return undefined + const sessionStorage = getSessionStorage() + if (!sessionStorage) return undefined - const savedUrl = window.sessionStorage.getItem(OAUTH_RETURN_URL_KEY) - window.sessionStorage.removeItem(OAUTH_RETURN_URL_KEY) + const savedUrl = sessionStorage.getItem(OAUTH_RETURN_URL_KEY) + sessionStorage.removeItem(OAUTH_RETURN_URL_KEY) if (!savedUrl) return undefined @@ -26,15 +36,17 @@ } } export function saveOAuthCallbackError(error: string) { - if (typeof window === 'undefined') return + const sessionStorage = getSessionStorage() + if (!sessionStorage) return - window.sessionStorage.setItem(OAUTH_CALLBACK_ERROR_KEY, error) + sessionStorage.setItem(OAUTH_CALLBACK_ERROR_KEY, error) } export function consumeOAuthCallbackError() { - if (typeof window === 'undefined') return undefined + const sessionStorage = getSessionStorage() + if (!sessionStorage) return undefined - const error = window.sessionStorage.getItem(OAUTH_CALLBACK_ERROR_KEY) - window.sessionStorage.removeItem(OAUTH_CALLBACK_ERROR_KEY) + const error = sessionStorage.getItem(OAUTH_CALLBACK_ERROR_KEY) + sessionStorage.removeItem(OAUTH_CALLBACK_ERROR_KEY) return error || undefined } -- tangled.sh