mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at verify-code 167 lines 4.9 kB view raw
1import React, {memo} from 'react' 2import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native' 3import {AppBskyActorDefs, ModerationDecision} from '@atproto/api' 4import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 5import {msg} from '@lingui/macro' 6import {useLingui} from '@lingui/react' 7import {useNavigation} from '@react-navigation/native' 8 9import {Shadow} from '#/state/cache/types' 10import {ProfileImageLightbox, useLightboxControls} from '#/state/lightbox' 11import {useSession} from '#/state/session' 12import {BACK_HITSLOP} from 'lib/constants' 13import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 14import {NavigationProp} from 'lib/routes/types' 15import {isIOS} from 'platform/detection' 16import {LoadingPlaceholder} from 'view/com/util/LoadingPlaceholder' 17import {UserAvatar} from 'view/com/util/UserAvatar' 18import {UserBanner} from 'view/com/util/UserBanner' 19import {atoms as a, useTheme} from '#/alf' 20import {LabelsOnMe} from '#/components/moderation/LabelsOnMe' 21import {ProfileHeaderAlerts} from '#/components/moderation/ProfileHeaderAlerts' 22 23interface Props { 24 profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> 25 moderation: ModerationDecision 26 hideBackButton?: boolean 27 isPlaceholderProfile?: boolean 28} 29 30let ProfileHeaderShell = ({ 31 children, 32 profile, 33 moderation, 34 hideBackButton = false, 35 isPlaceholderProfile, 36}: React.PropsWithChildren<Props>): React.ReactNode => { 37 const t = useTheme() 38 const {currentAccount} = useSession() 39 const {_} = useLingui() 40 const {openLightbox} = useLightboxControls() 41 const navigation = useNavigation<NavigationProp>() 42 const {isDesktop} = useWebMediaQueries() 43 44 const onPressBack = React.useCallback(() => { 45 if (navigation.canGoBack()) { 46 navigation.goBack() 47 } else { 48 navigation.navigate('Home') 49 } 50 }, [navigation]) 51 52 const onPressAvi = React.useCallback(() => { 53 const modui = moderation.ui('avatar') 54 if (profile.avatar && !(modui.blur && modui.noOverride)) { 55 openLightbox(new ProfileImageLightbox(profile)) 56 } 57 }, [openLightbox, profile, moderation]) 58 59 const isMe = React.useMemo( 60 () => currentAccount?.did === profile.did, 61 [currentAccount, profile], 62 ) 63 64 return ( 65 <View style={t.atoms.bg} pointerEvents={isIOS ? 'auto' : 'box-none'}> 66 <View pointerEvents={isIOS ? 'auto' : 'none'}> 67 {isPlaceholderProfile ? ( 68 <LoadingPlaceholder 69 width="100%" 70 height={150} 71 style={{borderRadius: 0}} 72 /> 73 ) : ( 74 <UserBanner 75 type={profile.associated?.labeler ? 'labeler' : 'default'} 76 banner={profile.banner} 77 moderation={moderation.ui('banner')} 78 /> 79 )} 80 </View> 81 82 {children} 83 84 {!isPlaceholderProfile && ( 85 <View 86 style={[a.px_lg, a.py_xs]} 87 pointerEvents={isIOS ? 'auto' : 'box-none'}> 88 {isMe ? ( 89 <LabelsOnMe type="account" labels={profile.labels} /> 90 ) : ( 91 <ProfileHeaderAlerts moderation={moderation} /> 92 )} 93 </View> 94 )} 95 96 {!isDesktop && !hideBackButton && ( 97 <TouchableWithoutFeedback 98 testID="profileHeaderBackBtn" 99 onPress={onPressBack} 100 hitSlop={BACK_HITSLOP} 101 accessibilityRole="button" 102 accessibilityLabel={_(msg`Back`)} 103 accessibilityHint=""> 104 <View style={styles.backBtnWrapper}> 105 <FontAwesomeIcon size={18} icon="angle-left" color="white" /> 106 </View> 107 </TouchableWithoutFeedback> 108 )} 109 <TouchableWithoutFeedback 110 testID="profileHeaderAviButton" 111 onPress={onPressAvi} 112 accessibilityRole="image" 113 accessibilityLabel={_(msg`View ${profile.handle}'s avatar`)} 114 accessibilityHint=""> 115 <View 116 style={[ 117 t.atoms.bg, 118 {borderColor: t.atoms.bg.backgroundColor}, 119 styles.avi, 120 profile.associated?.labeler && styles.aviLabeler, 121 ]}> 122 <UserAvatar 123 type={profile.associated?.labeler ? 'labeler' : 'user'} 124 size={90} 125 avatar={profile.avatar} 126 moderation={moderation.ui('avatar')} 127 /> 128 </View> 129 </TouchableWithoutFeedback> 130 </View> 131 ) 132} 133ProfileHeaderShell = memo(ProfileHeaderShell) 134export {ProfileHeaderShell} 135 136const styles = StyleSheet.create({ 137 backBtnWrapper: { 138 position: 'absolute', 139 top: 10, 140 left: 10, 141 width: 30, 142 height: 30, 143 overflow: 'hidden', 144 borderRadius: 15, 145 // @ts-ignore web only 146 cursor: 'pointer', 147 }, 148 backBtn: { 149 width: 30, 150 height: 30, 151 borderRadius: 15, 152 alignItems: 'center', 153 justifyContent: 'center', 154 }, 155 avi: { 156 position: 'absolute', 157 top: 110, 158 left: 10, 159 width: 94, 160 height: 94, 161 borderRadius: 47, 162 borderWidth: 2, 163 }, 164 aviLabeler: { 165 borderRadius: 10, 166 }, 167})