mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {Pressable, StyleSheet, View} from 'react-native'
3import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
4import {useNavigation} from '@react-navigation/native'
5import {usePalette} from 'lib/hooks/usePalette'
6import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
7import {Text} from '../util/text/Text'
8import {TextLink} from '../util/Link'
9import {UserAvatar, UserAvatarType} from '../util/UserAvatar'
10import {LoadingPlaceholder} from '../util/LoadingPlaceholder'
11import {CenteredView} from '../util/Views'
12import {sanitizeHandle} from 'lib/strings/handles'
13import {makeProfileLink} from 'lib/routes/links'
14import {NavigationProp} from 'lib/routes/types'
15import {BACK_HITSLOP} from 'lib/constants'
16import {isNative} from 'platform/detection'
17import {useLightboxControls, ImagesLightbox} from '#/state/lightbox'
18import {useLingui} from '@lingui/react'
19import {Trans, msg} from '@lingui/macro'
20import {useSetDrawerOpen} from '#/state/shell'
21import {emitSoftReset} from '#/state/events'
22
23export function ProfileSubpageHeader({
24 isLoading,
25 href,
26 title,
27 avatar,
28 isOwner,
29 creator,
30 avatarType,
31 children,
32}: React.PropsWithChildren<{
33 isLoading?: boolean
34 href: string
35 title: string | undefined
36 avatar: string | undefined
37 isOwner: boolean | undefined
38 creator:
39 | {
40 did: string
41 handle: string
42 }
43 | undefined
44 avatarType: UserAvatarType
45}>) {
46 const setDrawerOpen = useSetDrawerOpen()
47 const navigation = useNavigation<NavigationProp>()
48 const {_} = useLingui()
49 const {isMobile} = useWebMediaQueries()
50 const {openLightbox} = useLightboxControls()
51 const pal = usePalette('default')
52 const canGoBack = navigation.canGoBack()
53
54 const onPressBack = React.useCallback(() => {
55 if (navigation.canGoBack()) {
56 navigation.goBack()
57 } else {
58 navigation.navigate('Home')
59 }
60 }, [navigation])
61
62 const onPressMenu = React.useCallback(() => {
63 setDrawerOpen(true)
64 }, [setDrawerOpen])
65
66 const onPressAvi = React.useCallback(() => {
67 if (
68 avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
69 ) {
70 openLightbox(new ImagesLightbox([{uri: avatar}], 0))
71 }
72 }, [openLightbox, avatar])
73
74 return (
75 <CenteredView style={pal.view}>
76 {isMobile && (
77 <View
78 style={[
79 {
80 flexDirection: 'row',
81 alignItems: 'center',
82 borderBottomWidth: 1,
83 paddingTop: isNative ? 0 : 8,
84 paddingBottom: 8,
85 paddingHorizontal: isMobile ? 12 : 14,
86 },
87 pal.border,
88 ]}>
89 <Pressable
90 testID="headerDrawerBtn"
91 onPress={canGoBack ? onPressBack : onPressMenu}
92 hitSlop={BACK_HITSLOP}
93 style={canGoBack ? styles.backBtn : styles.backBtnWide}
94 accessibilityRole="button"
95 accessibilityLabel={canGoBack ? 'Back' : 'Menu'}
96 accessibilityHint="">
97 {canGoBack ? (
98 <FontAwesomeIcon
99 size={18}
100 icon="angle-left"
101 style={[styles.backIcon, pal.text]}
102 />
103 ) : (
104 <FontAwesomeIcon
105 size={18}
106 icon="bars"
107 style={[styles.backIcon, pal.textLight]}
108 />
109 )}
110 </Pressable>
111 <View style={{flex: 1}} />
112 {children}
113 </View>
114 )}
115 <View
116 style={{
117 flexDirection: 'row',
118 alignItems: 'flex-start',
119 gap: 10,
120 paddingTop: 14,
121 paddingBottom: 6,
122 paddingHorizontal: isMobile ? 12 : 14,
123 }}>
124 <Pressable
125 testID="headerAviButton"
126 onPress={onPressAvi}
127 accessibilityRole="image"
128 accessibilityLabel={_(msg`View the avatar`)}
129 accessibilityHint=""
130 style={{width: 58}}>
131 <UserAvatar type={avatarType} size={58} avatar={avatar} />
132 </Pressable>
133 <View style={{flex: 1}}>
134 {isLoading ? (
135 <LoadingPlaceholder
136 width={200}
137 height={32}
138 style={{marginVertical: 6}}
139 />
140 ) : (
141 <TextLink
142 testID="headerTitle"
143 type="title-xl"
144 href={href}
145 style={[pal.text, {fontWeight: 'bold'}]}
146 text={title || ''}
147 onPress={emitSoftReset}
148 numberOfLines={4}
149 />
150 )}
151
152 {isLoading ? (
153 <LoadingPlaceholder width={50} height={8} />
154 ) : (
155 <Text type="xl" style={[pal.textLight]} numberOfLines={1}>
156 {!creator ? (
157 <Trans>by —</Trans>
158 ) : isOwner ? (
159 <Trans>by you</Trans>
160 ) : (
161 <Trans>
162 by{' '}
163 <TextLink
164 text={sanitizeHandle(creator.handle, '@')}
165 href={makeProfileLink(creator)}
166 style={pal.textLight}
167 />
168 </Trans>
169 )}
170 </Text>
171 )}
172 </View>
173 {!isMobile && (
174 <View
175 style={{
176 flexDirection: 'row',
177 alignItems: 'center',
178 }}>
179 {children}
180 </View>
181 )}
182 </View>
183 </CenteredView>
184 )
185}
186
187const styles = StyleSheet.create({
188 backBtn: {
189 width: 20,
190 height: 30,
191 },
192 backBtnWide: {
193 width: 20,
194 height: 30,
195 paddingHorizontal: 6,
196 },
197 backIcon: {
198 marginTop: 6,
199 },
200})