From 13daf12c0cb870c9a284f95aefd0433316976cab Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Thu, 26 Jun 2025 18:24:32 -0500 Subject: [PATCH] Move provider inside query provider --- src/App.native.tsx | 143 +++++++++--------- src/App.web.tsx | 121 ++++++++------- .../ageAssurance/IsAgeRestricted.tsx | 8 +- src/state/ageAssurance.tsx | 80 ++++++---- 4 files changed, 181 insertions(+), 171 deletions(-) diff --git a/src/App.native.tsx b/src/App.native.tsx index 49fd13529e..29e359c48c 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -26,10 +26,7 @@ import I18nProvider from '#/locale/i18nProvider' import {logger} from '#/logger' import {isAndroid, isIOS} from '#/platform/detection' import {Provider as A11yProvider} from '#/state/a11y' -import { - Provider as AgeAssuranceProvider, - useAgeAssuranceAPIContext, -} from '#/state/ageAssurance' +import {Provider as AgeAssuranceProvider} from '#/state/ageAssurance' import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes' import {Provider as DialogStateProvider} from '#/state/dialogs' import {listenSessionDropped} from '#/state/events' @@ -100,7 +97,6 @@ function InnerApp() { const theme = useColorModeTheme() const {_} = useLingui() const hasCheckedReferrer = useStarterPackEntry() - const {refresh: refreshAgeAssurance} = useAgeAssuranceAPIContext() // init useEffect(() => { @@ -108,7 +104,6 @@ function InnerApp() { try { if (account) { await resumeSession(account) - await refreshAgeAssurance() } else { await tryFetchGates(undefined, 'prefer-fresh-gates') } @@ -120,7 +115,7 @@ function InnerApp() { } const account = readLastActiveAccount() onLaunch(account) - }, [resumeSession, refreshAgeAssurance]) + }, [resumeSession]) useEffect(() => { return listenSessionDropped(() => { @@ -142,47 +137,49 @@ function InnerApp() { // Resets the entire tree below when it changes: key={currentAccount?.did}> - - - - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -216,32 +213,30 @@ function App() { - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/App.web.tsx b/src/App.web.tsx index 487721dd40..ef60cb8a08 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -17,7 +17,6 @@ import {logger} from '#/logger' import {Provider as A11yProvider} from '#/state/a11y' import { Provider as AgeAssuranceProvider, - useAgeAssuranceAPIContext, } from '#/state/ageAssurance' import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes' import {Provider as DialogStateProvider} from '#/state/dialogs' @@ -79,7 +78,6 @@ function InnerApp() { const theme = useColorModeTheme() const {_} = useLingui() const hasCheckedReferrer = useStarterPackEntry() - const {refresh: refreshAgeAssurance} = useAgeAssuranceAPIContext() // init useEffect(() => { @@ -87,7 +85,6 @@ function InnerApp() { try { if (account) { await resumeSession(account) - await refreshAgeAssurance() } } catch (e) { logger.error(`session: resumeSession failed`, {message: e}) @@ -97,7 +94,7 @@ function InnerApp() { } const account = readLastActiveAccount() onLaunch(account) - }, [resumeSession, refreshAgeAssurance]) + }, [resumeSession]) useEffect(() => { return listenSessionDropped(() => { @@ -122,43 +119,45 @@ function InnerApp() { // Resets the entire tree below when it changes: key={currentAccount?.did}> - - - - {/* LabelDefsProvider MUST come before ModerationOptsProvider */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + {/* LabelDefsProvider MUST come before ModerationOptsProvider */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -192,27 +191,25 @@ function App() { - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/components/ageAssurance/IsAgeRestricted.tsx b/src/components/ageAssurance/IsAgeRestricted.tsx index 90e0340127..4d0638df86 100644 --- a/src/components/ageAssurance/IsAgeRestricted.tsx +++ b/src/components/ageAssurance/IsAgeRestricted.tsx @@ -1,13 +1,13 @@ import {useAgeAssuranceContext} from '#/state/ageAssurance' export function True({children}: {children: React.ReactNode}) { - const {isAgeRestricted} = useAgeAssuranceContext() - return isAgeRestricted ? children : null + const {isLoaded, isAgeRestricted} = useAgeAssuranceContext() + return isLoaded && isAgeRestricted ? children : null } export function False({children}: {children: React.ReactNode}) { - const {isAgeRestricted} = useAgeAssuranceContext() - return !isAgeRestricted ? children : null + const {isLoaded, isAgeRestricted} = useAgeAssuranceContext() + return isLoaded && !isAgeRestricted ? children : null } export const IsAgeRestricted = { diff --git a/src/state/ageAssurance.tsx b/src/state/ageAssurance.tsx index 7724438b57..e9fadb0e2d 100644 --- a/src/state/ageAssurance.tsx +++ b/src/state/ageAssurance.tsx @@ -1,12 +1,21 @@ -import {createContext, useCallback, useContext, useMemo, useState} from 'react' +import {createContext, useContext, useMemo} from 'react' +import { + // useQueryClient, + type QueryObserverBaseResult, + useQuery, +} from '@tanstack/react-query' import {wait} from '#/lib/async/wait' import {isNetworkError} from '#/lib/strings/errors' import {Logger} from '#/logger' -// import {useAgent} from '#/state/session' import {useGeolocation} from '#/state/geolocation' +import {useAgent} from '#/state/session' const logger = Logger.create(Logger.Context.AgeAssurance) +const ageAssuranceQueryKey = ['ageAssurance'] as const +const DEFAULT_AGE_ASSURANCE_STATE: TempAgeAssuranceState = { + status: 'unknown', +} type TempAgeAssuranceState = { lastInitiatedAt?: string @@ -14,6 +23,7 @@ type TempAgeAssuranceState = { } export type AgeAssuranceContextType = { + isLoaded: boolean /** * Whether the current user is age-restricted based on their geolocation and * age assurance state retrieved from the server. @@ -37,10 +47,11 @@ export type AgeAssuranceAPIContextType = { /** * Refreshes the age assurance state by fetching it from the server. */ - refresh: () => Promise + refetch: QueryObserverBaseResult['refetch'] } const AgeAssuranceContext = createContext({ + isLoaded: false, isAgeRestricted: false, status: 'unknown', lastInitiatedAt: undefined, @@ -48,42 +59,49 @@ const AgeAssuranceContext = createContext({ }) const AgeAssuranceAPIContext = createContext({ - refresh: () => Promise.resolve(), + // @ts-ignore + refetch: () => Promise.resolve(), }) export function Provider({children}: {children: React.ReactNode}) { - // const agent = useAgent() + // const qc = useQueryClient() + const agent = useAgent() const {geolocation} = useGeolocation() - const [ageAssuranceState, setAgeAssuranceState] = - useState({ - status: 'unknown', - }) - const refresh = useCallback(async () => { - try { - const {data} = await wait( - 200, - (() => ({ - data: { - lastInitiatedAt: undefined, - status: 'unknown', - } as TempAgeAssuranceState, - }))(), - ) + const {data, refetch} = useQuery({ + queryKey: ageAssuranceQueryKey, + async queryFn() { + try { + const {data} = await wait( + 1e3, + (() => ({ + data: { + lastInitiatedAt: new Date().toISOString(), + status: 'assured', + } as TempAgeAssuranceState, + }))(), + ) - logger.debug(`refresh`, {data}) + logger.debug(`fetch`, { + data, + account: agent.session?.did, + }) - setAgeAssuranceState(data) - } catch (e) { - if (!isNetworkError(e)) { - logger.error(`ageAssurance: failed to refresh`, {safeMessage: e}) + return data + } catch (e) { + if (!isNetworkError(e)) { + logger.error(`ageAssurance: failed to fetch`, {safeMessage: e}) + } + + return DEFAULT_AGE_ASSURANCE_STATE } - } - }, [setAgeAssuranceState]) + }, + }) const ageAssuranceContext = useMemo(() => { - const {status, lastInitiatedAt} = ageAssuranceState + const {status, lastInitiatedAt} = data || DEFAULT_AGE_ASSURANCE_STATE const ctx: AgeAssuranceContextType = { + isLoaded: !!data, status, lastInitiatedAt, hasInitiated: !!lastInitiatedAt, @@ -95,13 +113,13 @@ export function Provider({children}: {children: React.ReactNode}) { logger.debug(`context`, ctx) return ctx - }, [geolocation, ageAssuranceState]) + }, [geolocation, data]) const ageAssuranceAPIContext = useMemo( () => ({ - refresh, + refetch, }), - [refresh], + [refetch], ) return (