Replace resumeSession with getSession in the email check (#8670)
* replace resumeSession with getSession * copy lil type tweak from the other PR * Add partialRefreshSession to session API context, use session state to infer state further down tree * Review --------- Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
@@ -40,6 +40,7 @@ const ApiContext = React.createContext<SessionApiContext>({
|
||||
logoutEveryAccount: async () => {},
|
||||
resumeSession: async () => {},
|
||||
removeAccount: () => {},
|
||||
partialRefreshSession: async () => {},
|
||||
})
|
||||
|
||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
@@ -119,7 +120,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
)
|
||||
|
||||
const logoutCurrentAccount = React.useCallback<
|
||||
SessionApiContext['logoutEveryAccount']
|
||||
SessionApiContext['logoutCurrentAccount']
|
||||
>(
|
||||
logContext => {
|
||||
addSessionDebugLog({type: 'method:start', method: 'logout'})
|
||||
@@ -182,6 +183,23 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
[onAgentSessionChange, cancelPendingTask],
|
||||
)
|
||||
|
||||
const partialRefreshSession = React.useCallback<
|
||||
SessionApiContext['partialRefreshSession']
|
||||
>(async () => {
|
||||
const agent = state.currentAgentState.agent as BskyAppAgent
|
||||
const signal = cancelPendingTask()
|
||||
const {data} = await agent.com.atproto.server.getSession()
|
||||
if (signal.aborted) return
|
||||
dispatch({
|
||||
type: 'partial-refresh-session',
|
||||
accountDid: agent.session!.did,
|
||||
patch: {
|
||||
emailConfirmed: data.emailConfirmed,
|
||||
emailAuthFactor: data.emailAuthFactor,
|
||||
},
|
||||
})
|
||||
}, [state, cancelPendingTask])
|
||||
|
||||
const removeAccount = React.useCallback<SessionApiContext['removeAccount']>(
|
||||
account => {
|
||||
addSessionDebugLog({
|
||||
@@ -262,6 +280,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
logoutEveryAccount,
|
||||
resumeSession,
|
||||
removeAccount,
|
||||
partialRefreshSession,
|
||||
}),
|
||||
[
|
||||
createAccount,
|
||||
@@ -270,6 +289,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
logoutEveryAccount,
|
||||
resumeSession,
|
||||
removeAccount,
|
||||
partialRefreshSession,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {AtpSessionEvent} from '@atproto/api'
|
||||
import {type AtpSessionEvent, type BskyAgent} from '@atproto/api'
|
||||
|
||||
import {createPublicAgent} from './agent'
|
||||
import {wrapSessionReducerForLogging} from './logging'
|
||||
import {SessionAccount} from './types'
|
||||
import {type SessionAccount} from './types'
|
||||
|
||||
// A hack so that the reducer can't read anything from the agent.
|
||||
// From the reducer's point of view, it should be a completely opaque object.
|
||||
@@ -52,6 +52,11 @@ export type Action =
|
||||
syncedAccounts: SessionAccount[]
|
||||
syncedCurrentDid: string | undefined
|
||||
}
|
||||
| {
|
||||
type: 'partial-refresh-session'
|
||||
accountDid: string
|
||||
patch: Pick<SessionAccount, 'emailConfirmed' | 'emailAuthFactor'>
|
||||
}
|
||||
|
||||
function createPublicAgentState(): AgentState {
|
||||
return {
|
||||
@@ -180,6 +185,39 @@ let reducer = (state: State, action: Action): State => {
|
||||
needsPersist: false, // Synced from another tab. Don't persist to avoid cycles.
|
||||
}
|
||||
}
|
||||
case 'partial-refresh-session': {
|
||||
const {accountDid, patch} = action
|
||||
const agent = state.currentAgentState.agent as BskyAgent
|
||||
|
||||
/*
|
||||
* Only mutating values that are safe. Be very careful with this.
|
||||
*/
|
||||
if (agent.session) {
|
||||
agent.session.emailConfirmed =
|
||||
patch.emailConfirmed ?? agent.session.emailConfirmed
|
||||
agent.session.emailAuthFactor =
|
||||
patch.emailAuthFactor ?? agent.session.emailAuthFactor
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
currentAgentState: {
|
||||
...state.currentAgentState,
|
||||
agent,
|
||||
},
|
||||
accounts: state.accounts.map(a => {
|
||||
if (a.did === accountDid) {
|
||||
return {
|
||||
...a,
|
||||
emailConfirmed: patch.emailConfirmed ?? a.emailConfirmed,
|
||||
emailAuthFactor: patch.emailAuthFactor ?? a.emailAuthFactor,
|
||||
}
|
||||
}
|
||||
return a
|
||||
}),
|
||||
needsPersist: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reducer = wrapSessionReducerForLogging(reducer)
|
||||
|
||||
@@ -40,4 +40,12 @@ export type SessionApiContext = {
|
||||
) => void
|
||||
resumeSession: (account: SessionAccount) => Promise<void>
|
||||
removeAccount: (account: SessionAccount) => void
|
||||
/**
|
||||
* Calls `getSession` and updates select fields on the current account and
|
||||
* `BskyAgent`. This is an alternative to `resumeSession`, which updates
|
||||
* current account/agent using the `persistSessionHandler`, but is more load
|
||||
* bearing. This patches in updates without causing any side effects via
|
||||
* `persistSessionHandler`.
|
||||
*/
|
||||
partialRefreshSession: () => Promise<void>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user