diff options
author | dan <dan.abramov@gmail.com> | 2024-05-02 18:25:09 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-02 18:25:09 +0100 |
commit | 1a07e23192d06afd3879e89252f1bcfbb33df081 (patch) | |
tree | b3d84d07475a4a97864387025144ea67d81dd5cb | |
parent | 5ec945b7625a8daff3baaf76826c2f9e3c12e279 (diff) | |
download | voidsky-1a07e23192d06afd3879e89252f1bcfbb33df081.tar.zst |
[Session] Extract selectAccount out (#3812)
-rw-r--r-- | src/components/AccountList.tsx | 4 | ||||
-rw-r--r-- | src/components/dialogs/SwitchAccount.tsx | 3 | ||||
-rw-r--r-- | src/lib/hooks/useAccountSwitcher.ts | 16 | ||||
-rw-r--r-- | src/screens/Login/ChooseAccountForm.tsx | 5 | ||||
-rw-r--r-- | src/state/session/index.tsx | 25 | ||||
-rw-r--r-- | src/state/session/types.ts | 5 | ||||
-rw-r--r-- | src/view/screens/Settings/index.tsx | 32 |
7 files changed, 48 insertions, 42 deletions
diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx index 169e7b84f..76596df3e 100644 --- a/src/components/AccountList.tsx +++ b/src/components/AccountList.tsx @@ -16,12 +16,14 @@ export function AccountList({ onSelectAccount, onSelectOther, otherLabel, + isSwitchingAccounts, }: { onSelectAccount: (account: SessionAccount) => void onSelectOther: () => void otherLabel?: string + isSwitchingAccounts: boolean }) { - const {isSwitchingAccounts, currentAccount, accounts} = useSession() + const {currentAccount, accounts} = useSession() const t = useTheme() const {_} = useLingui() diff --git a/src/components/dialogs/SwitchAccount.tsx b/src/components/dialogs/SwitchAccount.tsx index 55628a790..18fc55aaf 100644 --- a/src/components/dialogs/SwitchAccount.tsx +++ b/src/components/dialogs/SwitchAccount.tsx @@ -18,7 +18,7 @@ export function SwitchAccountDialog({ }) { const {_} = useLingui() const {currentAccount} = useSession() - const {onPressSwitchAccount} = useAccountSwitcher() + const {onPressSwitchAccount, isSwitchingAccounts} = useAccountSwitcher() const {setShowLoggedOut} = useLoggedOutViewControls() const onSelectAccount = useCallback( @@ -54,6 +54,7 @@ export function SwitchAccountDialog({ onSelectAccount={onSelectAccount} onSelectOther={onPressAddAccount} otherLabel={_(msg`Add account`)} + isSwitchingAccounts={isSwitchingAccounts} /> </View> </Dialog.ScrollableInner> diff --git a/src/lib/hooks/useAccountSwitcher.ts b/src/lib/hooks/useAccountSwitcher.ts index 6d2f7b36b..d4e026958 100644 --- a/src/lib/hooks/useAccountSwitcher.ts +++ b/src/lib/hooks/useAccountSwitcher.ts @@ -1,4 +1,4 @@ -import {useCallback} from 'react' +import {useCallback, useState} from 'react' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -8,12 +8,14 @@ import {isWeb} from '#/platform/detection' import {SessionAccount, useSessionApi} from '#/state/session' import {useLoggedOutViewControls} from '#/state/shell/logged-out' import * as Toast from '#/view/com/util/Toast' +import {logEvent} from '../statsig/statsig' import {LogEvents} from '../statsig/statsig' export function useAccountSwitcher() { + const [isSwitchingAccounts, setIsSwitchingAccounts] = useState(false) const {_} = useLingui() const {track} = useAnalytics() - const {selectAccount, clearCurrentAccount} = useSessionApi() + const {initSession, clearCurrentAccount} = useSessionApi() const {requestSwitchToAccount} = useLoggedOutViewControls() const onPressSwitchAccount = useCallback( @@ -24,6 +26,7 @@ export function useAccountSwitcher() { track('Settings:SwitchAccountButtonClicked') try { + setIsSwitchingAccounts(true) if (account.accessJwt) { if (isWeb) { // We're switching accounts, which remounts the entire app. @@ -33,7 +36,8 @@ export function useAccountSwitcher() { // So we change the URL ourselves. The navigator will pick it up on remount. history.pushState(null, '', '/') } - await selectAccount(account, logContext) + await initSession(account) + logEvent('account:loggedIn', {logContext, withPassword: false}) setTimeout(() => { Toast.show(_(msg`Signed in as @${account.handle}`)) }, 100) @@ -52,10 +56,12 @@ export function useAccountSwitcher() { setTimeout(() => { Toast.show(_(msg`Sorry! We need you to enter your password.`)) }, 100) + } finally { + setIsSwitchingAccounts(false) } }, - [_, track, clearCurrentAccount, selectAccount, requestSwitchToAccount], + [_, track, clearCurrentAccount, initSession, requestSwitchToAccount], ) - return {onPressSwitchAccount} + return {onPressSwitchAccount, isSwitchingAccounts} } diff --git a/src/screens/Login/ChooseAccountForm.tsx b/src/screens/Login/ChooseAccountForm.tsx index d36d10977..8a58ac03d 100644 --- a/src/screens/Login/ChooseAccountForm.tsx +++ b/src/screens/Login/ChooseAccountForm.tsx @@ -22,6 +22,7 @@ export const ChooseAccountForm = ({ onSelectAccount: (account?: SessionAccount) => void onPressBack: () => void }) => { + const [isSwitchingAccounts, setIsSwitchingAccounts] = React.useState(false) const {track, screen} = useAnalytics() const {_} = useLingui() const {currentAccount} = useSession() @@ -40,6 +41,7 @@ export const ChooseAccountForm = ({ Toast.show(_(msg`Already signed in as @${account.handle}`)) } else { try { + setIsSwitchingAccounts(true) await initSession(account) logEvent('account:loggedIn', { logContext: 'ChooseAccountForm', @@ -54,6 +56,8 @@ export const ChooseAccountForm = ({ message: e.message, }) onSelectAccount(account) + } finally { + setIsSwitchingAccounts(false) } } } else { @@ -74,6 +78,7 @@ export const ChooseAccountForm = ({ <AccountList onSelectAccount={onSelect} onSelectOther={() => onSelectAccount()} + isSwitchingAccounts={isSwitchingAccounts} /> </View> <View style={[a.flex_row]}> diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx index 64f3837c7..6aa3f73cc 100644 --- a/src/state/session/index.tsx +++ b/src/state/session/index.tsx @@ -35,7 +35,6 @@ const PUBLIC_BSKY_AGENT = new BskyAgent({service: PUBLIC_BSKY_SERVICE}) configureModerationForGuest() const StateContext = React.createContext<SessionStateContext>({ - isSwitchingAccounts: false, accounts: [], currentAccount: undefined, hasSession: false, @@ -47,7 +46,6 @@ const ApiContext = React.createContext<SessionApiContext>({ logout: async () => {}, initSession: async () => {}, removeAccount: () => {}, - selectAccount: async () => {}, updateCurrentAccount: () => {}, clearCurrentAccount: () => {}, }) @@ -65,7 +63,6 @@ type State = { } export function Provider({children}: React.PropsWithChildren<{}>) { - const [isSwitchingAccounts, setIsSwitchingAccounts] = React.useState(false) const [state, setState] = React.useState<State>({ accounts: persisted.get('session').accounts, currentAccountDid: undefined, // assume logged out to start @@ -437,23 +434,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) { [setState], ) - const selectAccount = React.useCallback<SessionApiContext['selectAccount']>( - async (account, logContext) => { - setIsSwitchingAccounts(true) - try { - await initSession(account) - setIsSwitchingAccounts(false) - logEvent('account:loggedIn', {logContext, withPassword: false}) - } catch (e) { - // reset this in case of error - setIsSwitchingAccounts(false) - // but other listeners need a throw - throw e - } - }, - [initSession], - ) - React.useEffect(() => { if (state.needsPersist) { state.needsPersist = false @@ -529,10 +509,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) { currentAccount: state.accounts.find( a => a.did === state.currentAccountDid, ), - isSwitchingAccounts, hasSession: !!state.currentAccountDid, }), - [state, isSwitchingAccounts], + [state], ) const api = React.useMemo( @@ -542,7 +521,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) { logout, initSession, removeAccount, - selectAccount, updateCurrentAccount, clearCurrentAccount, }), @@ -552,7 +530,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) { logout, initSession, removeAccount, - selectAccount, updateCurrentAccount, clearCurrentAccount, ], diff --git a/src/state/session/types.ts b/src/state/session/types.ts index a2a9f8cf8..b3252f777 100644 --- a/src/state/session/types.ts +++ b/src/state/session/types.ts @@ -6,7 +6,6 @@ export type SessionAccount = PersistedAccount export type SessionStateContext = { accounts: SessionAccount[] currentAccount: SessionAccount | undefined - isSwitchingAccounts: boolean hasSession: boolean } export type SessionApiContext = { @@ -46,10 +45,6 @@ export type SessionApiContext = { clearCurrentAccount: () => void initSession: (account: SessionAccount) => Promise<void> removeAccount: (account: SessionAccount) => void - selectAccount: ( - account: SessionAccount, - logContext: LogEvents['account:loggedIn']['logContext'], - ) => Promise<void> updateCurrentAccount: ( account: Partial< Pick< diff --git a/src/view/screens/Settings/index.tsx b/src/view/screens/Settings/index.tsx index a0e4ff60f..b3313f60f 100644 --- a/src/view/screens/Settings/index.tsx +++ b/src/view/screens/Settings/index.tsx @@ -70,14 +70,24 @@ import {navigate, resetToTab} from '#/Navigation' import {Email2FAToggle} from './Email2FAToggle' import {ExportCarDialog} from './ExportCarDialog' -function SettingsAccountCard({account}: {account: SessionAccount}) { +function SettingsAccountCard({ + account, + isSwitchingAccounts, + onPressSwitchAccount, +}: { + account: SessionAccount + isSwitchingAccounts: boolean + onPressSwitchAccount: ( + account: SessionAccount, + logContext: 'Settings', + ) => void +}) { const pal = usePalette('default') const {_} = useLingui() - const {isSwitchingAccounts, currentAccount} = useSession() + const {currentAccount} = useSession() const {logout} = useSessionApi() const {data: profile} = useProfileQuery({did: account.did}) const isCurrentAccount = account.did === currentAccount?.did - const {onPressSwitchAccount} = useAccountSwitcher() const contents = ( <View style={[pal.view, styles.linkCard]}> @@ -165,12 +175,13 @@ export function SettingsScreen({}: Props) { const {isMobile} = useWebMediaQueries() const {screen, track} = useAnalytics() const {openModal} = useModalControls() - const {isSwitchingAccounts, accounts, currentAccount} = useSession() + const {accounts, currentAccount} = useSession() const {mutate: clearPreferences} = useClearPreferencesMutation() const {setShowLoggedOut} = useLoggedOutViewControls() const closeAllActiveElements = useCloseAllActiveElements() const exportCarControl = useDialogControl() const birthdayControl = useDialogControl() + const {isSwitchingAccounts, onPressSwitchAccount} = useAccountSwitcher() // TODO: TEMP REMOVE WHEN CLOPS ARE RELEASED const gate = useGate() @@ -385,13 +396,22 @@ export function SettingsScreen({}: Props) { <ActivityIndicator /> </View> ) : ( - <SettingsAccountCard account={currentAccount!} /> + <SettingsAccountCard + account={currentAccount!} + onPressSwitchAccount={onPressSwitchAccount} + isSwitchingAccounts={isSwitchingAccounts} + /> )} {accounts .filter(a => a.did !== currentAccount?.did) .map(account => ( - <SettingsAccountCard key={account.did} account={account} /> + <SettingsAccountCard + key={account.did} + account={account} + onPressSwitchAccount={onPressSwitchAccount} + isSwitchingAccounts={isSwitchingAccounts} + /> ))} <TouchableOpacity |