Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Session fixes, pt. 1 (#3762)

* Update persisted schema for new source of truth, implement in existing session

(cherry picked from commit b1e5f12baee932721d66c60dd51c981b46b0c274)

* Improve toasts, log caught error, during switch account

(cherry picked from commit fe0d1507063d2e532b7b1a447670b689292d1dc3)

* Handle thrown errors from initSession during login

(cherry picked from commit 2c85c045917e923901284b9ba310a82e28f37b5c)

---------

Co-authored-by: Eric Bailey <git@esb.lol>

authored by

dan
Eric Bailey
and committed by
GitHub
2b7d796c 4de78fb6

+62 -24
+14 -5
src/lib/hooks/useAccountSwitcher.ts
··· 1 1 import {useCallback} from 'react' 2 + import {msg} from '@lingui/macro' 3 + import {useLingui} from '@lingui/react' 2 4 3 5 import {useAnalytics} from '#/lib/analytics/analytics' 6 + import {logger} from '#/logger' 4 7 import {isWeb} from '#/platform/detection' 5 8 import {SessionAccount, useSessionApi} from '#/state/session' 6 9 import {useLoggedOutViewControls} from '#/state/shell/logged-out' ··· 8 11 import {LogEvents} from '../statsig/statsig' 9 12 10 13 export function useAccountSwitcher() { 14 + const {_} = useLingui() 11 15 const {track} = useAnalytics() 12 16 const {selectAccount, clearCurrentAccount} = useSessionApi() 13 17 const {requestSwitchToAccount} = useLoggedOutViewControls() ··· 31 35 } 32 36 await selectAccount(account, logContext) 33 37 setTimeout(() => { 34 - Toast.show(`Signed in as @${account.handle}`) 38 + Toast.show(_(msg`Signed in as @${account.handle}`)) 35 39 }, 100) 36 40 } else { 37 41 requestSwitchToAccount({requestedAccount: account.did}) 38 42 Toast.show( 39 - `Please sign in as @${account.handle}`, 43 + _(msg`Please sign in as @${account.handle}`), 40 44 'circle-exclamation', 41 45 ) 42 46 } 43 - } catch (e) { 44 - Toast.show('Sorry! We need you to enter your password.') 47 + } catch (e: any) { 48 + logger.error(`switch account: selectAccount failed`, { 49 + message: e.message, 50 + }) 45 51 clearCurrentAccount() // back user out to login 52 + setTimeout(() => { 53 + Toast.show(_(msg`Sorry! We need you to enter your password.`)) 54 + }, 100) 46 55 } 47 56 }, 48 - [track, clearCurrentAccount, selectAccount, requestSwitchToAccount], 57 + [_, track, clearCurrentAccount, selectAccount, requestSwitchToAccount], 49 58 ) 50 59 51 60 return {onPressSwitchAccount}
+17 -9
src/screens/Login/ChooseAccountForm.tsx
··· 5 5 6 6 import {useAnalytics} from '#/lib/analytics/analytics' 7 7 import {logEvent} from '#/lib/statsig/statsig' 8 + import {logger} from '#/logger' 8 9 import {SessionAccount, useSession, useSessionApi} from '#/state/session' 9 10 import {useLoggedOutViewControls} from '#/state/shell/logged-out' 10 11 import * as Toast from '#/view/com/util/Toast' ··· 38 39 setShowLoggedOut(false) 39 40 Toast.show(_(msg`Already signed in as @${account.handle}`)) 40 41 } else { 41 - await initSession(account) 42 - logEvent('account:loggedIn', { 43 - logContext: 'ChooseAccountForm', 44 - withPassword: false, 45 - }) 46 - track('Sign In', {resumedSession: true}) 47 - setTimeout(() => { 48 - Toast.show(_(msg`Signed in as @${account.handle}`)) 49 - }, 100) 42 + try { 43 + await initSession(account) 44 + logEvent('account:loggedIn', { 45 + logContext: 'ChooseAccountForm', 46 + withPassword: false, 47 + }) 48 + track('Sign In', {resumedSession: true}) 49 + setTimeout(() => { 50 + Toast.show(_(msg`Signed in as @${account.handle}`)) 51 + }, 100) 52 + } catch (e: any) { 53 + logger.error('choose account: initSession failed', { 54 + message: e.message, 55 + }) 56 + onSelectAccount(account) 57 + } 50 58 } 51 59 } else { 52 60 onSelectAccount(account)
+19 -2
src/state/persisted/schema.ts
··· 4 4 5 5 const externalEmbedOptions = ['show', 'hide'] as const 6 6 7 - // only data needed for rendering account page 7 + /** 8 + * A account persisted to storage. Stored in the `accounts[]` array. Contains 9 + * base account info and access tokens. 10 + */ 8 11 const accountSchema = z.object({ 9 12 service: z.string(), 10 13 did: z.string(), ··· 19 22 }) 20 23 export type PersistedAccount = z.infer<typeof accountSchema> 21 24 25 + /** 26 + * The current account. Stored in the `currentAccount` field. 27 + * 28 + * In previous versions, this included tokens and other info. Now, it's used 29 + * only to reference the `did` field, and all other fields are marked as 30 + * optional. They should be considered deprecated and not used, but are kept 31 + * here for backwards compat. 32 + */ 33 + const currentAccountSchema = accountSchema.extend({ 34 + service: z.string().optional(), 35 + handle: z.string().optional(), 36 + }) 37 + export type PersistedCurrentAccount = z.infer<typeof currentAccountSchema> 38 + 22 39 export const schema = z.object({ 23 40 colorMode: z.enum(['system', 'light', 'dark']), 24 41 darkTheme: z.enum(['dim', 'dark']).optional(), 25 42 session: z.object({ 26 43 accounts: z.array(accountSchema), 27 - currentAccount: accountSchema.optional(), 44 + currentAccount: currentAccountSchema.optional(), 28 45 }), 29 46 reminders: z.object({ 30 47 lastEmailConfirm: z.string().optional(),
+12 -8
src/state/session/index.tsx
··· 618 618 619 619 logger.debug(`session: persisted onUpdate`, {}) 620 620 621 - if (session.currentAccount && session.currentAccount.refreshJwt) { 622 - if (session.currentAccount?.did !== state.currentAccount?.did) { 621 + const selectedAccount = session.accounts.find( 622 + a => a.did === session.currentAccount?.did, 623 + ) 624 + 625 + if (selectedAccount && selectedAccount.refreshJwt) { 626 + if (selectedAccount.did !== state.currentAccount?.did) { 623 627 logger.debug(`session: persisted onUpdate, switching accounts`, { 624 628 from: { 625 629 did: state.currentAccount?.did, 626 630 handle: state.currentAccount?.handle, 627 631 }, 628 632 to: { 629 - did: session.currentAccount.did, 630 - handle: session.currentAccount.handle, 633 + did: selectedAccount.did, 634 + handle: selectedAccount.handle, 631 635 }, 632 636 }) 633 637 634 - initSession(session.currentAccount) 638 + initSession(selectedAccount) 635 639 } else { 636 640 logger.debug(`session: persisted onUpdate, updating session`, {}) 637 641 ··· 641 645 * already persisted, and we'll get a loop between tabs. 642 646 */ 643 647 // @ts-ignore we checked for `refreshJwt` above 644 - __globalAgent.session = session.currentAccount 648 + __globalAgent.session = selectedAccount 645 649 } 646 - } else if (!session.currentAccount && state.currentAccount) { 650 + } else if (!selectedAccount && state.currentAccount) { 647 651 logger.debug( 648 652 `session: persisted onUpdate, logging out`, 649 653 {}, ··· 662 666 setState(s => ({ 663 667 ...s, 664 668 accounts: session.accounts, 665 - currentAccount: session.currentAccount, 669 + currentAccount: selectedAccount, 666 670 })) 667 671 }) 668 672 }, [state, setState, clearCurrentAccount, initSession])