Showing
5 changed files
with
136 additions
and
32 deletions
| @@ -10,7 +10,11 @@ import { | @@ -10,7 +10,11 @@ import { | ||
| 10 | HeaderStyleInterpolators, | 10 | HeaderStyleInterpolators, |
| 11 | } from '@react-navigation/stack'; | 11 | } from '@react-navigation/stack'; |
| 12 | import Ionicons from 'react-native-vector-icons/Ionicons'; | 12 | import Ionicons from 'react-native-vector-icons/Ionicons'; |
| 13 | -import { MainTabParamList, MainStackParamList } from '../type/Navigation'; | 13 | +import { |
| 14 | + MainTabParamList, | ||
| 15 | + MainStackParamList, | ||
| 16 | + AuthStackParamList, | ||
| 17 | +} from '../type/Navigation'; | ||
| 14 | import SystemInfo from './SystemInfo'; | 18 | import SystemInfo from './SystemInfo'; |
| 15 | import DesignList from './DesignList'; | 19 | import DesignList from './DesignList'; |
| 16 | import { useDarkMode } from 'react-native-dark-mode'; | 20 | import { useDarkMode } from 'react-native-dark-mode'; |
| @@ -27,6 +31,9 @@ import { useDeepLinking } from '../utility/handleDeepLinking'; | @@ -27,6 +31,9 @@ import { useDeepLinking } from '../utility/handleDeepLinking'; | ||
| 27 | import { navigationRef, useMountedRef } from '../utility/rootNavigation'; | 31 | import { navigationRef, useMountedRef } from '../utility/rootNavigation'; |
| 28 | import ShortcutPage from './ShortcutItem'; | 32 | import ShortcutPage from './ShortcutItem'; |
| 29 | import useQuickAction from '../utility/useQuickAction'; | 33 | import useQuickAction from '../utility/useQuickAction'; |
| 34 | +import { useReduxState } from '../store/hooks'; | ||
| 35 | +import LoginScreen from './Login'; | ||
| 36 | +import MeScreen from './Me'; | ||
| 30 | 37 | ||
| 31 | const MainTab = createBottomTabNavigator<MainTabParamList>(); | 38 | const MainTab = createBottomTabNavigator<MainTabParamList>(); |
| 32 | 39 | ||
| @@ -36,7 +43,7 @@ function getTabHeader( | @@ -36,7 +43,7 @@ function getTabHeader( | ||
| 36 | } | 43 | } |
| 37 | ) { | 44 | ) { |
| 38 | const { state } = route; | 45 | const { state } = route; |
| 39 | - if (!state) return 'SystemInfo'; | 46 | + if (!state) return 'Library'; |
| 40 | const { routeNames, index } = state; | 47 | const { routeNames, index } = state; |
| 41 | const routeName = routeNames[index] as keyof MainTabParamList; | 48 | const routeName = routeNames[index] as keyof MainTabParamList; |
| 42 | return routeName; | 49 | return routeName; |
| @@ -78,6 +85,10 @@ const Home = () => { | @@ -78,6 +85,10 @@ const Home = () => { | ||
| 78 | name={focused ? 'ios-list-box' : 'ios-list'} | 85 | name={focused ? 'ios-list-box' : 'ios-list'} |
| 79 | /> | 86 | /> |
| 80 | ); | 87 | ); |
| 88 | + case 'Me': | ||
| 89 | + return ( | ||
| 90 | + <Ionicons size={size} color={color} name={'ios-person'} /> | ||
| 91 | + ); | ||
| 81 | default: | 92 | default: |
| 82 | break; | 93 | break; |
| 83 | } | 94 | } |
| @@ -88,15 +99,19 @@ const Home = () => { | @@ -88,15 +99,19 @@ const Home = () => { | ||
| 88 | <MainTab.Screen name="Library" component={Library} /> | 99 | <MainTab.Screen name="Library" component={Library} /> |
| 89 | <MainTab.Screen name="SystemInfo" component={SystemInfo} /> | 100 | <MainTab.Screen name="SystemInfo" component={SystemInfo} /> |
| 90 | <MainTab.Screen name="DesignList" component={DesignList} /> | 101 | <MainTab.Screen name="DesignList" component={DesignList} /> |
| 102 | + <MainTab.Screen name="Me" component={MeScreen} /> | ||
| 91 | </MainTab.Navigator> | 103 | </MainTab.Navigator> |
| 92 | ); | 104 | ); |
| 93 | }; | 105 | }; |
| 94 | 106 | ||
| 95 | const MainStack = createStackNavigator<MainStackParamList>(); | 107 | const MainStack = createStackNavigator<MainStackParamList>(); |
| 96 | 108 | ||
| 109 | +const AuthStack = createStackNavigator<AuthStackParamList>(); | ||
| 110 | + | ||
| 97 | const Container = () => { | 111 | const Container = () => { |
| 98 | const inDarkMode = useDarkMode(); | 112 | const inDarkMode = useDarkMode(); |
| 99 | const strings = useI18nStrings(); | 113 | const strings = useI18nStrings(); |
| 114 | + const user = useReduxState('user'); | ||
| 100 | 115 | ||
| 101 | useMountedRef(); | 116 | useMountedRef(); |
| 102 | useDeepLinking(); | 117 | useDeepLinking(); |
| @@ -107,36 +122,42 @@ const Container = () => { | @@ -107,36 +122,42 @@ const Container = () => { | ||
| 107 | ref={navigationRef} | 122 | ref={navigationRef} |
| 108 | theme={inDarkMode ? themeForNav.dark : themeForNav.light} | 123 | theme={inDarkMode ? themeForNav.dark : themeForNav.light} |
| 109 | > | 124 | > |
| 110 | - <MainStack.Navigator | 125 | + {user.token ? ( |
| 111 | - screenOptions={{ | 126 | + <MainStack.Navigator |
| 112 | - headerStyleInterpolator: HeaderStyleInterpolators.forUIKit, | 127 | + screenOptions={{ |
| 113 | - headerTruncatedBackTitle: strings.navigation.back, | 128 | + headerStyleInterpolator: HeaderStyleInterpolators.forUIKit, |
| 114 | - }} | 129 | + headerTruncatedBackTitle: strings.navigation.back, |
| 115 | - > | ||
| 116 | - <MainStack.Screen | ||
| 117 | - name="MainTab" | ||
| 118 | - component={Home} | ||
| 119 | - options={({ route }) => { | ||
| 120 | - return { headerTitle: getTabHeader(route) }; | ||
| 121 | }} | 130 | }} |
| 122 | - /> | 131 | + > |
| 123 | - <MainStack.Screen | 132 | + <MainStack.Screen |
| 124 | - name="RNDeviceInfoList" | 133 | + name="MainTab" |
| 125 | - component={RNDeviceInfoList} | 134 | + component={Home} |
| 126 | - /> | 135 | + options={({ route }) => { |
| 127 | - <MainStack.Screen | 136 | + return { headerTitle: getTabHeader(route) }; |
| 128 | - name="WebviewScreen" | 137 | + }} |
| 129 | - component={WebviewScreen} | 138 | + /> |
| 130 | - options={({ navigation, route }) => ({ | 139 | + <MainStack.Screen |
| 131 | - // FIXME: https://github.com/react-native-community/react-native-webview/issues/575#issuecomment-587267906 | 140 | + name="RNDeviceInfoList" |
| 132 | - animationEnabled: Platform.OS === 'ios', | 141 | + component={RNDeviceInfoList} |
| 133 | - })} | 142 | + /> |
| 134 | - /> | 143 | + <MainStack.Screen |
| 135 | - <MainStack.Screen name="RNLocalize" component={RNLocalize} /> | 144 | + name="WebviewScreen" |
| 136 | - <MainStack.Screen name="RNCamera" component={CameraScreen} /> | 145 | + component={WebviewScreen} |
| 137 | - <MainStack.Screen name="RNCode" component={ReadableCode} /> | 146 | + options={({ navigation, route }) => ({ |
| 138 | - <MainStack.Screen name="ShortcutItem" component={ShortcutPage} /> | 147 | + // FIXME: https://github.com/react-native-community/react-native-webview/issues/575#issuecomment-587267906 |
| 139 | - </MainStack.Navigator> | 148 | + animationEnabled: Platform.OS === 'ios', |
| 149 | + })} | ||
| 150 | + /> | ||
| 151 | + <MainStack.Screen name="RNLocalize" component={RNLocalize} /> | ||
| 152 | + <MainStack.Screen name="RNCamera" component={CameraScreen} /> | ||
| 153 | + <MainStack.Screen name="RNCode" component={ReadableCode} /> | ||
| 154 | + <MainStack.Screen name="ShortcutItem" component={ShortcutPage} /> | ||
| 155 | + </MainStack.Navigator> | ||
| 156 | + ) : ( | ||
| 157 | + <AuthStack.Navigator> | ||
| 158 | + <AuthStack.Screen name="Login" component={LoginScreen} /> | ||
| 159 | + </AuthStack.Navigator> | ||
| 160 | + )} | ||
| 140 | </NavigationContainer> | 161 | </NavigationContainer> |
| 141 | ); | 162 | ); |
| 142 | }; | 163 | }; |
src/screen/Login.tsx
0 → 100644
| 1 | +import React, { useCallback, useState } from 'react'; | ||
| 2 | +import { BGScroll, Card, ListItem, Divider } from '../component/View'; | ||
| 3 | +import { useReduxDispatch, useReduxState } from '../store/hooks'; | ||
| 4 | +import { rootActions } from '../store'; | ||
| 5 | +import { Alert } from 'react-native'; | ||
| 6 | + | ||
| 7 | +const LoginScreen = () => { | ||
| 8 | + const { list, current } = useReduxState('user'); | ||
| 9 | + const dispatch = useReduxDispatch(); | ||
| 10 | + | ||
| 11 | + const [userName, setUserName] = useState(current?.name); | ||
| 12 | + | ||
| 13 | + const onLogin = useCallback(() => { | ||
| 14 | + const newToken = userName ? 'yes!' + userName : 'no:('; | ||
| 15 | + if (userName) { | ||
| 16 | + const filtered = list.filter(u => u.name === userName)[0]; | ||
| 17 | + if (filtered) { | ||
| 18 | + dispatch(rootActions.userActions.setCurrentUser(filtered)); | ||
| 19 | + } else { | ||
| 20 | + const newUser = { name: userName }; | ||
| 21 | + dispatch(rootActions.userActions.addUser(newUser)); | ||
| 22 | + dispatch(rootActions.userActions.setCurrentUser(newUser)); | ||
| 23 | + } | ||
| 24 | + } | ||
| 25 | + dispatch(rootActions.userActions.setToken(newToken)); | ||
| 26 | + }, [userName, dispatch, list]); | ||
| 27 | + | ||
| 28 | + return ( | ||
| 29 | + <BGScroll> | ||
| 30 | + <Card round> | ||
| 31 | + <ListItem | ||
| 32 | + title="User Name" | ||
| 33 | + rightTitle={userName} | ||
| 34 | + onPress={() => { | ||
| 35 | + Alert.prompt('Your name?', undefined, setUserName); | ||
| 36 | + }} | ||
| 37 | + /> | ||
| 38 | + <Divider /> | ||
| 39 | + <ListItem title="login" onPress={onLogin} /> | ||
| 40 | + </Card> | ||
| 41 | + </BGScroll> | ||
| 42 | + ); | ||
| 43 | +}; | ||
| 44 | + | ||
| 45 | +export default LoginScreen; |
src/screen/Me/index.tsx
0 → 100644
| 1 | +import React, { useCallback } from 'react'; | ||
| 2 | +import { BGScroll, Card, ListItem } from '../../component/View'; | ||
| 3 | +import { useReduxState, useReduxDispatch } from '../../store/hooks'; | ||
| 4 | +import { rootActions } from '../../store'; | ||
| 5 | + | ||
| 6 | +const MeScreen = () => { | ||
| 7 | + const { current } = useReduxState('user'); | ||
| 8 | + const dispatch = useReduxDispatch(); | ||
| 9 | + | ||
| 10 | + const onLogout = useCallback(() => { | ||
| 11 | + dispatch(rootActions.userActions.setToken(null)); | ||
| 12 | + }, [dispatch]); | ||
| 13 | + | ||
| 14 | + return ( | ||
| 15 | + <BGScroll white> | ||
| 16 | + <Card shadow> | ||
| 17 | + <ListItem title={current?.name ?? '请登录'} /> | ||
| 18 | + </Card> | ||
| 19 | + <Card shadow> | ||
| 20 | + <ListItem title={'Log out'} onPress={onLogout} /> | ||
| 21 | + </Card> | ||
| 22 | + </BGScroll> | ||
| 23 | + ); | ||
| 24 | +}; | ||
| 25 | + | ||
| 26 | +export default MeScreen; |
| 1 | import { createAction } from 'typesafe-actions'; | 1 | import { createAction } from 'typesafe-actions'; |
| 2 | import { UserActionTypes, User } from './types'; | 2 | import { UserActionTypes, User } from './types'; |
| 3 | 3 | ||
| 4 | -export const setToken = createAction(UserActionTypes.SET_TOKEN)<string>(); | 4 | +export const setToken = createAction(UserActionTypes.SET_TOKEN)< |
| 5 | + string | null | ||
| 6 | +>(); | ||
| 5 | 7 | ||
| 6 | export const setCurrentUser = createAction(UserActionTypes.SET_CURRENT)<User>(); | 8 | export const setCurrentUser = createAction(UserActionTypes.SET_CURRENT)<User>(); |
| 7 | 9 |
| @@ -6,6 +6,7 @@ export type MainTabParamList = { | @@ -6,6 +6,7 @@ export type MainTabParamList = { | ||
| 6 | Library: undefined; | 6 | Library: undefined; |
| 7 | SystemInfo: undefined; | 7 | SystemInfo: undefined; |
| 8 | DesignList: undefined; | 8 | DesignList: undefined; |
| 9 | + Me: undefined; | ||
| 9 | }; | 10 | }; |
| 10 | 11 | ||
| 11 | export type MainStackParamList = { | 12 | export type MainStackParamList = { |
| @@ -18,6 +19,10 @@ export type MainStackParamList = { | @@ -18,6 +19,10 @@ export type MainStackParamList = { | ||
| 18 | ShortcutItem: { id?: string }; | 19 | ShortcutItem: { id?: string }; |
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 22 | +export type AuthStackParamList = { | ||
| 23 | + Login: undefined; | ||
| 24 | +}; | ||
| 25 | + | ||
| 21 | export type MainTabScreenProps<RouteName extends keyof MainTabParamList> = { | 26 | export type MainTabScreenProps<RouteName extends keyof MainTabParamList> = { |
| 22 | navigation: CompositeNavigationProp< | 27 | navigation: CompositeNavigationProp< |
| 23 | BottomTabNavigationProp<MainTabParamList, RouteName>, | 28 | BottomTabNavigationProp<MainTabParamList, RouteName>, |
| @@ -30,3 +35,8 @@ export type MainStackScreenProps<RouteName extends keyof MainStackParamList> = { | @@ -30,3 +35,8 @@ export type MainStackScreenProps<RouteName extends keyof MainStackParamList> = { | ||
| 30 | navigation: StackNavigationProp<MainStackParamList, RouteName>; | 35 | navigation: StackNavigationProp<MainStackParamList, RouteName>; |
| 31 | route: RouteProp<MainStackParamList, RouteName>; | 36 | route: RouteProp<MainStackParamList, RouteName>; |
| 32 | }; | 37 | }; |
| 38 | + | ||
| 39 | +export type AuthStackScreenProps<RouteName extends keyof AuthStackParamList> = { | ||
| 40 | + navigation: StackNavigationProp<AuthStackParamList, RouteName>; | ||
| 41 | + route: RouteProp<AuthStackParamList, RouteName>; | ||
| 42 | +}; |
-
Please register or login to post a comment