Persist navigation state
This commit is contained in:
+39
-2
@@ -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 Linking from 'expo-linking'
|
||||||
import * as Notifications from 'expo-notifications'
|
import * as Notifications from 'expo-notifications'
|
||||||
import {i18n, type MessageDescriptor} from '@lingui/core'
|
import {i18n, type MessageDescriptor} from '@lingui/core'
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
type LinkingOptions,
|
type LinkingOptions,
|
||||||
NavigationContainer,
|
NavigationContainer,
|
||||||
|
type NavigationState,
|
||||||
StackActions,
|
StackActions,
|
||||||
} from '@react-navigation/native'
|
} from '@react-navigation/native'
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ import {useAnalytics} from '#/analytics'
|
|||||||
import {setNavigationMetadata} from '#/analytics/metadata'
|
import {setNavigationMetadata} from '#/analytics/metadata'
|
||||||
import {IS_NATIVE, IS_WEB} from '#/env'
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
import {router} from '#/routes'
|
import {router} from '#/routes'
|
||||||
|
import {device} from '#/storage'
|
||||||
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
||||||
|
|
||||||
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
|
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
|
||||||
@@ -886,6 +888,39 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
|||||||
const closeAllActiveElements = useCloseAllActiveElements()
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
const linkingUrl = Linking.useLinkingURL()
|
const linkingUrl = Linking.useLinkingURL()
|
||||||
|
|
||||||
|
const [initialState] = useState(() => {
|
||||||
|
if (!IS_NATIVE) return
|
||||||
|
|
||||||
|
const previousNavState = device.get(['navigationState'])
|
||||||
|
if (previousNavState) {
|
||||||
|
// we want to clear it asap - even if we don't use it
|
||||||
|
// if they're opening it via an intent, we obviously prioritize the intent
|
||||||
|
// but also the *subsequent* open after that, it would be weird if it restored to the
|
||||||
|
// nav state *before* that, hence the aggressive clearing -sfn
|
||||||
|
device.remove(['navigationState'])
|
||||||
|
|
||||||
|
// we only want to use it if the current state is more-or-less where they left off:
|
||||||
|
// - logged in to the same account
|
||||||
|
// - no intent
|
||||||
|
// - not handling a notification
|
||||||
|
if (linkingUrl) return
|
||||||
|
if (notificationResponse) return
|
||||||
|
if (previousNavState.did !== currentAccount?.did) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return previousNavState.state
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const persistState = (state?: NavigationState) => {
|
||||||
|
if (!IS_NATIVE) return
|
||||||
|
if (!currentAccount) return
|
||||||
|
if (!state) return
|
||||||
|
|
||||||
|
device.set(['navigationState'], {did: currentAccount.did, state})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle navigation to a conversation, or prepares for account switch.
|
* Handle navigation to a conversation, or prepares for account switch.
|
||||||
*
|
*
|
||||||
@@ -1012,10 +1047,11 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
|
initialState={initialState}
|
||||||
ref={navigationRef}
|
ref={navigationRef}
|
||||||
linking={LINKING}
|
linking={LINKING}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
onStateChange={() => {
|
onStateChange={state => {
|
||||||
const currentScreen = getCurrentRouteName()
|
const currentScreen = getCurrentRouteName()
|
||||||
// do this before metric
|
// do this before metric
|
||||||
setNavigationMetadata({
|
setNavigationMetadata({
|
||||||
@@ -1024,6 +1060,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
|||||||
})
|
})
|
||||||
ax.metric('router:navigate', {from: previousScreen.current})
|
ax.metric('router:navigate', {from: previousScreen.current})
|
||||||
previousScreen.current = currentScreen
|
previousScreen.current = currentScreen
|
||||||
|
persistState(state)
|
||||||
}}
|
}}
|
||||||
onReady={onNavigationReady}
|
onReady={onNavigationReady}
|
||||||
// WARNING: Implicit navigation to nested navigators is depreciated in React Navigation 7.x
|
// WARNING: Implicit navigation to nested navigators is depreciated in React Navigation 7.x
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import {type InitialState} from '@react-navigation/native'
|
||||||
|
|
||||||
import {type ID as PolicyUpdate202508} from '#/components/PolicyUpdateOverlay/updates/202508/config'
|
import {type ID as PolicyUpdate202508} from '#/components/PolicyUpdateOverlay/updates/202508/config'
|
||||||
import {type Geolocation} from '#/geolocation/types'
|
import {type Geolocation} from '#/geolocation/types'
|
||||||
|
|
||||||
@@ -66,6 +68,11 @@ export type Device = {
|
|||||||
*/
|
*/
|
||||||
policyUpdateDebugOverride?: boolean
|
policyUpdateDebugOverride?: boolean
|
||||||
[PolicyUpdate202508]?: boolean
|
[PolicyUpdate202508]?: boolean
|
||||||
|
|
||||||
|
navigationState?: {
|
||||||
|
did: string
|
||||||
|
state: InitialState
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Account = {
|
export type Account = {
|
||||||
|
|||||||
Reference in New Issue
Block a user