add refreshSession to the session api and migrate its callers

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-08-04 00:55:02 +03:00
parent 7d8391aeb2
commit 483e79497b
10 changed files with 343 additions and 48 deletions
+22 -17
View File
@@ -7,10 +7,11 @@ import {Trans} from '@lingui/react/macro'
import {useQueryClient} from '@tanstack/react-query'
import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
import {isErrorMaybeAppPasswordPermissions} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {
type SessionAccount,
useAgent,
usePdsClient,
useSession,
useSessionApi,
} from '#/state/session'
@@ -25,6 +26,7 @@ import * as Layout from '#/components/Layout'
import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography'
import {IS_WEB} from '#/env'
import {com} from '#/lexicons'
const COL_WIDTH = 400
@@ -36,8 +38,8 @@ export function Deactivated() {
const {onPressSwitchAccount, pendingDid} = useAccountSwitcher()
const {setShowLoggedOut} = useLoggedOutViewControls()
const hasOtherAccounts = accounts.length > 1
const {logoutCurrentAccount} = useSessionApi()
const agent = useAgent()
const {logoutCurrentAccount, refreshSession} = useSessionApi()
const pdsClient = usePdsClient()
const [pending, setPending] = useState(false)
const [error, setError] = useState<string | undefined>()
const queryClient = useQueryClient()
@@ -70,21 +72,24 @@ export function Deactivated() {
const handleActivate = useCallback(async () => {
try {
setPending(true)
await agent.com.atproto.server.activateAccount()
await pdsClient.call(com.atproto.server.activateAccount)
await queryClient.resetQueries()
await agent.resumeSession(agent.session!)
await refreshSession()
} catch (e: any) {
switch (e.message) {
case 'Bad token scope':
setError(
_(
msg`You're signed in with an App Password. Please sign in with your main password to continue deactivating your account.`,
),
)
break
default:
setError(_(msg`Something went wrong, please try again`))
break
/*
* `activateAccount` declares no lexicon errors, so the app-password case
* arrives as an undeclared code plus a message. The shared helper matches
* both that and the plain-string form the old exact `e.message` switch
* relied on.
*/
if (isErrorMaybeAppPasswordPermissions(e)) {
setError(
_(
msg`You're signed in with an App Password. Please sign in with your main password to continue deactivating your account.`,
),
)
} else {
setError(_(msg`Something went wrong, please try again`))
}
logger.error(e, {
@@ -93,7 +98,7 @@ export function Deactivated() {
} finally {
setPending(false)
}
}, [_, agent, setPending, setError, queryClient])
}, [_, pdsClient, refreshSession, setPending, setError, queryClient])
return (
<View style={[a.util_screen_outer, a.flex_1]}>
@@ -27,7 +27,7 @@ import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle'
import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile'
import {useServiceQuery} from '#/state/queries/service'
import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile'
import {useAgent, useSession} from '#/state/session'
import {useAgent, useSession, useSessionApi} from '#/state/session'
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
import {atoms as a, native, useBreakpoints, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition'
@@ -152,7 +152,7 @@ function ProvidedHandlePage({
}) {
const {_} = useLingui()
const [subdomain, setSubdomain] = useState('')
const agent = useAgent()
const {refreshSession} = useSessionApi()
const control = Dialog.useDialogContext()
const {currentAccount} = useSession()
const queryClient = useQueryClient()
@@ -173,7 +173,7 @@ function ProvidedHandlePage({
queryKey: RQKEY_PROFILE(currentAccount.did),
})
}
agent.resumeSession(agent.session!).then(() => control.close())
refreshSession().then(() => control.close())
},
})
@@ -311,7 +311,7 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
const {currentAccount} = useSession()
const [dnsPanel, setDNSPanel] = useState(true)
const [domain, setDomain] = useState('')
const agent = useAgent()
const {refreshSession} = useSessionApi()
const control = Dialog.useDialogContext()
const fetchDid = useFetchDid()
const queryClient = useQueryClient()
@@ -328,7 +328,7 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
queryKey: RQKEY_PROFILE(currentAccount.did),
})
}
agent.resumeSession(agent.session!).then(() => control.close())
refreshSession().then(() => control.close())
},
})
@@ -5,7 +5,8 @@ import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {cleanError} from '#/lib/strings/errors'
import {useAgent, useSession} from '#/state/session'
import {matchXrpcError} from '#/lib/xrpc-error'
import {usePdsClient, useSession, useSessionApi} from '#/state/session'
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
@@ -16,6 +17,7 @@ import {Loader} from '#/components/Loader'
import * as Toast from '#/components/Toast'
import {P, Text} from '#/components/Typography'
import {IS_NATIVE} from '#/env'
import {com} from '#/lexicons'
enum Stages {
Email,
@@ -31,7 +33,8 @@ export function DisableEmail2FADialog({
const t = useTheme()
const {gtMobile} = useBreakpoints()
const {currentAccount} = useSession()
const agent = useAgent()
const pdsClient = usePdsClient()
const {refreshSession} = useSessionApi()
const [stage, setStage] = useState<Stages>(Stages.Email)
const [confirmationCode, setConfirmationCode] = useState<string>('')
@@ -42,7 +45,7 @@ export function DisableEmail2FADialog({
setError('')
setIsProcessing(true)
try {
await agent.com.atproto.server.requestEmailUpdate()
await pdsClient.call(com.atproto.server.requestEmailUpdate)
setStage(Stages.ConfirmCode)
} catch (e) {
setError(cleanError(String(e)))
@@ -56,21 +59,26 @@ export function DisableEmail2FADialog({
setIsProcessing(true)
try {
if (currentAccount?.email) {
await agent.com.atproto.server.updateEmail({
await pdsClient.call(com.atproto.server.updateEmail, {
email: currentAccount.email,
token: confirmationCode.trim(),
emailAuthFactor: false,
})
await agent.resumeSession(agent.session!)
await refreshSession()
Toast.show(_(msg({message: 'Email 2FA disabled', context: 'toast'})))
}
control.close()
} catch (e) {
const errMsg = String(e)
if (errMsg.includes('Token is invalid')) {
/*
* The old check matched the PDS message "Token is invalid"; the lexicon
* declares that case as `InvalidToken`, so match the code instead.
*/
if (
matchXrpcError(e, com.atproto.server.updateEmail) === 'InvalidToken'
) {
setError(_(msg`Invalid 2FA confirmation code.`))
} else {
setError(cleanError(errMsg))
setError(cleanError(e))
}
} finally {
setIsProcessing(false)