mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {useMemo} from 'react'
2
3import {useNux, useSaveNux} from '#/state/queries/nuxs'
4import {ACTIVE_UPDATE_ID} from '#/components/PolicyUpdateOverlay/config'
5import {logger} from '#/components/PolicyUpdateOverlay/logger'
6import {IS_DEV} from '#/env'
7import {device, useStorage} from '#/storage'
8
9export type PolicyUpdateState = {
10 completed: boolean
11 complete: () => void
12}
13
14export function usePolicyUpdateState({
15 enabled,
16}: {
17 /**
18 * Used to skip the policy update overlay until we're actually ready to
19 * show it.
20 */
21 enabled: boolean
22}) {
23 const nux = useNux(ACTIVE_UPDATE_ID)
24 const {mutate: save, variables} = useSaveNux()
25 const deviceStorage = useStorage(device, [ACTIVE_UPDATE_ID])
26 const debugOverride =
27 !!useStorage(device, ['policyUpdateDebugOverride'])[0] && IS_DEV
28
29 return useMemo(() => {
30 /**
31 * If not enabled, then just return a completed state so the app functions
32 * as normal.
33 */
34 if (!enabled) {
35 return {
36 completed: true,
37 complete() {},
38 }
39 }
40
41 const nuxIsReady = nux.status === 'ready'
42 const nuxIsCompleted = nux.nux?.completed === true
43 const nuxIsOptimisticallyCompleted = !!variables?.completed
44 const [completedForDevice, setCompletedForDevice] = deviceStorage
45
46 const completed = computeCompletedState({
47 nuxIsReady,
48 nuxIsCompleted,
49 nuxIsOptimisticallyCompleted,
50 completedForDevice,
51 })
52
53 logger.debug(`state`, {
54 completed,
55 nux,
56 completedForDevice,
57 })
58
59 if (!debugOverride) {
60 syncCompletedState({
61 nuxIsReady,
62 nuxIsCompleted,
63 nuxIsOptimisticallyCompleted,
64 completedForDevice,
65 save,
66 setCompletedForDevice,
67 })
68 }
69
70 return {
71 completed,
72 complete() {
73 logger.debug(`user completed`)
74 save({
75 id: ACTIVE_UPDATE_ID,
76 completed: true,
77 data: undefined,
78 })
79 setCompletedForDevice(true)
80 },
81 }
82 }, [enabled, nux, save, variables, deviceStorage, debugOverride])
83}
84
85export function computeCompletedState({
86 nuxIsReady,
87 nuxIsCompleted,
88 nuxIsOptimisticallyCompleted,
89 completedForDevice,
90}: {
91 nuxIsReady: boolean
92 nuxIsCompleted: boolean
93 nuxIsOptimisticallyCompleted: boolean
94 completedForDevice: boolean | undefined
95}): boolean {
96 /**
97 * Assume completed to prevent flash
98 */
99 let completed = true
100
101 /**
102 * Prefer server state, if available
103 */
104 if (nuxIsReady) {
105 completed = nuxIsCompleted
106 }
107
108 /**
109 * Override with optimistic state or device state
110 */
111 if (nuxIsOptimisticallyCompleted || !!completedForDevice) {
112 completed = true
113 }
114
115 return completed
116}
117
118export function syncCompletedState({
119 nuxIsReady,
120 nuxIsCompleted,
121 nuxIsOptimisticallyCompleted,
122 completedForDevice,
123 save,
124 setCompletedForDevice,
125}: {
126 nuxIsReady: boolean
127 nuxIsCompleted: boolean
128 nuxIsOptimisticallyCompleted: boolean
129 completedForDevice: boolean | undefined
130 save: ReturnType<typeof useSaveNux>['mutate']
131 setCompletedForDevice: (value: boolean) => void
132}) {
133 /*
134 * Sync device state to server state for this account
135 */
136 if (
137 nuxIsReady &&
138 !nuxIsCompleted &&
139 !nuxIsOptimisticallyCompleted &&
140 !!completedForDevice
141 ) {
142 logger.debug(`syncing device state to server state`)
143 save({
144 id: ACTIVE_UPDATE_ID,
145 completed: true,
146 data: undefined,
147 })
148 } else if (nuxIsReady && nuxIsCompleted && !completedForDevice) {
149 logger.debug(`syncing server state to device state`)
150 /*
151 * Sync server state to device state
152 */
153 setCompletedForDevice(true)
154 }
155}