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- NavigationProp
14+ Route
1515} from '@react-navigation/native'
1616import { createNativeStackNavigator , NativeStackNavigationOptions } from '@react-navigation/native-stack'
17- import {
18- createDrawerNavigator ,
19- DrawerNavigationProp ,
20- getDrawerStatusFromState ,
21- useDrawerStatus
22- } from '@react-navigation/drawer'
17+ import { Text } from '@src/components'
2318import { ToastProvider } from '@src/components/toast'
2419import { useAppSelector } from '@src/hooks'
2520import { useUnRead } from '@src/hooks/useUnRead'
2621import { changeLocale , LanguageTagType , translate } from '@src/i18n'
2722import * as Screens from '@src/screens'
23+ import { HeaderButton } from '@src/screens/components'
2824import { RootState , store } from '@src/store'
2925import { ITheme , useTheme } from '@src/theme'
3026import { wait } from '@src/utils/utils'
3127import dayjs from 'dayjs'
3228import enUS from 'dayjs/locale/en'
3329import zhCN from 'dayjs/locale/zh-cn'
3430import relativeTime from 'dayjs/plugin/relativeTime'
35- import React , { ReactNode , useEffect , useState } from 'react'
36- 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'
3733import { EdgeInsets , SafeAreaProvider , useSafeAreaInsets } from 'react-native-safe-area-context'
3834import SplashScreen from 'react-native-splash-screen'
3935import NavigationService from './NavigationService'
40- import { MainScreenProps , RootStackParamList , ROUTES } from './routes'
41- import { HeaderButton } from '@src/screens/components'
36+ import { CommonScreenProps , MainScreenProps , RootStackParamList , ROUTES } from './routes'
4237
4338/**
4439 * dayjs
4540 */
4641dayjs . extend ( relativeTime )
4742
48- const MainBottomTabNavigator = createBottomTabNavigator ( )
49- const bottomTabBarIconSize = 30
50-
51- /**
52- * Crate Drawer Navigator
53- */
54- const DrawerNavigator = createDrawerNavigator ( )
55-
5643/**
5744 * header background default style
5845 * @param borderWidth
@@ -72,31 +59,37 @@ const defaultHeaderBackground = (theme: ITheme, borderWidth?: number): ReactNode
7259 )
7360}
7461
75- const defaultScreenOptions = ( theme : ITheme ) : NativeStackNavigationOptions => ( {
76- animationTypeForReplace : 'push' ,
77- animation : 'slide_from_right' ,
78-
62+ const defaultCommonScreenOptions = ( theme : ITheme ) => ( {
7963 // hide header shadow
8064 headerShadowVisible : false ,
8165
8266 headerStyle : {
8367 backgroundColor : theme . colors . transparent
8468 } ,
85- headerTitleStyle : {
86- fontWeight : 'bold' ,
87- fontSize : theme . typography . titleText . fontSize
88- } ,
8969 headerBackground : ( ) => defaultHeaderBackground ( theme ) ,
90- headerBackTitle : undefined ,
9170 headerTintColor : theme . colors . appbarTint ,
92- headerBackTitleVisible : false ,
9371
9472 // screen main content style
9573 contentStyle : {
9674 backgroundColor : theme . colors . background
9775 }
9876} )
9977
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+
10093const resetLocales = ( locale : LanguageTagType ) => {
10194 changeLocale ( locale )
10295 dayjs . locale ( locale === 'zh' ? zhCN : enUS )
@@ -111,7 +104,7 @@ const badgeStyles = {
111104 } )
112105}
113106
114- const getHeaderTitle = (
107+ const getDrawHeaderTitle = (
115108 route : Partial < Route < string > > & {
116109 state ?: PartialState < NavigationState >
117110 }
@@ -121,32 +114,23 @@ const getHeaderTitle = (
121114 // In our case, it's "Feed" as that's the first screen inside the navigator
122115 const routeName = getFocusedRouteNameFromRoute ( route ) ?? ROUTES . Hot
123116 switch ( routeName ) {
124- case ROUTES . HotDraw :
125- return translate ( `router.${ ROUTES . Hot } ` )
126117 case ROUTES . Hot :
127118 return translate ( `router.${ ROUTES . Hot } ` )
128119 case ROUTES . Latest :
129120 return translate ( `router.${ ROUTES . Latest } ` )
130- case ROUTES . Nodes :
131- return translate ( `router.${ ROUTES . Nodes } ` )
132- case ROUTES . Notifications :
133- return translate ( `router.${ ROUTES . Notifications } ` )
134- case ROUTES . InterestNodes :
135- return translate ( `router.${ ROUTES . InterestNodes } ` )
136- case ROUTES . My :
137- return translate ( `router.${ ROUTES . My } ` )
138121 }
139122}
140123
124+ const bottomTabBarIconSize = 30
141125const renderBottomIcon = ( focused : boolean , activeIcon : any , inactiveIcon : any ) : Element => {
142126 const icon = focused ? activeIcon : inactiveIcon
143127 return < Image source = { icon } style = { { width : bottomTabBarIconSize , height : bottomTabBarIconSize } } />
144128}
145129
146130const defaultTabBarSetting = ( theme : ITheme , insets : EdgeInsets ) => {
147131 return {
148- ...defaultScreenOptions ,
149- headerShown : false ,
132+ ...defaultCommonScreenOptions ( theme ) ,
133+ headerShown : true ,
150134 tabBarActiveTintColor : theme . colors . tabBarIconActive ,
151135 tabBarInactiveTintColor : theme . colors . tabBarIconInactive ,
152136 tabBarShowLabel : false ,
@@ -162,73 +146,121 @@ const defaultTabBarSetting = (theme: ITheme, insets: EdgeInsets) => {
162146 }
163147}
164148
165- 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 ) => {
166218 initialRouteName = initialRouteName ?? ROUTES . Hot
219+ const { theme } = useTheme ( )
167220
168221 return (
169- < DrawerNavigator . Navigator initialRouteName = { initialRouteName } >
170- < 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 }
171240 name = { ROUTES . Hot }
172241 component = { Screens . HotScreen }
173242 options = { {
174- ...defaultScreenOptions ,
175- headerShown : false ,
243+ ...defaultCommonScreenOptions ( theme ) ,
244+ headerShown : true ,
176245 title : translate ( `router.${ ROUTES . Hot } ` )
177246 } }
178247 />
179- < DrawerNavigator . Screen
248+ < HotDraw . Screen
249+ key = { ROUTES . Latest }
180250 name = { ROUTES . Latest }
181251 component = { Screens . LatestScreen }
182252 options = { {
183- ...defaultScreenOptions ,
184- headerShown : false ,
253+ ...defaultCommonScreenOptions ( theme ) ,
254+ headerShown : true ,
185255 title : translate ( `router.${ ROUTES . Latest } ` )
186256 } }
187257 />
188- </ DrawerNavigator . Navigator >
258+ </ HotDraw . Navigator >
189259 )
190260}
191261
192- const MainBottomHeaderLeft = ( {
193- navigation,
194- route
195- } : {
196- route : RouteProp < RootStackParamList >
197- navigation : NavigationProp < RootStackParamList >
198- } ) : ReactNode => {
199- const { theme } = useTheme ( )
200- const focusRouteName = getFocusedRouteNameFromRoute ( route ) ?? ROUTES . HotDraw
201- return focusRouteName === ROUTES . HotDraw ? (
202- < HeaderButton
203- source = { theme . assets . images . icons . header . more }
204- onPress = { ( ) => {
205- console . log ( getFocusedRouteNameFromRoute ( route ) )
206- } }
207- />
208- ) : undefined
209- }
210-
211- const MainBottomTabHeaderRight = ( {
212- navigation,
213- route
214- } : {
215- route : RouteProp < RootStackParamList >
216- navigation : NavigationProp < RootStackParamList >
217- } ) : ReactNode => {
218- const { theme } = useTheme ( )
219-
220- const focusRouteName = getFocusedRouteNameFromRoute ( route ) ?? ROUTES . HotDraw
221- return focusRouteName === ROUTES . HotDraw ? (
222- < HeaderButton
223- source = { theme . assets . images . icons . header . stat }
224- onPress = { ( ) => {
225- NavigationService . navigate ( ROUTES . SiteStat )
226- } }
227- />
228- ) : undefined
229- }
230-
231- const MainAppNavigator = ( { navigation, route } : MainScreenProps ) => {
262+ const MainBottomTabNavigator = createBottomTabNavigator ( )
263+ const MainAppNavigator = ( ) => {
232264 const insets = useSafeAreaInsets ( )
233265 const { unread } = useUnRead ( )
234266 const { languageTag } = useAppSelector ( ( state : RootState ) => state . setting )
@@ -243,16 +275,17 @@ const MainAppNavigator = ({ navigation, route }: MainScreenProps) => {
243275 < MainBottomTabNavigator . Screen
244276 name = { ROUTES . HotDraw }
245277 component = { HotDrawerNavigator }
246- options = { {
247- title : translate ( `router. ${ ROUTES . HotDraw } ` ) ,
278+ options = { ( { route } ) => ( {
279+ title : getDrawHeaderTitle ( route ) ,
248280 ...defaultTabBarSetting ( theme , insets ) ,
281+ headerShown : false ,
249282 tabBarIcon : ( { focused } ) =>
250283 renderBottomIcon (
251284 focused ,
252285 theme . assets . images . icons . bottomTab . hot . active ,
253286 theme . assets . images . icons . bottomTab . hot . inActive
254287 )
255- } }
288+ } ) }
256289 />
257290 < MainBottomTabNavigator . Screen
258291 name = { ROUTES . Nodes }
@@ -384,12 +417,8 @@ export const AppNavigationContainer = () => {
384417 component = { MainAppNavigator }
385418 options = { ( { route, navigation } ) => ( {
386419 ...defaultScreenOptions ( theme ) ,
387- headerShadowVisible : ! [ ROUTES . HotDraw ] . includes (
388- getFocusedRouteNameFromRoute ( route ) ?? ( ROUTES . Nodes as any )
389- ) ,
390- headerLeft : ( ) => MainBottomHeaderLeft ( { route, navigation } ) ,
391- headerRight : ( ) => MainBottomTabHeaderRight ( { route, navigation } ) ,
392- headerTitle : getHeaderTitle ( route )
420+ headerBackground : undefined ,
421+ headerShown : false
393422 } ) }
394423 initialParams = { {
395424 initialRouteName : ROUTES . My
0 commit comments