Add routes and core views
This commit is contained in:
parent
d6942bffab
commit
fc3b2952bb
16 changed files with 293 additions and 118 deletions
|
@ -1,52 +1,6 @@
|
|||
import React, {useState, useEffect} from 'react'
|
||||
import {
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
Text,
|
||||
Button,
|
||||
useColorScheme,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {NavigationContainer} from '@react-navigation/native'
|
||||
import {
|
||||
createNativeStackNavigator,
|
||||
NativeStackScreenProps,
|
||||
} from '@react-navigation/native-stack'
|
||||
import {RootStore, setupState, RootStoreProvider} from './state'
|
||||
|
||||
type RootStackParamList = {
|
||||
Home: undefined
|
||||
Profile: {name: string}
|
||||
}
|
||||
const Stack = createNativeStackNavigator()
|
||||
|
||||
const HomeScreen = ({
|
||||
navigation,
|
||||
}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
|
||||
const isDarkMode = useColorScheme() === 'dark'
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic">
|
||||
<View>
|
||||
<Text>Native</Text>
|
||||
<Button
|
||||
title="Go to Jane's profile"
|
||||
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
const ProfileScreen = ({
|
||||
route,
|
||||
}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
|
||||
return <Text>This is {route.params.name}'s profile</Text>
|
||||
}
|
||||
import * as Routes from './routes'
|
||||
|
||||
function App() {
|
||||
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
|
||||
|
@ -63,16 +17,7 @@ function App() {
|
|||
|
||||
return (
|
||||
<RootStoreProvider value={rootStore}>
|
||||
<NavigationContainer>
|
||||
<Stack.Navigator>
|
||||
<Stack.Screen
|
||||
name="Home"
|
||||
component={HomeScreen}
|
||||
options={{title: 'Welcome'}}
|
||||
/>
|
||||
<Stack.Screen name="Profile" component={ProfileScreen} />
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
<Routes.Root />
|
||||
</RootStoreProvider>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,52 +1,6 @@
|
|||
import React, {useState, useEffect} from 'react'
|
||||
import {
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
Text,
|
||||
Button,
|
||||
useColorScheme,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {NavigationContainer} from '@react-navigation/native'
|
||||
import {
|
||||
createNativeStackNavigator,
|
||||
NativeStackScreenProps,
|
||||
} from '@react-navigation/native-stack'
|
||||
import {RootStore, setupState, RootStoreProvider} from './state'
|
||||
|
||||
type RootStackParamList = {
|
||||
Home: undefined
|
||||
Profile: {name: string}
|
||||
}
|
||||
const Stack = createNativeStackNavigator()
|
||||
|
||||
const HomeScreen = ({
|
||||
navigation,
|
||||
}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
|
||||
const isDarkMode = useColorScheme() === 'dark'
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic">
|
||||
<View>
|
||||
<Text>Web</Text>
|
||||
<Button
|
||||
title="Go to Jane's profile"
|
||||
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
const ProfileScreen = ({
|
||||
route,
|
||||
}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
|
||||
return <Text>This is {route.params.name}'s profile</Text>
|
||||
}
|
||||
import * as Routes from './routes'
|
||||
|
||||
function App() {
|
||||
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
|
||||
|
@ -63,16 +17,7 @@ function App() {
|
|||
|
||||
return (
|
||||
<RootStoreProvider value={rootStore}>
|
||||
<NavigationContainer>
|
||||
<Stack.Navigator>
|
||||
<Stack.Screen
|
||||
name="Home"
|
||||
component={HomeScreen}
|
||||
options={{title: 'Welcome'}}
|
||||
/>
|
||||
<Stack.Screen name="Profile" component={ProfileScreen} />
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
<Routes.Root />
|
||||
</RootStoreProvider>
|
||||
)
|
||||
}
|
||||
|
|
72
src/routes/index.tsx
Normal file
72
src/routes/index.tsx
Normal file
|
@ -0,0 +1,72 @@
|
|||
import React from 'react'
|
||||
import {Text} from 'react-native'
|
||||
import {
|
||||
NavigationContainer,
|
||||
LinkingOptions,
|
||||
RouteProp,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/native'
|
||||
import {createNativeStackNavigator} from '@react-navigation/native-stack'
|
||||
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
|
||||
import type {RootStackParamList} from './types'
|
||||
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 {NotFound} from '../screens/NotFound'
|
||||
|
||||
const linking: LinkingOptions<RootStackParamList> = {
|
||||
prefixes: [
|
||||
'http://localhost:3000', // local dev
|
||||
],
|
||||
config: {
|
||||
screens: {
|
||||
Primary: {
|
||||
screens: {
|
||||
Home: '',
|
||||
Search: 'search',
|
||||
Notifications: 'notifications',
|
||||
Menu: 'menu',
|
||||
},
|
||||
},
|
||||
Profile: 'profile/:name',
|
||||
NotFound: '*',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const RootStack = createNativeStackNavigator()
|
||||
export const PrimaryTab = createBottomTabNavigator()
|
||||
|
||||
const tabBarScreenOptions = ({
|
||||
route,
|
||||
}: {
|
||||
route: RouteProp<ParamListBase, string>
|
||||
}) => ({
|
||||
tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => {
|
||||
// TODO: icons
|
||||
return <Text>{route.name.at(0)}</Text>
|
||||
},
|
||||
})
|
||||
|
||||
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>
|
||||
)
|
||||
|
||||
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>
|
||||
)
|
24
src/routes/types.ts
Normal file
24
src/routes/types.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import type {NavigatorScreenParams} from '@react-navigation/native'
|
||||
import type {CompositeScreenProps} from '@react-navigation/native'
|
||||
import type {StackScreenProps} from '@react-navigation/stack'
|
||||
import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs'
|
||||
|
||||
export type RootStackParamList = {
|
||||
Primary: undefined
|
||||
Profile: {name: string}
|
||||
NotFound: undefined
|
||||
}
|
||||
export type RootStackScreenProps<T extends keyof RootStackParamList> =
|
||||
StackScreenProps<RootStackParamList, T>
|
||||
|
||||
export type PrimaryTabParamList = {
|
||||
Home: NavigatorScreenParams<RootStackParamList>
|
||||
Search: undefined
|
||||
Notifications: undefined
|
||||
Menu: undefined
|
||||
}
|
||||
export type PrimaryTabScreenProps<T extends keyof PrimaryTabParamList> =
|
||||
CompositeScreenProps<
|
||||
BottomTabScreenProps<PrimaryTabParamList, T>,
|
||||
RootStackScreenProps<keyof RootStackParamList>
|
||||
>
|
17
src/screens/Home.tsx
Normal file
17
src/screens/Home.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from 'react'
|
||||
import {Text, Button, View, SafeAreaView} from 'react-native'
|
||||
import type {PrimaryTabScreenProps} from '../routes/types'
|
||||
|
||||
export const Home = ({navigation}: PrimaryTabScreenProps<'Home'>) => {
|
||||
return (
|
||||
<SafeAreaView style={{flex: 1}}>
|
||||
<View style={{flex: 1}}>
|
||||
<Text>Hello world</Text>
|
||||
<Button
|
||||
title="Go to Jane's profile"
|
||||
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
|
||||
/>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
19
src/screens/Menu.tsx
Normal file
19
src/screens/Menu.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from 'react'
|
||||
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
|
||||
import type {PrimaryTabScreenProps} from '../routes/types'
|
||||
|
||||
export const Menu = ({navigation}: PrimaryTabScreenProps<'Menu'>) => {
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic">
|
||||
<View>
|
||||
<Text>Hello world</Text>
|
||||
<Button
|
||||
title="Go to Jane's profile"
|
||||
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
27
src/screens/NotFound.tsx
Normal file
27
src/screens/NotFound.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import React from 'react'
|
||||
import {
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
Text,
|
||||
Button,
|
||||
useColorScheme,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import type {RootStackScreenProps} from '../routes/types'
|
||||
|
||||
export const NotFound = ({navigation}: RootStackScreenProps<'NotFound'>) => {
|
||||
const isDarkMode = useColorScheme() === 'dark'
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic">
|
||||
<View>
|
||||
<Text>Page not found</Text>
|
||||
<Button title="Home" onPress={() => navigation.navigate('Primary')} />
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
21
src/screens/Notifications.tsx
Normal file
21
src/screens/Notifications.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from 'react'
|
||||
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
|
||||
import type {PrimaryTabScreenProps} from '../routes/types'
|
||||
|
||||
export const Notifications = ({
|
||||
navigation,
|
||||
}: PrimaryTabScreenProps<'Notifications'>) => {
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic">
|
||||
<View>
|
||||
<Text>Hello world</Text>
|
||||
<Button
|
||||
title="Go to Jane's profile"
|
||||
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
7
src/screens/Profile.tsx
Normal file
7
src/screens/Profile.tsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
import React from 'react'
|
||||
import {Text} from 'react-native'
|
||||
import type {RootStackScreenProps} from '../routes/types'
|
||||
|
||||
export const Profile = ({route}: RootStackScreenProps<'Profile'>) => {
|
||||
return <Text>This is {route.params.name}'s profile</Text>
|
||||
}
|
19
src/screens/Search.tsx
Normal file
19
src/screens/Search.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from 'react'
|
||||
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
|
||||
import type {PrimaryTabScreenProps} from '../routes/types'
|
||||
|
||||
export const Search = ({navigation}: PrimaryTabScreenProps<'Search'>) => {
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic">
|
||||
<View>
|
||||
<Text>Hello world</Text>
|
||||
<Button
|
||||
title="Go to Jane's profile"
|
||||
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue