Fix drawer behaviors

This commit is contained in:
Paul Frazee
2023-03-10 18:22:58 -06:00
parent d4d1fb820b
commit 320d69920e
15 changed files with 155 additions and 141 deletions
+2
View File
@@ -1,3 +1,5 @@
import 'react-native-gesture-handler' // must be first
import {LogBox} from 'react-native' import {LogBox} from 'react-native'
LogBox.ignoreLogs(['Require cycle:']) // suppress require-cycle warnings, it's fine LogBox.ignoreLogs(['Require cycle:']) // suppress require-cycle warnings, it's fine
+3 -1
View File
@@ -70,14 +70,16 @@
"react-native": "0.71.3", "react-native": "0.71.3",
"react-native-appstate-hook": "^1.0.6", "react-native-appstate-hook": "^1.0.6",
"react-native-background-fetch": "^4.1.8", "react-native-background-fetch": "^4.1.8",
"react-native-drawer-layout": "^3.2.0",
"react-native-fast-image": "^8.6.3", "react-native-fast-image": "^8.6.3",
"react-native-fs": "^2.20.0", "react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.9.0",
"react-native-haptic-feedback": "^1.14.0", "react-native-haptic-feedback": "^1.14.0",
"react-native-image-crop-picker": "^0.38.1", "react-native-image-crop-picker": "^0.38.1",
"react-native-inappbrowser-reborn": "^3.6.3", "react-native-inappbrowser-reborn": "^3.6.3",
"react-native-linear-gradient": "^2.6.2", "react-native-linear-gradient": "^2.6.2",
"react-native-progress": "^5.0.0", "react-native-progress": "^5.0.0",
"react-native-reanimated": "^2.9.1", "react-native-reanimated": "~2.14.4",
"react-native-root-siblings": "^4.1.1", "react-native-root-siblings": "^4.1.1",
"react-native-safe-area-context": "^4.4.1", "react-native-safe-area-context": "^4.4.1",
"react-native-screens": "^3.13.1", "react-native-screens": "^3.13.1",
+34
View File
@@ -8,6 +8,22 @@ export function getCurrentRoute(state: State) {
return node return node
} }
export function isStateAtTabRoot(state: State | undefined) {
if (!state) {
// NOTE
// if state is not defined it's because init is occuring
// and therefore we can safely assume we're at root
// -prf
return true
}
const currentRoute = getCurrentRoute(state)
return (
isTab(currentRoute.name, 'Home') ||
isTab(currentRoute.name, 'Search') ||
isTab(currentRoute.name, 'Notifications')
)
}
export function isTab(current: string, route: string) { export function isTab(current: string, route: string) {
// NOTE // NOTE
// our tab routes can be variously referenced by 3 different names // our tab routes can be variously referenced by 3 different names
@@ -19,3 +35,21 @@ export function isTab(current: string, route: string) {
current === `${route}Inner` current === `${route}Inner`
) )
} }
export enum TabState {
InsideAtRoot,
Inside,
Outside,
}
export function getTabState(state: State | undefined, tab: string): TabState {
if (!state) {
return TabState.Outside
}
const currentRoute = getCurrentRoute(state)
if (isTab(currentRoute.name, tab)) {
return TabState.InsideAtRoot
} else if (isTab(state.routes[state.index || 0].name, tab)) {
return TabState.Inside
}
return TabState.Outside
}
+1 -19
View File
@@ -20,26 +20,14 @@ export type HomeTabNavigatorParams = CommonNavigatorParams & {
Home: undefined Home: undefined
} }
export type HomeDrawerNavigatorParams = {
HomeInner: undefined
}
export type SearchTabNavigatorParams = CommonNavigatorParams & { export type SearchTabNavigatorParams = CommonNavigatorParams & {
Search: undefined Search: undefined
} }
export type SearchDrawerNavigatorParams = {
SearchInner: undefined
}
export type NotificationsTabNavigatorParams = CommonNavigatorParams & { export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
Notifications: undefined Notifications: undefined
} }
export type NotificationsDrawerNavigatorParams = {
NotificationsInner: undefined
}
export type AllNavigatorParams = CommonNavigatorParams & { export type AllNavigatorParams = CommonNavigatorParams & {
HomeTab: undefined HomeTab: undefined
Home: undefined Home: undefined
@@ -53,13 +41,7 @@ export type AllNavigatorParams = CommonNavigatorParams & {
// this isn't strictly correct but it should be close enough // this isn't strictly correct but it should be close enough
// a TS wizard might be able to get this 100% // a TS wizard might be able to get this 100%
// -prf // -prf
export type NavigationProp = NativeStackNavigationProp< export type NavigationProp = NativeStackNavigationProp<AllNavigatorParams>
CommonNavigatorParams & {
HomeTab: undefined
NotificationsTab: undefined
SearchTab: undefined
}
>
export type State = export type State =
| NavigationState | NavigationState
+3 -50
View File
@@ -5,16 +5,12 @@ import {
StackActions, StackActions,
} from '@react-navigation/native' } from '@react-navigation/native'
import {createNativeStackNavigator} from '@react-navigation/native-stack' import {createNativeStackNavigator} from '@react-navigation/native-stack'
import {createDrawerNavigator} from '@react-navigation/drawer'
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs' import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import { import {
HomeTabNavigatorParams, HomeTabNavigatorParams,
HomeDrawerNavigatorParams,
SearchTabNavigatorParams, SearchTabNavigatorParams,
SearchDrawerNavigatorParams,
NotificationsTabNavigatorParams, NotificationsTabNavigatorParams,
NotificationsDrawerNavigatorParams,
AllNavigatorParams, AllNavigatorParams,
State, State,
} from 'lib/routes/types' } from 'lib/routes/types'
@@ -38,12 +34,8 @@ import {LogScreen} from './view/screens/Log'
const navigationRef = createNavigationContainerRef<AllNavigatorParams>() const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
const HomeDrawer = createDrawerNavigator<HomeDrawerNavigatorParams>()
const HomeTab = createNativeStackNavigator<HomeTabNavigatorParams>() const HomeTab = createNativeStackNavigator<HomeTabNavigatorParams>()
const SearchDrawer = createDrawerNavigator<SearchDrawerNavigatorParams>()
const SearchTab = createNativeStackNavigator<SearchTabNavigatorParams>() const SearchTab = createNativeStackNavigator<SearchTabNavigatorParams>()
const NotificationsDrawer =
createDrawerNavigator<NotificationsDrawerNavigatorParams>()
const NotificationsTab = const NotificationsTab =
createNativeStackNavigator<NotificationsTabNavigatorParams>() createNativeStackNavigator<NotificationsTabNavigatorParams>()
const Tab = createBottomTabNavigator() const Tab = createBottomTabNavigator()
@@ -78,11 +70,8 @@ function r(pattern: string): Route {
} }
const ROUTES: Record<string, Route> = { const ROUTES: Record<string, Route> = {
Home: r('/'), Home: r('/'),
HomeInner: r('/'),
Search: r('/search'), Search: r('/search'),
SearchInner: r('/search'),
Notifications: r('/notifications'), Notifications: r('/notifications'),
NotificationsInner: r('/notifications'),
Settings: r('/settings'), Settings: r('/settings'),
Profile: r('/profile/:name'), Profile: r('/profile/:name'),
ProfileFollowers: r('/profile/:name/followers'), ProfileFollowers: r('/profile/:name/followers'),
@@ -171,17 +160,6 @@ function commonScreens(Stack: typeof HomeTab) {
) )
} }
function HomeDrawerNavigator() {
const drawerContent = React.useCallback(props => <Drawer {...props} />, [])
return (
<HomeDrawer.Navigator
drawerContent={drawerContent}
screenOptions={{swipeEdgeWidth: 300, headerShown: false}}>
<HomeDrawer.Screen name="HomeInner" component={HomeScreen} />
</HomeDrawer.Navigator>
)
}
function HomeTabNavigator() { function HomeTabNavigator() {
return ( return (
<HomeTab.Navigator <HomeTab.Navigator
@@ -190,23 +168,12 @@ function HomeTabNavigator() {
fullScreenGestureEnabled: true, fullScreenGestureEnabled: true,
headerShown: false, headerShown: false,
}}> }}>
<HomeTab.Screen name="Home" component={HomeDrawerNavigator} /> <HomeTab.Screen name="Home" component={HomeScreen} />
{commonScreens(HomeTab)} {commonScreens(HomeTab)}
</HomeTab.Navigator> </HomeTab.Navigator>
) )
} }
function SearchDrawerNavigator() {
const drawerContent = React.useCallback(props => <Drawer {...props} />, [])
return (
<SearchDrawer.Navigator
drawerContent={drawerContent}
screenOptions={{swipeEdgeWidth: 300, headerShown: false}}>
<SearchDrawer.Screen name="SearchInner" component={SearchScreen} />
</SearchDrawer.Navigator>
)
}
function SearchTabNavigator() { function SearchTabNavigator() {
return ( return (
<SearchTab.Navigator <SearchTab.Navigator
@@ -215,26 +182,12 @@ function SearchTabNavigator() {
fullScreenGestureEnabled: true, fullScreenGestureEnabled: true,
headerShown: false, headerShown: false,
}}> }}>
<SearchTab.Screen name="Search" component={SearchDrawerNavigator} /> <SearchTab.Screen name="Search" component={SearchScreen} />
{commonScreens(SearchTab as typeof HomeTab)} {commonScreens(SearchTab as typeof HomeTab)}
</SearchTab.Navigator> </SearchTab.Navigator>
) )
} }
function NotificationsDrawerNavigator() {
const drawerContent = React.useCallback(props => <Drawer {...props} />, [])
return (
<NotificationsDrawer.Navigator
drawerContent={drawerContent}
screenOptions={{swipeEdgeWidth: 300, headerShown: false}}>
<NotificationsDrawer.Screen
name="NotificationsInner"
component={NotificationsScreen}
/>
</NotificationsDrawer.Navigator>
)
}
function NotificationsTabNavigator() { function NotificationsTabNavigator() {
return ( return (
<NotificationsTab.Navigator <NotificationsTab.Navigator
@@ -245,7 +198,7 @@ function NotificationsTabNavigator() {
}}> }}>
<NotificationsTab.Screen <NotificationsTab.Screen
name="Notifications" name="Notifications"
component={NotificationsDrawerNavigator} component={NotificationsScreen}
/> />
{commonScreens(NotificationsTab as typeof HomeTab)} {commonScreens(NotificationsTab as typeof HomeTab)}
</NotificationsTab.Navigator> </NotificationsTab.Navigator>
+7 -3
View File
@@ -117,7 +117,7 @@ export interface ComposerOpts {
export class ShellUiModel { export class ShellUiModel {
darkMode = false darkMode = false
minimalShellMode = false minimalShellMode = false
isMainMenuOpen = false isDrawerOpen = false
isModalActive = false isModalActive = false
activeModals: Modal[] = [] activeModals: Modal[] = []
isLightboxActive = false isLightboxActive = false
@@ -156,8 +156,12 @@ export class ShellUiModel {
this.minimalShellMode = v this.minimalShellMode = v
} }
setMainMenuOpen(v: boolean) { openDrawer() {
this.isMainMenuOpen = v this.isDrawerOpen = true
}
closeDrawer() {
this.isDrawerOpen = false
} }
openModal(modal: Modal) { openModal(modal: Modal) {
+2 -2
View File
@@ -51,7 +51,7 @@ export const Link = observer(function Link({
if (noFeedback) { if (noFeedback) {
return ( return (
<TouchableWithoutFeedback delayPressIn={50} {...props}> <TouchableWithoutFeedback {...props}>
<View style={style} {...props}> <View style={style} {...props}>
{children ? children : <Text>{title || 'link'}</Text>} {children ? children : <Text>{title || 'link'}</Text>}
</View> </View>
@@ -59,7 +59,7 @@ export const Link = observer(function Link({
) )
} }
return ( return (
<TouchableOpacity delayPressIn={50} style={style} {...props}> <TouchableOpacity style={style} {...props}>
{children ? children : <Text>{title || 'link'}</Text>} {children ? children : <Text>{title || 'link'}</Text>}
</TouchableOpacity> </TouchableOpacity>
) )
+2 -2
View File
@@ -34,8 +34,8 @@ export const ViewHeader = observer(function ViewHeader({
const onPressMenu = React.useCallback(() => { const onPressMenu = React.useCallback(() => {
track('ViewHeader:MenuButtonClicked') track('ViewHeader:MenuButtonClicked')
navigation.dispatch(DrawerActions.openDrawer()) store.shell.openDrawer()
}, [track, navigation]) }, [track, store])
if (typeof canGoBack === 'undefined') { if (typeof canGoBack === 'undefined') {
canGoBack = navigation.canGoBack() canGoBack = navigation.canGoBack()
+2 -5
View File
@@ -3,10 +3,7 @@ import {FlatList, View} from 'react-native'
import {useFocusEffect, useIsFocused} from '@react-navigation/native' import {useFocusEffect, useIsFocused} from '@react-navigation/native'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import useAppState from 'react-native-appstate-hook' import useAppState from 'react-native-appstate-hook'
import { import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
NativeStackScreenProps,
HomeDrawerNavigatorParams,
} from 'lib/routes/types'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {Feed} from '../com/posts/Feed' import {Feed} from '../com/posts/Feed'
import {LoadLatestBtn} from '../com/util/LoadLatestBtn' import {LoadLatestBtn} from '../com/util/LoadLatestBtn'
@@ -20,7 +17,7 @@ import {ComposeIcon2} from 'lib/icons'
const HEADER_HEIGHT = 42 const HEADER_HEIGHT = 42
type Props = NativeStackScreenProps<HomeDrawerNavigatorParams, 'HomeInner'> type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export const HomeScreen = observer(function Home(_opts: Props) { export const HomeScreen = observer(function Home(_opts: Props) {
const store = useStores() const store = useStores()
const onMainScroll = useOnMainScroll(store) const onMainScroll = useOnMainScroll(store)
+3 -3
View File
@@ -4,7 +4,7 @@ import {useFocusEffect} from '@react-navigation/native'
import useAppState from 'react-native-appstate-hook' import useAppState from 'react-native-appstate-hook'
import { import {
NativeStackScreenProps, NativeStackScreenProps,
NotificationsDrawerNavigatorParams, NotificationsTabNavigatorParams,
} from 'lib/routes/types' } from 'lib/routes/types'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import {Feed} from '../com/notifications/Feed' import {Feed} from '../com/notifications/Feed'
@@ -16,8 +16,8 @@ import {useAnalytics} from 'lib/analytics'
const NOTIFICATIONS_POLL_INTERVAL = 15e3 const NOTIFICATIONS_POLL_INTERVAL = 15e3
type Props = NativeStackScreenProps< type Props = NativeStackScreenProps<
NotificationsDrawerNavigatorParams, NotificationsTabNavigatorParams,
'NotificationsInner' 'Notifications'
> >
export const NotificationsScreen = ({}: Props) => { export const NotificationsScreen = ({}: Props) => {
const store = useStores() const store = useStores()
+2 -2
View File
@@ -15,7 +15,7 @@ import {
import {ScrollView} from '../com/util/Views' import {ScrollView} from '../com/util/Views'
import { import {
NativeStackScreenProps, NativeStackScreenProps,
SearchDrawerNavigatorParams, SearchTabNavigatorParams,
} from 'lib/routes/types' } from 'lib/routes/types'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {UserAvatar} from '../com/util/UserAvatar' import {UserAvatar} from '../com/util/UserAvatar'
@@ -34,7 +34,7 @@ import {useAnalytics} from 'lib/analytics'
const MENU_HITSLOP = {left: 10, top: 10, right: 30, bottom: 10} const MENU_HITSLOP = {left: 10, top: 10, right: 30, bottom: 10}
const FIVE_MIN = 5 * 60 * 1e3 const FIVE_MIN = 5 * 60 * 1e3
type Props = NativeStackScreenProps<SearchDrawerNavigatorParams, 'SearchInner'> type Props = NativeStackScreenProps<SearchTabNavigatorParams, 'Search'>
export const SearchScreen = observer<Props>(({}: Props) => { export const SearchScreen = observer<Props>(({}: Props) => {
const pal = usePalette('default') const pal = usePalette('default')
const store = useStores() const store = useStores()
+4 -4
View File
@@ -26,7 +26,7 @@ import {
} from 'lib/icons' } from 'lib/icons'
import {colors} from 'lib/styles' import {colors} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {getCurrentRoute, isTab} from 'lib/routes/helpers' import {getCurrentRoute, isTab, getTabState, TabState} from 'lib/routes/helpers'
export const BottomBar = observer(({navigation}: BottomTabBarProps) => { export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
const store = useStores() const store = useStores()
@@ -60,10 +60,10 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
(tab: string) => { (tab: string) => {
track(`MobileShell:${tab}ButtonPressed`) track(`MobileShell:${tab}ButtonPressed`)
const state = navigation.getState() const state = navigation.getState()
const currentRoute = getCurrentRoute(state) const tabState = getTabState(state, tab)
if (isTab(currentRoute.name, tab)) { if (tabState === TabState.InsideAtRoot) {
store.emitScreenSoftReset() store.emitScreenSoftReset()
} else if (isTab(state.routes[state.index].name, tab)) { } else if (tabState === TabState.Inside) {
navigation.dispatch(StackActions.popToTop()) navigation.dispatch(StackActions.popToTop())
} else { } else {
navigation.navigate(`${tab}Tab`) navigation.navigate(`${tab}Tab`)
+30 -29
View File
@@ -9,10 +9,10 @@ import {
ViewStyle, ViewStyle,
} from 'react-native' } from 'react-native'
import { import {
DrawerContentComponentProps, useNavigation,
useDrawerStatus, useNavigationState,
} from '@react-navigation/drawer' StackActions,
import {StackActions} from '@react-navigation/native' } from '@react-navigation/native'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import { import {
FontAwesomeIcon, FontAwesomeIcon,
@@ -38,38 +38,44 @@ import {useTheme} from 'lib/ThemeContext'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useAnalytics} from 'lib/analytics' import {useAnalytics} from 'lib/analytics'
import {pluralize} from 'lib/strings/helpers' import {pluralize} from 'lib/strings/helpers'
import {getCurrentRoute, isTab} from 'lib/routes/helpers' import {getCurrentRoute, isTab, getTabState, TabState} from 'lib/routes/helpers'
import {NavigationProp} from 'lib/routes/types'
export const Drawer = observer(({navigation}: DrawerContentComponentProps) => { export const DrawerContent = observer(() => {
const theme = useTheme() const theme = useTheme()
const pal = usePalette('default') const pal = usePalette('default')
const store = useStores() const store = useStores()
const navigation = useNavigation<NavigationProp>()
const {track} = useAnalytics() const {track} = useAnalytics()
const isDrawerOpen = useDrawerStatus() === 'open' const {isAtHome, isAtSearch, isAtNotifications} = useNavigationState(
state => {
const currentRoute = state ? getCurrentRoute(state) : false
return {
isAtHome: currentRoute ? isTab(currentRoute.name, 'Home') : true,
isAtSearch: currentRoute ? isTab(currentRoute.name, 'Search') : false,
isAtNotifications: currentRoute
? isTab(currentRoute.name, 'Notifications')
: false,
}
},
)
// events // events
// = // =
React.useEffect(() => {
console.log('Drawer', isDrawerOpen ? 'minimizing' : 'unminimizing', 'shell')
store.shell.setMinimalShellMode(isDrawerOpen)
}, [isDrawerOpen, store])
const onPressTab = React.useCallback( const onPressTab = React.useCallback(
(tab: string) => { (tab: string) => {
track('Menu:ItemClicked', {url: tab}) track('Menu:ItemClicked', {url: tab})
const state = navigation.getState() const state = navigation.getState()
navigation.closeDrawer() store.shell.closeDrawer()
const currentRoute = getCurrentRoute(state) const tabState = getTabState(state, tab)
if (isTab(currentRoute.name, tab)) { if (tabState === TabState.InsideAtRoot) {
store.emitScreenSoftReset() store.emitScreenSoftReset()
} else if (isTab(state.routes[state.index].name, tab)) { } else if (tabState === TabState.Inside) {
navigation.dispatch(StackActions.popToTop()) navigation.dispatch(StackActions.popToTop())
} else { } else {
// wait for drawer anim to finish // @ts-ignore must be Home, Search, or Notifications
setTimeout(() => { navigation.navigate(`${tab}Tab`)
navigation.navigate(`${tab}Tab`)
}, 250)
} }
}, },
[store, track, navigation], [store, track, navigation],
@@ -90,14 +96,14 @@ export const Drawer = observer(({navigation}: DrawerContentComponentProps) => {
const onPressProfile = React.useCallback(() => { const onPressProfile = React.useCallback(() => {
track('Menu:ItemClicked', {url: 'Profile'}) track('Menu:ItemClicked', {url: 'Profile'})
navigation.navigate('Profile', {name: store.me.handle}) navigation.navigate('Profile', {name: store.me.handle})
navigation.closeDrawer() store.shell.closeDrawer()
}, [navigation, track, store.me.handle]) }, [navigation, track, store.me.handle, store.shell])
const onPressSettings = React.useCallback(() => { const onPressSettings = React.useCallback(() => {
track('Menu:ItemClicked', {url: 'Settings'}) track('Menu:ItemClicked', {url: 'Settings'})
navigation.navigate('Settings') navigation.navigate('Settings')
navigation.closeDrawer() store.shell.closeDrawer()
}, [navigation, track]) }, [navigation, track, store.shell])
const onPressFeedback = () => { const onPressFeedback = () => {
track('Menu:FeedbackClicked') track('Menu:FeedbackClicked')
@@ -146,11 +152,6 @@ export const Drawer = observer(({navigation}: DrawerContentComponentProps) => {
store.shell.setDarkMode(!store.shell.darkMode) store.shell.setDarkMode(!store.shell.darkMode)
} }
const currentRoute = getCurrentRoute(navigation.getState())
const isAtHome = isTab(currentRoute.name, 'Home')
const isAtSearch = isTab(currentRoute.name, 'Search')
const isAtNotifications = isTab(currentRoute.name, 'Notifications')
return ( return (
<View <View
testID="menuView" testID="menuView"
+51 -19
View File
@@ -2,21 +2,23 @@ import React from 'react'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {StatusBar, StyleSheet, useWindowDimensions, View} from 'react-native' import {StatusBar, StyleSheet, useWindowDimensions, View} from 'react-native'
import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {Drawer} from 'react-native-drawer-layout'
import {useNavigationState} from '@react-navigation/native'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import {Login} from 'view/screens/Login' import {Login} from 'view/screens/Login'
import {ModalsContainer} from 'view/com/modals/Modal' import {ModalsContainer} from 'view/com/modals/Modal'
import {Lightbox} from 'view/com/lightbox/Lightbox' import {Lightbox} from 'view/com/lightbox/Lightbox'
import {Text} from 'view/com/util/text/Text' import {Text} from 'view/com/util/text/Text'
import {ErrorBoundary} from 'view/com/util/ErrorBoundary' import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
import {DrawerContent} from './Drawer'
import {Composer} from './Composer' import {Composer} from './Composer'
import {s} from 'lib/styles' import {s} from 'lib/styles'
import {useTheme} from 'lib/ThemeContext' import {useTheme} from 'lib/ThemeContext'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {RoutesContainer, TabsNavigator} from '../../Routes' import {RoutesContainer, TabsNavigator} from '../../Routes'
import {isStateAtTabRoot} from 'lib/routes/helpers'
export const Shell: React.FC = observer(() => { const ShellInner = observer(() => {
const theme = useTheme()
const pal = usePalette('default')
const store = useStores() const store = useStores()
const winDim = useWindowDimensions() const winDim = useWindowDimensions()
const safeAreaInsets = useSafeAreaInsets() const safeAreaInsets = useSafeAreaInsets()
@@ -24,6 +26,51 @@ export const Shell: React.FC = observer(() => {
() => ({height: '100%', paddingTop: safeAreaInsets.top}), () => ({height: '100%', paddingTop: safeAreaInsets.top}),
[safeAreaInsets], [safeAreaInsets],
) )
const renderDrawerContent = React.useCallback(() => <DrawerContent />, [])
const onOpenDrawer = React.useCallback(
() => store.shell.openDrawer(),
[store],
)
const onCloseDrawer = React.useCallback(
() => store.shell.closeDrawer(),
[store],
)
const canGoBack = useNavigationState(state => !isStateAtTabRoot(state))
return (
<>
<View style={containerPadding}>
<ErrorBoundary>
<Drawer
renderDrawerContent={renderDrawerContent}
open={store.shell.isDrawerOpen}
onOpen={onOpenDrawer}
onClose={onCloseDrawer}
swipeEdgeWidth={winDim.width}
swipeEnabled={!canGoBack}>
<TabsNavigator />
</Drawer>
</ErrorBoundary>
</View>
<ModalsContainer />
<Lightbox />
<Composer
active={store.shell.isComposerActive}
onClose={() => store.shell.closeComposer()}
winHeight={winDim.height}
replyTo={store.shell.composerOpts?.replyTo}
imagesOpen={store.shell.composerOpts?.imagesOpen}
onPost={store.shell.composerOpts?.onPost}
quote={store.shell.composerOpts?.quote}
/>
</>
)
})
export const Shell: React.FC = observer(() => {
const theme = useTheme()
const pal = usePalette('default')
const store = useStores()
if (store.hackUpgradeNeeded) { if (store.hackUpgradeNeeded) {
return ( return (
@@ -80,22 +127,7 @@ export const Shell: React.FC = observer(() => {
} }
/> />
<RoutesContainer> <RoutesContainer>
<View style={containerPadding}> <ShellInner />
<ErrorBoundary>
<TabsNavigator />
</ErrorBoundary>
</View>
<ModalsContainer />
<Lightbox />
<Composer
active={store.shell.isComposerActive}
onClose={() => store.shell.closeComposer()}
winHeight={winDim.height}
replyTo={store.shell.composerOpts?.replyTo}
imagesOpen={store.shell.composerOpts?.imagesOpen}
onPost={store.shell.composerOpts?.onPost}
quote={store.shell.composerOpts?.quote}
/>
</RoutesContainer> </RoutesContainer>
</View> </View>
) )
+9 -2
View File
@@ -13184,6 +13184,13 @@ react-native-dotenv@^3.3.1:
dependencies: dependencies:
dotenv "^16.0.3" dotenv "^16.0.3"
react-native-drawer-layout@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/react-native-drawer-layout/-/react-native-drawer-layout-3.2.0.tgz#1ab05d0bed6bb684353c17c96e1d3e6c1a4e225d"
integrity sha512-d/kvzeBhXjqcRGlfkTSB96ZRKH6g6YxJK+gPtUOCOCH5piHpsupgX+tLAHdM8r8NUzN6Tl9656xfJTuVb8Zrgw==
dependencies:
use-latest-callback "^0.1.5"
react-native-fast-image@^8.6.3: react-native-fast-image@^8.6.3:
version "8.6.3" version "8.6.3"
resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.6.3.tgz#6edc3f9190092a909d636d93eecbcc54a8822255" resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.6.3.tgz#6edc3f9190092a909d636d93eecbcc54a8822255"
@@ -13197,7 +13204,7 @@ react-native-fs@^2.20.0:
base-64 "^0.1.0" base-64 "^0.1.0"
utf8 "^3.0.0" utf8 "^3.0.0"
react-native-gesture-handler@^2.5.0: react-native-gesture-handler@~2.9.0:
version "2.9.0" version "2.9.0"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.9.0.tgz#2f63812e523c646f25b9ad660fc6f75948e51241" resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.9.0.tgz#2f63812e523c646f25b9ad660fc6f75948e51241"
integrity sha512-a0BcH3Qb1tgVqUutc6d3VuWQkI1AM3+fJx8dkxzZs9t06qA27QgURYFoklpabuWpsUTzuKRpxleykp25E8m7tg== integrity sha512-a0BcH3Qb1tgVqUutc6d3VuWQkI1AM3+fJx8dkxzZs9t06qA27QgURYFoklpabuWpsUTzuKRpxleykp25E8m7tg==
@@ -13243,7 +13250,7 @@ react-native-progress@^5.0.0:
dependencies: dependencies:
prop-types "^15.7.2" prop-types "^15.7.2"
react-native-reanimated@^2.9.1: react-native-reanimated@~2.14.4:
version "2.14.4" version "2.14.4"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.14.4.tgz#3fa3da4e7b99f5dfb28f86bcf24d9d1024d38836" resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.14.4.tgz#3fa3da4e7b99f5dfb28f86bcf24d9d1024d38836"
integrity sha512-DquSbl7P8j4SAmc+kRdd75Ianm8G+IYQ9T4AQ6lrpLVeDkhZmjWI0wkutKWnp6L7c5XNVUrFDUf69dwETLCItQ== integrity sha512-DquSbl7P8j4SAmc+kRdd75Ianm8G+IYQ9T4AQ6lrpLVeDkhZmjWI0wkutKWnp6L7c5XNVUrFDUf69dwETLCItQ==