about summary refs log tree commit diff
path: root/src/Navigation.tsx
diff options
context:
space:
mode:
authorLW <git@llllvvuu.dev>2023-05-16 11:13:05 -0700
committerGitHub <noreply@github.com>2023-05-16 13:13:05 -0500
commit50c1841a06d0502428f70bb0bb225cca70f82c20 (patch)
tree47b12090bb18e04e599a45cae7648135c772ab28 /src/Navigation.tsx
parenta5838694bd7debecc1d66ce8f8e4492350ea289f (diff)
downloadvoidsky-50c1841a06d0502428f70bb0bb225cca70f82c20.tar.zst
feat: Update HTML `title` on web #626 #599 (#655)
For any `Screen` that shows on desktop, `title` is "(1) ... - Bluesky"
where "(1)" is the unread notification count.

The titles are unlocalized and the string "Bluesky" is hardcoded,
following the pattern of the rest of the app.

Display names and post content are loaded into the title as effects.

Tested:
* all screens
* screen changes / component mounts/unmounts
* long posts with links and images
* display name set/unset
* spamming myself with notifications, clearing notifications
* /profile/did:... links
* lint (only my changed files), jest, e2e.

New utilities: `useUnreadCountLabel`, `bskyTitle`,
`combinedDisplayName`, `useSetTitle`.

resolves: #626 #599
Diffstat (limited to 'src/Navigation.tsx')
-rw-r--r--src/Navigation.tsx133
1 files changed, 112 insertions, 21 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index 4e0403be9..17bb3c159 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -28,6 +28,7 @@ import {isNative} from 'platform/detection'
 import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
 import {router} from './routes'
 import {usePalette} from 'lib/hooks/usePalette'
+import {useUnreadCountLabel} from 'lib/hooks/useUnreadCountLabel'
 import {useStores} from './state'
 
 import {HomeScreen} from './view/screens/Home'
@@ -55,6 +56,7 @@ import {AppPasswords} from 'view/screens/AppPasswords'
 import {ModerationMutedAccounts} from 'view/screens/ModerationMutedAccounts'
 import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
 import {getRoutingInstrumentation} from 'lib/sentry'
+import {bskyTitle} from 'lib/strings/headings'
 
 const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
 
@@ -69,45 +71,120 @@ const Tab = createBottomTabNavigator<BottomTabNavigatorParams>()
 /**
  * These "common screens" are reused across stacks.
  */
-function commonScreens(Stack: typeof HomeTab) {
+function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
+  const title = (page: string) => bskyTitle(page, unreadCountLabel)
+
   return (
     <>
-      <Stack.Screen name="NotFound" component={NotFoundScreen} />
-      <Stack.Screen name="Moderation" component={ModerationScreen} />
+      <Stack.Screen
+        name="NotFound"
+        component={NotFoundScreen}
+        options={{title: title('Not Found')}}
+      />
+      <Stack.Screen
+        name="Moderation"
+        component={ModerationScreen}
+        options={{title: title('Moderation')}}
+      />
       <Stack.Screen
         name="ModerationMuteLists"
         component={ModerationMuteListsScreen}
+        options={{title: title('Mute Lists')}}
       />
       <Stack.Screen
         name="ModerationMutedAccounts"
         component={ModerationMutedAccounts}
+        options={{title: title('Muted Accounts')}}
       />
       <Stack.Screen
         name="ModerationBlockedAccounts"
         component={ModerationBlockedAccounts}
+        options={{title: title('Blocked Accounts')}}
+      />
+      <Stack.Screen
+        name="Settings"
+        component={SettingsScreen}
+        options={{title: title('Settings')}}
+      />
+      <Stack.Screen
+        name="Profile"
+        component={ProfileScreen}
+        options={({route}) => ({title: title(`@${route.params.name}`)})}
       />
-      <Stack.Screen name="Settings" component={SettingsScreen} />
-      <Stack.Screen name="Profile" component={ProfileScreen} />
       <Stack.Screen
         name="ProfileFollowers"
         component={ProfileFollowersScreen}
+        options={({route}) => ({
+          title: title(`People following @${route.params.name}`),
+        })}
+      />
+      <Stack.Screen
+        name="ProfileFollows"
+        component={ProfileFollowsScreen}
+        options={({route}) => ({
+          title: title(`People followed by @${route.params.name}`),
+        })}
+      />
+      <Stack.Screen
+        name="ProfileList"
+        component={ProfileListScreen}
+        options={{title: title('Mute List')}}
+      />
+      <Stack.Screen
+        name="PostThread"
+        component={PostThreadScreen}
+        options={({route}) => ({title: title(`Post by @${route.params.name}`)})}
+      />
+      <Stack.Screen
+        name="PostLikedBy"
+        component={PostLikedByScreen}
+        options={({route}) => ({title: title(`Post by @${route.params.name}`)})}
+      />
+      <Stack.Screen
+        name="PostRepostedBy"
+        component={PostRepostedByScreen}
+        options={({route}) => ({title: title(`Post by @${route.params.name}`)})}
+      />
+      <Stack.Screen
+        name="Debug"
+        component={DebugScreen}
+        options={{title: title('Debug')}}
+      />
+      <Stack.Screen
+        name="Log"
+        component={LogScreen}
+        options={{title: title('Log')}}
+      />
+      <Stack.Screen
+        name="Support"
+        component={SupportScreen}
+        options={{title: title('Support')}}
+      />
+      <Stack.Screen
+        name="PrivacyPolicy"
+        component={PrivacyPolicyScreen}
+        options={{title: title('Privacy Policy')}}
+      />
+      <Stack.Screen
+        name="TermsOfService"
+        component={TermsOfServiceScreen}
+        options={{title: title('Terms of Service')}}
       />
-      <Stack.Screen name="ProfileFollows" component={ProfileFollowsScreen} />
-      <Stack.Screen name="ProfileList" component={ProfileListScreen} />
-      <Stack.Screen name="PostThread" component={PostThreadScreen} />
-      <Stack.Screen name="PostLikedBy" component={PostLikedByScreen} />
-      <Stack.Screen name="PostRepostedBy" component={PostRepostedByScreen} />
-      <Stack.Screen name="Debug" component={DebugScreen} />
-      <Stack.Screen name="Log" component={LogScreen} />
-      <Stack.Screen name="Support" component={SupportScreen} />
-      <Stack.Screen name="PrivacyPolicy" component={PrivacyPolicyScreen} />
-      <Stack.Screen name="TermsOfService" component={TermsOfServiceScreen} />
       <Stack.Screen
         name="CommunityGuidelines"
         component={CommunityGuidelinesScreen}
+        options={{title: title('Community Guidelines')}}
+      />
+      <Stack.Screen
+        name="CopyrightPolicy"
+        component={CopyrightPolicyScreen}
+        options={{title: title('Copyright Policy')}}
+      />
+      <Stack.Screen
+        name="AppPasswords"
+        component={AppPasswords}
+        options={{title: title('App Passwords')}}
       />
-      <Stack.Screen name="CopyrightPolicy" component={CopyrightPolicyScreen} />
-      <Stack.Screen name="AppPasswords" component={AppPasswords} />
     </>
   )
 }
@@ -221,6 +298,8 @@ const MyProfileTabNavigator = observer(() => {
  */
 function FlatNavigator() {
   const pal = usePalette('default')
+  const unreadCountLabel = useUnreadCountLabel()
+  const title = (page: string) => bskyTitle(page, unreadCountLabel)
   return (
     <Flat.Navigator
       screenOptions={{
@@ -230,10 +309,22 @@ function FlatNavigator() {
         animationDuration: 250,
         contentStyle: [pal.view],
       }}>
-      <Flat.Screen name="Home" component={HomeScreen} />
-      <Flat.Screen name="Search" component={SearchScreen} />
-      <Flat.Screen name="Notifications" component={NotificationsScreen} />
-      {commonScreens(Flat as typeof HomeTab)}
+      <Flat.Screen
+        name="Home"
+        component={HomeScreen}
+        options={{title: title('Home')}}
+      />
+      <Flat.Screen
+        name="Search"
+        component={SearchScreen}
+        options={{title: title('Search')}}
+      />
+      <Flat.Screen
+        name="Notifications"
+        component={NotificationsScreen}
+        options={{title: title('Notifications')}}
+      />
+      {commonScreens(Flat as typeof HomeTab, unreadCountLabel)}
     </Flat.Navigator>
   )
 }