mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {useCallback} from 'react'
2import {TouchableOpacity, View} from 'react-native'
3import {
4 AppBskyActorDefs,
5 ModerationCause,
6 ModerationDecision,
7} from '@atproto/api'
8import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
9import {msg} from '@lingui/macro'
10import {useLingui} from '@lingui/react'
11import {useNavigation} from '@react-navigation/native'
12
13import {BACK_HITSLOP} from 'lib/constants'
14import {makeProfileLink} from 'lib/routes/links'
15import {NavigationProp} from 'lib/routes/types'
16import {sanitizeDisplayName} from 'lib/strings/display-names'
17import {isWeb} from 'platform/detection'
18import {useProfileShadow} from 'state/cache/profile-shadow'
19import {isConvoActive, useConvo} from 'state/messages/convo'
20import {PreviewableUserAvatar} from 'view/com/util/UserAvatar'
21import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
22import {ConvoMenu} from '#/components/dms/ConvoMenu'
23import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/Bell2'
24import {Link} from '#/components/Link'
25import {PostAlerts} from '#/components/moderation/PostAlerts'
26import {Text} from '#/components/Typography'
27
28const PFP_SIZE = isWeb ? 40 : 34
29
30export let MessagesListHeader = ({
31 profile,
32 moderation,
33 blockInfo,
34}: {
35 profile?: AppBskyActorDefs.ProfileViewBasic
36 moderation?: ModerationDecision
37 blockInfo?: {
38 listBlocks: ModerationCause[]
39 userBlock?: ModerationCause
40 }
41}): React.ReactNode => {
42 const t = useTheme()
43 const {_} = useLingui()
44 const {gtTablet} = useBreakpoints()
45 const navigation = useNavigation<NavigationProp>()
46
47 const onPressBack = useCallback(() => {
48 if (isWeb) {
49 navigation.replace('Messages', {})
50 } else {
51 navigation.goBack()
52 }
53 }, [navigation])
54
55 return (
56 <View
57 style={[
58 t.atoms.bg,
59 t.atoms.border_contrast_low,
60 a.border_b,
61 a.flex_row,
62 a.align_start,
63 a.gap_sm,
64 gtTablet ? a.pl_lg : a.pl_xl,
65 a.pr_lg,
66 a.py_sm,
67 ]}>
68 {!gtTablet && (
69 <TouchableOpacity
70 testID="conversationHeaderBackBtn"
71 onPress={onPressBack}
72 hitSlop={BACK_HITSLOP}
73 style={{width: 30, height: 30, marginTop: isWeb ? 6 : 4}}
74 accessibilityRole="button"
75 accessibilityLabel={_(msg`Back`)}
76 accessibilityHint="">
77 <FontAwesomeIcon
78 size={18}
79 icon="angle-left"
80 style={{
81 marginTop: 6,
82 }}
83 color={t.atoms.text.color}
84 />
85 </TouchableOpacity>
86 )}
87
88 {profile && moderation && blockInfo ? (
89 <HeaderReady
90 profile={profile}
91 moderation={moderation}
92 blockInfo={blockInfo}
93 />
94 ) : (
95 <>
96 <View style={[a.flex_row, a.align_center, a.gap_md, a.flex_1]}>
97 <View
98 style={[
99 {width: PFP_SIZE, height: PFP_SIZE},
100 a.rounded_full,
101 t.atoms.bg_contrast_25,
102 ]}
103 />
104 <View style={a.gap_xs}>
105 <View
106 style={[
107 {width: 120, height: 16},
108 a.rounded_xs,
109 t.atoms.bg_contrast_25,
110 a.mt_xs,
111 ]}
112 />
113 <View
114 style={[
115 {width: 175, height: 12},
116 a.rounded_xs,
117 t.atoms.bg_contrast_25,
118 ]}
119 />
120 </View>
121 </View>
122
123 <View style={{width: 30}} />
124 </>
125 )}
126 </View>
127 )
128}
129MessagesListHeader = React.memo(MessagesListHeader)
130
131function HeaderReady({
132 profile: profileUnshadowed,
133 moderation,
134 blockInfo,
135}: {
136 profile: AppBskyActorDefs.ProfileViewBasic
137 moderation: ModerationDecision
138 blockInfo: {
139 listBlocks: ModerationCause[]
140 userBlock?: ModerationCause
141 }
142}) {
143 const {_} = useLingui()
144 const t = useTheme()
145 const convoState = useConvo()
146 const profile = useProfileShadow(profileUnshadowed)
147
148 const isDeletedAccount = profile?.handle === 'missing.invalid'
149 const displayName = isDeletedAccount
150 ? 'Deleted Account'
151 : sanitizeDisplayName(
152 profile.displayName || profile.handle,
153 moderation.ui('displayName'),
154 )
155
156 return (
157 <View style={[a.flex_1]}>
158 <View style={[a.w_full, a.flex_row, a.align_center, a.justify_between]}>
159 <Link
160 label={_(msg`View ${displayName}'s profile`)}
161 style={[a.flex_row, a.align_start, a.gap_md, a.flex_1, a.pr_md]}
162 to={makeProfileLink(profile)}>
163 <View style={[a.pt_2xs]}>
164 <PreviewableUserAvatar
165 size={PFP_SIZE}
166 profile={profile}
167 moderation={moderation.ui('avatar')}
168 disableHoverCard={moderation.blocked}
169 />
170 </View>
171 <View style={a.flex_1}>
172 <Text
173 style={[
174 a.text_md,
175 a.font_bold,
176 a.self_start,
177 web(a.leading_normal),
178 ]}
179 numberOfLines={1}>
180 {displayName}
181 </Text>
182 {!isDeletedAccount && (
183 <Text
184 style={[
185 t.atoms.text_contrast_medium,
186 a.text_sm,
187 web([a.leading_normal, {marginTop: -2}]),
188 ]}
189 numberOfLines={1}>
190 @{profile.handle}
191 {convoState.convo?.muted && (
192 <>
193 {' '}
194 ·{' '}
195 <BellStroke
196 size="xs"
197 style={t.atoms.text_contrast_medium}
198 />
199 </>
200 )}
201 </Text>
202 )}
203 </View>
204 </Link>
205
206 {isConvoActive(convoState) && (
207 <ConvoMenu
208 convo={convoState.convo}
209 profile={profile}
210 currentScreen="conversation"
211 blockInfo={blockInfo}
212 />
213 )}
214 </View>
215
216 <View
217 style={[
218 {
219 paddingLeft: PFP_SIZE + a.gap_md.gap,
220 },
221 ]}>
222 <PostAlerts
223 modui={moderation.ui('contentList')}
224 size="lg"
225 style={[a.pt_xs]}
226 />
227 </View>
228 </View>
229 )
230}