diff --git a/src/screens/Onboarding/StepProfile/PlaceholderCanvas.tsx b/src/screens/Onboarding/StepProfile/PlaceholderCanvas.tsx new file mode 100644 index 0000000000..f803a9e162 --- /dev/null +++ b/src/screens/Onboarding/StepProfile/PlaceholderCanvas.tsx @@ -0,0 +1,44 @@ +import React from 'react' +import {useAvatar} from '#/screens/Onboarding/StepProfile/index' +import ViewShot from 'react-native-view-shot' +import {StyleSheet, View} from 'react-native' + +// This component is supposed to be invisible to the user. We only need this for ViewShot to have something to +// "screenshot" +export const PlaceholderCanvas = React.forwardRef(function PlaceholderCanvas( + {}, + ref, +) { + const avatar = useAvatar() + const viewshotRef = React.useRef() + const Icon = avatar.placeholder.component + + // React.useEffect(() => { + // // @ts-ignore this library doesn't have types + // viewshotRef.current.capture().then(uri => { + // return uri + // }) + // }, [avatar, ref]) + + return ( + + + + + + + + ) +}) + +const styles = StyleSheet.create({ + imageContainer: { + top: 100, + position: 'absolute', + zIndex: -5, + }, +}) diff --git a/src/screens/Onboarding/StepProfile/PlaceholderCanvasDontNeedThisLol.web.tsx b/src/screens/Onboarding/StepProfile/PlaceholderCanvasDontNeedThisLol.web.tsx new file mode 100644 index 0000000000..c998ea5f00 --- /dev/null +++ b/src/screens/Onboarding/StepProfile/PlaceholderCanvasDontNeedThisLol.web.tsx @@ -0,0 +1,43 @@ +import React from 'react' +import {useAvatar} from '#/screens/Onboarding/StepProfile/index' + +const CANVAS_HEIGHT = 24 * 10 +const CANVAS_OFFSET = 24 * 1.5 + +interface PlaceholderCanvasRef { + capture: () => string +} + +export const PlaceholderCanvas = React.forwardRef(function PlaceholderCanvas( + {}, + ref, +) { + const avatar = useAvatar() + const canvasRef = React.useRef(null) + + const capture = React.useCallback(() => { + return '' + }, []) + + React.useImperativeHandle(ref, () => ({ + capture, + })) + + React.useEffect(() => { + // @ts-ignore web only + const path = new Path2D(avatar.placeholder.path) + // @ts-ignore web only + const ctx = canvasRef.current?.getContext('2d') + ctx?.reset() + ctx.fillStyle = avatar.backgroundColor + ctx?.moveTo(0, 0) + ctx?.fillRect(0, 0, CANVAS_HEIGHT, CANVAS_HEIGHT) + ctx.fillStyle = '#fff' + ctx.lineWidth = 0.1 + ctx?.translate(CANVAS_OFFSET, CANVAS_OFFSET) + ctx?.scale(7, 7) + ctx?.fill(path) + }, [avatar.backgroundColor, avatar.placeholder.path]) + + return +}) diff --git a/src/screens/Onboarding/StepProfile/SelectImageButton.web.tsx b/src/screens/Onboarding/StepProfile/SelectImageButton.web.tsx deleted file mode 100644 index 653047c71e..0000000000 --- a/src/screens/Onboarding/StepProfile/SelectImageButton.web.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import React from 'react' -import {Pressable, StyleSheet} from 'react-native' -import {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera' -import {useAvatar, useSetAvatar} from '#/screens/Onboarding/StepProfile/index' -import {useTheme} from '#/alf' -import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions' -import {openPicker} from 'lib/media/picker.shared' -import {openCropper} from 'lib/media/picker' - -export function SelectImageButton() { - const t = useTheme() - const setAvatar = useSetAvatar() - const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission() - - const onCameraPress = React.useCallback(async () => { - if (!(await requestPhotoAccessIfNeeded())) { - return - } - - const items = await openPicker({ - aspect: [1, 1], - }) - const item = items[0] - if (!item) return - - const croppedImage = await openCropper({ - mediaType: 'photo', - cropperCircleOverlay: true, - height: item.height, - width: item.width, - path: item.path, - }) - - setAvatar(prev => ({ - ...prev, - image: croppedImage, - })) - }, [requestPhotoAccessIfNeeded, setAvatar]) - - return ( - <> - - - - - - ) -} - -function Canvas() { - const avatar = useAvatar() - const canvasRef = React.useRef(null) - - React.useEffect(() => { - // @ts-ignore web only - const path = new Path2D(avatar.placeholder.path) - // @ts-ignore web only - const ctx = canvasRef.current?.getContext('2d') - ctx?.reset() - ctx.fillStyle = avatar.backgroundColor - ctx?.moveTo(0, 0) - ctx?.fillRect(0, 0, 24 * 10, 24 * 10) - ctx.fillStyle = '#fff' - ctx.lineWidth = 0.1 - ctx?.translate(24 * 1.5, 24 * 1.5) - ctx?.scale(7, 7) - ctx?.fill(path) - }, [avatar.backgroundColor, avatar.placeholder.path]) - - return -} - -const styles = StyleSheet.create({ - imageContainer: { - borderRadius: 100, - borderWidth: 2, - height: 150, - width: 150, - overflow: 'hidden', - alignItems: 'center', - justifyContent: 'center', - }, - paletteContainer: { - height: 80, - width: 80, - marginHorizontal: 5, - }, - flatListOuter: { - height: 100, - }, - flatListContainer: { - paddingLeft: 40, - paddingRight: 40, - }, -}) diff --git a/src/screens/Onboarding/StepProfile/index.tsx b/src/screens/Onboarding/StepProfile/index.tsx index e943c3e81b..83058433e7 100644 --- a/src/screens/Onboarding/StepProfile/index.tsx +++ b/src/screens/Onboarding/StepProfile/index.tsx @@ -10,7 +10,7 @@ import { import {useLingui} from '@lingui/react' import {msg, Trans} from '@lingui/macro' -import {atoms as a, 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 {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera' @@ -31,6 +31,8 @@ import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions' import {openCropper, openPicker} from 'lib/media/picker' import {Emoji, EmojiName, emojiItems, emojiNames} from './types' import {SelectImageButton} from '#/screens/Onboarding/StepProfile/SelectImageButton' +import ViewShot from 'react-native-view-shot' +import {PlaceholderCanvas} from '#/screens/Onboarding/StepProfile/PlaceholderCanvas' interface Avatar { image?: { @@ -53,6 +55,8 @@ export const useSetAvatar = () => React.useContext(SetAvatarContext) export function StepProfile() { const {_} = useLingui() + const t = useTheme() + const {gtMobile} = useBreakpoints() const {track} = useAnalytics() const {state, dispatch} = React.useContext(Context) const [avatar, setAvatar] = React.useState({ @@ -72,42 +76,46 @@ export function StepProfile() { return ( - - + <> + + + - - <Trans>Set your profile picture</Trans> - - - - Help people know you're not a bot by uploading a picture or - creating an avatar! - - - - - - + + <Trans>Set your profile picture</Trans> + + + + Help people know you're not a bot by uploading a picture or + creating an avatar! + + + + + + + + + - - - - - - - + + + + + + )