22 * Created by leon<[email protected] > on 22/2/21. 33 */
44import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
5+ import { createDrawerNavigator , DrawerContentComponentProps } from '@react-navigation/drawer'
56import {
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'
1516import { createNativeStackNavigator , NativeStackNavigationOptions } from '@react-navigation/native-stack'
16- import { createDrawerNavigator } from '@react-navigation/drawer '
17+ import { Text } from '@src/components '
1718import { ToastProvider } from '@src/components/toast'
1819import { useAppSelector } from '@src/hooks'
1920import { useUnRead } from '@src/hooks/useUnRead'
2021import { changeLocale , LanguageTagType , translate } from '@src/i18n'
2122import * as Screens from '@src/screens'
23+ import { HeaderButton } from '@src/screens/components'
2224import { RootState , store } from '@src/store'
2325import { ITheme , useTheme } from '@src/theme'
2426import { wait } from '@src/utils/utils'
2527import dayjs from 'dayjs'
2628import enUS from 'dayjs/locale/en'
2729import zhCN from 'dayjs/locale/zh-cn'
2830import 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'
3133import { EdgeInsets , SafeAreaProvider , useSafeAreaInsets } from 'react-native-safe-area-context'
3234import SplashScreen from 'react-native-splash-screen'
3335import 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 */
4041dayjs . 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+
9493const 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
131125const 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
136130const 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