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

This commit is contained in:
Elijah Seed-Arita
2025-07-24 11:22:19 -07:00
committed by GitHub
parent f0b869aeeb
commit dff0332dd0
5 changed files with 20 additions and 13 deletions
+10 -6
View File
@@ -1,6 +1,10 @@
import React from 'react' import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api' import {
type AppBskyActorDefs,
moderateProfile,
type ModerationOpts,
} from '@atproto/api'
import {msg, Plural, Trans} from '@lingui/macro' import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
@@ -8,9 +12,9 @@ import {makeProfileLink} from '#/lib/routes/links'
import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Link, LinkProps} from '#/components/Link' import {Link, type LinkProps} from '#/components/Link'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
const AVI_SIZE = 30 const AVI_SIZE = 30
const AVI_SIZE_SMALL = 20 const AVI_SIZE_SMALL = 20
@@ -137,9 +141,9 @@ function KnownFollowersInner({
<> <>
<View <View
style={[ style={[
a.flex_row,
{ {
height: SIZE, height: SIZE,
width: SIZE + (slice.length - 1) * a.gap_md.gap,
}, },
pressed && { pressed && {
opacity: 0.5, opacity: 0.5,
@@ -149,15 +153,14 @@ function KnownFollowersInner({
<View <View
key={prof.did} key={prof.did}
style={[ style={[
a.absolute,
a.rounded_full, a.rounded_full,
{ {
borderWidth: AVI_BORDER, borderWidth: AVI_BORDER,
borderColor: t.atoms.bg.backgroundColor, borderColor: t.atoms.bg.backgroundColor,
width: SIZE + AVI_BORDER * 2, width: SIZE + AVI_BORDER * 2,
height: SIZE + AVI_BORDER * 2, height: SIZE + AVI_BORDER * 2,
left: i * a.gap_md.gap,
zIndex: AVI_BORDER - i, zIndex: AVI_BORDER - i,
marginLeft: i > 0 ? -8 : 0,
}, },
]}> ]}>
<UserAvatar <UserAvatar
@@ -165,6 +168,7 @@ function KnownFollowersInner({
avatar={prof.avatar} avatar={prof.avatar}
moderation={moderation.ui('avatar')} moderation={moderation.ui('avatar')}
type={prof.associated?.labeler ? 'labeler' : 'user'} type={prof.associated?.labeler ? 'labeler' : 'user'}
noBorder
/> />
</View> </View>
))} ))}
+1 -1
View File
@@ -23,7 +23,7 @@ export function ProfileHeaderHandle({
const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy
return ( return (
<View <View
style={[a.flex_row, a.gap_xs, a.align_center, {maxWidth: '100%'}]} style={[a.flex_row, a.gap_sm, a.align_center, {maxWidth: '100%'}]}
pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}> pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}>
<NewskieDialog profile={profile} disabled={disableTaps} /> <NewskieDialog profile={profile} disabled={disableTaps} />
{profile.viewer?.followedBy && !blockHide ? ( {profile.viewer?.followedBy && !blockHide ? (
@@ -251,7 +251,7 @@ let ProfileHeaderStandard = ({
<ProfileMenu profile={profile} /> <ProfileMenu profile={profile} />
</View> </View>
<View <View
style={[a.flex_col, a.gap_2xs, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}> style={[a.flex_col, a.gap_sm, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}>
<View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}> <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
<Text <Text
emoji emoji
+4 -3
View File
@@ -229,6 +229,7 @@ let ProfileHeaderShell = ({
size={live.isActive ? 88 : 90} size={live.isActive ? 88 : 90}
avatar={profile.avatar} avatar={profile.avatar}
moderation={moderation.ui('avatar')} moderation={moderation.ui('avatar')}
noBorder
/> />
{live.isActive && <LiveIndicator size="large" />} {live.isActive && <LiveIndicator size="large" />}
</Animated.View> </Animated.View>
@@ -260,7 +261,7 @@ export {ProfileHeaderShell}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
backBtnWrapper: { backBtnWrapper: {
position: 'absolute', position: 'absolute',
left: 10, left: 12,
width: 30, width: 30,
height: 30, height: 30,
overflow: 'hidden', overflow: 'hidden',
@@ -279,8 +280,8 @@ const styles = StyleSheet.create({
}, },
aviPosition: { aviPosition: {
position: 'absolute', position: 'absolute',
top: 110, top: 104,
left: 10, left: 16,
}, },
avi: { avi: {
width: 94, width: 94,
+4 -2
View File
@@ -70,6 +70,7 @@ interface UserAvatarProps extends BaseUserAvatarProps {
type: UserAvatarType type: UserAvatarType
moderation?: ModerationUI moderation?: ModerationUI
usePlainRNImage?: boolean usePlainRNImage?: boolean
noBorder?: boolean
onLoad?: () => void onLoad?: () => void
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
} }
@@ -219,6 +220,7 @@ let UserAvatar = ({
style, style,
live, live,
hideLiveBadge, hideLiveBadge,
noBorder,
}: UserAvatarProps): React.ReactNode => { }: UserAvatarProps): React.ReactNode => {
const t = useTheme() const t = useTheme()
const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square') const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
@@ -309,7 +311,7 @@ let UserAvatar = ({
onLoad={onLoad} onLoad={onLoad}
/> />
)} )}
<MediaInsetBorder style={borderStyle} /> {!noBorder && <MediaInsetBorder style={borderStyle} />}
{live && size > 16 && !hideLiveBadge && ( {live && size > 16 && !hideLiveBadge && (
<LiveIndicator size={size > 32 ? 'small' : 'tiny'} /> <LiveIndicator size={size > 32 ? 'small' : 'tiny'} />
)} )}
@@ -318,7 +320,7 @@ let UserAvatar = ({
) : ( ) : (
<View style={containerStyle}> <View style={containerStyle}>
<DefaultAvatar type={type} shape={finalShape} size={size} /> <DefaultAvatar type={type} shape={finalShape} size={size} />
<MediaInsetBorder style={borderStyle} /> {!noBorder && <MediaInsetBorder style={borderStyle} />}
{live && size > 16 && !hideLiveBadge && ( {live && size > 16 && !hideLiveBadge && (
<LiveIndicator size={size > 32 ? 'small' : 'tiny'} /> <LiveIndicator size={size > 32 ? 'small' : 'tiny'} />
)} )}