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
+55 -55
View File
@@ -138,49 +138,51 @@ function InnerApp() {
// Resets the entire tree below when it changes:
key={currentAccount?.did}>
<QueryProvider currentDid={currentAccount?.did}>
<StatsigProvider>
<AgeAssuranceProvider>
<ComposerProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<HomeBadgeProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<ProgressGuideProvider>
<ServiceAccountManager>
<HideBottomBarBorderProvider>
<GestureHandlerRootView
style={s.h100pct}>
<GlobalGestureEventsProvider>
<IntentDialogProvider>
<TestCtrls />
<Shell />
<NuxDialogs />
</IntentDialogProvider>
</GlobalGestureEventsProvider>
</GestureHandlerRootView>
</HideBottomBarBorderProvider>
</ServiceAccountManager>
</ProgressGuideProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HomeBadgeProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</ComposerProvider>
</AgeAssuranceProvider>
</StatsigProvider>
<PolicyUpdateOverlayProvider>
<StatsigProvider>
<AgeAssuranceProvider>
<ComposerProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<HomeBadgeProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<ProgressGuideProvider>
<ServiceAccountManager>
<HideBottomBarBorderProvider>
<GestureHandlerRootView
style={s.h100pct}>
<GlobalGestureEventsProvider>
<IntentDialogProvider>
<TestCtrls />
<Shell />
<NuxDialogs />
</IntentDialogProvider>
</GlobalGestureEventsProvider>
</GestureHandlerRootView>
</HideBottomBarBorderProvider>
</ServiceAccountManager>
</ProgressGuideProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HomeBadgeProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</ComposerProvider>
</AgeAssuranceProvider>
</StatsigProvider>
</PolicyUpdateOverlayProvider>
</QueryProvider>
</React.Fragment>
</VideoVolumeProvider>
@@ -221,18 +223,16 @@ function App() {
<ModalStateProvider>
<DialogStateProvider>
<LightboxStateProvider>
<PolicyUpdateOverlayProvider>
<PortalProvider>
<BottomSheetProvider>
<StarterPackProvider>
<SafeAreaProvider
initialMetrics={initialWindowMetrics}>
<InnerApp />
</SafeAreaProvider>
</StarterPackProvider>
</BottomSheetProvider>
</PortalProvider>
</PolicyUpdateOverlayProvider>
<PortalProvider>
<BottomSheetProvider>
<StarterPackProvider>
<SafeAreaProvider
initialMetrics={initialWindowMetrics}>
<InnerApp />
</SafeAreaProvider>
</StarterPackProvider>
</BottomSheetProvider>
</PortalProvider>
</LightboxStateProvider>
</DialogStateProvider>
</ModalStateProvider>
+46 -46
View File
@@ -118,45 +118,47 @@ function InnerApp() {
// Resets the entire tree below when it changes:
key={currentAccount?.did}>
<QueryProvider currentDid={currentAccount?.did}>
<StatsigProvider>
<AgeAssuranceProvider>
<ComposerProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<HomeBadgeProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<SafeAreaProvider>
<ProgressGuideProvider>
<ServiceConfigProvider>
<HideBottomBarBorderProvider>
<IntentDialogProvider>
<Shell />
<NuxDialogs />
</IntentDialogProvider>
</HideBottomBarBorderProvider>
</ServiceConfigProvider>
</ProgressGuideProvider>
</SafeAreaProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HomeBadgeProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</ComposerProvider>
</AgeAssuranceProvider>
</StatsigProvider>
<PolicyUpdateOverlayProvider>
<StatsigProvider>
<AgeAssuranceProvider>
<ComposerProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<HomeBadgeProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<SafeAreaProvider>
<ProgressGuideProvider>
<ServiceConfigProvider>
<HideBottomBarBorderProvider>
<IntentDialogProvider>
<Shell />
<NuxDialogs />
</IntentDialogProvider>
</HideBottomBarBorderProvider>
</ServiceConfigProvider>
</ProgressGuideProvider>
</SafeAreaProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HomeBadgeProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</ComposerProvider>
</AgeAssuranceProvider>
</StatsigProvider>
</PolicyUpdateOverlayProvider>
</QueryProvider>
<ToastContainer />
</React.Fragment>
@@ -197,13 +199,11 @@ function App() {
<ModalStateProvider>
<DialogStateProvider>
<LightboxStateProvider>
<PolicyUpdateOverlayProvider>
<PortalProvider>
<StarterPackProvider>
<InnerApp />
</StarterPackProvider>
</PortalProvider>
</PolicyUpdateOverlayProvider>
<PortalProvider>
<StarterPackProvider>
<InnerApp />
</StarterPackProvider>
</PortalProvider>
</LightboxStateProvider>
</DialogStateProvider>
</ModalStateProvider>
@@ -109,6 +109,7 @@ export function Overlay({
<FocusScope>
<View
accessibilityViewIsModal
accessible={isAndroid}
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 {atoms as a} from '#/alf'
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 {usePolicyUpdateState} from '#/components/PolicyUpdateOverlay/usePolicyUpdateState'
import {createPortalGroup} from '#/components/Portal'
const portalGroup = createPortalGroup()
export const Provider = portalGroup.Provider
export const Portal = portalGroup.Portal
export const Outlet = portalGroup.Outlet
export {Provider} from '#/components/PolicyUpdateOverlay/context'
export {usePolicyUpdateStateContext} from '#/components/PolicyUpdateOverlay/context'
export {Outlet} from '#/components/PolicyUpdateOverlay/Portal'
export function PolicyUpdateOverlay() {
const state = usePolicyUpdateState()
const state = usePolicyUpdateStateContext()
/*
* See `window.clearNux` example in `/state/queries/nuxs` for a way to clear
+15 -5
View File
@@ -31,7 +31,10 @@ import {InAppBrowserConsentDialog} from '#/components/dialogs/InAppBrowserConsen
import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
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 {RoutesContainer, TabsNavigator} from '#/Navigation'
import {BottomSheetOutlet} from '../../../modules/bottom-sheet'
@@ -46,6 +49,7 @@ function ShellInner() {
const setIsDrawerOpen = useSetDrawerOpen()
const winDim = useWindowDimensions()
const insets = useSafeAreaInsets()
const policyUpdateState = usePolicyUpdateStateContext()
const renderDrawerContent = useCallback(() => <DrawerContent />, [])
const onOpenDrawer = useCallback(
@@ -152,6 +156,7 @@ function ShellInner() {
</Drawer>
</ErrorBoundary>
</View>
<Composer winHeight={winDim.height} />
<ModalsContainer />
<MutedWordsDialog />
@@ -161,11 +166,16 @@ function ShellInner() {
<InAppBrowserConsentDialog />
<LinkWarningDialog />
<Lightbox />
<PortalOutlet />
<BottomSheetOutlet />
{/* MUST BE LAST */}
<PolicyUpdateOverlayPortal />
{/* Until policy update has been completed by the user, don't render anything that is portaled */}
{policyUpdateState.completed && (
<>
<PortalOutlet />
<BottomSheetOutlet />
</>
)}
<PolicyUpdateOverlayPortalOutlet />
</>
)
}
+2 -3
View File
@@ -22,7 +22,7 @@ import {EmailDialog} from '#/components/dialogs/EmailDialog'
import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
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 {FlatNavigator, RoutesContainer} from '#/Navigation'
import {Composer} from './Composer.web'
@@ -115,8 +115,7 @@ function ShellInner() {
</>
)}
{/* MUST BE LAST */}
<PolicyUpdateOverlayPortal />
<PolicyUpdateOverlayPortalOutlet />
</>
)
}