Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork

fix drawer layout on mobile web (#9618)

authored by samuel.fm and committed by GitHub 0aaf11aa 9cfa7d0b

Changed files
+50 -29
src
+11 -3
src/Navigation.tsx
··· 5 5 import {msg} from '@lingui/macro' 6 6 import { 7 7 type BottomTabBarProps, 8 - type BottomTabNavigatorProps, 9 8 createBottomTabNavigator, 10 9 } from '@react-navigation/bottom-tabs' 11 10 import { ··· 637 636 * The TabsNavigator is used by native mobile to represent the routes 638 637 * in 3 distinct tab-stacks with a different root screen on each. 639 638 */ 640 - function TabsNavigator({layout}: {layout: BottomTabNavigatorProps['layout']}) { 639 + function TabsNavigator({ 640 + layout, 641 + }: { 642 + layout: React.ComponentProps<typeof Tab.Navigator>['layout'] 643 + }) { 641 644 const tabBar = useCallback( 642 645 (props: JSX.IntrinsicAttributes & BottomTabBarProps) => ( 643 646 <BottomBar {...props} /> ··· 759 762 * The FlatNavigator is used by Web to represent the routes 760 763 * in a single ("flat") stack. 761 764 */ 762 - const FlatNavigator = () => { 765 + const FlatNavigator = ({ 766 + layout, 767 + }: { 768 + layout: React.ComponentProps<typeof Flat.Navigator>['layout'] 769 + }) => { 763 770 const t = useTheme() 764 771 const numUnread = useUnreadNotifications() 765 772 const screenListeners = useWebScrollRestoration() ··· 767 774 768 775 return ( 769 776 <Flat.Navigator 777 + layout={layout} 770 778 screenListeners={screenListeners} 771 779 screenOptions={screenOptions(t)}> 772 780 <Flat.Screen
+39 -26
src/view/shell/index.web.tsx
··· 1 - import {useEffect, useLayoutEffect, useState} from 'react' 1 + import {useCallback, useEffect, useLayoutEffect, useState} from 'react' 2 2 import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native' 3 3 import {msg} from '@lingui/macro' 4 4 import {useLingui} from '@lingui/react' ··· 6 6 import {RemoveScrollBar} from 'react-remove-scroll-bar' 7 7 8 8 import {useIntentHandler} from '#/lib/hooks/useIntentHandler' 9 - import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 10 9 import {type NavigationProp} from '#/lib/routes/types' 11 10 import {useSession} from '#/state/session' 12 11 import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' ··· 17 16 import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' 18 17 import {Deactivated} from '#/screens/Deactivated' 19 18 import {Takendown} from '#/screens/Takendown' 20 - import {atoms as a, select, useTheme} from '#/alf' 19 + import {atoms as a, select, useBreakpoints, useTheme} from '#/alf' 21 20 import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog' 22 21 import {EmailDialog} from '#/components/dialogs/EmailDialog' 23 22 import {LinkWarningDialog} from '#/components/dialogs/LinkWarning' ··· 39 38 import {DrawerContent} from './Drawer' 40 39 41 40 function ShellInner() { 42 - const t = useTheme() 43 - const isDrawerOpen = useIsDrawerOpen() 44 - const setDrawerOpen = useSetDrawerOpen() 45 - const {isDesktop} = useWebMediaQueries() 46 41 const navigator = useNavigation<NavigationProp>() 47 42 const closeAllActiveElements = useCloseAllActiveElements() 48 - const {_} = useLingui() 49 - const showDrawer = !isDesktop && isDrawerOpen 50 - const [showDrawerDelayedExit, setShowDrawerDelayedExit] = useState(showDrawer) 51 43 const {state: policyUpdateState} = usePolicyUpdateContext() 52 44 const welcomeModalControl = useWelcomeModal() 53 45 54 - useLayoutEffect(() => { 55 - if (showDrawer !== showDrawerDelayedExit) { 56 - if (showDrawer) { 57 - setShowDrawerDelayedExit(true) 58 - } else { 59 - const timeout = setTimeout(() => { 60 - setShowDrawerDelayedExit(false) 61 - }, 160) 62 - return () => clearTimeout(timeout) 63 - } 64 - } 65 - }, [showDrawer, showDrawerDelayedExit]) 66 - 67 46 useComposerKeyboardShortcut() 68 47 useIntentHandler() 69 48 ··· 74 53 return unsubscribe 75 54 }, [navigator, closeAllActiveElements]) 76 55 56 + const drawerLayout = useCallback( 57 + ({children}: {children: React.ReactNode}) => ( 58 + <DrawerLayout>{children}</DrawerLayout> 59 + ), 60 + [], 61 + ) 77 62 return ( 78 63 <> 79 64 <ErrorBoundary> 80 - <FlatNavigator /> 65 + <FlatNavigator layout={drawerLayout} /> 81 66 </ErrorBoundary> 82 67 <Composer winHeight={0} /> 83 68 <ModalsContainer /> ··· 100 85 </> 101 86 )} 102 87 88 + <PolicyUpdateOverlayPortalOutlet /> 89 + </> 90 + ) 91 + } 92 + 93 + function DrawerLayout({children}: {children: React.ReactNode}) { 94 + const t = useTheme() 95 + const isDrawerOpen = useIsDrawerOpen() 96 + const setDrawerOpen = useSetDrawerOpen() 97 + const {gtTablet} = useBreakpoints() 98 + const {_} = useLingui() 99 + const showDrawer = !gtTablet && isDrawerOpen 100 + const [showDrawerDelayedExit, setShowDrawerDelayedExit] = useState(showDrawer) 101 + 102 + useLayoutEffect(() => { 103 + if (showDrawer !== showDrawerDelayedExit) { 104 + if (showDrawer) { 105 + setShowDrawerDelayedExit(true) 106 + } else { 107 + const timeout = setTimeout(() => { 108 + setShowDrawerDelayedExit(false) 109 + }, 160) 110 + return () => clearTimeout(timeout) 111 + } 112 + } 113 + }, [showDrawer, showDrawerDelayedExit]) 114 + 115 + return ( 116 + <> 117 + {children} 103 118 {showDrawerDelayedExit && ( 104 119 <> 105 120 <RemoveScrollBar /> ··· 137 152 </TouchableWithoutFeedback> 138 153 </> 139 154 )} 140 - 141 - <PolicyUpdateOverlayPortalOutlet /> 142 155 </> 143 156 ) 144 157 }