WIP Switch to react-navigation 3
This commit is contained in:
+130
-56
@@ -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,
|
||||||
return (
|
'Settings'
|
||||||
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
|
>) {
|
||||||
<Text>{name} Screen</Text>
|
return (
|
||||||
<Button
|
<View>
|
||||||
title="Go to Home"
|
<Text>SettingsScreen</Text>
|
||||||
onPress={() => navigation.navigate('Home')}
|
</View>
|
||||||
/>
|
)
|
||||||
<Button title="Go back" onPress={() => navigation.goBack()} />
|
|
||||||
<Button
|
|
||||||
title="Go back to first screen in stack"
|
|
||||||
onPress={() => navigation.popToTop()}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SettingsScreen = debugMkScreen('Settings')
|
function ProfileScreen({
|
||||||
const ProfileScreen = debugMkScreen('Profile')
|
route,
|
||||||
const ProfileFollowersScreen = debugMkScreen('ProfileFollowers')
|
}: NativeStackScreenProps<CommonNavigatorParams, 'Profile'>) {
|
||||||
const ProfileFollowsScreen = debugMkScreen('ProfileFollows')
|
return (
|
||||||
const PostThreadScreen = debugMkScreen('PostThread')
|
<View>
|
||||||
const PostUpvotedByScreen = debugMkScreen('PostUpvotedBy')
|
<Text>ProfileScreen {route.params.name}</Text>
|
||||||
const PostDownvotedByScreen = debugMkScreen('PostDownvotedBy')
|
</View>
|
||||||
const PostRepostedByScreen = debugMkScreen('PostRepostedBy')
|
)
|
||||||
const DebugScreen = debugMkScreen('Debug')
|
}
|
||||||
const LogScreen = debugMkScreen('Log')
|
|
||||||
|
function ProfileFollowersScreen({
|
||||||
|
route,
|
||||||
|
}: NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'>) {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>ProfileFollowersScreen {route.params.name}</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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} />
|
||||||
|
|||||||
Reference in New Issue
Block a user