Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at a876aae44ea07494ebea9727350aa060b81f317b 187 lines 5.9 kB view raw
1import {useCallback} from 'react' 2import {Pressable, View} from 'react-native' 3import Animated, {useAnimatedRef} from 'react-native-reanimated' 4import {type AppBskyGraphDefs} from '@atproto/api' 5import {msg} from '@lingui/core/macro' 6import {useLingui} from '@lingui/react' 7import {Trans} from '@lingui/react/macro' 8import {useNavigation} from '@react-navigation/native' 9 10import {usePalette} from '#/lib/hooks/usePalette' 11import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 12import {makeProfileLink} from '#/lib/routes/links' 13import {type NavigationProp} from '#/lib/routes/types' 14import {sanitizeHandle} from '#/lib/strings/handles' 15import {emitSoftReset} from '#/state/events' 16import {useLightboxControls} from '#/state/lightbox' 17import {TextLink} from '#/view/com/util/Link' 18import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' 19import {Text} from '#/view/com/util/text/Text' 20import {UserAvatar, type UserAvatarType} from '#/view/com/util/UserAvatar' 21import {StarterPack} from '#/components/icons/StarterPack' 22import * as Layout from '#/components/Layout' 23 24export function ProfileSubpageHeader({ 25 isLoading, 26 href, 27 title, 28 avatar, 29 isOwner, 30 purpose, 31 creator, 32 avatarType, 33 children, 34}: React.PropsWithChildren<{ 35 isLoading?: boolean 36 href: string 37 title: string | undefined 38 avatar: string | undefined 39 isOwner: boolean | undefined 40 purpose: AppBskyGraphDefs.ListPurpose | undefined 41 creator: 42 | { 43 did: string 44 handle: string 45 } 46 | undefined 47 avatarType: UserAvatarType | 'starter-pack' 48}>) { 49 const navigation = useNavigation<NavigationProp>() 50 const {_} = useLingui() 51 const {isMobile} = useWebMediaQueries() 52 const {openLightbox} = useLightboxControls() 53 const pal = usePalette('default') 54 const canGoBack = navigation.canGoBack() 55 const aviRef = useAnimatedRef() 56 57 const onPressAvi = useCallback(() => { 58 if ( 59 avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride) 60 ) { 61 openLightbox({ 62 images: [ 63 { 64 uri: avatar, 65 thumbUri: avatar, 66 thumbRect: null, 67 thumbRef: aviRef, 68 dimensions: { 69 // It's fine if it's actually smaller but we know it's 1:1. 70 height: 1000, 71 width: 1000, 72 }, 73 thumbDimensions: null, 74 type: 'rect-avi', 75 }, 76 ], 77 index: 0, 78 }) 79 } 80 }, [openLightbox, avatar, aviRef]) 81 82 return ( 83 <> 84 <Layout.Header.Outer> 85 {canGoBack ? ( 86 <Layout.Header.BackButton /> 87 ) : ( 88 <Layout.Header.MenuButton /> 89 )} 90 <Layout.Header.Content /> 91 {children} 92 </Layout.Header.Outer> 93 94 <View 95 style={{ 96 flexDirection: 'row', 97 alignItems: 'flex-start', 98 gap: 10, 99 paddingTop: 14, 100 paddingBottom: 14, 101 paddingHorizontal: isMobile ? 12 : 14, 102 }}> 103 <Animated.View ref={aviRef} collapsable={false}> 104 <Pressable 105 testID="headerAviButton" 106 onPress={onPressAvi} 107 accessibilityRole="image" 108 accessibilityLabel={_(msg`View the avatar`)} 109 accessibilityHint="" 110 style={{width: 58}}> 111 {avatarType === 'starter-pack' ? ( 112 <StarterPack width={58} gradient="sky" /> 113 ) : ( 114 <UserAvatar type={avatarType} size={58} avatar={avatar} /> 115 )} 116 </Pressable> 117 </Animated.View> 118 <View style={{flex: 1, gap: 4}}> 119 {isLoading ? ( 120 <LoadingPlaceholder 121 width={200} 122 height={32} 123 style={{marginVertical: 6}} 124 /> 125 ) : ( 126 <TextLink 127 testID="headerTitle" 128 type="title-xl" 129 href={href} 130 style={[pal.text, {fontWeight: '600'}]} 131 text={title || ''} 132 onPress={emitSoftReset} 133 numberOfLines={4} 134 /> 135 )} 136 137 {isLoading || !creator ? ( 138 <LoadingPlaceholder width={50} height={8} /> 139 ) : ( 140 <Text type="lg" style={[pal.textLight]} numberOfLines={1}> 141 {purpose === 'app.bsky.graph.defs#curatelist' ? ( 142 isOwner ? ( 143 <Trans>List by you</Trans> 144 ) : ( 145 <Trans> 146 List by{' '} 147 <TextLink 148 text={sanitizeHandle(creator.handle || '', '@')} 149 href={makeProfileLink(creator)} 150 style={pal.textLight} 151 /> 152 </Trans> 153 ) 154 ) : purpose === 'app.bsky.graph.defs#modlist' ? ( 155 isOwner ? ( 156 <Trans>Moderation list by you</Trans> 157 ) : ( 158 <Trans> 159 Moderation list by{' '} 160 <TextLink 161 text={sanitizeHandle(creator.handle || '', '@')} 162 href={makeProfileLink(creator)} 163 style={pal.textLight} 164 /> 165 </Trans> 166 ) 167 ) : purpose === 'app.bsky.graph.defs#referencelist' ? ( 168 isOwner ? ( 169 <Trans>Starter pack by you</Trans> 170 ) : ( 171 <Trans> 172 Starter pack by{' '} 173 <TextLink 174 text={sanitizeHandle(creator.handle || '', '@')} 175 href={makeProfileLink(creator)} 176 style={pal.textLight} 177 /> 178 </Trans> 179 ) 180 ) : null} 181 </Text> 182 )} 183 </View> 184 </View> 185 </> 186 ) 187}