Bluesky app fork with some witchin' additions 💫

fix: general profile component layout fixes, and ability to disable the inset border for UserAvatar (#8711)

authored by

Elijah Seed-Arita and committed by
GitHub
dff0332d f0b869ae

+20 -13
+10 -6
src/components/KnownFollowers.tsx
··· 1 import React from 'react' 2 import {View} from 'react-native' 3 - import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api' 4 import {msg, Plural, Trans} from '@lingui/macro' 5 import {useLingui} from '@lingui/react' 6 ··· 8 import {sanitizeDisplayName} from '#/lib/strings/display-names' 9 import {UserAvatar} from '#/view/com/util/UserAvatar' 10 import {atoms as a, useTheme} from '#/alf' 11 - import {Link, LinkProps} from '#/components/Link' 12 import {Text} from '#/components/Typography' 13 - import * as bsky from '#/types/bsky' 14 15 const AVI_SIZE = 30 16 const AVI_SIZE_SMALL = 20 ··· 137 <> 138 <View 139 style={[ 140 { 141 height: SIZE, 142 - width: SIZE + (slice.length - 1) * a.gap_md.gap, 143 }, 144 pressed && { 145 opacity: 0.5, ··· 149 <View 150 key={prof.did} 151 style={[ 152 - a.absolute, 153 a.rounded_full, 154 { 155 borderWidth: AVI_BORDER, 156 borderColor: t.atoms.bg.backgroundColor, 157 width: SIZE + AVI_BORDER * 2, 158 height: SIZE + AVI_BORDER * 2, 159 - left: i * a.gap_md.gap, 160 zIndex: AVI_BORDER - i, 161 }, 162 ]}> 163 <UserAvatar ··· 165 avatar={prof.avatar} 166 moderation={moderation.ui('avatar')} 167 type={prof.associated?.labeler ? 'labeler' : 'user'} 168 /> 169 </View> 170 ))}
··· 1 import React from 'react' 2 import {View} from 'react-native' 3 + import { 4 + type AppBskyActorDefs, 5 + moderateProfile, 6 + type ModerationOpts, 7 + } from '@atproto/api' 8 import {msg, Plural, Trans} from '@lingui/macro' 9 import {useLingui} from '@lingui/react' 10 ··· 12 import {sanitizeDisplayName} from '#/lib/strings/display-names' 13 import {UserAvatar} from '#/view/com/util/UserAvatar' 14 import {atoms as a, useTheme} from '#/alf' 15 + import {Link, type LinkProps} from '#/components/Link' 16 import {Text} from '#/components/Typography' 17 + import type * as bsky from '#/types/bsky' 18 19 const AVI_SIZE = 30 20 const AVI_SIZE_SMALL = 20 ··· 141 <> 142 <View 143 style={[ 144 + a.flex_row, 145 { 146 height: SIZE, 147 }, 148 pressed && { 149 opacity: 0.5, ··· 153 <View 154 key={prof.did} 155 style={[ 156 a.rounded_full, 157 { 158 borderWidth: AVI_BORDER, 159 borderColor: t.atoms.bg.backgroundColor, 160 width: SIZE + AVI_BORDER * 2, 161 height: SIZE + AVI_BORDER * 2, 162 zIndex: AVI_BORDER - i, 163 + marginLeft: i > 0 ? -8 : 0, 164 }, 165 ]}> 166 <UserAvatar ··· 168 avatar={prof.avatar} 169 moderation={moderation.ui('avatar')} 170 type={prof.associated?.labeler ? 'labeler' : 'user'} 171 + noBorder 172 /> 173 </View> 174 ))}
+1 -1
src/screens/Profile/Header/Handle.tsx
··· 23 const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy 24 return ( 25 <View 26 - style={[a.flex_row, a.gap_xs, a.align_center, {maxWidth: '100%'}]} 27 pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}> 28 <NewskieDialog profile={profile} disabled={disableTaps} /> 29 {profile.viewer?.followedBy && !blockHide ? (
··· 23 const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy 24 return ( 25 <View 26 + style={[a.flex_row, a.gap_sm, a.align_center, {maxWidth: '100%'}]} 27 pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}> 28 <NewskieDialog profile={profile} disabled={disableTaps} /> 29 {profile.viewer?.followedBy && !blockHide ? (
+1 -1
src/screens/Profile/Header/ProfileHeaderStandard.tsx
··· 251 <ProfileMenu profile={profile} /> 252 </View> 253 <View 254 - style={[a.flex_col, a.gap_2xs, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}> 255 <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}> 256 <Text 257 emoji
··· 251 <ProfileMenu profile={profile} /> 252 </View> 253 <View 254 + style={[a.flex_col, a.gap_sm, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}> 255 <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}> 256 <Text 257 emoji
+4 -3
src/screens/Profile/Header/Shell.tsx
··· 229 size={live.isActive ? 88 : 90} 230 avatar={profile.avatar} 231 moderation={moderation.ui('avatar')} 232 /> 233 {live.isActive && <LiveIndicator size="large" />} 234 </Animated.View> ··· 260 const styles = StyleSheet.create({ 261 backBtnWrapper: { 262 position: 'absolute', 263 - left: 10, 264 width: 30, 265 height: 30, 266 overflow: 'hidden', ··· 279 }, 280 aviPosition: { 281 position: 'absolute', 282 - top: 110, 283 - left: 10, 284 }, 285 avi: { 286 width: 94,
··· 229 size={live.isActive ? 88 : 90} 230 avatar={profile.avatar} 231 moderation={moderation.ui('avatar')} 232 + noBorder 233 /> 234 {live.isActive && <LiveIndicator size="large" />} 235 </Animated.View> ··· 261 const styles = StyleSheet.create({ 262 backBtnWrapper: { 263 position: 'absolute', 264 + left: 12, 265 width: 30, 266 height: 30, 267 overflow: 'hidden', ··· 280 }, 281 aviPosition: { 282 position: 'absolute', 283 + top: 104, 284 + left: 16, 285 }, 286 avi: { 287 width: 94,
+4 -2
src/view/com/util/UserAvatar.tsx
··· 70 type: UserAvatarType 71 moderation?: ModerationUI 72 usePlainRNImage?: boolean 73 onLoad?: () => void 74 style?: StyleProp<ViewStyle> 75 } ··· 219 style, 220 live, 221 hideLiveBadge, 222 }: UserAvatarProps): React.ReactNode => { 223 const t = useTheme() 224 const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square') ··· 309 onLoad={onLoad} 310 /> 311 )} 312 - <MediaInsetBorder style={borderStyle} /> 313 {live && size > 16 && !hideLiveBadge && ( 314 <LiveIndicator size={size > 32 ? 'small' : 'tiny'} /> 315 )} ··· 318 ) : ( 319 <View style={containerStyle}> 320 <DefaultAvatar type={type} shape={finalShape} size={size} /> 321 - <MediaInsetBorder style={borderStyle} /> 322 {live && size > 16 && !hideLiveBadge && ( 323 <LiveIndicator size={size > 32 ? 'small' : 'tiny'} /> 324 )}
··· 70 type: UserAvatarType 71 moderation?: ModerationUI 72 usePlainRNImage?: boolean 73 + noBorder?: boolean 74 onLoad?: () => void 75 style?: StyleProp<ViewStyle> 76 } ··· 220 style, 221 live, 222 hideLiveBadge, 223 + noBorder, 224 }: UserAvatarProps): React.ReactNode => { 225 const t = useTheme() 226 const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square') ··· 311 onLoad={onLoad} 312 /> 313 )} 314 + {!noBorder && <MediaInsetBorder style={borderStyle} />} 315 {live && size > 16 && !hideLiveBadge && ( 316 <LiveIndicator size={size > 32 ? 'small' : 'tiny'} /> 317 )} ··· 320 ) : ( 321 <View style={containerStyle}> 322 <DefaultAvatar type={type} shape={finalShape} size={size} /> 323 + {!noBorder && <MediaInsetBorder style={borderStyle} />} 324 {live && size > 16 && !hideLiveBadge && ( 325 <LiveIndicator size={size > 32 ? 'small' : 'tiny'} /> 326 )}