forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
2
3import {useGetAndRegisterPushToken} from '#/lib/notifications/notifications'
4import {Provider as RedirectOverlayProvider} from '#/ageAssurance/components/RedirectOverlay'
5import {AgeAssuranceDataProvider} from '#/ageAssurance/data'
6import {useAgeAssuranceDataContext} from '#/ageAssurance/data'
7import {logger} from '#/ageAssurance/logger'
8import {
9 useAgeAssuranceState,
10 useOnAgeAssuranceAccessUpdate,
11} from '#/ageAssurance/state'
12import {
13 AgeAssuranceAccess,
14 type AgeAssuranceState,
15 AgeAssuranceStatus,
16} from '#/ageAssurance/types'
17import {
18 isUnderAge,
19 MIN_ACCESS_AGE,
20 useAgeAssuranceRegionConfigWithFallback,
21} from '#/ageAssurance/util'
22
23export {
24 prefetchConfig as prefetchAgeAssuranceConfig,
25 prefetchAgeAssuranceData,
26 refetchServerState as refetchAgeAssuranceServerState,
27 usePatchOtherRequiredData as usePatchAgeAssuranceOtherRequiredData,
28 usePatchServerState as usePatchAgeAssuranceServerState,
29} from '#/ageAssurance/data'
30export {logger} from '#/ageAssurance/logger'
31export {MIN_ACCESS_AGE} from '#/ageAssurance/util'
32
33const AgeAssuranceStateContext = createContext<{
34 Access: typeof AgeAssuranceAccess
35 Status: typeof AgeAssuranceStatus
36 state: AgeAssuranceState
37 flags: {
38 adultContentDisabled: boolean
39 chatDisabled: boolean
40 isOverRegionMinAccessAge: boolean
41 isOverAppMinAccessAge: boolean
42 }
43}>({
44 Access: AgeAssuranceAccess,
45 Status: AgeAssuranceStatus,
46 state: {
47 lastInitiatedAt: undefined,
48 status: AgeAssuranceStatus.Unknown,
49 access: AgeAssuranceAccess.Full,
50 },
51 flags: {
52 adultContentDisabled: false,
53 chatDisabled: false,
54 isOverRegionMinAccessAge: false,
55 isOverAppMinAccessAge: false,
56 },
57})
58
59/**
60 * THE MAIN AGE ASSURANCE CONTEXT HOOK
61 *
62 * Prefer this to using any of the lower-level data-provider hooks.
63 */
64export function useAgeAssurance() {
65 return useContext(AgeAssuranceStateContext)
66}
67
68export function Provider({children}: {children: React.ReactNode}) {
69 return (
70 <AgeAssuranceDataProvider>
71 <InnerProvider>
72 <RedirectOverlayProvider>{children}</RedirectOverlayProvider>
73 </InnerProvider>
74 </AgeAssuranceDataProvider>
75 )
76}
77
78function InnerProvider({children}: {children: React.ReactNode}) {
79 const state = useAgeAssuranceState()
80 const {data} = useAgeAssuranceDataContext()
81 const config = useAgeAssuranceRegionConfigWithFallback()
82 const getAndRegisterPushToken = useGetAndRegisterPushToken()
83
84 const handleAccessUpdate = useCallback(
85 (s: AgeAssuranceState) => {
86 getAndRegisterPushToken({
87 isAgeRestricted: s.access !== AgeAssuranceAccess.Full,
88 })
89 },
90 [getAndRegisterPushToken],
91 )
92 useOnAgeAssuranceAccessUpdate(handleAccessUpdate)
93
94 useEffect(() => {
95 logger.debug(`useAgeAssuranceState`, {state})
96 }, [state])
97
98 return (
99 <AgeAssuranceStateContext.Provider
100 value={useMemo(() => {
101 const chatDisabled = state.access !== AgeAssuranceAccess.Full
102 const isUnderAdultAge = data?.birthdate
103 ? isUnderAge(data.birthdate, 18)
104 : true
105 const isOverRegionMinAccessAge = data?.birthdate
106 ? !isUnderAge(data.birthdate, config.minAccessAge)
107 : false
108 const isOverAppMinAccessAge = data?.birthdate
109 ? !isUnderAge(data.birthdate, MIN_ACCESS_AGE)
110 : false
111 const adultContentDisabled =
112 state.access !== AgeAssuranceAccess.Full || isUnderAdultAge
113 return {
114 Access: AgeAssuranceAccess,
115 Status: AgeAssuranceStatus,
116 state,
117 flags: {
118 adultContentDisabled,
119 chatDisabled,
120 isOverRegionMinAccessAge,
121 isOverAppMinAccessAge,
122 },
123 }
124 }, [state, data, config])}>
125 {children}
126 </AgeAssuranceStateContext.Provider>
127 )
128}