organize imports and cleanup styles
This commit is contained in:
@@ -1,21 +1,16 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
LayoutAnimation,
|
||||
Pressable,
|
||||
PressableProps,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {LayoutAnimation, Pressable, PressableProps, View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {TimesLarge_Stroke2_Corner0_Rounded as Times} from '#/components/icons/Times'
|
||||
import {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera'
|
||||
import {useAvatar, useSetAvatar} from '#/screens/Onboarding/StepProfile/index'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
|
||||
import {openPicker} from 'lib/media/picker.shared'
|
||||
import {isNative, isWeb} from 'platform/detection'
|
||||
import {openCropper} from 'lib/media/picker'
|
||||
import {compressIfNeeded} from 'lib/media/manip'
|
||||
import {Image} from 'expo-image'
|
||||
import {TimesLarge_Stroke2_Corner0_Rounded as Times} from '#/components/icons/Times'
|
||||
import {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera'
|
||||
import {useAvatar, useSetAvatar} from '#/screens/Onboarding/StepProfile/index'
|
||||
|
||||
export function AvatarBottomButton({...props}: PressableProps) {
|
||||
const t = useTheme()
|
||||
@@ -43,6 +38,25 @@ export function AvatarCircle() {
|
||||
const Icon = avatar.placeholder.component
|
||||
const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
|
||||
|
||||
const styles = React.useMemo(
|
||||
() => ({
|
||||
imageContainer: [
|
||||
a.rounded_full,
|
||||
a.overflow_hidden,
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
t.atoms.border_contrast_high,
|
||||
{
|
||||
height: 150,
|
||||
width: 150,
|
||||
borderWidth: 2,
|
||||
backgroundColor: avatar.backgroundColor,
|
||||
},
|
||||
],
|
||||
}),
|
||||
[avatar.backgroundColor, t.atoms.border_contrast_high],
|
||||
)
|
||||
|
||||
const onCameraPress = React.useCallback(async () => {
|
||||
if (!(await requestPhotoAccessIfNeeded())) {
|
||||
return
|
||||
@@ -93,7 +107,7 @@ export function AvatarCircle() {
|
||||
<View>
|
||||
<Image
|
||||
source={avatar.image.path}
|
||||
style={[styles.imageContainer, t.atoms.border_contrast_high]}
|
||||
style={styles.imageContainer}
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
<AvatarBottomButton onPress={onPressRemoveAvatar}>
|
||||
@@ -105,14 +119,7 @@ export function AvatarCircle() {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View
|
||||
style={[
|
||||
styles.imageContainer,
|
||||
t.atoms.border_contrast_high,
|
||||
{
|
||||
backgroundColor: avatar.backgroundColor,
|
||||
},
|
||||
]}>
|
||||
<View style={styles.imageContainer}>
|
||||
<Icon height={85} width={85} style={{color: t.palette.white}} />
|
||||
</View>
|
||||
<AvatarBottomButton onPress={onCameraPress}>
|
||||
@@ -121,15 +128,3 @@ export function AvatarCircle() {
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
imageContainer: {
|
||||
borderRadius: 100,
|
||||
height: 150,
|
||||
width: 150,
|
||||
overflow: 'hidden',
|
||||
borderWidth: 2,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import React from 'react'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {FlatList, ListRenderItemInfo, Pressable, View} from 'react-native'
|
||||
import Animated, {
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withTiming,
|
||||
} from 'react-native-reanimated'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useAvatar, useSetAvatar} from '#/screens/Onboarding/StepProfile/index'
|
||||
import {
|
||||
AvatarColor,
|
||||
avatarColors,
|
||||
@@ -13,15 +15,7 @@ import {
|
||||
EmojiName,
|
||||
emojiNames,
|
||||
} from '#/screens/Onboarding/StepProfile/types'
|
||||
import {
|
||||
FlatList,
|
||||
FlatListProps,
|
||||
ListRenderItemInfo,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {useAvatar, useSetAvatar} from '#/screens/Onboarding/StepProfile/index'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
|
||||
const WITH_TIMING_CONFIG = {duration: 150}
|
||||
|
||||
@@ -31,9 +25,26 @@ function AnimatedCircle({
|
||||
}: React.PropsWithChildren<{selected: boolean}>) {
|
||||
const t = useTheme()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const styles = useStyles()
|
||||
const size = useSharedValue(selected ? 1.2 : 1)
|
||||
|
||||
const styles = React.useMemo(
|
||||
() => ({
|
||||
imageContainer: [
|
||||
a.rounded_full,
|
||||
a.overflow_hidden,
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
{height: 150, width: 150, borderWidth: 2},
|
||||
],
|
||||
paletteContainer: {
|
||||
height: 70,
|
||||
width: 70,
|
||||
margin: isTabletOrDesktop ? 8 : 2,
|
||||
},
|
||||
}),
|
||||
[isTabletOrDesktop],
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (selected && size.value !== 1.2) {
|
||||
size.value = withTiming(1.2, WITH_TIMING_CONFIG)
|
||||
@@ -125,63 +136,40 @@ function emojiRenderItem({item}: ListRenderItemInfo<EmojiName>) {
|
||||
|
||||
export function AvatarCreatorItems({type}: {type: 'emojis' | 'colors'}) {
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const styles = useStyles()
|
||||
|
||||
const styles = React.useMemo(
|
||||
() => ({
|
||||
flatListOuter: isTabletOrDesktop
|
||||
? {
|
||||
height: 435,
|
||||
}
|
||||
: [a.flex_row, a.align_center, {height: 100}],
|
||||
}),
|
||||
[isTabletOrDesktop],
|
||||
)
|
||||
|
||||
return (
|
||||
<View style={styles.flatListOuter}>
|
||||
<FlatList
|
||||
<View
|
||||
style={[
|
||||
styles.flatListOuter,
|
||||
isTabletOrDesktop && type === 'colors' && {width: 125},
|
||||
]}>
|
||||
<FlatList<any>
|
||||
// Changing the value of numColumns on the fly isn't supported, so we want the flatlist to re-render whenever
|
||||
// the size of the screen changes
|
||||
// the size of the screen changes. Should only happen when `isTabletOrDesktop` changes.
|
||||
key={isTabletOrDesktop ? 0 : 1}
|
||||
data={type === 'colors' ? avatarColors : emojiNames}
|
||||
renderItem={type === 'colors' ? colorRenderItem : emojiRenderItem}
|
||||
style={[isTabletOrDesktop && {marginHorizontal: 10}]}
|
||||
contentContainerStyle={[
|
||||
a.align_center,
|
||||
{height: 100},
|
||||
!isTabletOrDesktop && styles.flatListContainer,
|
||||
isTabletOrDesktop && type === 'colors' && a.pr_xs,
|
||||
!isTabletOrDesktop && {paddingHorizontal: 40},
|
||||
]}
|
||||
numColumns={isTabletOrDesktop && type === 'emojis' ? 4 : undefined}
|
||||
showsHorizontalScrollIndicator={isTabletOrDesktop && type === 'colors'}
|
||||
horizontal={!isTabletOrDesktop}
|
||||
{...commonFlatListProps}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = () => {
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
|
||||
return StyleSheet.create({
|
||||
imageContainer: {
|
||||
borderRadius: 100,
|
||||
height: 150,
|
||||
width: 150,
|
||||
overflow: 'hidden',
|
||||
borderWidth: 2,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
paletteContainer: {
|
||||
height: 70,
|
||||
width: 70,
|
||||
margin: isTabletOrDesktop ? 8 : 2,
|
||||
},
|
||||
flatListOuter: isTabletOrDesktop
|
||||
? {
|
||||
height: 435,
|
||||
}
|
||||
: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: 100,
|
||||
},
|
||||
flatListContainer: {
|
||||
paddingHorizontal: 40,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const commonFlatListProps: Partial<FlatListProps<any>> = {}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from 'react'
|
||||
import {useAvatar} from '#/screens/Onboarding/StepProfile/index'
|
||||
import ViewShot from 'react-native-view-shot'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
|
||||
export interface PlaceholderCanvasRef {
|
||||
capture: () => Promise<string>
|
||||
@@ -15,6 +17,18 @@ export const PlaceholderCanvas = React.forwardRef<PlaceholderCanvasRef, {}>(
|
||||
const viewshotRef = React.useRef()
|
||||
const Icon = avatar.placeholder.component
|
||||
|
||||
const styles = React.useMemo(
|
||||
() => ({
|
||||
container: [a.absolute, {top: -2000}],
|
||||
imageContainer: [
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
{height: 150 * 5, width: 150 * 5},
|
||||
],
|
||||
}),
|
||||
[],
|
||||
)
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
// @ts-ignore this library doesn't have types
|
||||
capture: viewshotRef.current.capture,
|
||||
@@ -43,16 +57,3 @@ export const PlaceholderCanvas = React.forwardRef<PlaceholderCanvasRef, {}>(
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
top: -2000,
|
||||
position: 'absolute',
|
||||
},
|
||||
imageContainer: {
|
||||
height: 150 * 5,
|
||||
width: 150 * 5,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -4,26 +4,25 @@ import {useLingui} from '@lingui/react'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
import {Button, ButtonText, ButtonIcon} from '#/components/Button'
|
||||
import {StreamingLive_Stroke2_Corner0_Rounded as StreamingLive} from '#/components/icons/StreamingLive'
|
||||
import {useAnalytics} from '#/lib/analytics/analytics'
|
||||
|
||||
import {Context} from '#/screens/Onboarding/state'
|
||||
import {
|
||||
Title,
|
||||
Description,
|
||||
OnboardingControls,
|
||||
} from '#/screens/Onboarding/Layout'
|
||||
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
|
||||
import {IconCircle} from '#/components/IconCircle'
|
||||
import {AvatarCreatorItems} from '#/screens/Onboarding/StepProfile/AvatarCreatorItems'
|
||||
import {AvatarCircle} from '#/screens/Onboarding/StepProfile/AvatarCircle'
|
||||
import {Emoji, emojiItems, AvatarColor, avatarColors} from './types'
|
||||
import {
|
||||
PlaceholderCanvas,
|
||||
PlaceholderCanvasRef,
|
||||
} from '#/screens/Onboarding/StepProfile/PlaceholderCanvas'
|
||||
import {Button, ButtonText, ButtonIcon} from '#/components/Button'
|
||||
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
|
||||
import {IconCircle} from '#/components/IconCircle'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {AvatarCircle} from '#/screens/Onboarding/StepProfile/AvatarCircle'
|
||||
import {AvatarCreatorItems} from '#/screens/Onboarding/StepProfile/AvatarCreatorItems'
|
||||
import {useAnalytics} from '#/lib/analytics/analytics'
|
||||
|
||||
interface Avatar {
|
||||
image?: {
|
||||
@@ -64,7 +63,6 @@ export function StepProfile() {
|
||||
|
||||
const onContinue = React.useCallback(async () => {
|
||||
let imageUri = avatar?.image?.path
|
||||
let imageMime = avatar?.image?.mime
|
||||
if (!imageUri) {
|
||||
imageUri = await canvasRef.current?.capture()
|
||||
}
|
||||
@@ -73,7 +71,7 @@ export function StepProfile() {
|
||||
dispatch({
|
||||
type: 'setProfileStepResults',
|
||||
imageUri,
|
||||
imageMime: imageMime ?? 'image/jpeg',
|
||||
imageMime: avatar.image?.mime ?? 'image/jpeg',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -81,9 +81,8 @@ export type ApiResponseMap = {
|
||||
export const initialState: OnboardingState = {
|
||||
hasPrev: false,
|
||||
totalSteps: 8,
|
||||
// activeStep: 'interests', // TODO revert this
|
||||
activeStep: 'profile',
|
||||
activeStepIndex: 7,
|
||||
activeStep: 'interests',
|
||||
activeStepIndex: 1,
|
||||
|
||||
interestsStepResults: {
|
||||
selectedInterests: [],
|
||||
|
||||
Reference in New Issue
Block a user