Move context around, unmount portals on native

This commit is contained in:
Eric Bailey
2025-08-05 15:42:39 -05:00
parent f978d9bff5
commit b8cfb2d0af
8 changed files with 166 additions and 117 deletions
+2 -2
View File
@@ -138,6 +138,7 @@ function InnerApp() {
// Resets the entire tree below when it changes: // Resets the entire tree below when it changes:
key={currentAccount?.did}> key={currentAccount?.did}>
<QueryProvider currentDid={currentAccount?.did}> <QueryProvider currentDid={currentAccount?.did}>
<PolicyUpdateOverlayProvider>
<StatsigProvider> <StatsigProvider>
<AgeAssuranceProvider> <AgeAssuranceProvider>
<ComposerProvider> <ComposerProvider>
@@ -181,6 +182,7 @@ function InnerApp() {
</ComposerProvider> </ComposerProvider>
</AgeAssuranceProvider> </AgeAssuranceProvider>
</StatsigProvider> </StatsigProvider>
</PolicyUpdateOverlayProvider>
</QueryProvider> </QueryProvider>
</React.Fragment> </React.Fragment>
</VideoVolumeProvider> </VideoVolumeProvider>
@@ -221,7 +223,6 @@ function App() {
<ModalStateProvider> <ModalStateProvider>
<DialogStateProvider> <DialogStateProvider>
<LightboxStateProvider> <LightboxStateProvider>
<PolicyUpdateOverlayProvider>
<PortalProvider> <PortalProvider>
<BottomSheetProvider> <BottomSheetProvider>
<StarterPackProvider> <StarterPackProvider>
@@ -232,7 +233,6 @@ function App() {
</StarterPackProvider> </StarterPackProvider>
</BottomSheetProvider> </BottomSheetProvider>
</PortalProvider> </PortalProvider>
</PolicyUpdateOverlayProvider>
</LightboxStateProvider> </LightboxStateProvider>
</DialogStateProvider> </DialogStateProvider>
</ModalStateProvider> </ModalStateProvider>
+2 -2
View File
@@ -118,6 +118,7 @@ function InnerApp() {
// Resets the entire tree below when it changes: // Resets the entire tree below when it changes:
key={currentAccount?.did}> key={currentAccount?.did}>
<QueryProvider currentDid={currentAccount?.did}> <QueryProvider currentDid={currentAccount?.did}>
<PolicyUpdateOverlayProvider>
<StatsigProvider> <StatsigProvider>
<AgeAssuranceProvider> <AgeAssuranceProvider>
<ComposerProvider> <ComposerProvider>
@@ -157,6 +158,7 @@ function InnerApp() {
</ComposerProvider> </ComposerProvider>
</AgeAssuranceProvider> </AgeAssuranceProvider>
</StatsigProvider> </StatsigProvider>
</PolicyUpdateOverlayProvider>
</QueryProvider> </QueryProvider>
<ToastContainer /> <ToastContainer />
</React.Fragment> </React.Fragment>
@@ -197,13 +199,11 @@ function App() {
<ModalStateProvider> <ModalStateProvider>
<DialogStateProvider> <DialogStateProvider>
<LightboxStateProvider> <LightboxStateProvider>
<PolicyUpdateOverlayProvider>
<PortalProvider> <PortalProvider>
<StarterPackProvider> <StarterPackProvider>
<InnerApp /> <InnerApp />
</StarterPackProvider> </StarterPackProvider>
</PortalProvider> </PortalProvider>
</PolicyUpdateOverlayProvider>
</LightboxStateProvider> </LightboxStateProvider>
</DialogStateProvider> </DialogStateProvider>
</ModalStateProvider> </ModalStateProvider>
@@ -109,6 +109,7 @@ export function Overlay({
<FocusScope> <FocusScope>
<View <View
accessibilityViewIsModal
accessible={isAndroid} accessible={isAndroid}
role="dialog" role="dialog"
aria-role="dialog" aria-role="dialog"
@@ -0,0 +1,7 @@
import {createPortalGroup} from '#/components/Portal'
const portalGroup = createPortalGroup()
export const Provider = portalGroup.Provider
export const Portal = portalGroup.Portal
export const Outlet = portalGroup.Outlet
@@ -0,0 +1,34 @@
import {createContext, type ReactNode, useContext, useMemo} from 'react'
import {Provider as PortalProvider} from '#/components/PolicyUpdateOverlay/Portal'
import {
type PolicyUpdateState,
usePolicyUpdateState,
} from '#/components/PolicyUpdateOverlay/usePolicyUpdateState'
const Context = createContext<PolicyUpdateState>({
completed: true,
complete: () => {},
})
export function usePolicyUpdateStateContext() {
const context = useContext(Context)
if (!context) {
throw new Error(
'usePolicyUpdateStateContext must be used within a PolicyUpdateProvider',
)
}
return context
}
export function Provider({children}: {children?: ReactNode}) {
const state = usePolicyUpdateState()
return (
<PortalProvider>
<Context.Provider value={useMemo(() => state, [state])}>
{children}
</Context.Provider>
</PortalProvider>
)
}
+6 -8
View File
@@ -3,18 +3,16 @@ import {View} from 'react-native'
import {isIOS} from '#/platform/detection' import {isIOS} from '#/platform/detection'
import {atoms as a} from '#/alf' import {atoms as a} from '#/alf'
import {FullWindowOverlay} from '#/components/FullWindowOverlay' import {FullWindowOverlay} from '#/components/FullWindowOverlay'
import {usePolicyUpdateStateContext} from '#/components/PolicyUpdateOverlay/context'
import {Portal} from '#/components/PolicyUpdateOverlay/Portal'
import {Content} from '#/components/PolicyUpdateOverlay/updates/202508' import {Content} from '#/components/PolicyUpdateOverlay/updates/202508'
import {usePolicyUpdateState} from '#/components/PolicyUpdateOverlay/usePolicyUpdateState'
import {createPortalGroup} from '#/components/Portal'
const portalGroup = createPortalGroup() export {Provider} from '#/components/PolicyUpdateOverlay/context'
export {usePolicyUpdateStateContext} from '#/components/PolicyUpdateOverlay/context'
export const Provider = portalGroup.Provider export {Outlet} from '#/components/PolicyUpdateOverlay/Portal'
export const Portal = portalGroup.Portal
export const Outlet = portalGroup.Outlet
export function PolicyUpdateOverlay() { export function PolicyUpdateOverlay() {
const state = usePolicyUpdateState() const state = usePolicyUpdateStateContext()
/* /*
* See `window.clearNux` example in `/state/queries/nuxs` for a way to clear * See `window.clearNux` example in `/state/queries/nuxs` for a way to clear
+13 -3
View File
@@ -31,7 +31,10 @@ import {InAppBrowserConsentDialog} from '#/components/dialogs/InAppBrowserConsen
import {LinkWarningDialog} from '#/components/dialogs/LinkWarning' import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
import {MutedWordsDialog} from '#/components/dialogs/MutedWords' import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
import {SigninDialog} from '#/components/dialogs/Signin' import {SigninDialog} from '#/components/dialogs/Signin'
import {Outlet as PolicyUpdateOverlayPortal} from '#/components/PolicyUpdateOverlay' import {
Outlet as PolicyUpdateOverlayPortalOutlet,
usePolicyUpdateStateContext,
} from '#/components/PolicyUpdateOverlay'
import {Outlet as PortalOutlet} from '#/components/Portal' import {Outlet as PortalOutlet} from '#/components/Portal'
import {RoutesContainer, TabsNavigator} from '#/Navigation' import {RoutesContainer, TabsNavigator} from '#/Navigation'
import {BottomSheetOutlet} from '../../../modules/bottom-sheet' import {BottomSheetOutlet} from '../../../modules/bottom-sheet'
@@ -46,6 +49,7 @@ function ShellInner() {
const setIsDrawerOpen = useSetDrawerOpen() const setIsDrawerOpen = useSetDrawerOpen()
const winDim = useWindowDimensions() const winDim = useWindowDimensions()
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
const policyUpdateState = usePolicyUpdateStateContext()
const renderDrawerContent = useCallback(() => <DrawerContent />, []) const renderDrawerContent = useCallback(() => <DrawerContent />, [])
const onOpenDrawer = useCallback( const onOpenDrawer = useCallback(
@@ -152,6 +156,7 @@ function ShellInner() {
</Drawer> </Drawer>
</ErrorBoundary> </ErrorBoundary>
</View> </View>
<Composer winHeight={winDim.height} /> <Composer winHeight={winDim.height} />
<ModalsContainer /> <ModalsContainer />
<MutedWordsDialog /> <MutedWordsDialog />
@@ -161,11 +166,16 @@ function ShellInner() {
<InAppBrowserConsentDialog /> <InAppBrowserConsentDialog />
<LinkWarningDialog /> <LinkWarningDialog />
<Lightbox /> <Lightbox />
{/* Until policy update has been completed by the user, don't render anything that is portaled */}
{policyUpdateState.completed && (
<>
<PortalOutlet /> <PortalOutlet />
<BottomSheetOutlet /> <BottomSheetOutlet />
</>
)}
{/* MUST BE LAST */} <PolicyUpdateOverlayPortalOutlet />
<PolicyUpdateOverlayPortal />
</> </>
) )
} }
+2 -3
View File
@@ -22,7 +22,7 @@ import {EmailDialog} from '#/components/dialogs/EmailDialog'
import {LinkWarningDialog} from '#/components/dialogs/LinkWarning' import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
import {MutedWordsDialog} from '#/components/dialogs/MutedWords' import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
import {SigninDialog} from '#/components/dialogs/Signin' import {SigninDialog} from '#/components/dialogs/Signin'
import {Outlet as PolicyUpdateOverlayPortal} from '#/components/PolicyUpdateOverlay' import {Outlet as PolicyUpdateOverlayPortalOutlet} from '#/components/PolicyUpdateOverlay'
import {Outlet as PortalOutlet} from '#/components/Portal' import {Outlet as PortalOutlet} from '#/components/Portal'
import {FlatNavigator, RoutesContainer} from '#/Navigation' import {FlatNavigator, RoutesContainer} from '#/Navigation'
import {Composer} from './Composer.web' import {Composer} from './Composer.web'
@@ -115,8 +115,7 @@ function ShellInner() {
</> </>
)} )}
{/* MUST BE LAST */} <PolicyUpdateOverlayPortalOutlet />
<PolicyUpdateOverlayPortal />
</> </>
) )
} }