From ae26963b45082b842803076a5b55532031f9f69a Mon Sep 17 00:00:00 2001 From: Piotr P Date: Sat, 27 Apr 2024 14:21:13 +0200 Subject: eslint autofixes --- src/lib/media/picker.web.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib/media/picker.web.tsx') diff --git a/src/lib/media/picker.web.tsx b/src/lib/media/picker.web.tsx index 995a0c95f..7e2562e29 100644 --- a/src/lib/media/picker.web.tsx +++ b/src/lib/media/picker.web.tsx @@ -1,7 +1,8 @@ /// -import {CameraOpts, CropperOptions} from './types' import {Image as RNImage} from 'react-native-image-crop-picker' + +import {CameraOpts, CropperOptions} from './types' export {openPicker} from './picker.shared' import {unstable__openModal} from '#/state/modals' -- cgit 1.4.1 From ebd333b331d7103322d4e0a1c6f5035c0b22bdd9 Mon Sep 17 00:00:00 2001 From: Piotr P Date: Sat, 27 Apr 2024 14:21:52 +0200 Subject: Fix cropper crashing after clicking cancel --- src/lib/media/picker.web.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/lib/media/picker.web.tsx') diff --git a/src/lib/media/picker.web.tsx b/src/lib/media/picker.web.tsx index 7e2562e29..70e28838b 100644 --- a/src/lib/media/picker.web.tsx +++ b/src/lib/media/picker.web.tsx @@ -13,15 +13,13 @@ export async function openCamera(_opts: CameraOpts): Promise { export async function openCropper(opts: CropperOptions): Promise { // TODO handle more opts - return new Promise((resolve, reject) => { + return new Promise(resolve => { unstable__openModal({ name: 'crop-image', uri: opts.path, onSelect: (img?: RNImage) => { if (img) { resolve(img) - } else { - reject(new Error('Canceled')) } }, }) -- cgit 1.4.1 From bc956803b800715ae2ebbc2105b44c9dc335863b Mon Sep 17 00:00:00 2001 From: Piotr P Date: Sat, 27 Apr 2024 14:23:11 +0200 Subject: allow for custom cropper aspect ration based on image --- src/lib/media/picker.web.tsx | 4 ++++ src/state/modals/index.tsx | 1 + src/view/com/modals/crop-image/CropImage.web.tsx | 30 ++++++++++++++++++++---- 3 files changed, 30 insertions(+), 5 deletions(-) (limited to 'src/lib/media/picker.web.tsx') diff --git a/src/lib/media/picker.web.tsx b/src/lib/media/picker.web.tsx index 70e28838b..fde6a64ac 100644 --- a/src/lib/media/picker.web.tsx +++ b/src/lib/media/picker.web.tsx @@ -17,6 +17,10 @@ export async function openCropper(opts: CropperOptions): Promise { unstable__openModal({ name: 'crop-image', uri: opts.path, + dimensions: + opts.height && opts.width + ? {width: opts.width, height: opts.height} + : undefined, onSelect: (img?: RNImage) => { if (img) { resolve(img) diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index 0f61a9711..cf82bcd07 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -47,6 +47,7 @@ export interface EditImageModal { export interface CropImageModal { name: 'crop-image' uri: string + dimensions?: {width: number; height: number} onSelect: (img?: RNImage) => void } diff --git a/src/view/com/modals/crop-image/CropImage.web.tsx b/src/view/com/modals/crop-image/CropImage.web.tsx index 79ff5a02a..a359ed44d 100644 --- a/src/view/com/modals/crop-image/CropImage.web.tsx +++ b/src/view/com/modals/crop-image/CropImage.web.tsx @@ -14,11 +14,13 @@ import {Dimensions} from 'lib/media/types' import {getDataUriSize} from 'lib/media/util' import {gradients, s} from 'lib/styles' import {Text} from 'view/com/util/text/Text' +import {calculateDimensions} from './cropImageUtil' enum AspectRatio { Square = 'square', Wide = 'wide', Tall = 'tall', + Custom = 'custom', } const DIMS: Record = { @@ -31,17 +33,24 @@ export const snapPoints = ['0%'] export function Component({ uri, + dimensions, onSelect, }: { uri: string + dimensions?: Dimensions onSelect: (img?: RNImage) => void }) { const {closeModal} = useModalControls() const pal = usePalette('default') const {_} = useLingui() - const [as, setAs] = React.useState(AspectRatio.Square) + const defaultAspectStyle = dimensions + ? AspectRatio.Custom + : AspectRatio.Square + const [as, setAs] = React.useState(defaultAspectStyle) const [scale, setScale] = React.useState(1) const editorRef = React.useRef(null) + const imageEditorWidth = dimensions ? dimensions.width : DIMS[as].width + const imageEditorHeight = dimensions ? dimensions.height : DIMS[as].height const doSetAs = (v: AspectRatio) => () => setAs(v) @@ -57,8 +66,8 @@ export function Component({ path: dataUri, mime: 'image/jpeg', size: getDataUriSize(dataUri), - width: DIMS[as].width, - height: DIMS[as].height, + width: imageEditorWidth, + height: imageEditorHeight, }) } else { onSelect(undefined) @@ -73,7 +82,18 @@ export function Component({ cropperStyle = styles.cropperWide } else if (as === AspectRatio.Tall) { cropperStyle = styles.cropperTall + } else if (as === AspectRatio.Custom) { + const cropperDimensions = calculateDimensions( + 550, + imageEditorHeight, + imageEditorWidth, + ) + cropperStyle = { + width: cropperDimensions.width, + height: cropperDimensions.height, + } } + return ( @@ -81,8 +101,8 @@ export function Component({ ref={editorRef} style={styles.imageEditor} image={uri} - width={DIMS[as].width} - height={DIMS[as].height} + width={imageEditorWidth} + height={imageEditorHeight} scale={scale} border={0} /> -- cgit 1.4.1 From fe82257801f49b3d7aceca9dd611ef4005da48ce Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 6 May 2024 15:44:19 -0700 Subject: Dont leave promise unresolved --- src/lib/media/picker.web.tsx | 4 +++- src/view/com/util/UserAvatar.tsx | 23 +++++++++++++++-------- src/view/com/util/UserBanner.tsx | 23 +++++++++++++++-------- 3 files changed, 33 insertions(+), 17 deletions(-) (limited to 'src/lib/media/picker.web.tsx') diff --git a/src/lib/media/picker.web.tsx b/src/lib/media/picker.web.tsx index fde6a64ac..8782e1457 100644 --- a/src/lib/media/picker.web.tsx +++ b/src/lib/media/picker.web.tsx @@ -13,7 +13,7 @@ export async function openCamera(_opts: CameraOpts): Promise { export async function openCropper(opts: CropperOptions): Promise { // TODO handle more opts - return new Promise(resolve => { + return new Promise((resolve, reject) => { unstable__openModal({ name: 'crop-image', uri: opts.path, @@ -24,6 +24,8 @@ export async function openCropper(opts: CropperOptions): Promise { onSelect: (img?: RNImage) => { if (img) { resolve(img) + } else { + reject(new Error('Canceled')) } }, }) diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx index 118e2ce2b..45327669b 100644 --- a/src/view/com/util/UserAvatar.tsx +++ b/src/view/com/util/UserAvatar.tsx @@ -8,6 +8,7 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useQueryClient} from '@tanstack/react-query' +import {logger} from '#/logger' import {usePalette} from 'lib/hooks/usePalette' import { useCameraPermission, @@ -282,15 +283,21 @@ let EditableUserAvatar = ({ return } - const croppedImage = await openCropper({ - mediaType: 'photo', - cropperCircleOverlay: true, - height: item.height, - width: item.width, - path: item.path, - }) + try { + const croppedImage = await openCropper({ + mediaType: 'photo', + cropperCircleOverlay: true, + height: item.height, + width: item.width, + path: item.path, + }) - onSelectNewAvatar(croppedImage) + onSelectNewAvatar(croppedImage) + } catch (e: any) { + if (!String(e).includes('Canceled')) { + logger.error('Failed to crop banner', {error: e}) + } + } }, [onSelectNewAvatar, requestPhotoAccessIfNeeded]) const onRemoveAvatar = React.useCallback(() => { diff --git a/src/view/com/util/UserBanner.tsx b/src/view/com/util/UserBanner.tsx index f08044ec3..93ea32750 100644 --- a/src/view/com/util/UserBanner.tsx +++ b/src/view/com/util/UserBanner.tsx @@ -6,6 +6,7 @@ import {ModerationUI} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {logger} from '#/logger' import {usePalette} from 'lib/hooks/usePalette' import { useCameraPermission, @@ -64,14 +65,20 @@ export function UserBanner({ return } - onSelectNewBanner?.( - await openCropper({ - mediaType: 'photo', - path: items[0].path, - width: 3000, - height: 1000, - }), - ) + try { + onSelectNewBanner?.( + await openCropper({ + mediaType: 'photo', + path: items[0].path, + width: 3000, + height: 1000, + }), + ) + } catch (e: any) { + if (!String(e).includes('Canceled')) { + logger.error('Failed to crop banner', {error: e}) + } + } }, [onSelectNewBanner, requestPhotoAccessIfNeeded]) const onRemoveBanner = React.useCallback(() => { -- cgit 1.4.1