Merge branch 'hailey/swap-out-cropper' into hailey/79fab

This commit is contained in:
Hailey
2025-05-05 14:16:23 -07:00
22 changed files with 148 additions and 209 deletions
@@ -8,7 +8,7 @@ import {useCameraPermission} from '#/lib/hooks/usePermissions'
import {openCamera} from '#/lib/media/picker'
import {logger} from '#/logger'
import {isMobileWeb, isNative} from '#/platform/detection'
import {ComposerImage, createComposerImage} from '#/state/gallery'
import {type ComposerImage, createComposerImage} from '#/state/gallery'
import {atoms as a, useTheme} from '#/alf'
import {Button} from '#/components/Button'
import {Camera_Stroke2_Corner0_Rounded as Camera} from '#/components/icons/Camera'
@@ -35,9 +35,7 @@ export function OpenCameraBtn({disabled, onAdd}: Props) {
}
const img = await openCamera({
width: POST_IMG_MAX.width,
height: POST_IMG_MAX.height,
freeStyleCropEnabled: true,
aspect: [POST_IMG_MAX.width, POST_IMG_MAX.height],
})
// If we don't have permissions it's fine, we just wont save it. The post itself will still have access to
+3 -3
View File
@@ -8,7 +8,6 @@ import {
TouchableOpacity,
View,
} from 'react-native'
import {type Image as RNImage} from 'react-native-image-crop-picker'
import {LinearGradient} from 'expo-linear-gradient'
import {type AppBskyGraphDefs, RichText as RichTextAPI} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
@@ -17,6 +16,7 @@ import {useLingui} from '@lingui/react'
import {usePalette} from '#/lib/hooks/usePalette'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {compressIfNeeded} from '#/lib/media/manip'
import {type PickerImage} from '#/lib/media/picker.shared'
import {cleanError, isNetworkError} from '#/lib/strings/errors'
import {enforceLen} from '#/lib/strings/helpers'
import {richTextToString} from '#/lib/strings/rich-text-helpers'
@@ -95,7 +95,7 @@ export function Component({
const isDescriptionOver = graphemeLength > MAX_DESCRIPTION
const [avatar, setAvatar] = useState<string | undefined>(list?.avatar)
const [newAvatar, setNewAvatar] = useState<RNImage | undefined | null>()
const [newAvatar, setNewAvatar] = useState<PickerImage | undefined | null>()
const onDescriptionChange = useCallback(
(newText: string) => {
@@ -112,7 +112,7 @@ export function Component({
}, [closeModal])
const onSelectNewAvatar = useCallback(
async (img: RNImage | null) => {
async (img: PickerImage | null) => {
if (!img) {
setNewAvatar(null)
setAvatar(undefined)
+3 -3
View File
@@ -1,14 +1,14 @@
import React from 'react'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {Image as RNImage} from 'react-native-image-crop-picker'
import {manipulateAsync, SaveFormat} from 'expo-image-manipulator'
import {LinearGradient} from 'expo-linear-gradient'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import ReactCrop, {PercentCrop} from 'react-image-crop'
import ReactCrop, {type PercentCrop} from 'react-image-crop'
import {usePalette} from '#/lib/hooks/usePalette'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {type PickerImage} from '#/lib/media/picker.shared'
import {getDataUriSize} from '#/lib/media/util'
import {gradients, s} from '#/lib/styles'
import {useModalControls} from '#/state/modals'
@@ -25,7 +25,7 @@ export function Component({
uri: string
aspect?: number
circular?: boolean
onSelect: (img?: RNImage) => void
onSelect: (img?: PickerImage) => void
}) {
const pal = usePalette('default')
const {_} = useLingui()
+5 -5
View File
@@ -8,7 +8,6 @@ import {
TouchableOpacity,
View,
} from 'react-native'
import {type Image as RNImage} from 'react-native-image-crop-picker'
import Animated, {FadeOut} from 'react-native-reanimated'
import {LinearGradient} from 'expo-linear-gradient'
import {type AppBskyActorDefs} from '@atproto/api'
@@ -18,6 +17,7 @@ import {useLingui} from '@lingui/react'
import {MAX_DESCRIPTION, MAX_DISPLAY_NAME, urls} from '#/lib/constants'
import {usePalette} from '#/lib/hooks/usePalette'
import {compressIfNeeded} from '#/lib/media/manip'
import {type PickerImage} from '#/lib/media/picker.shared'
import {cleanError} from '#/lib/strings/errors'
import {enforceLen} from '#/lib/strings/helpers'
import {colors, gradients, s} from '#/lib/styles'
@@ -67,16 +67,16 @@ export function Component({
profile.avatar,
)
const [newUserBanner, setNewUserBanner] = useState<
RNImage | undefined | null
PickerImage | undefined | null
>()
const [newUserAvatar, setNewUserAvatar] = useState<
RNImage | undefined | null
PickerImage | undefined | null
>()
const onPressCancel = () => {
closeModal()
}
const onSelectNewAvatar = useCallback(
async (img: RNImage | null) => {
async (img: PickerImage | null) => {
setImageError('')
if (img === null) {
setNewUserAvatar(null)
@@ -95,7 +95,7 @@ export function Component({
)
const onSelectNewBanner = useCallback(
async (img: RNImage | null) => {
async (img: PickerImage | null) => {
setImageError('')
if (!img) {
setNewUserBanner(null)
+14 -17
View File
@@ -2,14 +2,13 @@ import React, {memo, useMemo} from 'react'
import {
Image,
Pressable,
StyleProp,
type StyleProp,
StyleSheet,
View,
ViewStyle,
type ViewStyle,
} from 'react-native'
import {Image as RNImage} from 'react-native-image-crop-picker'
import Svg, {Circle, Path, Rect} from 'react-native-svg'
import {ModerationUI} from '@atproto/api'
import {type ModerationUI} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -38,8 +37,13 @@ import {Link} from '#/components/Link'
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
import * as Menu from '#/components/Menu'
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
import * as bsky from '#/types/bsky'
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
import type * as bsky from '#/types/bsky'
import {
openCamera,
openCropper,
openPicker,
type RNImage,
} from '../../../lib/media/picker'
export type UserAvatarType = 'user' | 'algo' | 'list' | 'labeler'
@@ -312,9 +316,7 @@ let EditableUserAvatar = ({
onSelectNewAvatar(
await openCamera({
width: 1000,
height: 1000,
cropperCircleOverlay: true,
aspect: [1, 1],
}),
)
}, [onSelectNewAvatar, requestCameraAccessIfNeeded])
@@ -336,15 +338,10 @@ let EditableUserAvatar = ({
try {
const croppedImage = await openCropper({
mediaType: 'photo',
cropperCircleOverlay: true,
height: 1000,
width: 1000,
path: item.path,
webAspectRatio: 1,
webCircularCrop: true,
imageUri: item.path,
shape: 'circle',
aspectRatio: 1,
})
onSelectNewAvatar(croppedImage)
} catch (e: any) {
// Don't log errors for cancelling selection to sentry on ios or android
+10 -10
View File
@@ -1,8 +1,7 @@
import React from 'react'
import {Pressable, StyleSheet, View} from 'react-native'
import {Image as RNImage} from 'react-native-image-crop-picker'
import {Image} from 'expo-image'
import {ModerationUI} from '@atproto/api'
import {type ModerationUI} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -25,7 +24,12 @@ import {
import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
import * as Menu from '#/components/Menu'
import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
import {
openCamera,
openCropper,
openPicker,
type RNImage,
} from '../../../lib/media/picker'
export function UserBanner({
type,
@@ -52,8 +56,7 @@ export function UserBanner({
}
onSelectNewBanner?.(
await openCamera({
width: 3000,
height: 1000,
aspect: [3, 1],
}),
)
}, [onSelectNewBanner, requestCameraAccessIfNeeded])
@@ -70,11 +73,8 @@ export function UserBanner({
try {
onSelectNewBanner?.(
await openCropper({
mediaType: 'photo',
path: items[0].path,
width: 3000,
height: 1000,
webAspectRatio: 3,
imageUri: items[0].path,
aspectRatio: 3 / 1,
}),
)
} catch (e: any) {