Add 'algo' variant of avatars

zio/stable
Paul Frazee 2023-05-17 13:42:29 -05:00
parent 85910cdbea
commit a2b089d315
4 changed files with 53 additions and 21 deletions

View File

@ -61,7 +61,7 @@ const AlgoItem = observer(
key={item.data.uri}> key={item.data.uri}>
<View style={[styles.headerContainer]}> <View style={[styles.headerContainer]}>
<View style={[s.mr10]}> <View style={[s.mr10]}>
<UserAvatar size={36} avatar={item.data.avatar} /> <UserAvatar type="algo" size={36} avatar={item.data.avatar} />
</View> </View>
<View style={[styles.headerTextContainer]}> <View style={[styles.headerTextContainer]}>
<Text style={[pal.text, s.bold]}> <Text style={[pal.text, s.bold]}>

View File

@ -1,6 +1,6 @@
import React, {useMemo} from 'react' import React, {useMemo} from 'react'
import {StyleSheet, View} from 'react-native' import {StyleSheet, View} from 'react-native'
import Svg, {Circle, Path} from 'react-native-svg' import Svg, {Circle, Rect, Path} from 'react-native-svg'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {IconProp} from '@fortawesome/fontawesome-svg-core' import {IconProp} from '@fortawesome/fontawesome-svg-core'
import {HighPriorityImage} from 'view/com/util/images/Image' import {HighPriorityImage} from 'view/com/util/images/Image'
@ -17,9 +17,29 @@ import {isWeb, isAndroid} from 'platform/detection'
import {Image as RNImage} from 'react-native-image-crop-picker' import {Image as RNImage} from 'react-native-image-crop-picker'
import {AvatarModeration} from 'lib/labeling/types' import {AvatarModeration} from 'lib/labeling/types'
type Type = 'user' | 'algo'
const BLUR_AMOUNT = isWeb ? 5 : 100 const BLUR_AMOUNT = isWeb ? 5 : 100
function DefaultAvatar({size}: {size: number}) { function DefaultAvatar({type, size}: {type: Type; size: number}) {
if (type === 'algo') {
// Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
return (
<Svg
testID="userAvatarFallback"
width={size}
height={size}
viewBox="0 0 32 32"
fill="none"
stroke="none">
<Rect width="32" height="32" rx="4" fill="#0070FF" />
<Path
d="M13.5 7.25C13.5 6.55859 14.0586 6 14.75 6C20.9648 6 26 11.0352 26 17.25C26 17.9414 25.4414 18.5 24.75 18.5C24.0586 18.5 23.5 17.9414 23.5 17.25C23.5 12.418 19.582 8.5 14.75 8.5C14.0586 8.5 13.5 7.94141 13.5 7.25ZM8.36719 14.6172L12.4336 18.6836L13.543 17.5742C13.5156 17.4727 13.5 17.3633 13.5 17.25C13.5 16.5586 14.0586 16 14.75 16C15.4414 16 16 16.5586 16 17.25C16 17.9414 15.4414 18.5 14.75 18.5C14.6367 18.5 14.5312 18.4844 14.4258 18.457L13.3164 19.5664L17.3828 23.6328C17.9492 24.1992 17.8438 25.1484 17.0977 25.4414C16.1758 25.8008 15.1758 26 14.125 26C9.63672 26 6 22.3633 6 17.875C6 16.8242 6.19922 15.8242 6.5625 14.9023C6.85547 14.1602 7.80469 14.0508 8.37109 14.6172H8.36719ZM14.75 9.75C18.8906 9.75 22.25 13.1094 22.25 17.25C22.25 17.9414 21.6914 18.5 21 18.5C20.3086 18.5 19.75 17.9414 19.75 17.25C19.75 14.4883 17.5117 12.25 14.75 12.25C14.0586 12.25 13.5 11.6914 13.5 11C13.5 10.3086 14.0586 9.75 14.75 9.75Z"
fill="white"
/>
</Svg>
)
}
return ( return (
<Svg <Svg
testID="userAvatarFallback" testID="userAvatarFallback"
@ -41,11 +61,13 @@ function DefaultAvatar({size}: {size: number}) {
} }
export function UserAvatar({ export function UserAvatar({
type = 'user',
size, size,
avatar, avatar,
moderation, moderation,
onSelectNewAvatar, onSelectNewAvatar,
}: { }: {
type?: Type
size: number size: number
avatar?: string | null avatar?: string | null
moderation?: AvatarModeration moderation?: AvatarModeration
@ -56,6 +78,21 @@ export function UserAvatar({
const {requestCameraAccessIfNeeded} = useCameraPermission() const {requestCameraAccessIfNeeded} = useCameraPermission()
const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission() const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
const aviStyle = useMemo(() => {
if (type === 'algo') {
return {
width: size,
height: size,
borderRadius: 8,
}
}
return {
width: size,
height: size,
borderRadius: Math.floor(size / 2),
}
}, [type, size])
const dropdownItems = useMemo( const dropdownItems = useMemo(
() => [ () => [
!isWeb && { !isWeb && {
@ -146,11 +183,7 @@ export function UserAvatar({
{avatar ? ( {avatar ? (
<HighPriorityImage <HighPriorityImage
testID="userAvatarImage" testID="userAvatarImage"
style={{ style={aviStyle}
width: size,
height: size,
borderRadius: Math.floor(size / 2),
}}
source={{uri: avatar}} source={{uri: avatar}}
accessibilityRole="image" accessibilityRole="image"
/> />
@ -170,11 +203,7 @@ export function UserAvatar({
<View style={{width: size, height: size}}> <View style={{width: size, height: size}}>
<HighPriorityImage <HighPriorityImage
testID="userAvatarImage" testID="userAvatarImage"
style={{ style={aviStyle}
width: size,
height: size,
borderRadius: Math.floor(size / 2),
}}
contentFit="cover" contentFit="cover"
source={{uri: avatar}} source={{uri: avatar}}
blurRadius={moderation?.blur ? BLUR_AMOUNT : 0} blurRadius={moderation?.blur ? BLUR_AMOUNT : 0}
@ -183,7 +212,7 @@ export function UserAvatar({
</View> </View>
) : ( ) : (
<View style={{width: size, height: size}}> <View style={{width: size, height: size}}>
<DefaultAvatar size={size} /> <DefaultAvatar type={type} size={size} />
{warning} {warning}
</View> </View>
) )
@ -201,11 +230,6 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
backgroundColor: colors.gray5, backgroundColor: colors.gray5,
}, },
avatarImage: {
width: 80,
height: 80,
borderRadius: 40,
},
warningIconContainer: { warningIconContainer: {
position: 'absolute', position: 'absolute',
right: 0, right: 0,

View File

@ -67,7 +67,11 @@ const ListHeaderComponent = observer(({uri}: {uri: string}) => {
<View style={[styles.headerContainer]}> <View style={[styles.headerContainer]}>
<View style={[styles.header]}> <View style={[styles.header]}>
<View style={styles.avatarContainer}> <View style={styles.avatarContainer}>
<UserAvatar size={28} avatar={currentFeed?.data.creator.avatar} /> <UserAvatar
type="algo"
size={28}
avatar={currentFeed?.data.creator.avatar}
/>
<Link href={`/profile/${currentFeed?.data.creator.handle}`}> <Link href={`/profile/${currentFeed?.data.creator.handle}`}>
<Text style={[pal.textLight]}> <Text style={[pal.textLight]}>
@{currentFeed?.data.creator.handle} @{currentFeed?.data.creator.handle}

View File

@ -146,7 +146,11 @@ const ListHeaderComponent = observer(
}) })
}} }}
style={styles.pinnedItem}> style={styles.pinnedItem}>
<UserAvatar avatar={item.data.avatar} size={80} /> <UserAvatar
type="algo"
avatar={item.data.avatar}
size={80}
/>
<Text <Text
type="sm-medium" type="sm-medium"
numberOfLines={1} numberOfLines={1}