Add prelim fetch

This commit is contained in:
Eric Bailey
2025-06-25 17:25:24 -05:00
parent 43d0c73d32
commit 5ef52f708f
4 changed files with 162 additions and 46 deletions
+9 -2
View File
@@ -26,6 +26,10 @@ import I18nProvider from '#/locale/i18nProvider'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isAndroid, isIOS} from '#/platform/detection' import {isAndroid, isIOS} from '#/platform/detection'
import {Provider as A11yProvider} from '#/state/a11y' 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 MutedThreadsProvider} from '#/state/cache/thread-mutes'
import {Provider as DialogStateProvider} from '#/state/dialogs' import {Provider as DialogStateProvider} from '#/state/dialogs'
import {listenSessionDropped} from '#/state/events' import {listenSessionDropped} from '#/state/events'
@@ -95,8 +99,8 @@ function InnerApp() {
const {resumeSession} = useSessionApi() const {resumeSession} = useSessionApi()
const theme = useColorModeTheme() const theme = useColorModeTheme()
const {_} = useLingui() const {_} = useLingui()
const hasCheckedReferrer = useStarterPackEntry() const hasCheckedReferrer = useStarterPackEntry()
const {refresh: refreshAgeAssurance} = useAgeAssuranceAPIContext()
// init // init
useEffect(() => { useEffect(() => {
@@ -104,6 +108,7 @@ function InnerApp() {
try { try {
if (account) { if (account) {
await resumeSession(account) await resumeSession(account)
await refreshAgeAssurance()
} else { } else {
await tryFetchGates(undefined, 'prefer-fresh-gates') await tryFetchGates(undefined, 'prefer-fresh-gates')
} }
@@ -115,7 +120,7 @@ function InnerApp() {
} }
const account = readLastActiveAccount() const account = readLastActiveAccount()
onLaunch(account) onLaunch(account)
}, [resumeSession]) }, [resumeSession, refreshAgeAssurance])
useEffect(() => { useEffect(() => {
return listenSessionDropped(() => { return listenSessionDropped(() => {
@@ -211,6 +216,7 @@ function App() {
<A11yProvider> <A11yProvider>
<KeyboardControllerProvider> <KeyboardControllerProvider>
<SessionProvider> <SessionProvider>
<AgeAssuranceProvider>
<PrefsStateProvider> <PrefsStateProvider>
<I18nProvider> <I18nProvider>
<ShellStateProvider> <ShellStateProvider>
@@ -235,6 +241,7 @@ function App() {
</ShellStateProvider> </ShellStateProvider>
</I18nProvider> </I18nProvider>
</PrefsStateProvider> </PrefsStateProvider>
</AgeAssuranceProvider>
</SessionProvider> </SessionProvider>
</KeyboardControllerProvider> </KeyboardControllerProvider>
</A11yProvider> </A11yProvider>
+9 -1
View File
@@ -15,6 +15,10 @@ import {ThemeProvider} from '#/lib/ThemeContext'
import I18nProvider from '#/locale/i18nProvider' import I18nProvider from '#/locale/i18nProvider'
import {logger} from '#/logger' import {logger} from '#/logger'
import {Provider as A11yProvider} from '#/state/a11y' 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 MutedThreadsProvider} from '#/state/cache/thread-mutes'
import {Provider as DialogStateProvider} from '#/state/dialogs' import {Provider as DialogStateProvider} from '#/state/dialogs'
import {listenSessionDropped} from '#/state/events' import {listenSessionDropped} from '#/state/events'
@@ -75,6 +79,7 @@ function InnerApp() {
const theme = useColorModeTheme() const theme = useColorModeTheme()
const {_} = useLingui() const {_} = useLingui()
const hasCheckedReferrer = useStarterPackEntry() const hasCheckedReferrer = useStarterPackEntry()
const {refresh: refreshAgeAssurance} = useAgeAssuranceAPIContext()
// init // init
useEffect(() => { useEffect(() => {
@@ -82,6 +87,7 @@ function InnerApp() {
try { try {
if (account) { if (account) {
await resumeSession(account) await resumeSession(account)
await refreshAgeAssurance()
} }
} catch (e) { } catch (e) {
logger.error(`session: resumeSession failed`, {message: e}) logger.error(`session: resumeSession failed`, {message: e})
@@ -91,7 +97,7 @@ function InnerApp() {
} }
const account = readLastActiveAccount() const account = readLastActiveAccount()
onLaunch(account) onLaunch(account)
}, [resumeSession]) }, [resumeSession, refreshAgeAssurance])
useEffect(() => { useEffect(() => {
return listenSessionDropped(() => { return listenSessionDropped(() => {
@@ -186,6 +192,7 @@ function App() {
<GeolocationProvider> <GeolocationProvider>
<A11yProvider> <A11yProvider>
<SessionProvider> <SessionProvider>
<AgeAssuranceProvider>
<PrefsStateProvider> <PrefsStateProvider>
<I18nProvider> <I18nProvider>
<ShellStateProvider> <ShellStateProvider>
@@ -205,6 +212,7 @@ function App() {
</ShellStateProvider> </ShellStateProvider>
</I18nProvider> </I18nProvider>
</PrefsStateProvider> </PrefsStateProvider>
</AgeAssuranceProvider>
</SessionProvider> </SessionProvider>
</A11yProvider> </A11yProvider>
</GeolocationProvider> </GeolocationProvider>
+1
View File
@@ -12,6 +12,7 @@ export enum LogContext {
ReportDialog = 'report-dialog', ReportDialog = 'report-dialog',
FeedFeedback = 'feed-feedback', FeedFeedback = 'feed-feedback',
PostSource = 'post-source', PostSource = 'post-source',
AgeAssurance = 'age-assurance',
/** /**
* METRIC IS FOR INTERNAL USE ONLY, don't create any other loggers using this * METRIC IS FOR INTERNAL USE ONLY, don't create any other loggers using this
+100
View File
@@ -0,0 +1,100 @@
import {createContext, useCallback, useContext, useMemo, useState} from 'react'
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'
const logger = Logger.create(Logger.Context.AgeAssurance)
type TempAgeAssuranceState = {
updatedAt?: string
status: 'unknown' | 'pending' | 'assured'
}
export type AgeAssuranceContextType = {
required: boolean
status: TempAgeAssuranceState['status']
}
export type AgeAssuranceAPIContextType = {
refresh: () => Promise<void>
}
const AgeAssuranceContext = createContext<AgeAssuranceContextType>({
required: false,
status: 'unknown',
})
const AgeAssuranceAPIContext = createContext<AgeAssuranceAPIContextType>({
refresh: () => Promise.resolve(),
})
export function Provider({children}: {children: React.ReactNode}) {
// const agent = useAgent()
const {geolocation} = useGeolocation()
const [ageAssuranceState, setAgeAssuranceState] =
useState<TempAgeAssuranceState>({
status: 'unknown',
})
const refresh = useCallback(async () => {
try {
const {data} = await wait(
200,
(() => ({
data: {
updatedAt: undefined,
status: 'pending',
} as TempAgeAssuranceState,
}))(),
)
logger.debug(`refresh`, {data})
setAgeAssuranceState(data)
} catch (e) {
if (!isNetworkError(e)) {
logger.error(`ageAssurance: failed to refresh`, {safeMessage: e})
}
}
}, [setAgeAssuranceState])
const ageAssuranceContext = useMemo<AgeAssuranceContextType>(() => {
const {status} = ageAssuranceState
const ctx: AgeAssuranceContextType = {
required: Boolean(
geolocation?.isAgeRestrictedGeo && status !== 'assured',
),
status,
}
logger.debug(`context`, ctx)
return ctx
}, [geolocation, ageAssuranceState])
const ageAssuranceAPIContext = useMemo<AgeAssuranceAPIContextType>(
() => ({
refresh,
}),
[refresh],
)
return (
<AgeAssuranceAPIContext.Provider value={ageAssuranceAPIContext}>
<AgeAssuranceContext.Provider value={ageAssuranceContext}>
{children}
</AgeAssuranceContext.Provider>
</AgeAssuranceAPIContext.Provider>
)
}
export function useAgeAssuranceContext() {
return useContext(AgeAssuranceContext)
}
export function useAgeAssuranceAPIContext() {
return useContext(AgeAssuranceAPIContext)
}