add state context, pressables
This commit is contained in:
@@ -2,7 +2,9 @@ import React from 'react'
|
|||||||
import {
|
import {
|
||||||
ColorValue,
|
ColorValue,
|
||||||
FlatList,
|
FlatList,
|
||||||
|
FlatListProps,
|
||||||
ListRenderItemInfo,
|
ListRenderItemInfo,
|
||||||
|
Pressable,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
@@ -34,10 +36,17 @@ type AvatarPlaceholder = 'thinking' | 'heart' | 'laughing'
|
|||||||
|
|
||||||
interface Avatar {
|
interface Avatar {
|
||||||
imageUri?: string
|
imageUri?: string
|
||||||
backgroundColor?: ColorValue
|
backgroundColor?: Color
|
||||||
placeholder?: AvatarPlaceholder
|
placeholder?: Emoji
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AvatarContext = React.createContext<Avatar>({} as Avatar)
|
||||||
|
const SetAvatarContext = React.createContext<
|
||||||
|
React.Dispatch<React.SetStateAction<Avatar>>
|
||||||
|
>({} as React.Dispatch<React.SetStateAction<Avatar>>)
|
||||||
|
const useAvatar = () => React.useContext(AvatarContext)
|
||||||
|
const useSetAvatar = () => React.useContext(SetAvatarContext)
|
||||||
|
|
||||||
export function StepProfile() {
|
export function StepProfile() {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -56,6 +65,8 @@ export function StepProfile() {
|
|||||||
}, [track, dispatch])
|
}, [track, dispatch])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<SetAvatarContext.Provider value={setAvatar}>
|
||||||
|
<AvatarContext.Provider value={avatar}>
|
||||||
<View style={[a.align_start]}>
|
<View style={[a.align_start]}>
|
||||||
<IconCircle icon={StreamingLive} style={[a.mb_2xl]} />
|
<IconCircle icon={StreamingLive} style={[a.mb_2xl]} />
|
||||||
|
|
||||||
@@ -67,8 +78,8 @@ export function StepProfile() {
|
|||||||
</Description>
|
</Description>
|
||||||
|
|
||||||
<View style={[a.pt_5xl, a.gap_3xl]}>
|
<View style={[a.pt_5xl, a.gap_3xl]}>
|
||||||
<Items type="colors" />
|
|
||||||
<Items type="emojis" />
|
<Items type="emojis" />
|
||||||
|
<Items type="colors" />
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<OnboardingControls.Portal>
|
<OnboardingControls.Portal>
|
||||||
@@ -86,16 +97,14 @@ export function StepProfile() {
|
|||||||
</Button>
|
</Button>
|
||||||
</OnboardingControls.Portal>
|
</OnboardingControls.Portal>
|
||||||
</View>
|
</View>
|
||||||
|
</AvatarContext.Provider>
|
||||||
|
</SetAvatarContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function AvatarCircle({
|
function AvatarCircle() {
|
||||||
avatar,
|
const avatar = useAvatar()
|
||||||
setAvatar,
|
|
||||||
}: {
|
|
||||||
avatar: Avatar
|
|
||||||
setAvatar: React.Dispatch<React.SetStateAction<Avatar>>
|
|
||||||
}) {
|
|
||||||
if (avatar.imageUri) {
|
if (avatar.imageUri) {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.imageContainer]}>
|
<View style={[styles.imageContainer]}>
|
||||||
@@ -127,15 +136,30 @@ const emojiItems: Record<Emoji, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ColorItem({color}: {color: Color}) {
|
function ColorItem({color}: {color: Color}) {
|
||||||
|
const avatar = useAvatar()
|
||||||
|
const setAvatar = useSetAvatar()
|
||||||
|
|
||||||
|
const onPress = React.useCallback(() => {
|
||||||
|
setAvatar(prev => ({
|
||||||
|
...prev,
|
||||||
|
backgroundColor: color,
|
||||||
|
}))
|
||||||
|
}, [color, setAvatar])
|
||||||
|
|
||||||
if (color === 'image') return null
|
if (color === 'image') return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<Pressable
|
||||||
|
accessibilityRole="button"
|
||||||
style={[
|
style={[
|
||||||
styles.imageContainer,
|
styles.imageContainer,
|
||||||
styles.paletteContainer,
|
styles.paletteContainer,
|
||||||
{backgroundColor: color},
|
{
|
||||||
|
backgroundColor: color,
|
||||||
|
borderWidth: avatar.backgroundColor === color ? 3 : 1,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -144,10 +168,31 @@ function colorRenderItem({item}: ListRenderItemInfo<Color>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function EmojiItem({emoji}: {emoji: Emoji}) {
|
function EmojiItem({emoji}: {emoji: Emoji}) {
|
||||||
|
const avatar = useAvatar()
|
||||||
|
const setAvatar = useSetAvatar()
|
||||||
|
|
||||||
|
const onPress = React.useCallback(() => {
|
||||||
|
setAvatar(prev => ({
|
||||||
|
...prev,
|
||||||
|
placeholder: emoji,
|
||||||
|
}))
|
||||||
|
}, [emoji, setAvatar])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.imageContainer, styles.paletteContainer]}>
|
<Pressable
|
||||||
<Text>{emojiItems[emoji]}</Text>
|
accessibilityRole="button"
|
||||||
</View>
|
style={[
|
||||||
|
styles.imageContainer,
|
||||||
|
styles.paletteContainer,
|
||||||
|
{
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
borderWidth: avatar.placeholder === emoji ? 3 : 1,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPress={onPress}>
|
||||||
|
<Text style={[a.text_5xl]}>{emojiItems[emoji]}</Text>
|
||||||
|
</Pressable>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
function emojiRenderItem({item}: ListRenderItemInfo<Emoji>) {
|
function emojiRenderItem({item}: ListRenderItemInfo<Emoji>) {
|
||||||
@@ -157,23 +202,25 @@ function emojiRenderItem({item}: ListRenderItemInfo<Emoji>) {
|
|||||||
function Items({type}: {type: 'emojis' | 'colors'}) {
|
function Items({type}: {type: 'emojis' | 'colors'}) {
|
||||||
if (type === 'colors') {
|
if (type === 'colors') {
|
||||||
return (
|
return (
|
||||||
|
<View style={styles.flatListOuter}>
|
||||||
<FlatList<Color>
|
<FlatList<Color>
|
||||||
style={{height: 100}}
|
style={{height: 100}}
|
||||||
data={colors}
|
data={colors}
|
||||||
renderItem={colorRenderItem}
|
renderItem={colorRenderItem}
|
||||||
horizontal
|
{...commonFlatListProps}
|
||||||
contentContainerStyle={styles.flatListContainer}
|
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<View style={styles.flatListOuter}>
|
||||||
<FlatList<Emoji>
|
<FlatList<Emoji>
|
||||||
data={emojis}
|
data={emojis}
|
||||||
renderItem={emojiRenderItem}
|
renderItem={emojiRenderItem}
|
||||||
horizontal
|
{...commonFlatListProps}
|
||||||
contentContainerStyle={styles.flatListContainer}
|
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,8 +236,17 @@ const styles = StyleSheet.create({
|
|||||||
width: 90,
|
width: 90,
|
||||||
marginHorizontal: 5,
|
marginHorizontal: 5,
|
||||||
},
|
},
|
||||||
|
flatListOuter: {
|
||||||
|
height: 100,
|
||||||
|
},
|
||||||
flatListContainer: {
|
flatListContainer: {
|
||||||
paddingLeft: 40,
|
paddingLeft: 40,
|
||||||
paddingRight: 40,
|
paddingRight: 40,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const commonFlatListProps: Partial<FlatListProps<any>> = {
|
||||||
|
horizontal: true,
|
||||||
|
contentContainerStyle: styles.flatListContainer,
|
||||||
|
showsHorizontalScrollIndicator: false,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user