[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>
This commit is contained in:
Eric Bailey
2025-08-06 15:15:52 -05:00
committed by GitHub
parent fd37d92f85
commit 328aa2be94
29 changed files with 1214 additions and 88 deletions
+4 -2
View File
@@ -3,11 +3,12 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
import {logger} from '#/logger'
import {
defaults,
Schema,
type Schema,
tryParse,
tryStringify,
} from '#/state/persisted/schema'
import {PersistedApi} from './types'
import {device} from '#/storage'
import {type PersistedApi} from './types'
import {normalizeData} from './util'
export type {PersistedAccount, Schema} from '#/state/persisted/schema'
@@ -53,6 +54,7 @@ onUpdate satisfies PersistedApi['onUpdate']
export async function clearStorage() {
try {
await AsyncStorage.removeItem(BSKY_STORAGE)
device.removeAll()
} catch (e: any) {
logger.error(`persisted store: failed to clear`, {message: e.toString()})
}
+25
View File
@@ -0,0 +1,25 @@
import {jest} from '@jest/globals'
export {Nux} from '#/state/queries/nuxs/definitions'
export const useNuxs = jest.fn(() => {
return {
nuxs: undefined,
status: 'loading' as const,
}
})
export const useNux = jest.fn((id: string) => {
return {
nux: undefined,
status: 'loading' as const,
}
})
export const useSaveNux = jest.fn(() => {
return {}
})
export const useResetNuxs = jest.fn(() => {
return {}
})
+10
View File
@@ -9,6 +9,11 @@ export enum Nux {
ActivitySubscriptions = 'ActivitySubscriptions',
AgeAssuranceDismissibleNotice = 'AgeAssuranceDismissibleNotice',
AgeAssuranceDismissibleFeedBanner = 'AgeAssuranceDismissibleFeedBanner',
/*
* Blocking announcements. New IDs are required for each new announcement.
*/
PolicyUpdate202508 = 'PolicyUpdate202508',
}
export const nuxNames = new Set(Object.values(Nux))
@@ -38,6 +43,10 @@ export type AppNux = BaseNux<
id: Nux.AgeAssuranceDismissibleFeedBanner
data: undefined
}
| {
id: Nux.PolicyUpdate202508
data: undefined
}
>
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
@@ -47,4 +56,5 @@ export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
[Nux.ActivitySubscriptions]: undefined,
[Nux.AgeAssuranceDismissibleNotice]: undefined,
[Nux.AgeAssuranceDismissibleFeedBanner]: undefined,
[Nux.PolicyUpdate202508]: undefined,
}