Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[Session] Extract selectAccount out (#3812)

authored by

dan and committed by
GitHub
1a07e231 5ec945b7

+48 -42
+3 -1
src/components/AccountList.tsx
··· 16 16 onSelectAccount, 17 17 onSelectOther, 18 18 otherLabel, 19 + isSwitchingAccounts, 19 20 }: { 20 21 onSelectAccount: (account: SessionAccount) => void 21 22 onSelectOther: () => void 22 23 otherLabel?: string 24 + isSwitchingAccounts: boolean 23 25 }) { 24 - const {isSwitchingAccounts, currentAccount, accounts} = useSession() 26 + const {currentAccount, accounts} = useSession() 25 27 const t = useTheme() 26 28 const {_} = useLingui() 27 29
+2 -1
src/components/dialogs/SwitchAccount.tsx
··· 18 18 }) { 19 19 const {_} = useLingui() 20 20 const {currentAccount} = useSession() 21 - const {onPressSwitchAccount} = useAccountSwitcher() 21 + const {onPressSwitchAccount, isSwitchingAccounts} = useAccountSwitcher() 22 22 const {setShowLoggedOut} = useLoggedOutViewControls() 23 23 24 24 const onSelectAccount = useCallback( ··· 54 54 onSelectAccount={onSelectAccount} 55 55 onSelectOther={onPressAddAccount} 56 56 otherLabel={_(msg`Add account`)} 57 + isSwitchingAccounts={isSwitchingAccounts} 57 58 /> 58 59 </View> 59 60 </Dialog.ScrollableInner>
+11 -5
src/lib/hooks/useAccountSwitcher.ts
··· 1 - import {useCallback} from 'react' 1 + import {useCallback, useState} from 'react' 2 2 import {msg} from '@lingui/macro' 3 3 import {useLingui} from '@lingui/react' 4 4 ··· 8 8 import {SessionAccount, useSessionApi} from '#/state/session' 9 9 import {useLoggedOutViewControls} from '#/state/shell/logged-out' 10 10 import * as Toast from '#/view/com/util/Toast' 11 + import {logEvent} from '../statsig/statsig' 11 12 import {LogEvents} from '../statsig/statsig' 12 13 13 14 export function useAccountSwitcher() { 15 + const [isSwitchingAccounts, setIsSwitchingAccounts] = useState(false) 14 16 const {_} = useLingui() 15 17 const {track} = useAnalytics() 16 - const {selectAccount, clearCurrentAccount} = useSessionApi() 18 + const {initSession, clearCurrentAccount} = useSessionApi() 17 19 const {requestSwitchToAccount} = useLoggedOutViewControls() 18 20 19 21 const onPressSwitchAccount = useCallback( ··· 24 26 track('Settings:SwitchAccountButtonClicked') 25 27 26 28 try { 29 + setIsSwitchingAccounts(true) 27 30 if (account.accessJwt) { 28 31 if (isWeb) { 29 32 // We're switching accounts, which remounts the entire app. ··· 33 36 // So we change the URL ourselves. The navigator will pick it up on remount. 34 37 history.pushState(null, '', '/') 35 38 } 36 - await selectAccount(account, logContext) 39 + await initSession(account) 40 + logEvent('account:loggedIn', {logContext, withPassword: false}) 37 41 setTimeout(() => { 38 42 Toast.show(_(msg`Signed in as @${account.handle}`)) 39 43 }, 100) ··· 52 56 setTimeout(() => { 53 57 Toast.show(_(msg`Sorry! We need you to enter your password.`)) 54 58 }, 100) 59 + } finally { 60 + setIsSwitchingAccounts(false) 55 61 } 56 62 }, 57 - [_, track, clearCurrentAccount, selectAccount, requestSwitchToAccount], 63 + [_, track, clearCurrentAccount, initSession, requestSwitchToAccount], 58 64 ) 59 65 60 - return {onPressSwitchAccount} 66 + return {onPressSwitchAccount, isSwitchingAccounts} 61 67 }
+5
src/screens/Login/ChooseAccountForm.tsx
··· 22 22 onSelectAccount: (account?: SessionAccount) => void 23 23 onPressBack: () => void 24 24 }) => { 25 + const [isSwitchingAccounts, setIsSwitchingAccounts] = React.useState(false) 25 26 const {track, screen} = useAnalytics() 26 27 const {_} = useLingui() 27 28 const {currentAccount} = useSession() ··· 40 41 Toast.show(_(msg`Already signed in as @${account.handle}`)) 41 42 } else { 42 43 try { 44 + setIsSwitchingAccounts(true) 43 45 await initSession(account) 44 46 logEvent('account:loggedIn', { 45 47 logContext: 'ChooseAccountForm', ··· 54 56 message: e.message, 55 57 }) 56 58 onSelectAccount(account) 59 + } finally { 60 + setIsSwitchingAccounts(false) 57 61 } 58 62 } 59 63 } else { ··· 74 78 <AccountList 75 79 onSelectAccount={onSelect} 76 80 onSelectOther={() => onSelectAccount()} 81 + isSwitchingAccounts={isSwitchingAccounts} 77 82 /> 78 83 </View> 79 84 <View style={[a.flex_row]}>
+1 -24
src/state/session/index.tsx
··· 35 35 configureModerationForGuest() 36 36 37 37 const StateContext = React.createContext<SessionStateContext>({ 38 - isSwitchingAccounts: false, 39 38 accounts: [], 40 39 currentAccount: undefined, 41 40 hasSession: false, ··· 47 46 logout: async () => {}, 48 47 initSession: async () => {}, 49 48 removeAccount: () => {}, 50 - selectAccount: async () => {}, 51 49 updateCurrentAccount: () => {}, 52 50 clearCurrentAccount: () => {}, 53 51 }) ··· 65 63 } 66 64 67 65 export function Provider({children}: React.PropsWithChildren<{}>) { 68 - const [isSwitchingAccounts, setIsSwitchingAccounts] = React.useState(false) 69 66 const [state, setState] = React.useState<State>({ 70 67 accounts: persisted.get('session').accounts, 71 68 currentAccountDid: undefined, // assume logged out to start ··· 437 434 [setState], 438 435 ) 439 436 440 - const selectAccount = React.useCallback<SessionApiContext['selectAccount']>( 441 - async (account, logContext) => { 442 - setIsSwitchingAccounts(true) 443 - try { 444 - await initSession(account) 445 - setIsSwitchingAccounts(false) 446 - logEvent('account:loggedIn', {logContext, withPassword: false}) 447 - } catch (e) { 448 - // reset this in case of error 449 - setIsSwitchingAccounts(false) 450 - // but other listeners need a throw 451 - throw e 452 - } 453 - }, 454 - [initSession], 455 - ) 456 - 457 437 React.useEffect(() => { 458 438 if (state.needsPersist) { 459 439 state.needsPersist = false ··· 529 509 currentAccount: state.accounts.find( 530 510 a => a.did === state.currentAccountDid, 531 511 ), 532 - isSwitchingAccounts, 533 512 hasSession: !!state.currentAccountDid, 534 513 }), 535 - [state, isSwitchingAccounts], 514 + [state], 536 515 ) 537 516 538 517 const api = React.useMemo( ··· 542 521 logout, 543 522 initSession, 544 523 removeAccount, 545 - selectAccount, 546 524 updateCurrentAccount, 547 525 clearCurrentAccount, 548 526 }), ··· 552 530 logout, 553 531 initSession, 554 532 removeAccount, 555 - selectAccount, 556 533 updateCurrentAccount, 557 534 clearCurrentAccount, 558 535 ],
-5
src/state/session/types.ts
··· 6 6 export type SessionStateContext = { 7 7 accounts: SessionAccount[] 8 8 currentAccount: SessionAccount | undefined 9 - isSwitchingAccounts: boolean 10 9 hasSession: boolean 11 10 } 12 11 export type SessionApiContext = { ··· 46 45 clearCurrentAccount: () => void 47 46 initSession: (account: SessionAccount) => Promise<void> 48 47 removeAccount: (account: SessionAccount) => void 49 - selectAccount: ( 50 - account: SessionAccount, 51 - logContext: LogEvents['account:loggedIn']['logContext'], 52 - ) => Promise<void> 53 48 updateCurrentAccount: ( 54 49 account: Partial< 55 50 Pick<
+26 -6
src/view/screens/Settings/index.tsx
··· 70 70 import {Email2FAToggle} from './Email2FAToggle' 71 71 import {ExportCarDialog} from './ExportCarDialog' 72 72 73 - function SettingsAccountCard({account}: {account: SessionAccount}) { 73 + function SettingsAccountCard({ 74 + account, 75 + isSwitchingAccounts, 76 + onPressSwitchAccount, 77 + }: { 78 + account: SessionAccount 79 + isSwitchingAccounts: boolean 80 + onPressSwitchAccount: ( 81 + account: SessionAccount, 82 + logContext: 'Settings', 83 + ) => void 84 + }) { 74 85 const pal = usePalette('default') 75 86 const {_} = useLingui() 76 - const {isSwitchingAccounts, currentAccount} = useSession() 87 + const {currentAccount} = useSession() 77 88 const {logout} = useSessionApi() 78 89 const {data: profile} = useProfileQuery({did: account.did}) 79 90 const isCurrentAccount = account.did === currentAccount?.did 80 - const {onPressSwitchAccount} = useAccountSwitcher() 81 91 82 92 const contents = ( 83 93 <View style={[pal.view, styles.linkCard]}> ··· 165 175 const {isMobile} = useWebMediaQueries() 166 176 const {screen, track} = useAnalytics() 167 177 const {openModal} = useModalControls() 168 - const {isSwitchingAccounts, accounts, currentAccount} = useSession() 178 + const {accounts, currentAccount} = useSession() 169 179 const {mutate: clearPreferences} = useClearPreferencesMutation() 170 180 const {setShowLoggedOut} = useLoggedOutViewControls() 171 181 const closeAllActiveElements = useCloseAllActiveElements() 172 182 const exportCarControl = useDialogControl() 173 183 const birthdayControl = useDialogControl() 184 + const {isSwitchingAccounts, onPressSwitchAccount} = useAccountSwitcher() 174 185 175 186 // TODO: TEMP REMOVE WHEN CLOPS ARE RELEASED 176 187 const gate = useGate() ··· 385 396 <ActivityIndicator /> 386 397 </View> 387 398 ) : ( 388 - <SettingsAccountCard account={currentAccount!} /> 399 + <SettingsAccountCard 400 + account={currentAccount!} 401 + onPressSwitchAccount={onPressSwitchAccount} 402 + isSwitchingAccounts={isSwitchingAccounts} 403 + /> 389 404 )} 390 405 391 406 {accounts 392 407 .filter(a => a.did !== currentAccount?.did) 393 408 .map(account => ( 394 - <SettingsAccountCard key={account.did} account={account} /> 409 + <SettingsAccountCard 410 + key={account.did} 411 + account={account} 412 + onPressSwitchAccount={onPressSwitchAccount} 413 + isSwitchingAccounts={isSwitchingAccounts} 414 + /> 395 415 ))} 396 416 397 417 <TouchableOpacity