diff options
author | Eric Bailey <git@esb.lol> | 2025-08-06 15:15:52 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-06 15:15:52 -0500 |
commit | 328aa2be9482f77cb1cf86c5d227fdcee9981b16 (patch) | |
tree | 27174f10e0fe80288c0cd6907f8686486131d082 /src/components/PolicyUpdateOverlay/usePolicyUpdateState.ts | |
parent | fd37d92f85ddf0f075a67c4e9b2d85bef38f1835 (diff) | |
download | voidsky-328aa2be9482f77cb1cf86c5d227fdcee9981b16.tar.zst |
[APP-1356] Policy update dialog (#8782)
* Add blocking announcement dialog feature * WIP custom dialog * Rework dialog and add native FocusScope * Lock scroll on web, fix backdrop * Add web FocusScope * Create custom Outlet for these announcements * Clean up FocusScope native impl * Comments * Some styling fixes * Handle screen reader specifically * Clean up state, remove Portal edits * Reorg, rename * Add syncing, tests * Revert dialog updates * Revert formatting * Delete unused file * Format * Add FullWindowOverlay * remove mmkv storage in debug btn * Add debug code * fix taps passing through on iOS * Reorg * Reorg, rename everything * Complete policy update after signup * Add logger * Move context around, unmount portals on native * Move a11y prop into FocusScope * Remove useMemo * Update dates * Move debug to dev settings * Unmount web portals until policy update completed * UPdate dates --------- Co-authored-by: Samuel Newman <mozzius@protonmail.com>
Diffstat (limited to 'src/components/PolicyUpdateOverlay/usePolicyUpdateState.ts')
-rw-r--r-- | src/components/PolicyUpdateOverlay/usePolicyUpdateState.ts | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/components/PolicyUpdateOverlay/usePolicyUpdateState.ts b/src/components/PolicyUpdateOverlay/usePolicyUpdateState.ts new file mode 100644 index 000000000..29d8afe06 --- /dev/null +++ b/src/components/PolicyUpdateOverlay/usePolicyUpdateState.ts @@ -0,0 +1,135 @@ +import {useMemo} from 'react' + +import {useNux, useSaveNux} from '#/state/queries/nuxs' +import {ACTIVE_UPDATE_ID} from '#/components/PolicyUpdateOverlay/config' +import {logger} from '#/components/PolicyUpdateOverlay/logger' +import {IS_DEV} from '#/env' +import {device, useStorage} from '#/storage' + +export type PolicyUpdateState = { + completed: boolean + complete: () => void +} + +export function usePolicyUpdateState() { + const nux = useNux(ACTIVE_UPDATE_ID) + const {mutate: save, variables} = useSaveNux() + const deviceStorage = useStorage(device, [ACTIVE_UPDATE_ID]) + const debugOverride = + !!useStorage(device, ['policyUpdateDebugOverride'])[0] && IS_DEV + return useMemo(() => { + const nuxIsReady = nux.status === 'ready' + const nuxIsCompleted = nux.nux?.completed === true + const nuxIsOptimisticallyCompleted = !!variables?.completed + const [completedForDevice, setCompletedForDevice] = deviceStorage + + const completed = computeCompletedState({ + nuxIsReady, + nuxIsCompleted, + nuxIsOptimisticallyCompleted, + completedForDevice, + }) + + logger.debug(`state`, { + completed, + nux, + completedForDevice, + }) + + if (!debugOverride) { + syncCompletedState({ + nuxIsReady, + nuxIsCompleted, + nuxIsOptimisticallyCompleted, + completedForDevice, + save, + setCompletedForDevice, + }) + } + + return { + completed, + complete() { + logger.debug(`user completed`) + save({ + id: ACTIVE_UPDATE_ID, + completed: true, + data: undefined, + }) + setCompletedForDevice(true) + }, + } + }, [nux, save, variables, deviceStorage, debugOverride]) +} + +export function computeCompletedState({ + nuxIsReady, + nuxIsCompleted, + nuxIsOptimisticallyCompleted, + completedForDevice, +}: { + nuxIsReady: boolean + nuxIsCompleted: boolean + nuxIsOptimisticallyCompleted: boolean + completedForDevice: boolean | undefined +}): boolean { + /** + * Assume completed to prevent flash + */ + let completed = true + + /** + * Prefer server state, if available + */ + if (nuxIsReady) { + completed = nuxIsCompleted + } + + /** + * Override with optimistic state or device state + */ + if (nuxIsOptimisticallyCompleted || !!completedForDevice) { + completed = true + } + + return completed +} + +export function syncCompletedState({ + nuxIsReady, + nuxIsCompleted, + nuxIsOptimisticallyCompleted, + completedForDevice, + save, + setCompletedForDevice, +}: { + nuxIsReady: boolean + nuxIsCompleted: boolean + nuxIsOptimisticallyCompleted: boolean + completedForDevice: boolean | undefined + save: ReturnType<typeof useSaveNux>['mutate'] + setCompletedForDevice: (value: boolean) => void +}) { + /* + * Sync device state to server state for this account + */ + if ( + nuxIsReady && + !nuxIsCompleted && + !nuxIsOptimisticallyCompleted && + !!completedForDevice + ) { + logger.debug(`syncing device state to server state`) + save({ + id: ACTIVE_UPDATE_ID, + completed: true, + data: undefined, + }) + } else if (nuxIsReady && nuxIsCompleted && !completedForDevice) { + logger.debug(`syncing server state to device state`) + /* + * Sync server state to device state + */ + setCompletedForDevice(true) + } +} |