From 5ee69940a60f3b438fcf2fcb7b17c6f0f2322dcd Mon Sep 17 00:00:00 2001 From: "xan.lol" Date: Sun, 3 May 2026 23:51:52 -0700 Subject: [PATCH] fix: native app regressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 0a58ac031..013ecb4b8 100644 --- 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 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) { 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 index 37f8326d3..38719b0b4 100644 --- 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 - window.sessionStorage.setItem(OAUTH_RETURN_URL_KEY, url) + return window.sessionStorage +} + +export function saveOAuthReturnUrl(url?: string) { + const sessionStorage = getSessionStorage() + if (!sessionStorage) return + + 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 consumeOAuthReturnUrl() { } 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 } -- 2.51.2