···136136 }
137137 })
138138}
139139+export async function refetchConfig() {
140140+ logger.debug(`refetchConfig: fetching...`)
141141+ const res = await getConfig()
142142+ qc.setQueryData<AppBskyAgeassuranceGetConfig.OutputSchema>(
143143+ configQueryKey,
144144+ res,
145145+ )
146146+ return res
147147+}
139148export function useConfigQuery() {
140149 return useQuery(
141150 {
···146155 * @see https://tanstack.com/query/latest/docs/framework/react/guides/initial-query-data#initial-data-from-the-cache-with-initialdataupdatedat
147156 */
148157 staleTime: IS_DEV ? 5e3 : 1000 * 60 * 60,
158158+ /**
159159+ * N.B. if prefetch failed above, we'll have no `initialData`, and this
160160+ * query will run on startup.
161161+ */
149162 initialData: getConfigFromCache(),
150163 initialDataUpdatedAt: () =>
151164 qc.getQueryState(configQueryKey)?.dataUpdatedAt,
+9-2
src/ageAssurance/state.ts
···3030 access: AgeAssuranceAccess.Safe,
3131 }
32323333- // should never happen, but need to guard
3333+ /**
3434+ * This can happen if the prefetch fails (such as due to network issues).
3535+ * The query handler will try it again, but if it continues to fail, of
3636+ * course we won't have config.
3737+ *
3838+ * In this case, fail open to avoid blocking users.
3939+ */
3440 if (!config) {
3541 logger.warn('useAgeAssuranceState: missing config')
3642 return {
3743 status: AgeAssuranceStatus.Unknown,
3838- access: AgeAssuranceAccess.Unknown,
4444+ access: AgeAssuranceAccess.Safe,
4545+ error: 'config',
3946 }
4047 }
4148
+1
src/ageAssurance/types.ts
···1818 lastInitiatedAt?: string
1919 status: AgeAssuranceStatus
2020 access: AgeAssuranceAccess
2121+ error?: 'config' // maybe other specific cases in the future
2122}
22232324export function parseStatusFromString(raw: string) {
···33import {useLingui} from '@lingui/react'
4455import {atoms as a, select, useTheme, type ViewStyleProp} from '#/alf'
66+import {AgeAssuranceConfigUnavailableError} from '#/components/ageAssurance/AgeAssuranceErrors'
67import {useDialogControl} from '#/components/ageAssurance/AgeAssuranceInitDialog'
78import type * as Dialog from '#/components/Dialog'
89import {ShieldCheck_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
···1920 const aa = useAgeAssurance()
20212122 if (aa.state.access === aa.Access.Full) return null
2323+ if (aa.state.error === 'config') {
2424+ return <AgeAssuranceConfigUnavailableError style={style} />
2525+ }
22262327 return (
2428 <Inner style={style} control={control}>