From bf951421eaa8cf2ad05ab150b966f2f425f63e3e Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Thu, 9 Mar 2023 14:54:49 -0600 Subject: [PATCH] WIP Switch to react-navigation 2 --- src/view/screens.tsx | 294 +++++++++++++++++++++++++------------------ 1 file changed, 169 insertions(+), 125 deletions(-) diff --git a/src/view/screens.tsx b/src/view/screens.tsx index b572682b6a..07679df84d 100644 --- a/src/view/screens.tsx +++ b/src/view/screens.tsx @@ -5,56 +5,120 @@ import {createNativeStackNavigator} from '@react-navigation/native-stack' import {createDrawerNavigator} from '@react-navigation/drawer' import {createBottomTabNavigator} from '@react-navigation/bottom-tabs' -import { - getStateFromPath, - NavigationState, - PartialState, -} from '@react-navigation/native' +import {NavigationState, PartialState} from '@react-navigation/native' -type StackNavigatorParamlist = { - FeedList: undefined - Details: { - id: number - name: string - handle: string - date: string - content: string - image: string - avatar: string - comments: number - retweets: number - hearts: number - } +type CommonNavigatorParamlist = { + Settings: undefined + Profile: {name: string} + ProfileFollowers: {name: string} + ProfileFollows: {name: string} + PostThread: {name: string; rkey: string} + PostUpvotedBy: {name: string; rkey: string} + PostDownvotedBy: {name: string; rkey: string} + PostRepostedBy: {name: string; rkey: string} + Debug: undefined + Log: undefined +} +type HomeStackNavigatorParamlist = CommonNavigatorParamlist & { + Home: undefined +} +type NotificationsStackNavigatorParamlist = CommonNavigatorParamlist & { + Notifications: undefined +} +type SearchStackNavigatorParamlist = CommonNavigatorParamlist & { + Search: undefined } type State = NavigationState | Omit, 'stale'> -const PATHS = { - Home: '/', - Notifications: '/notifications', - Search: '/search', - Details: '/details', - Profile: '/profile', +const HomeDrawer = createDrawerNavigator() +const HomeStack = createNativeStackNavigator() +const SearchDrawer = createDrawerNavigator() +const SearchStack = + createNativeStackNavigator() +const NotificationsDrawer = createDrawerNavigator() +const NotificationsStack = + createNativeStackNavigator() +const Tab = createBottomTabNavigator() + +type RouteParams = Record +type MatchResult = {params: RouteParams} +type Route = { + match: (path: string) => MatchResult | undefined + build: (params: RouteParams) => string +} +function r(pattern: string): Route { + let matcherReInternal = pattern.replace( + /:([\w]+)/g, + (_m, name) => `(?<${name}>[^/]+)`, + ) + const matcherRe = new RegExp(`^${matcherReInternal}([?]|$)`, 'i') + return { + match(path: string) { + const res = matcherRe.exec(path) + if (res) { + return {params: res.groups} + } + return undefined + }, + build(params: Record) { + return pattern.replace( + /:([\w]+)/g, + (_m, name) => params[name] || 'undefined', + ) + }, + } +} +const ROUTES: Record = { + Home: r('/'), + Search: r('/search'), + Notifications: r('/notifications'), + Settings: r('/settings'), + Profile: r('/profile/:name'), + ProfileFollowers: r('/profile/:name/followers'), + ProfileFollows: r('/profile/:name/follows'), + PostThread: r('/profile/:name/post/:rkey'), + PostUpvotedBy: r('/profile/:name/post/:rkey/upvoted-by'), + PostDownvotedBy: r('/profile/:name/post/:rkey/downvoted-by'), + PostRepostedBy: r('/profile/:name/post/:rkey/reposted-by'), + Debug: r('/sys/debug'), + Log: r('/sys/log'), } const LINKING = { prefixes: ['bsky://', 'https://bsky.app'], + getPathFromState(state: State, options?: any) { - // TODO add parameterization + // find the current node in the navigation tree let node = state.routes[state.index] while (node.state?.routes && typeof node.state?.index === 'number') { node = node.state?.routes[node.state?.index] } - return PATHS[node.name] || '/' + + // build the path + const route = ROUTES[node.name] + if (typeof route === 'undefined') { + return '/' // default to home + } + return route.build({ + /* TODO */ + }) }, + getStateFromPath(path: string, options?: any) { - // TODO add parameterization + // match the route let match = 'Home' // TODO should be not found - for (const [name, matcher] of Object.entries(PATHS)) { - if (path === matcher) { + let params: Record = {} + for (const [name, matcher] of Object.entries(ROUTES)) { + const res = matcher.match(path) + if (res) { match = name + params = res.params break } } + + // build the state object + // TODO params let container = 'HomeStack' if (match === 'Notifications') { container = 'NotificationsStack' @@ -74,19 +138,13 @@ const LINKING = { }, } -const Drawer = createDrawerNavigator() -const HomeStack = createNativeStackNavigator() -const NotificationsStack = createNativeStackNavigator() -const SearchStack = createNativeStackNavigator() -const Tab = createBottomTabNavigator() - function HomeScreen({navigation}) { return ( Home Screen