Simplify the avatar component (#1744)

* Copypaste UserAvatar to EditableUserAvatar

* Swap usages with onSelectNewAvatar to EditableUserAvatar

* Split prop types into UserAvatarProps and EditableUserAvatarProps

* Remove dead branches from EditableUserAvatar

* Remove dead branches from UserAvatar
zio/stable
dan 2023-10-25 04:57:34 +01:00 committed by GitHub
parent c6e28f88e5
commit 32fbb9dba7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 44 deletions

View File

@ -18,7 +18,7 @@ import {ListModel} from 'state/models/content/list'
import {s, colors, gradients} from 'lib/styles'
import {enforceLen} from 'lib/strings/helpers'
import {compressIfNeeded} from 'lib/media/manip'
import {UserAvatar} from '../util/UserAvatar'
import {EditableUserAvatar} from '../util/UserAvatar'
import {usePalette} from 'lib/hooks/usePalette'
import {useTheme} from 'lib/ThemeContext'
import {useAnalytics} from 'lib/analytics/analytics'
@ -148,7 +148,7 @@ export function Component({
)}
<Text style={[styles.label, pal.text]}>List Avatar</Text>
<View style={[styles.avi, {borderColor: pal.colors.background}]}>
<UserAvatar
<EditableUserAvatar
type="list"
size={80}
avatar={avatar}

View File

@ -20,7 +20,7 @@ import {enforceLen} from 'lib/strings/helpers'
import {MAX_DISPLAY_NAME, MAX_DESCRIPTION} from 'lib/constants'
import {compressIfNeeded} from 'lib/media/manip'
import {UserBanner} from '../util/UserBanner'
import {UserAvatar} from '../util/UserAvatar'
import {EditableUserAvatar} from '../util/UserAvatar'
import {usePalette} from 'lib/hooks/usePalette'
import {useTheme} from 'lib/ThemeContext'
import {useAnalytics} from 'lib/analytics/analytics'
@ -153,7 +153,7 @@ export function Component({
onSelectNewBanner={onSelectNewBanner}
/>
<View style={[styles.avi, {borderColor: pal.colors.background}]}>
<UserAvatar
<EditableUserAvatar
size={80}
avatar={userAvatar}
onSelectNewAvatar={onSelectNewAvatar}

View File

@ -23,14 +23,18 @@ interface BaseUserAvatarProps {
type?: Type
size: number
avatar?: string | null
moderation?: ModerationUI
}
interface UserAvatarProps extends BaseUserAvatarProps {
onSelectNewAvatar?: (img: RNImage | null) => void
moderation?: ModerationUI
}
interface EditableUserAvatarProps extends BaseUserAvatarProps {
onSelectNewAvatar: (img: RNImage | null) => void
}
interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
moderation?: ModerationUI
did: string
handle: string
}
@ -106,8 +110,65 @@ export function UserAvatar({
size,
avatar,
moderation,
onSelectNewAvatar,
}: UserAvatarProps) {
const pal = usePalette('default')
const aviStyle = useMemo(() => {
if (type === 'algo' || type === 'list') {
return {
width: size,
height: size,
borderRadius: size > 32 ? 8 : 3,
}
}
return {
width: size,
height: size,
borderRadius: Math.floor(size / 2),
}
}, [type, size])
const alert = useMemo(() => {
if (!moderation?.alert) {
return null
}
return (
<View style={[styles.alertIconContainer, pal.view]}>
<FontAwesomeIcon
icon="exclamation-circle"
style={styles.alertIcon}
size={Math.floor(size / 3)}
/>
</View>
)
}, [moderation?.alert, size, pal])
return avatar &&
!((moderation?.blur && isAndroid) /* android crashes with blur */) ? (
<View style={{width: size, height: size}}>
<HighPriorityImage
testID="userAvatarImage"
style={aviStyle}
contentFit="cover"
source={{uri: avatar}}
blurRadius={moderation?.blur ? BLUR_AMOUNT : 0}
/>
{alert}
</View>
) : (
<View style={{width: size, height: size}}>
<DefaultAvatar type={type} size={size} />
{alert}
</View>
)
}
export function EditableUserAvatar({
type = 'user',
size,
avatar,
onSelectNewAvatar,
}: EditableUserAvatarProps) {
const store = useStores()
const pal = usePalette('default')
const {requestCameraAccessIfNeeded} = useCameraPermission()
@ -146,7 +207,7 @@ export function UserAvatar({
return
}
onSelectNewAvatar?.(
onSelectNewAvatar(
await openCamera(store, {
width: 1000,
height: 1000,
@ -186,7 +247,7 @@ export function UserAvatar({
path: item.path,
})
onSelectNewAvatar?.(croppedImage)
onSelectNewAvatar(croppedImage)
},
},
!!avatar && {
@ -203,7 +264,7 @@ export function UserAvatar({
web: 'trash',
},
onPress: async () => {
onSelectNewAvatar?.(null)
onSelectNewAvatar(null)
},
},
].filter(Boolean) as DropdownItem[],
@ -216,23 +277,7 @@ export function UserAvatar({
],
)
const alert = useMemo(() => {
if (!moderation?.alert) {
return null
}
return (
<View style={[styles.alertIconContainer, pal.view]}>
<FontAwesomeIcon
icon="exclamation-circle"
style={styles.alertIcon}
size={Math.floor(size / 3)}
/>
</View>
)
}, [moderation?.alert, size, pal])
// onSelectNewAvatar is only passed as prop on the EditProfile component
return onSelectNewAvatar ? (
return (
<NativeDropdown
testID="changeAvatarBtn"
items={dropdownItems}
@ -256,23 +301,6 @@ export function UserAvatar({
/>
</View>
</NativeDropdown>
) : avatar &&
!((moderation?.blur && isAndroid) /* android crashes with blur */) ? (
<View style={{width: size, height: size}}>
<HighPriorityImage
testID="userAvatarImage"
style={aviStyle}
contentFit="cover"
source={{uri: avatar}}
blurRadius={moderation?.blur ? BLUR_AMOUNT : 0}
/>
{alert}
</View>
) : (
<View style={{width: size, height: size}}>
<DefaultAvatar type={type} size={size} />
{alert}
</View>
)
}