WIP Switch to react-navigation 3

This commit is contained in:
Paul Frazee
2023-03-09 18:45:59 -06:00
parent bf951421ea
commit 6a4961caa5
+126 -52
View File
@@ -1,43 +1,44 @@
import * as React from 'react' import * as React from 'react'
import {View, Text, Button} from 'react-native' import {View, Text, Button} from 'react-native'
import {NavigationContainer} from '@react-navigation/native' import {NavigationContainer} from '@react-navigation/native'
import {createNativeStackNavigator} from '@react-navigation/native-stack' import {
createNativeStackNavigator,
NativeStackScreenProps,
} from '@react-navigation/native-stack'
import {createDrawerNavigator} from '@react-navigation/drawer' import {createDrawerNavigator} from '@react-navigation/drawer'
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs' import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import {NavigationState, PartialState} from '@react-navigation/native' import {NavigationState, PartialState} from '@react-navigation/native'
type CommonNavigatorParamlist = { type CommonNavigatorParams = {
Settings: undefined Settings: undefined
Profile: {name: string} Profile: {name: string}
ProfileFollowers: {name: string} ProfileFollowers: {name: string}
ProfileFollows: {name: string} ProfileFollows: {name: string}
PostThread: {name: string; rkey: string} PostThread: {name: string; rkey: string}
PostUpvotedBy: {name: string; rkey: string} PostUpvotedBy: {name: string; rkey: string}
PostDownvotedBy: {name: string; rkey: string}
PostRepostedBy: {name: string; rkey: string} PostRepostedBy: {name: string; rkey: string}
Debug: undefined Debug: undefined
Log: undefined Log: undefined
} }
type HomeStackNavigatorParamlist = CommonNavigatorParamlist & { type HomeStackNavigatorParams = CommonNavigatorParams & {
Home: undefined Home: undefined
} }
type NotificationsStackNavigatorParamlist = CommonNavigatorParamlist & { type NotificationsStackNavigatorParams = CommonNavigatorParams & {
Notifications: undefined Notifications: undefined
} }
type SearchStackNavigatorParamlist = CommonNavigatorParamlist & { type SearchStackNavigatorParams = CommonNavigatorParams & {
Search: undefined Search: undefined
} }
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'> type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>
const HomeDrawer = createDrawerNavigator() const HomeDrawer = createDrawerNavigator()
const HomeStack = createNativeStackNavigator<HomeStackNavigatorParamlist>() const HomeStack = createNativeStackNavigator<HomeStackNavigatorParams>()
const SearchDrawer = createDrawerNavigator() const SearchDrawer = createDrawerNavigator()
const SearchStack = const SearchStack = createNativeStackNavigator<SearchStackNavigatorParams>()
createNativeStackNavigator<NotificationsStackNavigatorParamlist>()
const NotificationsDrawer = createDrawerNavigator() const NotificationsDrawer = createDrawerNavigator()
const NotificationsStack = const NotificationsStack =
createNativeStackNavigator<SearchStackNavigatorParamlist>() createNativeStackNavigator<NotificationsStackNavigatorParams>()
const Tab = createBottomTabNavigator() const Tab = createBottomTabNavigator()
type RouteParams = Record<string, string> type RouteParams = Record<string, string>
@@ -78,7 +79,6 @@ const ROUTES: Record<string, Route> = {
ProfileFollows: r('/profile/:name/follows'), ProfileFollows: r('/profile/:name/follows'),
PostThread: r('/profile/:name/post/:rkey'), PostThread: r('/profile/:name/post/:rkey'),
PostUpvotedBy: r('/profile/:name/post/:rkey/upvoted-by'), PostUpvotedBy: r('/profile/:name/post/:rkey/upvoted-by'),
PostDownvotedBy: r('/profile/:name/post/:rkey/downvoted-by'),
PostRepostedBy: r('/profile/:name/post/:rkey/reposted-by'), PostRepostedBy: r('/profile/:name/post/:rkey/reposted-by'),
Debug: r('/sys/debug'), Debug: r('/sys/debug'),
Log: r('/sys/log'), Log: r('/sys/log'),
@@ -87,7 +87,7 @@ const ROUTES: Record<string, Route> = {
const LINKING = { const LINKING = {
prefixes: ['bsky://', 'https://bsky.app'], prefixes: ['bsky://', 'https://bsky.app'],
getPathFromState(state: State, options?: any) { getPathFromState(state: State) {
// find the current node in the navigation tree // find the current node in the navigation tree
let node = state.routes[state.index] let node = state.routes[state.index]
while (node.state?.routes && typeof node.state?.index === 'number') { while (node.state?.routes && typeof node.state?.index === 'number') {
@@ -99,15 +99,13 @@ const LINKING = {
if (typeof route === 'undefined') { if (typeof route === 'undefined') {
return '/' // default to home return '/' // default to home
} }
return route.build({ return route.build((node.params || {}) as RouteParams)
/* TODO */
})
}, },
getStateFromPath(path: string, options?: any) { getStateFromPath(path: string) {
// match the route // match the route
let match = 'Home' // TODO should be not found let match = 'Home' // TODO should be not found
let params: Record<string, string> = {} let params: RouteParams = {}
for (const [name, matcher] of Object.entries(ROUTES)) { for (const [name, matcher] of Object.entries(ROUTES)) {
const res = matcher.match(path) const res = matcher.match(path)
if (res) { if (res) {
@@ -118,7 +116,6 @@ const LINKING = {
} }
// build the state object // build the state object
// TODO params
let container = 'HomeStack' let container = 'HomeStack'
if (match === 'Notifications') { if (match === 'Notifications') {
container = 'NotificationsStack' container = 'NotificationsStack'
@@ -130,7 +127,7 @@ const LINKING = {
{ {
name: container, name: container,
state: { state: {
routes: [{name: match}], routes: [{name: match, params}],
}, },
}, },
], ],
@@ -138,83 +135,161 @@ const LINKING = {
}, },
} }
function HomeScreen({navigation}) { function HomeScreen({
navigation,
}: NativeStackScreenProps<HomeStackNavigatorParams, 'Home'>) {
return ( return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}> <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Home Screen</Text> <Text>Home Screen</Text>
<Button <Button
title="Go to Post" title="Go to Post"
onPress={() => navigation.push('PostThread', {name: 'bob', rkey: 123})} onPress={() =>
navigation.push('PostThread', {name: 'bob', rkey: '123'})
}
/> />
<Button <Button
title="Go to profile" title="Go to profile"
onPress={() => navigation.push('Profile')} onPress={() => navigation.push('Profile', {name: 'alice'})}
/> />
</View> </View>
) )
} }
function NotificationsScreen({navigation}) { function NotificationsScreen({
navigation,
}: NativeStackScreenProps<NotificationsStackNavigatorParams, 'Notifications'>) {
return ( return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}> <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Notifications Screen</Text> <Text>Notifications Screen</Text>
<Button <Button
title="Go to Post" title="Go to Post"
onPress={() => navigation.push('PostThread', {name: 'bob', rkey: 123})} onPress={() =>
navigation.push('PostThread', {name: 'bob', rkey: '123'})
}
/> />
<Button <Button
title="Go to profile" title="Go to profile"
onPress={() => navigation.push('Profile')} onPress={() => navigation.push('Profile', {name: 'alice'})}
/> />
</View> </View>
) )
} }
function SearchScreen({navigation}) { function SearchScreen({
navigation,
}: NativeStackScreenProps<SearchStackNavigatorParams, 'Search'>) {
return ( return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}> <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Search Screen</Text> <Text>Search Screen</Text>
<Button <Button
title="Go to Post" title="Go to Post"
onPress={() => navigation.push('PostThread', {name: 'bob', rkey: 123})} onPress={() =>
navigation.push('PostThread', {name: 'bob', rkey: '123'})
}
/> />
<Button <Button
title="Go to profile" title="Go to profile"
onPress={() => navigation.push('Profile')} onPress={() => navigation.push('Profile', {name: 'alice'})}
/> />
</View> </View>
) )
} }
function debugMkScreen(name: string) { function SettingsScreen({}: NativeStackScreenProps<
return function ({navigation}) { CommonNavigatorParams,
'Settings'
>) {
return ( return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}> <View>
<Text>{name} Screen</Text> <Text>SettingsScreen</Text>
<Button
title="Go to Home"
onPress={() => navigation.navigate('Home')}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
<Button
title="Go back to first screen in stack"
onPress={() => navigation.popToTop()}
/>
</View> </View>
) )
} }
function ProfileScreen({
route,
}: NativeStackScreenProps<CommonNavigatorParams, 'Profile'>) {
return (
<View>
<Text>ProfileScreen {route.params.name}</Text>
</View>
)
} }
const SettingsScreen = debugMkScreen('Settings') function ProfileFollowersScreen({
const ProfileScreen = debugMkScreen('Profile') route,
const ProfileFollowersScreen = debugMkScreen('ProfileFollowers') }: NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'>) {
const ProfileFollowsScreen = debugMkScreen('ProfileFollows') return (
const PostThreadScreen = debugMkScreen('PostThread') <View>
const PostUpvotedByScreen = debugMkScreen('PostUpvotedBy') <Text>ProfileFollowersScreen {route.params.name}</Text>
const PostDownvotedByScreen = debugMkScreen('PostDownvotedBy') </View>
const PostRepostedByScreen = debugMkScreen('PostRepostedBy') )
const DebugScreen = debugMkScreen('Debug') }
const LogScreen = debugMkScreen('Log')
function ProfileFollowsScreen({
route,
}: NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'>) {
return (
<View>
<Text>ProfileFollowsScreen {route.params.name}</Text>
</View>
)
}
function PostThreadScreen({
route,
}: NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>) {
return (
<View>
<Text>
PostThreadScreen {route.params.name} {route.params.rkey}
</Text>
</View>
)
}
function PostUpvotedByScreen({
route,
}: NativeStackScreenProps<CommonNavigatorParams, 'PostUpvotedBy'>) {
return (
<View>
<Text>
PostUpvotedByScreen {route.params.name} {route.params.rkey}
</Text>
</View>
)
}
function PostRepostedByScreen({
route,
}: NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>) {
return (
<View>
<Text>
PostRepostedByScreen {route.params.name} {route.params.rkey}
</Text>
</View>
)
}
function DebugScreen({}: NativeStackScreenProps<
CommonNavigatorParams,
'Debug'
>) {
return (
<View>
<Text>DebugScreen</Text>
</View>
)
}
function LogScreen({}: NativeStackScreenProps<CommonNavigatorParams, 'Log'>) {
return (
<View>
<Text>LogScreen</Text>
</View>
)
}
function DrawerContent() { function DrawerContent() {
return ( return (
@@ -236,7 +311,6 @@ function commonScreens(Stack: ReturnType<typeof createNativeStackNavigator>) {
<Stack.Screen name="ProfileFollows" component={ProfileFollowsScreen} /> <Stack.Screen name="ProfileFollows" component={ProfileFollowsScreen} />
<Stack.Screen name="PostThread" component={PostThreadScreen} /> <Stack.Screen name="PostThread" component={PostThreadScreen} />
<Stack.Screen name="PostUpvotedBy" component={PostUpvotedByScreen} /> <Stack.Screen name="PostUpvotedBy" component={PostUpvotedByScreen} />
<Stack.Screen name="PostDownvotedBy" component={PostDownvotedByScreen} />
<Stack.Screen name="PostRepostedBy" component={PostRepostedByScreen} /> <Stack.Screen name="PostRepostedBy" component={PostRepostedByScreen} />
<Stack.Screen name="Debug" component={DebugScreen} /> <Stack.Screen name="Debug" component={DebugScreen} />
<Stack.Screen name="Log" component={LogScreen} /> <Stack.Screen name="Log" component={LogScreen} />