Skip to content

Commit 2c0aec2

Browse files
authored
Merge pull request #43 from funnyzak/feature/hotdrawer
2 parents 5ef7094 + 005fd93 commit 2c0aec2

File tree

2 files changed

+251
-172
lines changed

2 files changed

+251
-172
lines changed

src/navigation/Navigator.tsx

Lines changed: 137 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,44 @@
22
* Created by leon<[email protected]> on 22/2/21.
33
*/
44
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
5+
import { createDrawerNavigator, DrawerContentComponentProps } from '@react-navigation/drawer'
56
import {
7+
DefaultTheme,
68
getFocusedRouteNameFromRoute,
79
NavigationContainer,
810
NavigationContainerRefWithCurrent,
11+
NavigationProp,
912
NavigationState,
1013
PartialState,
11-
DefaultTheme,
12-
Route,
13-
RouteProp
14+
Route
1415
} from '@react-navigation/native'
1516
import { createNativeStackNavigator, NativeStackNavigationOptions } from '@react-navigation/native-stack'
16-
import { createDrawerNavigator } from '@react-navigation/drawer'
17+
import { Text } from '@src/components'
1718
import { ToastProvider } from '@src/components/toast'
1819
import { useAppSelector } from '@src/hooks'
1920
import { useUnRead } from '@src/hooks/useUnRead'
2021
import { changeLocale, LanguageTagType, translate } from '@src/i18n'
2122
import * as Screens from '@src/screens'
23+
import { HeaderButton } from '@src/screens/components'
2224
import { RootState, store } from '@src/store'
2325
import { ITheme, useTheme } from '@src/theme'
2426
import { wait } from '@src/utils/utils'
2527
import dayjs from 'dayjs'
2628
import enUS from 'dayjs/locale/en'
2729
import zhCN from 'dayjs/locale/zh-cn'
2830
import relativeTime from 'dayjs/plugin/relativeTime'
29-
import React, { ReactNode, useEffect, useState } from 'react'
30-
import { Image, Platform, StatusBar, TextStyle, View } from 'react-native'
31+
import React, { ReactNode, useCallback, useEffect, useState } from 'react'
32+
import { Image, Platform, StatusBar, TextStyle, TouchableOpacity, View, ViewStyle } from 'react-native'
3133
import { EdgeInsets, SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'
3234
import SplashScreen from 'react-native-splash-screen'
3335
import NavigationService from './NavigationService'
34-
import { MainScreenProps, RootStackParamList, ROUTES } from './routes'
35-
import { HeaderButton } from '@src/screens/components'
36+
import { CommonScreenProps, MainScreenProps, RootStackParamList, ROUTES } from './routes'
3637

3738
/**
3839
* dayjs
3940
*/
4041
dayjs.extend(relativeTime)
4142

42-
const MainBottomTabNavigator = createBottomTabNavigator()
43-
const bottomTabBarIconSize = 30
44-
45-
/**
46-
* Crate Drawer Navigator
47-
*/
48-
const DrawerNavigator = createDrawerNavigator()
49-
5043
/**
5144
* header background default style
5245
* @param borderWidth
@@ -66,31 +59,37 @@ const defaultHeaderBackground = (theme: ITheme, borderWidth?: number): ReactNode
6659
)
6760
}
6861

69-
const defaultScreenOptions = (theme: ITheme): NativeStackNavigationOptions => ({
70-
animationTypeForReplace: 'push',
71-
animation: 'slide_from_right',
72-
62+
const defaultCommonScreenOptions = (theme: ITheme) => ({
7363
// hide header shadow
7464
headerShadowVisible: false,
7565

7666
headerStyle: {
7767
backgroundColor: theme.colors.transparent
7868
},
79-
headerTitleStyle: {
80-
fontWeight: 'bold',
81-
fontSize: theme.typography.titleText.fontSize
82-
},
8369
headerBackground: () => defaultHeaderBackground(theme),
84-
headerBackTitle: undefined,
8570
headerTintColor: theme.colors.appbarTint,
86-
headerBackTitleVisible: false,
8771

8872
// screen main content style
8973
contentStyle: {
9074
backgroundColor: theme.colors.background
9175
}
9276
})
9377

78+
const defaultScreenOptions = (theme: ITheme): NativeStackNavigationOptions => ({
79+
...defaultCommonScreenOptions(theme),
80+
81+
animationTypeForReplace: 'push',
82+
animation: 'slide_from_right',
83+
84+
headerTitleStyle: {
85+
fontWeight: 'bold',
86+
fontSize: theme.typography.titleText.fontSize
87+
},
88+
89+
headerBackTitle: undefined,
90+
headerBackTitleVisible: false
91+
})
92+
9493
const resetLocales = (locale: LanguageTagType) => {
9594
changeLocale(locale)
9695
dayjs.locale(locale === 'zh' ? zhCN : enUS)
@@ -105,38 +104,33 @@ const badgeStyles = {
105104
})
106105
}
107106

108-
const getHeaderTitle = (
107+
const getDrawHeaderTitle = (
109108
route: Partial<Route<string>> & {
110109
state?: PartialState<NavigationState>
111110
}
112111
) => {
113112
// If the focused route is not found, we need to assume it's the initial screen
114113
// This can happen during if there hasn't been any navigation inside the screen
115114
// In our case, it's "Feed" as that's the first screen inside the navigator
116-
const routeName = getFocusedRouteNameFromRoute(route) ?? ROUTES.HotDraw
115+
const routeName = getFocusedRouteNameFromRoute(route) ?? ROUTES.Hot
117116
switch (routeName) {
118-
case ROUTES.HotDraw:
117+
case ROUTES.Hot:
119118
return translate(`router.${ROUTES.Hot}`)
120-
case ROUTES.Nodes:
121-
return translate(`router.${ROUTES.Nodes}`)
122-
case ROUTES.Notifications:
123-
return translate(`router.${ROUTES.Notifications}`)
124-
case ROUTES.InterestNodes:
125-
return translate(`router.${ROUTES.InterestNodes}`)
126-
case ROUTES.My:
127-
return translate(`router.${ROUTES.My}`)
119+
case ROUTES.Latest:
120+
return translate(`router.${ROUTES.Latest}`)
128121
}
129122
}
130123

124+
const bottomTabBarIconSize = 30
131125
const renderBottomIcon = (focused: boolean, activeIcon: any, inactiveIcon: any): Element => {
132126
const icon = focused ? activeIcon : inactiveIcon
133127
return <Image source={icon} style={{ width: bottomTabBarIconSize, height: bottomTabBarIconSize }} />
134128
}
135129

136130
const defaultTabBarSetting = (theme: ITheme, insets: EdgeInsets) => {
137131
return {
138-
...defaultScreenOptions,
139-
headerShown: false,
132+
...defaultCommonScreenOptions(theme),
133+
headerShown: true,
140134
tabBarActiveTintColor: theme.colors.tabBarIconActive,
141135
tabBarInactiveTintColor: theme.colors.tabBarIconInactive,
142136
tabBarShowLabel: false,
@@ -152,47 +146,121 @@ const defaultTabBarSetting = (theme: ITheme, insets: EdgeInsets) => {
152146
}
153147
}
154148

155-
const HotDrawerNavigator = (initialRouteName?: string) => {
149+
const HotDrawerContent = (props: DrawerContentComponentProps) => {
150+
const { theme } = useTheme()
151+
const insets = useSafeAreaInsets()
152+
153+
const isFocus = useCallback(
154+
(route_index: number) => {
155+
return props.state.index === route_index
156+
},
157+
[theme, props]
158+
)
159+
160+
const textStyle = useCallback(
161+
(route_index: number) => {
162+
return {
163+
color: isFocus(route_index) ? theme.colors.secondary : theme.colors.captionText
164+
}
165+
},
166+
[theme, props]
167+
)
168+
return (
169+
<View style={[drawContentStyles.drawerContent(theme), { paddingTop: insets.top }]}>
170+
<TouchableOpacity
171+
style={drawContentStyles.drawItem(theme)}
172+
onPress={() => {
173+
NavigationService.navigate(ROUTES.Hot)
174+
}}>
175+
<Image source={theme.assets.images.icons.draw.hot[isFocus(0) ? 'active' : 'inActive']} />
176+
<Text type="label" style={textStyle(0)}>
177+
{translate(`router.${ROUTES.Hot}`)}
178+
</Text>
179+
</TouchableOpacity>
180+
<TouchableOpacity
181+
style={drawContentStyles.drawItem(theme)}
182+
onPress={() => {
183+
NavigationService.navigate(ROUTES.Latest)
184+
}}>
185+
<Image source={theme.assets.images.icons.draw.latest[isFocus(1) ? 'active' : 'inActive']} />
186+
<Text type="label" style={textStyle(1)}>
187+
{translate(`router.${ROUTES.Latest}`)}
188+
</Text>
189+
</TouchableOpacity>
190+
</View>
191+
)
192+
}
193+
194+
const drawContentStyles = {
195+
drawerContent: (theme: ITheme): ViewStyle => ({
196+
flexDirection: 'column',
197+
justifyContent: 'flex-start',
198+
alignItems: 'center',
199+
flex: 1,
200+
backgroundColor: theme.colors.background
201+
}),
202+
drawItem: (theme: ITheme): ViewStyle => ({
203+
marginBottom: theme.spacing.medium
204+
})
205+
}
206+
207+
/**
208+
* Crate Drawer Navigator
209+
*/
210+
const HotDraw = createDrawerNavigator()
211+
const HotDrawerNavigator = ({
212+
initialRouteName,
213+
navigation
214+
}: {
215+
initialRouteName?: string
216+
navigation: NavigationProp<RootStackParamList>
217+
} & CommonScreenProps) => {
156218
initialRouteName = initialRouteName ?? ROUTES.Hot
219+
const { theme } = useTheme()
157220

158221
return (
159-
<DrawerNavigator.Navigator initialRouteName={initialRouteName}>
160-
<DrawerNavigator.Screen
222+
<HotDraw.Navigator
223+
initialRouteName={initialRouteName}
224+
drawerContent={(props) => <HotDrawerContent {...props} />}
225+
screenOptions={{
226+
headerRight: () => (
227+
<HeaderButton
228+
onPress={() => navigation.navigate(ROUTES.SiteStat)}
229+
source={theme.assets.images.icons.header.stat}
230+
containerStyle={[{ marginRight: theme.spacing.medium }]}
231+
/>
232+
),
233+
drawerActiveTintColor: theme.colors.secondary,
234+
drawerActiveBackgroundColor: theme.colors.secondary,
235+
drawerInactiveTintColor: theme.colors.captionText,
236+
drawerStyle: { width: 45 }
237+
}}>
238+
<HotDraw.Screen
239+
key={ROUTES.Hot}
161240
name={ROUTES.Hot}
162241
component={Screens.HotScreen}
163242
options={{
164-
...defaultScreenOptions,
165-
headerShown: false,
243+
...defaultCommonScreenOptions(theme),
244+
headerShown: true,
166245
title: translate(`router.${ROUTES.Hot}`)
167246
}}
168247
/>
169-
<DrawerNavigator.Screen
248+
<HotDraw.Screen
249+
key={ROUTES.Latest}
170250
name={ROUTES.Latest}
171251
component={Screens.LatestScreen}
172252
options={{
173-
...defaultScreenOptions,
174-
headerShown: false,
253+
...defaultCommonScreenOptions(theme),
254+
headerShown: true,
175255
title: translate(`router.${ROUTES.Latest}`)
176256
}}
177257
/>
178-
</DrawerNavigator.Navigator>
258+
</HotDraw.Navigator>
179259
)
180260
}
181261

182-
const MainBottomHeaderLeft = ({ route }: { route: RouteProp<RootStackParamList> }): ReactNode => {
183-
const { theme } = useTheme()
184-
const focusRouteName = getFocusedRouteNameFromRoute(route) ?? ROUTES.HotDraw
185-
return focusRouteName === ROUTES.HotDraw ? <HeaderButton source={theme.assets.images.icons.header.more} /> : undefined
186-
}
187-
188-
const MainBottomTabHeaderRight = ({ route }: { route: RouteProp<RootStackParamList> }): ReactNode => {
189-
const { theme } = useTheme()
190-
191-
const focusRouteName = getFocusedRouteNameFromRoute(route) ?? ROUTES.HotDraw
192-
return focusRouteName === ROUTES.HotDraw ? <HeaderButton source={theme.assets.images.icons.header.stat} /> : undefined
193-
}
194-
195-
const MainAppNavigator = ({ navigation, route }: MainScreenProps) => {
262+
const MainBottomTabNavigator = createBottomTabNavigator()
263+
const MainAppNavigator = () => {
196264
const insets = useSafeAreaInsets()
197265
const { unread } = useUnRead()
198266
const { languageTag } = useAppSelector((state: RootState) => state.setting)
@@ -207,16 +275,17 @@ const MainAppNavigator = ({ navigation, route }: MainScreenProps) => {
207275
<MainBottomTabNavigator.Screen
208276
name={ROUTES.HotDraw}
209277
component={HotDrawerNavigator}
210-
options={{
211-
title: translate(`router.${ROUTES.HotDraw}`),
278+
options={({ route }) => ({
279+
title: getDrawHeaderTitle(route),
212280
...defaultTabBarSetting(theme, insets),
281+
headerShown: false,
213282
tabBarIcon: ({ focused }) =>
214283
renderBottomIcon(
215284
focused,
216285
theme.assets.images.icons.bottomTab.hot.active,
217286
theme.assets.images.icons.bottomTab.hot.inActive
218287
)
219-
}}
288+
})}
220289
/>
221290
<MainBottomTabNavigator.Screen
222291
name={ROUTES.Nodes}
@@ -346,14 +415,10 @@ export const AppNavigationContainer = () => {
346415
<StackNavigator.Screen
347416
name={ROUTES.Main}
348417
component={MainAppNavigator}
349-
options={({ route }) => ({
418+
options={({ route, navigation }) => ({
350419
...defaultScreenOptions(theme),
351-
headerShadowVisible: ![ROUTES.HotDraw].includes(
352-
getFocusedRouteNameFromRoute(route) ?? (ROUTES.Nodes as any)
353-
),
354-
headerLeft: () => MainBottomHeaderLeft({ route }),
355-
headerRight: () => MainBottomTabHeaderRight({ route }),
356-
headerTitle: getHeaderTitle(route)
420+
headerBackground: undefined,
421+
headerShown: false
357422
})}
358423
initialParams={{
359424
initialRouteName: ROUTES.My

0 commit comments

Comments
 (0)