about summary refs log tree commit diff
path: root/src/components/ProfileCard.tsx
blob: a0d222854b7e51775c6c667794c7d72d523fb1c2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import React from 'react'
import {View} from 'react-native'
import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'

import {createSanitizedDisplayName} from 'lib/moderation/create-sanitized-display-name'
import {sanitizeHandle} from 'lib/strings/handles'
import {useProfileShadow} from 'state/cache/profile-shadow'
import {useSession} from 'state/session'
import {FollowButton} from 'view/com/profile/FollowButton'
import {ProfileCardPills} from 'view/com/profile/ProfileCard'
import {UserAvatar} from 'view/com/util/UserAvatar'
import {atoms as a, useTheme} from '#/alf'
import {Link} from '#/components/Link'
import {Text} from '#/components/Typography'

export function Default({
  profile: profileUnshadowed,
  moderationOpts,
  logContext = 'ProfileCard',
}: {
  profile: AppBskyActorDefs.ProfileViewDetailed
  moderationOpts: ModerationOpts
  logContext?: 'ProfileCard' | 'StarterPackProfilesList'
}) {
  const t = useTheme()
  const {currentAccount, hasSession} = useSession()

  const profile = useProfileShadow(profileUnshadowed)
  const name = createSanitizedDisplayName(profile)
  const handle = `@${sanitizeHandle(profile.handle)}`
  const moderation = moderateProfile(profile, moderationOpts)

  return (
    <Wrapper did={profile.did}>
      <View style={[a.flex_row, a.gap_sm]}>
        <UserAvatar
          size={42}
          avatar={profile.avatar}
          type={
            profile.associated?.labeler
              ? 'labeler'
              : profile.associated?.feedgens
              ? 'algo'
              : 'user'
          }
          moderation={moderation.ui('avatar')}
        />
        <View style={[a.flex_1]}>
          <Text
            style={[a.text_md, a.font_bold, a.leading_snug]}
            numberOfLines={1}>
            {name}
          </Text>
          <Text
            style={[a.leading_snug, t.atoms.text_contrast_medium]}
            numberOfLines={1}>
            {handle}
          </Text>
        </View>
        {hasSession && profile.did !== currentAccount?.did && (
          <View style={[a.justify_center, {marginLeft: 'auto'}]}>
            <FollowButton profile={profile} logContext={logContext} />
          </View>
        )}
      </View>
      <View style={[a.mb_xs]}>
        <ProfileCardPills
          followedBy={Boolean(profile.viewer?.followedBy)}
          moderation={moderation}
        />
      </View>
      {profile.description && (
        <Text numberOfLines={3} style={[a.leading_snug]}>
          {profile.description}
        </Text>
      )}
    </Wrapper>
  )
}

function Wrapper({did, children}: {did: string; children: React.ReactNode}) {
  return (
    <Link
      to={{
        screen: 'Profile',
        params: {name: did},
      }}>
      <View style={[a.flex_1, a.gap_xs]}>{children}</View>
    </Link>
  )
}