about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/state/session/index.tsx5
-rw-r--r--src/view/com/profile/ProfileHeader.tsx175
-rw-r--r--src/view/screens/Profile.tsx48
3 files changed, 126 insertions, 102 deletions
diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx
index d7541295b..1e7fa2297 100644
--- a/src/state/session/index.tsx
+++ b/src/state/session/index.tsx
@@ -9,6 +9,7 @@ import {PUBLIC_BSKY_AGENT} from '#/state/queries'
 import {IS_PROD} from '#/lib/constants'
 import {emitSessionLoaded, emitSessionDropped} from '../events'
 import {useLoggedOutViewControls} from '#/state/shell/logged-out'
+import {useCloseAllActiveElements} from '#/state/util'
 
 let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
 
@@ -520,15 +521,17 @@ export function useSessionApi() {
 export function useRequireAuth() {
   const {hasSession} = useSession()
   const {setShowLoggedOut} = useLoggedOutViewControls()
+  const closeAll = useCloseAllActiveElements()
 
   return React.useCallback(
     (fn: () => void) => {
       if (hasSession) {
         fn()
       } else {
+        closeAll()
         setShowLoggedOut(true)
       }
     },
-    [hasSession, setShowLoggedOut],
+    [hasSession, setShowLoggedOut, closeAll],
   )
 }
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 45998406c..30446fba1 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -51,6 +51,7 @@ import {s, colors} from 'lib/styles'
 import {logger} from '#/logger'
 import {useSession} from '#/state/session'
 import {Shadow} from '#/state/cache/types'
+import {useRequireAuth} from '#/state/session'
 
 interface Props {
   profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> | null
@@ -113,7 +114,8 @@ let ProfileHeaderLoaded = ({
 }: LoadedProps): React.ReactNode => {
   const pal = usePalette('default')
   const palInverted = usePalette('inverted')
-  const {currentAccount} = useSession()
+  const {currentAccount, hasSession} = useSession()
+  const requireAuth = useRequireAuth()
   const {_} = useLingui()
   const {openModal} = useModalControls()
   const {openLightbox} = useLightboxControls()
@@ -150,38 +152,42 @@ let ProfileHeaderLoaded = ({
     }
   }, [openLightbox, profile, moderation])
 
-  const onPressFollow = async () => {
-    try {
-      track('ProfileHeader:FollowButtonClicked')
-      await queueFollow()
-      Toast.show(
-        `Following ${sanitizeDisplayName(
-          profile.displayName || profile.handle,
-        )}`,
-      )
-    } catch (e: any) {
-      if (e?.name !== 'AbortError') {
-        logger.error('Failed to follow', {error: String(e)})
-        Toast.show(`There was an issue! ${e.toString()}`)
+  const onPressFollow = () => {
+    requireAuth(async () => {
+      try {
+        track('ProfileHeader:FollowButtonClicked')
+        await queueFollow()
+        Toast.show(
+          `Following ${sanitizeDisplayName(
+            profile.displayName || profile.handle,
+          )}`,
+        )
+      } catch (e: any) {
+        if (e?.name !== 'AbortError') {
+          logger.error('Failed to follow', {error: String(e)})
+          Toast.show(`There was an issue! ${e.toString()}`)
+        }
       }
-    }
+    })
   }
 
-  const onPressUnfollow = async () => {
-    try {
-      track('ProfileHeader:UnfollowButtonClicked')
-      await queueUnfollow()
-      Toast.show(
-        `No longer following ${sanitizeDisplayName(
-          profile.displayName || profile.handle,
-        )}`,
-      )
-    } catch (e: any) {
-      if (e?.name !== 'AbortError') {
-        logger.error('Failed to unfollow', {error: String(e)})
-        Toast.show(`There was an issue! ${e.toString()}`)
+  const onPressUnfollow = () => {
+    requireAuth(async () => {
+      try {
+        track('ProfileHeader:UnfollowButtonClicked')
+        await queueUnfollow()
+        Toast.show(
+          `No longer following ${sanitizeDisplayName(
+            profile.displayName || profile.handle,
+          )}`,
+        )
+      } catch (e: any) {
+        if (e?.name !== 'AbortError') {
+          logger.error('Failed to unfollow', {error: String(e)})
+          Toast.show(`There was an issue! ${e.toString()}`)
+        }
       }
-    }
+    })
   }
 
   const onPressEditProfile = React.useCallback(() => {
@@ -303,72 +309,75 @@ let ProfileHeaderLoaded = ({
         },
       },
     ]
-    items.push({label: 'separator'})
-    items.push({
-      testID: 'profileHeaderDropdownListAddRemoveBtn',
-      label: _(msg`Add to Lists`),
-      onPress: onPressAddRemoveLists,
-      icon: {
-        ios: {
-          name: 'list.bullet',
+    if (hasSession) {
+      items.push({label: 'separator'})
+      items.push({
+        testID: 'profileHeaderDropdownListAddRemoveBtn',
+        label: _(msg`Add to Lists`),
+        onPress: onPressAddRemoveLists,
+        icon: {
+          ios: {
+            name: 'list.bullet',
+          },
+          android: 'ic_menu_add',
+          web: 'list',
         },
-        android: 'ic_menu_add',
-        web: 'list',
-      },
-    })
-    if (!isMe) {
-      if (!profile.viewer?.blocking) {
-        items.push({
-          testID: 'profileHeaderDropdownMuteBtn',
-          label: profile.viewer?.muted
-            ? _(msg`Unmute Account`)
-            : _(msg`Mute Account`),
-          onPress: profile.viewer?.muted
-            ? onPressUnmuteAccount
-            : onPressMuteAccount,
-          icon: {
-            ios: {
-              name: 'speaker.slash',
+      })
+      if (!isMe) {
+        if (!profile.viewer?.blocking) {
+          items.push({
+            testID: 'profileHeaderDropdownMuteBtn',
+            label: profile.viewer?.muted
+              ? _(msg`Unmute Account`)
+              : _(msg`Mute Account`),
+            onPress: profile.viewer?.muted
+              ? onPressUnmuteAccount
+              : onPressMuteAccount,
+            icon: {
+              ios: {
+                name: 'speaker.slash',
+              },
+              android: 'ic_lock_silent_mode',
+              web: 'comment-slash',
             },
-            android: 'ic_lock_silent_mode',
-            web: 'comment-slash',
-          },
-        })
-      }
-      if (!profile.viewer?.blockingByList) {
+          })
+        }
+        if (!profile.viewer?.blockingByList) {
+          items.push({
+            testID: 'profileHeaderDropdownBlockBtn',
+            label: profile.viewer?.blocking
+              ? _(msg`Unblock Account`)
+              : _(msg`Block Account`),
+            onPress: profile.viewer?.blocking
+              ? onPressUnblockAccount
+              : onPressBlockAccount,
+            icon: {
+              ios: {
+                name: 'person.fill.xmark',
+              },
+              android: 'ic_menu_close_clear_cancel',
+              web: 'user-slash',
+            },
+          })
+        }
         items.push({
-          testID: 'profileHeaderDropdownBlockBtn',
-          label: profile.viewer?.blocking
-            ? _(msg`Unblock Account`)
-            : _(msg`Block Account`),
-          onPress: profile.viewer?.blocking
-            ? onPressUnblockAccount
-            : onPressBlockAccount,
+          testID: 'profileHeaderDropdownReportBtn',
+          label: _(msg`Report Account`),
+          onPress: onPressReportAccount,
           icon: {
             ios: {
-              name: 'person.fill.xmark',
+              name: 'exclamationmark.triangle',
             },
-            android: 'ic_menu_close_clear_cancel',
-            web: 'user-slash',
+            android: 'ic_menu_report_image',
+            web: 'circle-exclamation',
           },
         })
       }
-      items.push({
-        testID: 'profileHeaderDropdownReportBtn',
-        label: _(msg`Report Account`),
-        onPress: onPressReportAccount,
-        icon: {
-          ios: {
-            name: 'exclamationmark.triangle',
-          },
-          android: 'ic_menu_report_image',
-          web: 'circle-exclamation',
-        },
-      })
     }
     return items
   }, [
     isMe,
+    hasSession,
     profile.viewer?.muted,
     profile.viewer?.blocking,
     profile.viewer?.blockingByList,
@@ -421,7 +430,7 @@ let ProfileHeaderLoaded = ({
             )
           ) : !profile.viewer?.blockedBy ? (
             <>
-              {!isProfilePreview && (
+              {!isProfilePreview && hasSession && (
                 <TouchableOpacity
                   testID="suggestedFollowsBtn"
                   onPress={() => setShowSuggestedFollows(!showSuggestedFollows)}
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index 55fe02cdd..7c0491d52 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -155,23 +155,27 @@ function ProfileScreenLoaded({
   )
 
   const isMe = profile.did === currentAccount?.did
+  const showRepliesTab = hasSession
   const showLikesTab = isMe
-  const showFeedsTab = isMe || extraInfoQuery.data?.hasFeedgens
-  const showListsTab = isMe || extraInfoQuery.data?.hasLists
+  const showFeedsTab = hasSession && (isMe || extraInfoQuery.data?.hasFeedgens)
+  const showListsTab = hasSession && (isMe || extraInfoQuery.data?.hasLists)
   const sectionTitles = useMemo<string[]>(() => {
     return [
       'Posts',
-      'Posts & Replies',
+      showRepliesTab ? 'Posts & Replies' : undefined,
       'Media',
       showLikesTab ? 'Likes' : undefined,
       showFeedsTab ? 'Feeds' : undefined,
       showListsTab ? 'Lists' : undefined,
     ].filter(Boolean) as string[]
-  }, [showLikesTab, showFeedsTab, showListsTab])
+  }, [showRepliesTab, showLikesTab, showFeedsTab, showListsTab])
 
   let nextIndex = 0
   const postsIndex = nextIndex++
-  const repliesIndex = nextIndex++
+  let repliesIndex: number | null = null
+  if (showRepliesTab) {
+    repliesIndex = nextIndex++
+  }
   const mediaIndex = nextIndex++
   let likesIndex: number | null = null
   if (showLikesTab) {
@@ -282,19 +286,27 @@ function ProfileScreenLoaded({
             }
           />
         )}
-        {({onScroll, headerHeight, isFocused, isScrolledDown, scrollElRef}) => (
-          <FeedSection
-            ref={repliesSectionRef}
-            feed={`author|${profile.did}|posts_with_replies`}
-            onScroll={onScroll}
-            headerHeight={headerHeight}
-            isFocused={isFocused}
-            isScrolledDown={isScrolledDown}
-            scrollElRef={
-              scrollElRef as React.MutableRefObject<FlatList<any> | null>
-            }
-          />
-        )}
+        {showRepliesTab
+          ? ({
+              onScroll,
+              headerHeight,
+              isFocused,
+              isScrolledDown,
+              scrollElRef,
+            }) => (
+              <FeedSection
+                ref={repliesSectionRef}
+                feed={`author|${profile.did}|posts_with_replies`}
+                onScroll={onScroll}
+                headerHeight={headerHeight}
+                isFocused={isFocused}
+                isScrolledDown={isScrolledDown}
+                scrollElRef={
+                  scrollElRef as React.MutableRefObject<FlatList<any> | null>
+                }
+              />
+            )
+          : null}
         {({onScroll, headerHeight, isFocused, isScrolledDown, scrollElRef}) => (
           <FeedSection
             ref={mediaSectionRef}