import React from 'react' import {StyleSheet, TouchableOpacity, View} from 'react-native' import {Image as RNImage} from 'react-native-image-crop-picker' import {LinearGradient} from 'expo-linear-gradient' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {Slider} from '@miblanchard/react-native-slider' import ImageEditor from 'react-avatar-editor' import {useModalControls} from '#/state/modals' import {usePalette} from 'lib/hooks/usePalette' import {RectTallIcon, RectWideIcon, SquareIcon} from 'lib/icons' 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 = { [AspectRatio.Square]: {width: 1000, height: 1000}, [AspectRatio.Wide]: {width: 1000, height: 750}, [AspectRatio.Tall]: {width: 750, height: 1000}, } 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 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) const onPressCancel = () => { onSelect(undefined) closeModal() } const onPressDone = () => { const canvas = editorRef.current?.getImageScaledToCanvas() if (canvas) { const dataUri = canvas.toDataURL('image/jpeg') onSelect({ path: dataUri, mime: 'image/jpeg', size: getDataUriSize(dataUri), width: imageEditorWidth, height: imageEditorHeight, }) } else { onSelect(undefined) } closeModal() } let cropperStyle if (as === AspectRatio.Square) { cropperStyle = styles.cropperSquare } else if (as === AspectRatio.Wide) { 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 ( setScale(Array.isArray(v) ? v[0] : v) } minimumValue={1} maximumValue={3} containerStyle={styles.slider} /> {as === AspectRatio.Custom ? null : ( <> )} Cancel Done ) } const styles = StyleSheet.create({ cropper: { marginLeft: 'auto', marginRight: 'auto', borderWidth: 1, borderRadius: 4, overflow: 'hidden', }, cropperSquare: { width: 400, height: 400, }, cropperWide: { width: 400, height: 300, }, cropperTall: { width: 300, height: 400, }, imageEditor: { maxWidth: '100%', }, ctrls: { flexDirection: 'row', alignItems: 'center', marginTop: 10, }, slider: { flex: 1, marginRight: 10, }, btns: { flexDirection: 'row', alignItems: 'center', marginTop: 10, }, btn: { borderRadius: 4, paddingVertical: 8, paddingHorizontal: 24, }, })