···200 e.GET("/support/community-guidelines", server.WebGeneric)
201 e.GET("/support/copyright", server.WebGeneric)
202 e.GET("/intent/compose", server.WebGeneric)
00203204 // profile endpoints; only first populates info
205 e.GET("/profile/:handleOrDID", server.WebProfile)
···200 e.GET("/support/community-guidelines", server.WebGeneric)
201 e.GET("/support/copyright", server.WebGeneric)
202 e.GET("/intent/compose", server.WebGeneric)
203+ e.GET("/messages", server.WebGeneric)
204+ e.GET("/messages/:conversation", server.WebGeneric)
205206 // profile endpoints; only first populates info
207 e.GET("/profile/:handleOrDID", server.WebProfile)
+50
src/Navigation.tsx
···25 FeedsTabNavigatorParams,
26 FlatNavigatorParams,
27 HomeTabNavigatorParams,
028 MyProfileTabNavigatorParams,
29 NotificationsTabNavigatorParams,
30 SearchTabNavigatorParams,
···46import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration'
47import {attachRouteToLogEvents, logEvent} from './lib/statsig/statsig'
48import {router} from './routes'
00049import {useModalControls} from './state/modals'
50import {useUnreadNotifications} from './state/queries/notifications/unread'
51import {useSession} from './state/session'
···92 createNativeStackNavigatorWithAuth<NotificationsTabNavigatorParams>()
93const MyProfileTab =
94 createNativeStackNavigatorWithAuth<MyProfileTabNavigatorParams>()
0095const Flat = createNativeStackNavigatorWithAuth<FlatNavigatorParams>()
96const Tab = createBottomTabNavigator<BottomTabNavigatorParams>()
97···290 getComponent={() => HashtagScreen}
291 options={{title: title(msg`Hashtag`)}}
292 />
0000000000293 </>
294 )
295}
···322 <Tab.Screen
323 name="MyProfileTab"
324 getComponent={() => MyProfileTabNavigator}
0000325 />
326 </Tab.Navigator>
327 )
···429 )
430}
4310000000000000000000000432/**
433 * The FlatNavigator is used by Web to represent the routes
434 * in a single ("flat") stack.
···468 name="Notifications"
469 getComponent={() => NotificationsScreen}
470 options={{title: title(msg`Notifications`), requireAuth: true}}
00000471 />
472 {commonScreens(Flat as typeof HomeTab, numUnread)}
473 </Flat.Navigator>
···521 }
522 if (name === 'Home') {
523 return buildStateObject('HomeTab', 'Home', params)
000524 }
525 // if the path is something else, like a post, profile, or even settings, we need to initialize the home tab as pre-existing state otherwise the back button will not work
526 return buildStateObject('HomeTab', name, params, [
···25 FeedsTabNavigatorParams,
26 FlatNavigatorParams,
27 HomeTabNavigatorParams,
28+ MessagesTabNavigatorParams,
29 MyProfileTabNavigatorParams,
30 NotificationsTabNavigatorParams,
31 SearchTabNavigatorParams,
···47import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration'
48import {attachRouteToLogEvents, logEvent} from './lib/statsig/statsig'
49import {router} from './routes'
50+import {MessagesConversationScreen} from './screens/Messages/Conversation'
51+import {MessagesListScreen} from './screens/Messages/List'
52+import {MessagesSettingsScreen} from './screens/Messages/Settings'
53import {useModalControls} from './state/modals'
54import {useUnreadNotifications} from './state/queries/notifications/unread'
55import {useSession} from './state/session'
···96 createNativeStackNavigatorWithAuth<NotificationsTabNavigatorParams>()
97const MyProfileTab =
98 createNativeStackNavigatorWithAuth<MyProfileTabNavigatorParams>()
99+const MessagesTab =
100+ createNativeStackNavigatorWithAuth<MessagesTabNavigatorParams>()
101const Flat = createNativeStackNavigatorWithAuth<FlatNavigatorParams>()
102const Tab = createBottomTabNavigator<BottomTabNavigatorParams>()
103···296 getComponent={() => HashtagScreen}
297 options={{title: title(msg`Hashtag`)}}
298 />
299+ <Stack.Screen
300+ name="MessagesConversation"
301+ getComponent={() => MessagesConversationScreen}
302+ options={{title: title(msg`Chat`), requireAuth: true}}
303+ />
304+ <Stack.Screen
305+ name="MessagesSettings"
306+ getComponent={() => MessagesSettingsScreen}
307+ options={{title: title(msg`Messaging settings`), requireAuth: true}}
308+ />
309 </>
310 )
311}
···338 <Tab.Screen
339 name="MyProfileTab"
340 getComponent={() => MyProfileTabNavigator}
341+ />
342+ <Tab.Screen
343+ name="MessagesTab"
344+ getComponent={() => MessagesTabNavigator}
345 />
346 </Tab.Navigator>
347 )
···449 )
450}
451452+function MessagesTabNavigator() {
453+ const pal = usePalette('default')
454+ return (
455+ <MessagesTab.Navigator
456+ screenOptions={{
457+ animation: isAndroid ? 'none' : undefined,
458+ gestureEnabled: true,
459+ fullScreenGestureEnabled: true,
460+ headerShown: false,
461+ animationDuration: 250,
462+ contentStyle: pal.view,
463+ }}>
464+ <MessagesTab.Screen
465+ name="MessagesList"
466+ getComponent={() => MessagesListScreen}
467+ options={{requireAuth: true}}
468+ />
469+ {commonScreens(MessagesTab as typeof HomeTab)}
470+ </MessagesTab.Navigator>
471+ )
472+}
473+474/**
475 * The FlatNavigator is used by Web to represent the routes
476 * in a single ("flat") stack.
···510 name="Notifications"
511 getComponent={() => NotificationsScreen}
512 options={{title: title(msg`Notifications`), requireAuth: true}}
513+ />
514+ <Flat.Screen
515+ name="MessagesList"
516+ getComponent={() => MessagesListScreen}
517+ options={{title: title(msg`Messages`), requireAuth: true}}
518 />
519 {commonScreens(Flat as typeof HomeTab, numUnread)}
520 </Flat.Navigator>
···568 }
569 if (name === 'Home') {
570 return buildStateObject('HomeTab', 'Home', params)
571+ }
572+ if (name === 'Messages') {
573+ return buildStateObject('MessagesTab', 'MessagesList', params)
574 }
575 // if the path is something else, like a post, profile, or even settings, we need to initialize the home tab as pre-existing state otherwise the back button will not work
576 return buildStateObject('HomeTab', name, params, [
···1import {useNavigationState} from '@react-navigation/native'
02import {getTabState, TabState} from 'lib/routes/helpers'
34export function useNavigationTabState() {
···10 isAtNotifications:
11 getTabState(state, 'Notifications') !== TabState.Outside,
12 isAtMyProfile: getTabState(state, 'MyProfile') !== TabState.Outside,
013 }
14 if (
15 !res.isAtHome &&
16 !res.isAtSearch &&
17 !res.isAtFeeds &&
18 !res.isAtNotifications &&
19- !res.isAtMyProfile
020 ) {
21 // HACK for some reason useNavigationState will give us pre-hydration results
22 // and not update after, so we force isAtHome if all came back false
···1import {useNavigationState} from '@react-navigation/native'
2+3import {getTabState, TabState} from 'lib/routes/helpers'
45export function useNavigationTabState() {
···11 isAtNotifications:
12 getTabState(state, 'Notifications') !== TabState.Outside,
13 isAtMyProfile: getTabState(state, 'MyProfile') !== TabState.Outside,
14+ isAtMessages: getTabState(state, 'MessagesList') !== TabState.Outside,
15 }
16 if (
17 !res.isAtHome &&
18 !res.isAtSearch &&
19 !res.isAtFeeds &&
20 !res.isAtNotifications &&
21+ !res.isAtMyProfile &&
22+ !res.isAtMessages
23 ) {
24 // HACK for some reason useNavigationState will give us pre-hydration results
25 // and not update after, so we force isAtHome if all came back false
+1-1
src/lib/routes/router.ts
···1-import {RouteParams, Route} from './types'
23export class Router {
4 routes: [string, Route][] = []
···1+import {Route, RouteParams} from './types'
23export class Router {
4 routes: [string, Route][] = []