Age Assurance V2 (#9479)
* Age Assurance V2 * Tighten up test * Add todos for sdk migration * Align RQ versions * Use useEffect for side effect * Improve effects, memoize * Standarize on birthdate * Copy feedback * Copilot * Add support link * Reove double .. * Cleanup * Remove redirect dialog * Cleanup todos, add comments * Update splash in main template too * Mock some stuff * Exhaustive checks Co-authored-by: Samuel Newman <mozzius@protonmail.com> * Exhaustive checks Co-authored-by: Samuel Newman <mozzius@protonmail.com> * Small fix to bday handling * Add comment * onboarding style tweak sneaking this in sorry! * rm unreachable breaks * Put useIntentHandler back on web * Remove misleading success set * Align on birthdate --------- Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import {useEffect, useMemo, useState} from 'react'
|
||||
import {computeAgeAssuranceRegionAccess} from '@atproto/api'
|
||||
|
||||
import {useSession} from '#/state/session'
|
||||
import {useAgeAssuranceDataContext} from '#/ageAssurance/data'
|
||||
import {logger} from '#/ageAssurance/logger'
|
||||
import {
|
||||
AgeAssuranceAccess,
|
||||
type AgeAssuranceState,
|
||||
AgeAssuranceStatus,
|
||||
parseAccessFromString,
|
||||
parseStatusFromString,
|
||||
} from '#/ageAssurance/types'
|
||||
import {getAgeAssuranceRegionConfigWithFallback} from '#/ageAssurance/util'
|
||||
import {useGeolocation} from '#/geolocation'
|
||||
|
||||
export function useAgeAssuranceState(): AgeAssuranceState {
|
||||
const {hasSession} = useSession()
|
||||
const geolocation = useGeolocation()
|
||||
const {config, state, data} = useAgeAssuranceDataContext()
|
||||
|
||||
return useMemo(() => {
|
||||
/**
|
||||
* This is where we control logged-out moderation prefs. It's all
|
||||
* downstream of AA now.
|
||||
*/
|
||||
if (!hasSession)
|
||||
return {
|
||||
status: AgeAssuranceStatus.Unknown,
|
||||
access: AgeAssuranceAccess.Safe,
|
||||
}
|
||||
|
||||
// should never happen, but need to guard
|
||||
if (!config) {
|
||||
logger.warn('useAgeAssuranceState: missing config')
|
||||
return {
|
||||
status: AgeAssuranceStatus.Unknown,
|
||||
access: AgeAssuranceAccess.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
const region = getAgeAssuranceRegionConfigWithFallback(config, geolocation)
|
||||
const isAARequired = region.countryCode !== '*'
|
||||
const isTerminalState =
|
||||
state?.status === 'assured' || state?.status === 'blocked'
|
||||
|
||||
/*
|
||||
* If we are in a terminal state and AA is required for this region,
|
||||
* we can trust the server state completely and avoid recomputing.
|
||||
*/
|
||||
if (isTerminalState && isAARequired) {
|
||||
return {
|
||||
lastInitiatedAt: state.lastInitiatedAt,
|
||||
status: parseStatusFromString(state.status),
|
||||
access: parseAccessFromString(state.access),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, we need to compute the access based on the latest data. For
|
||||
* accounts with an accurate birthdate, our default fallback rules should
|
||||
* ensure correct access.
|
||||
*/
|
||||
const result = computeAgeAssuranceRegionAccess(region, data)
|
||||
const computed = {
|
||||
lastInitiatedAt: state?.lastInitiatedAt,
|
||||
// prefer server state
|
||||
status: state?.status
|
||||
? parseStatusFromString(state?.status)
|
||||
: AgeAssuranceStatus.Unknown,
|
||||
// prefer server state
|
||||
access: result
|
||||
? parseAccessFromString(result.access)
|
||||
: AgeAssuranceAccess.Full,
|
||||
}
|
||||
logger.debug('debug useAgeAssuranceState', {
|
||||
region,
|
||||
state,
|
||||
data,
|
||||
computed,
|
||||
})
|
||||
return computed
|
||||
}, [hasSession, geolocation, config, state, data])
|
||||
}
|
||||
|
||||
export function useOnAgeAssuranceAccessUpdate(
|
||||
cb: (state: AgeAssuranceState) => void,
|
||||
) {
|
||||
const state = useAgeAssuranceState()
|
||||
// start with null to ensure callback is called on first render
|
||||
const [prevAccess, setPrevAccess] = useState<AgeAssuranceAccess | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (prevAccess !== state.access) {
|
||||
setPrevAccess(state.access)
|
||||
cb(state)
|
||||
logger.debug(`useOnAgeAssuranceAccessUpdate`, {state})
|
||||
}
|
||||
}, [cb, state, prevAccess])
|
||||
}
|
||||
Reference in New Issue
Block a user