Refactor
This commit is contained in:
@@ -8,7 +8,7 @@ import debounce from 'lodash.debounce'
|
|||||||
import {PUBLIC_APPVIEW_DID, PUBLIC_STAGING_APPVIEW_DID} from '#/lib/constants'
|
import {PUBLIC_APPVIEW_DID, PUBLIC_STAGING_APPVIEW_DID} from '#/lib/constants'
|
||||||
import {logger as notyLogger} from '#/lib/notifications/util'
|
import {logger as notyLogger} from '#/lib/notifications/util'
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
import {useIsAgeRestricted} from '#/state/ageAssurance/useIsAgeRestricted'
|
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||||
import {type SessionAccount, useAgent, useSession} from '#/state/session'
|
import {type SessionAccount, useAgent, useSession} from '#/state/session'
|
||||||
import BackgroundNotificationHandler from '#/../modules/expo-background-notification-handler'
|
import BackgroundNotificationHandler from '#/../modules/expo-background-notification-handler'
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ async function getPushToken() {
|
|||||||
* @see https://github.com/bluesky-social/social-app/pull/4467
|
* @see https://github.com/bluesky-social/social-app/pull/4467
|
||||||
*/
|
*/
|
||||||
export function useGetAndRegisterPushToken() {
|
export function useGetAndRegisterPushToken() {
|
||||||
const {isAgeRestricted} = useIsAgeRestricted()
|
const {isAgeRestricted} = useAgeAssuranceContext()
|
||||||
const registerPushToken = useRegisterPushToken()
|
const registerPushToken = useRegisterPushToken()
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async ({
|
async ({
|
||||||
@@ -170,7 +170,8 @@ export function useNotificationsRegistration() {
|
|||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const registerPushToken = useRegisterPushToken()
|
const registerPushToken = useRegisterPushToken()
|
||||||
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
||||||
const {isReady: isAgeRestrictionReady, isAgeRestricted} = useIsAgeRestricted()
|
const {isReady: isAgeRestrictionReady, isAgeRestricted} =
|
||||||
|
useAgeAssuranceContext()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
type AgeAssuranceAPIContextType,
|
type AgeAssuranceAPIContextType,
|
||||||
type AgeAssuranceContextType,
|
type AgeAssuranceContextType,
|
||||||
} from '#/state/ageAssurance/types'
|
} from '#/state/ageAssurance/types'
|
||||||
|
import {useIsAgeAssuranceEnabled} from '#/state/ageAssurance/useIsAgeAssuranceEnabled'
|
||||||
import {useGeolocation} from '#/state/geolocation'
|
import {useGeolocation} from '#/state/geolocation'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ const AgeAssuranceContext = createContext<AgeAssuranceContextType>({
|
|||||||
status: 'unknown',
|
status: 'unknown',
|
||||||
isReady: false,
|
isReady: false,
|
||||||
lastInitiatedAt: undefined,
|
lastInitiatedAt: undefined,
|
||||||
|
isAgeRestricted: false,
|
||||||
})
|
})
|
||||||
const AgeAssuranceAPIContext = createContext<AgeAssuranceAPIContextType>({
|
const AgeAssuranceAPIContext = createContext<AgeAssuranceAPIContextType>({
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -38,11 +40,11 @@ const AgeAssuranceAPIContext = createContext<AgeAssuranceAPIContextType>({
|
|||||||
* performance.
|
* performance.
|
||||||
*/
|
*/
|
||||||
export function Provider({children}: {children: React.ReactNode}) {
|
export function Provider({children}: {children: React.ReactNode}) {
|
||||||
|
const gate = useGate()
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const {geolocation} = useGeolocation()
|
const {geolocation} = useGeolocation()
|
||||||
|
const isAgeAssuranceEnabled = useIsAgeAssuranceEnabled()
|
||||||
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
||||||
const isAgeRestrictedGeo = !!geolocation?.isAgeRestrictedGeo
|
|
||||||
const gate = useGate()
|
|
||||||
|
|
||||||
const {data, isFetched, refetch} = useQuery({
|
const {data, isFetched, refetch} = useQuery({
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +52,7 @@ export function Provider({children}: {children: React.ReactNode}) {
|
|||||||
* "fetched" state, even if we fall back to defaults. This lets the rest of
|
* "fetched" state, even if we fall back to defaults. This lets the rest of
|
||||||
* the app know that we've at least attempted to load the AA state.
|
* the app know that we've at least attempted to load the AA state.
|
||||||
*/
|
*/
|
||||||
enabled: true,
|
enabled: isAgeAssuranceEnabled,
|
||||||
queryKey: createAgeAssuranceQueryKey(agent.session?.did ?? 'never'),
|
queryKey: createAgeAssuranceQueryKey(agent.session?.did ?? 'never'),
|
||||||
async queryFn() {
|
async queryFn() {
|
||||||
if (!agent.session) return null
|
if (!agent.session) return null
|
||||||
@@ -76,9 +78,8 @@ export function Provider({children}: {children: React.ReactNode}) {
|
|||||||
|
|
||||||
if (gate('age_assurance')) {
|
if (gate('age_assurance')) {
|
||||||
await getAndRegisterPushToken({
|
await getAndRegisterPushToken({
|
||||||
isAgeRestricted: Boolean(
|
isAgeRestricted:
|
||||||
isAgeRestrictedGeo && data.status !== 'assured',
|
!!geolocation?.isAgeRestrictedGeo && data.status !== 'assured',
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,13 +100,14 @@ export function Provider({children}: {children: React.ReactNode}) {
|
|||||||
const ageAssuranceContext = useMemo<AgeAssuranceContextType>(() => {
|
const ageAssuranceContext = useMemo<AgeAssuranceContextType>(() => {
|
||||||
const {status, lastInitiatedAt} = data || DEFAULT_AGE_ASSURANCE_STATE
|
const {status, lastInitiatedAt} = data || DEFAULT_AGE_ASSURANCE_STATE
|
||||||
const ctx: AgeAssuranceContextType = {
|
const ctx: AgeAssuranceContextType = {
|
||||||
isReady: isFetched,
|
isReady: isFetched || !isAgeAssuranceEnabled,
|
||||||
status,
|
status,
|
||||||
lastInitiatedAt,
|
lastInitiatedAt,
|
||||||
|
isAgeRestricted: isAgeAssuranceEnabled ? status !== 'assured' : false,
|
||||||
}
|
}
|
||||||
logger.debug(`context`, ctx)
|
logger.debug(`context`, ctx)
|
||||||
return ctx
|
return ctx
|
||||||
}, [isFetched, data])
|
}, [isFetched, data, isAgeAssuranceEnabled])
|
||||||
|
|
||||||
const ageAssuranceAPIContext = useMemo<AgeAssuranceAPIContextType>(
|
const ageAssuranceAPIContext = useMemo<AgeAssuranceAPIContextType>(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import {type QueryObserverBaseResult} from '@tanstack/react-query'
|
|||||||
|
|
||||||
export type AgeAssuranceContextType = {
|
export type AgeAssuranceContextType = {
|
||||||
/**
|
/**
|
||||||
* Whether the age assurance state has been fetched from the server.
|
* Whether the age assurance state has been fetched from the server. If user
|
||||||
|
* is not in a region that requires AA, or AA is otherwise disabled, this
|
||||||
|
* will always be `true`.
|
||||||
*/
|
*/
|
||||||
isReady: boolean
|
isReady: boolean
|
||||||
/**
|
/**
|
||||||
@@ -14,6 +16,13 @@ export type AgeAssuranceContextType = {
|
|||||||
* The last time the age assurance state was attempted by the user.
|
* The last time the age assurance state was attempted by the user.
|
||||||
*/
|
*/
|
||||||
lastInitiatedAt: AppBskyUnspeccedDefs.AgeAssuranceState['lastInitiatedAt']
|
lastInitiatedAt: AppBskyUnspeccedDefs.AgeAssuranceState['lastInitiatedAt']
|
||||||
|
/**
|
||||||
|
* Indicates the user is age restricted based on the requirements of their
|
||||||
|
* region, and their server-provided age assurance status. Does not factor in
|
||||||
|
* the user's declared age. If AA is otherise disabled, this will always be
|
||||||
|
* `false`.
|
||||||
|
*/
|
||||||
|
isAgeRestricted: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AgeAssuranceAPIContextType = {
|
export type AgeAssuranceAPIContextType = {
|
||||||
|
|||||||
@@ -2,18 +2,11 @@ import {useMemo} from 'react'
|
|||||||
|
|
||||||
import {Logger} from '#/logger'
|
import {Logger} from '#/logger'
|
||||||
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||||
import {useIsAgeRestricted} from '#/state/ageAssurance/useIsAgeRestricted'
|
|
||||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
|
|
||||||
const logger = Logger.create(Logger.Context.AgeAssurance)
|
const logger = Logger.create(Logger.Context.AgeAssurance)
|
||||||
|
|
||||||
type AgeAssurance = ReturnType<typeof useAgeAssuranceContext> & {
|
type AgeAssurance = ReturnType<typeof useAgeAssuranceContext> & {
|
||||||
/**
|
|
||||||
* Indicates the user is age restricted based on the requirements of their
|
|
||||||
* region, and their server-provided age assurance status. Does not factor in
|
|
||||||
* the user's declared age.
|
|
||||||
*/
|
|
||||||
isAgeRestricted: boolean
|
|
||||||
/**
|
/**
|
||||||
* The age the user has declared in their preferences, if any.
|
* The age the user has declared in their preferences, if any.
|
||||||
*/
|
*/
|
||||||
@@ -30,24 +23,23 @@ type AgeAssurance = ReturnType<typeof useAgeAssuranceContext> & {
|
|||||||
* more user-friendly interface.
|
* more user-friendly interface.
|
||||||
*/
|
*/
|
||||||
export function useAgeAssurance(): AgeAssurance {
|
export function useAgeAssurance(): AgeAssurance {
|
||||||
const ctx = useAgeAssuranceContext()
|
const aa = useAgeAssuranceContext()
|
||||||
const {isAgeRestricted} = useIsAgeRestricted()
|
|
||||||
const {isFetched: preferencesLoaded, data: preferences} =
|
const {isFetched: preferencesLoaded, data: preferences} =
|
||||||
usePreferencesQuery()
|
usePreferencesQuery()
|
||||||
const declaredAge = preferences?.userAge
|
const declaredAge = preferences?.userAge
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const isReady = ctx.isReady && preferencesLoaded
|
const isReady = aa.isReady && preferencesLoaded
|
||||||
const isDeclaredUnderage = (declaredAge || 0) < 18
|
const isDeclaredUnderage = (declaredAge || 0) < 18
|
||||||
const state: AgeAssurance = {
|
const state: AgeAssurance = {
|
||||||
isReady,
|
isReady,
|
||||||
status: ctx.status,
|
status: aa.status,
|
||||||
lastInitiatedAt: ctx.lastInitiatedAt,
|
lastInitiatedAt: aa.lastInitiatedAt,
|
||||||
isAgeRestricted,
|
isAgeRestricted: aa.isAgeRestricted,
|
||||||
declaredAge,
|
declaredAge,
|
||||||
isDeclaredUnderage,
|
isDeclaredUnderage,
|
||||||
}
|
}
|
||||||
logger.debug(`state`, state)
|
logger.debug(`state`, state)
|
||||||
return state
|
return state
|
||||||
}, [ctx, preferencesLoaded, declaredAge, isAgeRestricted])
|
}, [aa, preferencesLoaded, declaredAge])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import {useMemo} from 'react'
|
||||||
|
|
||||||
|
import {useGate} from '#/lib/statsig/statsig'
|
||||||
|
import {useGeolocation} from '#/state/geolocation'
|
||||||
|
|
||||||
|
export function useIsAgeAssuranceEnabled() {
|
||||||
|
const gate = useGate()
|
||||||
|
const {geolocation} = useGeolocation()
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return gate('age_assurance') && !!geolocation?.isAgeRestrictedGeo
|
||||||
|
}, [geolocation, gate])
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import {useMemo} from 'react'
|
|
||||||
|
|
||||||
import {useGate} from '#/lib/statsig/statsig'
|
|
||||||
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
|
||||||
import {useGeolocation} from '#/state/geolocation'
|
|
||||||
|
|
||||||
export function useIsAgeRestricted() {
|
|
||||||
const {isReady, status} = useAgeAssuranceContext()
|
|
||||||
const {geolocation} = useGeolocation()
|
|
||||||
const gate = useGate()
|
|
||||||
|
|
||||||
return useMemo(() => {
|
|
||||||
if (!gate('age_assurance') || !geolocation?.isAgeRestrictedGeo) {
|
|
||||||
return {
|
|
||||||
isReady: true,
|
|
||||||
isAgeRestricted: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
isReady,
|
|
||||||
isAgeRestricted: status !== 'assured',
|
|
||||||
}
|
|
||||||
}, [isReady, status, geolocation, gate])
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,8 @@ import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
|||||||
import {replaceEqualDeep} from '#/lib/functions'
|
import {replaceEqualDeep} from '#/lib/functions'
|
||||||
import {getAge} from '#/lib/strings/time'
|
import {getAge} from '#/lib/strings/time'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
|
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||||
import {AGE_RESTRICTED_MODERATION_PREFS} from '#/state/ageAssurance/const'
|
import {AGE_RESTRICTED_MODERATION_PREFS} from '#/state/ageAssurance/const'
|
||||||
import {useIsAgeRestricted} from '#/state/ageAssurance/useIsAgeRestricted'
|
|
||||||
import {STALE} from '#/state/queries'
|
import {STALE} from '#/state/queries'
|
||||||
import {
|
import {
|
||||||
DEFAULT_HOME_FEED_PREFS,
|
DEFAULT_HOME_FEED_PREFS,
|
||||||
@@ -34,7 +34,8 @@ export const preferencesQueryKey = [preferencesQueryKeyRoot]
|
|||||||
|
|
||||||
export function usePreferencesQuery() {
|
export function usePreferencesQuery() {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const {isReady: isAgeRestrictionReady, isAgeRestricted} = useIsAgeRestricted()
|
const {isReady: isAgeRestrictionReady, isAgeRestricted} =
|
||||||
|
useAgeAssuranceContext()
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
staleTime: STALE.SECONDS.FIFTEEN,
|
staleTime: STALE.SECONDS.FIFTEEN,
|
||||||
|
|||||||
Reference in New Issue
Block a user