about summary refs log tree commit diff
path: root/src/screens/Profile/Header/ProfileHeaderStandard.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens/Profile/Header/ProfileHeaderStandard.tsx')
-rw-r--r--src/screens/Profile/Header/ProfileHeaderStandard.tsx329
1 files changed, 172 insertions, 157 deletions
diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx
index 2f61ba4df..32111dd3b 100644
--- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx
+++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx
@@ -1,4 +1,4 @@
-import React, {memo, useMemo} from 'react'
+import {memo, useCallback, useMemo, useState} from 'react'
 import {View} from 'react-native'
 import {
   type AppBskyActorDefs,
@@ -40,6 +40,7 @@ import {EditProfileDialog} from './EditProfileDialog'
 import {ProfileHeaderHandle} from './Handle'
 import {ProfileHeaderMetrics} from './Metrics'
 import {ProfileHeaderShell} from './Shell'
+import {AnimatedProfileHeaderSuggestedFollows} from './SuggestedFollows'
 
 interface Props {
   profile: AppBskyActorDefs.ProfileViewDetailed
@@ -73,6 +74,7 @@ let ProfileHeaderStandard = ({
   const [_queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
   const unblockPromptControl = Prompt.usePromptControl()
   const requireAuth = useRequireAuth()
+  const [showSuggestedFollows, setShowSuggestedFollows] = useState(false)
   const isBlockedUser =
     profile.viewer?.blocking ||
     profile.viewer?.blockedBy ||
@@ -81,6 +83,7 @@ let ProfileHeaderStandard = ({
   const editProfileControl = useDialogControl()
 
   const onPressFollow = () => {
+    setShowSuggestedFollows(true)
     requireAuth(async () => {
       try {
         await queueFollow()
@@ -102,6 +105,7 @@ let ProfileHeaderStandard = ({
   }
 
   const onPressUnfollow = () => {
+    setShowSuggestedFollows(false)
     requireAuth(async () => {
       try {
         await queueUnfollow()
@@ -122,7 +126,7 @@ let ProfileHeaderStandard = ({
     })
   }
 
-  const unblockAccount = React.useCallback(async () => {
+  const unblockAccount = useCallback(async () => {
     try {
       await queueUnblock()
       Toast.show(_(msg({message: 'Account unblocked', context: 'toast'})))
@@ -155,174 +159,185 @@ let ProfileHeaderStandard = ({
   }, [profile])
 
   return (
-    <ProfileHeaderShell
-      profile={profile}
-      moderation={moderation}
-      hideBackButton={hideBackButton}
-      isPlaceholderProfile={isPlaceholderProfile}>
-      <View
-        style={[a.px_lg, a.pt_md, a.pb_sm, a.overflow_hidden]}
-        pointerEvents={isIOS ? 'auto' : 'box-none'}>
+    <>
+      <ProfileHeaderShell
+        profile={profile}
+        moderation={moderation}
+        hideBackButton={hideBackButton}
+        isPlaceholderProfile={isPlaceholderProfile}>
         <View
-          style={[
-            {paddingLeft: 90},
-            a.flex_row,
-            a.align_center,
-            a.justify_end,
-            a.gap_xs,
-            a.pb_sm,
-            a.flex_wrap,
-          ]}
+          style={[a.px_lg, a.pt_md, a.pb_sm, a.overflow_hidden]}
           pointerEvents={isIOS ? 'auto' : 'box-none'}>
-          {isMe ? (
-            <>
-              <Button
-                testID="profileHeaderEditProfileButton"
-                size="small"
-                color="secondary"
-                variant="solid"
-                onPress={editProfileControl.open}
-                label={_(msg`Edit profile`)}
-                style={[a.rounded_full]}>
-                <ButtonText>
-                  <Trans>Edit Profile</Trans>
-                </ButtonText>
-              </Button>
-              <EditProfileDialog
-                profile={profile}
-                control={editProfileControl}
-              />
-            </>
-          ) : profile.viewer?.blocking ? (
-            profile.viewer?.blockingByList ? null : (
-              <Button
-                testID="unblockBtn"
-                size="small"
-                color="secondary"
-                variant="solid"
-                label={_(msg`Unblock`)}
-                disabled={!hasSession}
-                onPress={() => unblockPromptControl.open()}
-                style={[a.rounded_full]}>
-                <ButtonText>
-                  <Trans context="action">Unblock</Trans>
-                </ButtonText>
-              </Button>
-            )
-          ) : !profile.viewer?.blockedBy ? (
-            <>
-              {hasSession && subscriptionsAllowed && (
-                <SubscribeProfileButton
+          <View
+            style={[
+              {paddingLeft: 90},
+              a.flex_row,
+              a.align_center,
+              a.justify_end,
+              a.gap_xs,
+              a.pb_sm,
+              a.flex_wrap,
+            ]}
+            pointerEvents={isIOS ? 'auto' : 'box-none'}>
+            {isMe ? (
+              <>
+                <Button
+                  testID="profileHeaderEditProfileButton"
+                  size="small"
+                  color="secondary"
+                  variant="solid"
+                  onPress={editProfileControl.open}
+                  label={_(msg`Edit profile`)}
+                  style={[a.rounded_full]}>
+                  <ButtonText>
+                    <Trans>Edit Profile</Trans>
+                  </ButtonText>
+                </Button>
+                <EditProfileDialog
                   profile={profile}
-                  moderationOpts={moderationOpts}
+                  control={editProfileControl}
                 />
-              )}
-              {hasSession && <MessageProfileButton profile={profile} />}
-
-              <Button
-                testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'}
-                size="small"
-                color={profile.viewer?.following ? 'secondary' : 'primary'}
-                variant="solid"
-                label={
-                  profile.viewer?.following
-                    ? _(msg`Unfollow ${profile.handle}`)
-                    : _(msg`Follow ${profile.handle}`)
-                }
-                onPress={
-                  profile.viewer?.following ? onPressUnfollow : onPressFollow
-                }
-                style={[a.rounded_full]}>
-                {!profile.viewer?.following && (
-                  <ButtonIcon position="left" icon={Plus} />
+              </>
+            ) : profile.viewer?.blocking ? (
+              profile.viewer?.blockingByList ? null : (
+                <Button
+                  testID="unblockBtn"
+                  size="small"
+                  color="secondary"
+                  variant="solid"
+                  label={_(msg`Unblock`)}
+                  disabled={!hasSession}
+                  onPress={() => unblockPromptControl.open()}
+                  style={[a.rounded_full]}>
+                  <ButtonText>
+                    <Trans context="action">Unblock</Trans>
+                  </ButtonText>
+                </Button>
+              )
+            ) : !profile.viewer?.blockedBy ? (
+              <>
+                {hasSession && subscriptionsAllowed && (
+                  <SubscribeProfileButton
+                    profile={profile}
+                    moderationOpts={moderationOpts}
+                  />
                 )}
-                <ButtonText>
-                  {profile.viewer?.following ? (
-                    <Trans>Following</Trans>
-                  ) : profile.viewer?.followedBy ? (
-                    <Trans>Follow Back</Trans>
-                  ) : (
-                    <Trans>Follow</Trans>
+                {hasSession && <MessageProfileButton profile={profile} />}
+
+                <Button
+                  testID={
+                    profile.viewer?.following ? 'unfollowBtn' : 'followBtn'
+                  }
+                  size="small"
+                  color={profile.viewer?.following ? 'secondary' : 'primary'}
+                  variant="solid"
+                  label={
+                    profile.viewer?.following
+                      ? _(msg`Unfollow ${profile.handle}`)
+                      : _(msg`Follow ${profile.handle}`)
+                  }
+                  onPress={
+                    profile.viewer?.following ? onPressUnfollow : onPressFollow
+                  }
+                  style={[a.rounded_full]}>
+                  {!profile.viewer?.following && (
+                    <ButtonIcon position="left" icon={Plus} />
                   )}
-                </ButtonText>
-              </Button>
-            </>
-          ) : null}
-          <ProfileMenu profile={profile} />
-        </View>
-        <View
-          style={[a.flex_col, a.gap_xs, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}>
-          <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
-            <Text
-              emoji
-              testID="profileHeaderDisplayName"
-              style={[
-                t.atoms.text,
-                gtMobile ? a.text_4xl : a.text_3xl,
-                a.self_start,
-                a.font_heavy,
-                a.leading_tight,
-              ]}>
-              {sanitizeDisplayName(
-                profile.displayName || sanitizeHandle(profile.handle),
-                moderation.ui('displayName'),
-              )}
-              <View
+                  <ButtonText>
+                    {profile.viewer?.following ? (
+                      <Trans>Following</Trans>
+                    ) : profile.viewer?.followedBy ? (
+                      <Trans>Follow back</Trans>
+                    ) : (
+                      <Trans>Follow</Trans>
+                    )}
+                  </ButtonText>
+                </Button>
+              </>
+            ) : null}
+            <ProfileMenu profile={profile} />
+          </View>
+          <View
+            style={[a.flex_col, a.gap_xs, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}>
+            <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
+              <Text
+                emoji
+                testID="profileHeaderDisplayName"
                 style={[
-                  a.pl_xs,
-                  {
-                    marginTop: platform({ios: 2}),
-                  },
+                  t.atoms.text,
+                  gtMobile ? a.text_4xl : a.text_3xl,
+                  a.self_start,
+                  a.font_heavy,
+                  a.leading_tight,
                 ]}>
-                <VerificationCheckButton profile={profile} size="lg" />
-              </View>
-            </Text>
+                {sanitizeDisplayName(
+                  profile.displayName || sanitizeHandle(profile.handle),
+                  moderation.ui('displayName'),
+                )}
+                <View
+                  style={[
+                    a.pl_xs,
+                    {
+                      marginTop: platform({ios: 2}),
+                    },
+                  ]}>
+                  <VerificationCheckButton profile={profile} size="lg" />
+                </View>
+              </Text>
+            </View>
+            <ProfileHeaderHandle profile={profile} />
           </View>
-          <ProfileHeaderHandle profile={profile} />
-        </View>
-        {!isPlaceholderProfile && !isBlockedUser && (
-          <View style={a.gap_md}>
-            <ProfileHeaderMetrics profile={profile} />
-            {descriptionRT && !moderation.ui('profileView').blur ? (
-              <View pointerEvents="auto">
-                <RichText
-                  testID="profileHeaderDescription"
-                  style={[a.text_md]}
-                  numberOfLines={15}
-                  value={descriptionRT}
-                  enableTags
-                  authorHandle={profile.handle}
-                />
-              </View>
-            ) : undefined}
-
-            {!isMe &&
-              !isBlockedUser &&
-              shouldShowKnownFollowers(profile.viewer?.knownFollowers) && (
-                <View style={[a.flex_row, a.align_center, a.gap_sm]}>
-                  <KnownFollowers
-                    profile={profile}
-                    moderationOpts={moderationOpts}
+          {!isPlaceholderProfile && !isBlockedUser && (
+            <View style={a.gap_md}>
+              <ProfileHeaderMetrics profile={profile} />
+              {descriptionRT && !moderation.ui('profileView').blur ? (
+                <View pointerEvents="auto">
+                  <RichText
+                    testID="profileHeaderDescription"
+                    style={[a.text_md]}
+                    numberOfLines={15}
+                    value={descriptionRT}
+                    enableTags
+                    authorHandle={profile.handle}
                   />
                 </View>
-              )}
-          </View>
-        )}
-      </View>
-      <Prompt.Basic
-        control={unblockPromptControl}
-        title={_(msg`Unblock Account?`)}
-        description={_(
-          msg`The account will be able to interact with you after unblocking.`,
-        )}
-        onConfirm={unblockAccount}
-        confirmButtonCta={
-          profile.viewer?.blocking ? _(msg`Unblock`) : _(msg`Block`)
-        }
-        confirmButtonColor="negative"
+              ) : undefined}
+
+              {!isMe &&
+                !isBlockedUser &&
+                shouldShowKnownFollowers(profile.viewer?.knownFollowers) && (
+                  <View style={[a.flex_row, a.align_center, a.gap_sm]}>
+                    <KnownFollowers
+                      profile={profile}
+                      moderationOpts={moderationOpts}
+                    />
+                  </View>
+                )}
+            </View>
+          )}
+        </View>
+
+        <Prompt.Basic
+          control={unblockPromptControl}
+          title={_(msg`Unblock Account?`)}
+          description={_(
+            msg`The account will be able to interact with you after unblocking.`,
+          )}
+          onConfirm={unblockAccount}
+          confirmButtonCta={
+            profile.viewer?.blocking ? _(msg`Unblock`) : _(msg`Block`)
+          }
+          confirmButtonColor="negative"
+        />
+      </ProfileHeaderShell>
+
+      <AnimatedProfileHeaderSuggestedFollows
+        isExpanded={showSuggestedFollows}
+        actorDid={profile.did}
       />
-    </ProfileHeaderShell>
+    </>
   )
 }
+
 ProfileHeaderStandard = memo(ProfileHeaderStandard)
 export {ProfileHeaderStandard}