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