[Session] Extract resumeSession out (#3811)

zio/stable
dan 2024-05-02 18:17:53 +01:00 committed by GitHub
parent dadf27fd2f
commit 5ec945b762
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 43 additions and 36 deletions

View File

@ -16,6 +16,7 @@ import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {Provider as StatsigProvider} from '#/lib/statsig/statsig' import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {init as initPersistedState} from '#/state/persisted' import {init as initPersistedState} from '#/state/persisted'
import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs' import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts' import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
@ -34,6 +35,7 @@ import {Provider as PrefsStateProvider} from 'state/preferences'
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread' import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
import { import {
Provider as SessionProvider, Provider as SessionProvider,
SessionAccount,
useSession, useSession,
useSessionApi, useSessionApi,
} from 'state/session' } from 'state/session'
@ -53,8 +55,9 @@ import {listenSessionDropped} from './state/events'
SplashScreen.preventAutoHideAsync() SplashScreen.preventAutoHideAsync()
function InnerApp() { function InnerApp() {
const {isInitialLoad, currentAccount} = useSession() const [isReady, setIsReady] = React.useState(false)
const {resumeSession} = useSessionApi() const {currentAccount} = useSession()
const {initSession} = useSessionApi()
const theme = useColorModeTheme() const theme = useColorModeTheme()
const {_} = useLingui() const {_} = useLingui()
@ -62,18 +65,31 @@ function InnerApp() {
// init // init
useEffect(() => { useEffect(() => {
listenSessionDropped(() => { async function resumeSession(account?: SessionAccount) {
Toast.show(_(msg`Sorry! Your session expired. Please log in again.`)) try {
}) if (account) {
await initSession(account)
}
} catch (e) {
logger.error(`session: resumeSession failed`, {message: e})
} finally {
setIsReady(true)
}
}
const account = readLastActiveAccount() const account = readLastActiveAccount()
resumeSession(account) resumeSession(account)
}, [resumeSession, _]) }, [initSession])
useEffect(() => {
return listenSessionDropped(() => {
Toast.show(_(msg`Sorry! Your session expired. Please log in again.`))
})
}, [_])
return ( return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}> <SafeAreaProvider initialMetrics={initialWindowMetrics}>
<Alf theme={theme}> <Alf theme={theme}>
<Splash isReady={!isInitialLoad}> <Splash isReady={isReady}>
<React.Fragment <React.Fragment
// Resets the entire tree below when it changes: // Resets the entire tree below when it changes:
key={currentAccount?.did}> key={currentAccount?.did}>

View File

@ -6,6 +6,7 @@ import {RootSiblingParent} from 'react-native-root-siblings'
import {SafeAreaProvider} from 'react-native-safe-area-context' import {SafeAreaProvider} from 'react-native-safe-area-context'
import {Provider as StatsigProvider} from '#/lib/statsig/statsig' import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {init as initPersistedState} from '#/state/persisted' import {init as initPersistedState} from '#/state/persisted'
import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs' import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts' import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
@ -22,6 +23,7 @@ import {Provider as PrefsStateProvider} from 'state/preferences'
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread' import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
import { import {
Provider as SessionProvider, Provider as SessionProvider,
SessionAccount,
useSession, useSession,
useSessionApi, useSessionApi,
} from 'state/session' } from 'state/session'
@ -36,19 +38,31 @@ import {Provider as PortalProvider} from '#/components/Portal'
import I18nProvider from './locale/i18nProvider' import I18nProvider from './locale/i18nProvider'
function InnerApp() { function InnerApp() {
const {isInitialLoad, currentAccount} = useSession() const [isReady, setIsReady] = React.useState(false)
const {resumeSession} = useSessionApi() const {currentAccount} = useSession()
const {initSession} = useSessionApi()
const theme = useColorModeTheme() const theme = useColorModeTheme()
useIntentHandler() useIntentHandler()
// init // init
useEffect(() => { useEffect(() => {
async function resumeSession(account?: SessionAccount) {
try {
if (account) {
await initSession(account)
}
} catch (e) {
logger.error(`session: resumeSession failed`, {message: e})
} finally {
setIsReady(true)
}
}
const account = readLastActiveAccount() const account = readLastActiveAccount()
resumeSession(account) resumeSession(account)
}, [resumeSession]) }, [initSession])
// wait for session to resume // wait for session to resume
if (isInitialLoad) return null if (!isReady) return null
return ( return (
<Alf theme={theme}> <Alf theme={theme}>

View File

@ -35,7 +35,6 @@ const PUBLIC_BSKY_AGENT = new BskyAgent({service: PUBLIC_BSKY_SERVICE})
configureModerationForGuest() configureModerationForGuest()
const StateContext = React.createContext<SessionStateContext>({ const StateContext = React.createContext<SessionStateContext>({
isInitialLoad: true,
isSwitchingAccounts: false, isSwitchingAccounts: false,
accounts: [], accounts: [],
currentAccount: undefined, currentAccount: undefined,
@ -47,7 +46,6 @@ const ApiContext = React.createContext<SessionApiContext>({
login: async () => {}, login: async () => {},
logout: async () => {}, logout: async () => {},
initSession: async () => {}, initSession: async () => {},
resumeSession: async () => {},
removeAccount: () => {}, removeAccount: () => {},
selectAccount: async () => {}, selectAccount: async () => {},
updateCurrentAccount: () => {}, updateCurrentAccount: () => {},
@ -67,7 +65,6 @@ type State = {
} }
export function Provider({children}: React.PropsWithChildren<{}>) { export function Provider({children}: React.PropsWithChildren<{}>) {
const [isInitialLoad, setIsInitialLoad] = React.useState(true)
const [isSwitchingAccounts, setIsSwitchingAccounts] = React.useState(false) const [isSwitchingAccounts, setIsSwitchingAccounts] = React.useState(false)
const [state, setState] = React.useState<State>({ const [state, setState] = React.useState<State>({
accounts: persisted.get('session').accounts, accounts: persisted.get('session').accounts,
@ -389,21 +386,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
[upsertAccount, clearCurrentAccount, createPersistSessionHandler], [upsertAccount, clearCurrentAccount, createPersistSessionHandler],
) )
const resumeSession = React.useCallback<SessionApiContext['resumeSession']>(
async account => {
try {
if (account) {
await initSession(account)
}
} catch (e) {
logger.error(`session: resumeSession failed`, {message: e})
} finally {
setIsInitialLoad(false)
}
},
[initSession],
)
const removeAccount = React.useCallback<SessionApiContext['removeAccount']>( const removeAccount = React.useCallback<SessionApiContext['removeAccount']>(
account => { account => {
setState(s => { setState(s => {
@ -547,11 +529,10 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
currentAccount: state.accounts.find( currentAccount: state.accounts.find(
a => a.did === state.currentAccountDid, a => a.did === state.currentAccountDid,
), ),
isInitialLoad,
isSwitchingAccounts, isSwitchingAccounts,
hasSession: !!state.currentAccountDid, hasSession: !!state.currentAccountDid,
}), }),
[state, isInitialLoad, isSwitchingAccounts], [state, isSwitchingAccounts],
) )
const api = React.useMemo( const api = React.useMemo(
@ -560,7 +541,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
login, login,
logout, logout,
initSession, initSession,
resumeSession,
removeAccount, removeAccount,
selectAccount, selectAccount,
updateCurrentAccount, updateCurrentAccount,
@ -571,7 +551,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
login, login,
logout, logout,
initSession, initSession,
resumeSession,
removeAccount, removeAccount,
selectAccount, selectAccount,
updateCurrentAccount, updateCurrentAccount,

View File

@ -6,7 +6,6 @@ export type SessionAccount = PersistedAccount
export type SessionStateContext = { export type SessionStateContext = {
accounts: SessionAccount[] accounts: SessionAccount[]
currentAccount: SessionAccount | undefined currentAccount: SessionAccount | undefined
isInitialLoad: boolean
isSwitchingAccounts: boolean isSwitchingAccounts: boolean
hasSession: boolean hasSession: boolean
} }
@ -46,7 +45,6 @@ export type SessionApiContext = {
*/ */
clearCurrentAccount: () => void clearCurrentAccount: () => void
initSession: (account: SessionAccount) => Promise<void> initSession: (account: SessionAccount) => Promise<void>
resumeSession: (account?: SessionAccount) => Promise<void>
removeAccount: (account: SessionAccount) => void removeAccount: (account: SessionAccount) => void
selectAccount: ( selectAccount: (
account: SessionAccount, account: SessionAccount,