diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/routes/index.tsx | 59 | ||||
-rw-r--r-- | src/routes/types.ts | 2 | ||||
-rw-r--r-- | src/screens/Home.tsx | 5 | ||||
-rw-r--r-- | src/screens/Login.tsx | 17 | ||||
-rw-r--r-- | src/screens/Signup.tsx | 23 | ||||
-rw-r--r-- | src/state/index.ts | 8 | ||||
-rw-r--r-- | src/state/models/root-store.ts | 11 | ||||
-rw-r--r-- | src/state/models/session.ts | 21 | ||||
-rw-r--r-- | yarn.lock | 5 |
11 files changed, 129 insertions, 25 deletions
diff --git a/README.md b/README.md index 159d374ad..9627e39ed 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,6 @@ Uses: ## TODOs -- Navigation - - Auth / Unauthed - Web - Desktop vs mobile styling - API diff --git a/package.json b/package.json index 764c79b44..763f6d89e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@react-navigation/native-stack": "^6.6.2", "@react-navigation/stack": "^6.2.1", "mobx": "^6.6.0", + "mobx-react-lite": "^3.4.0", "mobx-state-tree": "^5.1.5", "react": "17.0.2", "react-dom": "17.0.2", diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 9ea1766f5..fa035e3c9 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -8,12 +8,16 @@ import { } from '@react-navigation/native' import {createNativeStackNavigator} from '@react-navigation/native-stack' import {createBottomTabNavigator} from '@react-navigation/bottom-tabs' +import {observer} from 'mobx-react-lite' import type {RootStackParamList} from './types' +import {useStores} from '../state' import {Home} from '../screens/Home' import {Search} from '../screens/Search' import {Notifications} from '../screens/Notifications' import {Menu} from '../screens/Menu' import {Profile} from '../screens/Profile' +import {Login} from '../screens/Login' +import {Signup} from '../screens/Signup' import {NotFound} from '../screens/NotFound' const linking: LinkingOptions<RootStackParamList> = { @@ -30,6 +34,8 @@ const linking: LinkingOptions<RootStackParamList> = { Menu: 'menu', }, }, + Login: 'login', + Signup: 'signup', Profile: 'profile/:name', NotFound: '*', }, @@ -50,23 +56,38 @@ const tabBarScreenOptions = ({ }, }) -const Primary = () => ( - <PrimaryTab.Navigator - screenOptions={tabBarScreenOptions} - initialRouteName="Home"> - <PrimaryTab.Screen name="Home" component={Home} /> - <PrimaryTab.Screen name="Search" component={Search} /> - <PrimaryTab.Screen name="Notifications" component={Notifications} /> - <PrimaryTab.Screen name="Menu" component={Menu} /> - </PrimaryTab.Navigator> -) +function Primary() { + return ( + <PrimaryTab.Navigator + screenOptions={tabBarScreenOptions} + initialRouteName="Home"> + <PrimaryTab.Screen name="Home" component={Home} /> + <PrimaryTab.Screen name="Search" component={Search} /> + <PrimaryTab.Screen name="Notifications" component={Notifications} /> + <PrimaryTab.Screen name="Menu" component={Menu} /> + </PrimaryTab.Navigator> + ) +} -export const Root = () => ( - <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}> - <RootStack.Navigator initialRouteName="Primary"> - <RootStack.Screen name="Primary" component={Primary} /> - <RootStack.Screen name="Profile" component={Profile} /> - <RootStack.Screen name="NotFound" component={NotFound} /> - </RootStack.Navigator> - </NavigationContainer> -) +export const Root = observer(() => { + const store = useStores() + return ( + <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}> + <RootStack.Navigator + initialRouteName={store.session.isAuthed ? 'Primary' : 'Login'}> + {store.session.isAuthed ? ( + <> + <RootStack.Screen name="Primary" component={Primary} /> + <RootStack.Screen name="Profile" component={Profile} /> + <RootStack.Screen name="NotFound" component={NotFound} /> + </> + ) : ( + <> + <RootStack.Screen name="Login" component={Login} /> + <RootStack.Screen name="Signup" component={Signup} /> + </> + )} + </RootStack.Navigator> + </NavigationContainer> + ) +}) diff --git a/src/routes/types.ts b/src/routes/types.ts index 668dc2e2f..88148fd4d 100644 --- a/src/routes/types.ts +++ b/src/routes/types.ts @@ -6,6 +6,8 @@ import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs' export type RootStackParamList = { Primary: undefined Profile: {name: string} + Login: undefined + Signup: undefined NotFound: undefined } export type RootStackScreenProps<T extends keyof RootStackParamList> = diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx index f4b8ffb63..a2d013abe 100644 --- a/src/screens/Home.tsx +++ b/src/screens/Home.tsx @@ -1,8 +1,10 @@ import React from 'react' import {Text, Button, View, SafeAreaView} from 'react-native' import type {PrimaryTabScreenProps} from '../routes/types' +import {useStores} from '../state' -export const Home = ({navigation}: PrimaryTabScreenProps<'Home'>) => { +export function Home({navigation}: PrimaryTabScreenProps<'Home'>) { + const store = useStores() return ( <SafeAreaView style={{flex: 1}}> <View style={{flex: 1}}> @@ -11,6 +13,7 @@ export const Home = ({navigation}: PrimaryTabScreenProps<'Home'>) => { title="Go to Jane's profile" onPress={() => navigation.navigate('Profile', {name: 'Jane'})} /> + <Button title="Logout" onPress={() => store.session.setAuthed(false)} /> </View> </SafeAreaView> ) diff --git a/src/screens/Login.tsx b/src/screens/Login.tsx new file mode 100644 index 000000000..77580748c --- /dev/null +++ b/src/screens/Login.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import {Text, Button, View, SafeAreaView} from 'react-native' +import type {RootStackScreenProps} from '../routes/types' +import {useStores} from '../state' + +export function Login({navigation}: RootStackScreenProps<'Login'>) { + const store = useStores() + return ( + <SafeAreaView style={{flex: 1}}> + <View style={{flex: 1}}> + <Text>Welcome! Time to sign in</Text> + <Button title="Login" onPress={() => store.session.setAuthed(true)} /> + <Button title="Sign Up" onPress={() => navigation.navigate('Signup')} /> + </View> + </SafeAreaView> + ) +} diff --git a/src/screens/Signup.tsx b/src/screens/Signup.tsx new file mode 100644 index 000000000..bf7f8f2f8 --- /dev/null +++ b/src/screens/Signup.tsx @@ -0,0 +1,23 @@ +import React from 'react' +import {Text, Button, View, SafeAreaView} from 'react-native' +import type {RootStackScreenProps} from '../routes/types' +import {useStores} from '../state' + +export function Signup({navigation}: RootStackScreenProps<'Signup'>) { + const store = useStores() + return ( + <SafeAreaView style={{flex: 1}}> + <View style={{flex: 1}}> + <Text>Let's create your account</Text> + <Button + title="Create new account" + onPress={() => store.session.setAuthed(true)} + /> + <Button + title="Log in to an existing account" + onPress={() => navigation.navigate('Login')} + /> + </View> + </SafeAreaView> + ) +} diff --git a/src/state/index.ts b/src/state/index.ts index 7c97ce294..496f3631d 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -1,5 +1,9 @@ import {onSnapshot} from 'mobx-state-tree' -import {RootStoreModel, RootStore} from './models/root-store' +import { + RootStoreModel, + RootStore, + createDefaultRootStore, +} from './models/root-store' import {Environment} from './env' import * as storage from './storage' @@ -15,7 +19,7 @@ export async function setupState() { rootStore = RootStoreModel.create(data, env) } catch (e) { console.error('Failed to load state from storage', e) - rootStore = RootStoreModel.create({}, env) + rootStore = RootStoreModel.create(createDefaultRootStore(), env) } // track changes & save to storage diff --git a/src/state/models/root-store.ts b/src/state/models/root-store.ts index 164dfcced..143c59ea1 100644 --- a/src/state/models/root-store.ts +++ b/src/state/models/root-store.ts @@ -4,12 +4,21 @@ import {Instance, SnapshotOut, types} from 'mobx-state-tree' import {createContext, useContext} from 'react' +import {SessionModel, createDefaultSession} from './session' -export const RootStoreModel = types.model('RootStore').props({}) +export const RootStoreModel = types.model('RootStore').props({ + session: SessionModel, +}) export interface RootStore extends Instance<typeof RootStoreModel> {} export interface RootStoreSnapshot extends SnapshotOut<typeof RootStoreModel> {} +export function createDefaultRootStore() { + return { + session: createDefaultSession(), + } +} + // react context & hook utilities const RootStoreContext = createContext<RootStore>({} as RootStore) export const RootStoreProvider = RootStoreContext.Provider diff --git a/src/state/models/session.ts b/src/state/models/session.ts new file mode 100644 index 000000000..675feb8bc --- /dev/null +++ b/src/state/models/session.ts @@ -0,0 +1,21 @@ +import {Instance, SnapshotOut, types} from 'mobx-state-tree' + +export const SessionModel = types + .model('Session') + .props({ + isAuthed: types.boolean, + }) + .actions(self => ({ + setAuthed: (v: boolean) => { + self.isAuthed = v + }, + })) + +export interface Session extends Instance<typeof SessionModel> {} +export interface SessionSnapshot extends SnapshotOut<typeof SessionModel> {} + +export function createDefaultSession() { + return { + isAuthed: false, + } +} diff --git a/yarn.lock b/yarn.lock index 9202cfe7b..837633c54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8564,6 +8564,11 @@ mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "^1.2.6" +mobx-react-lite@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.0.tgz#d59156a96889cdadad751e5e4dab95f28926dfff" + integrity sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ== + mobx-state-tree@^5.1.5: version "5.1.5" resolved "https://registry.yarnpkg.com/mobx-state-tree/-/mobx-state-tree-5.1.5.tgz#7344d61072705747abb98d23ad21302e38200105" |