import {RouteProp} from '@react-navigation/core'; import {useFocusEffect} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; import {default as React, useCallback, useEffect, useState} from 'react'; import {Image, StyleSheet, TouchableOpacity} from 'react-native'; import {normalize} from 'react-native-elements'; import ImageZoom, {IOnMove} from 'react-native-image-pan-zoom'; import PhotoManipulator from 'react-native-photo-manipulator'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; import {MainStackParams} from '../../routes'; import {HeaderHeight, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import {TaggSquareButton} from '../common'; type ZoomInCropperRouteProps = RouteProp; type ZoomInCropperNavigationProps = StackNavigationProp< MainStackParams, 'ZoomInCropper' >; interface ZoomInCropperProps { route: ZoomInCropperRouteProps; navigation: ZoomInCropperNavigationProps; } export const ZoomInCropper: React.FC = ({ route, navigation, }) => { const {screenType, title, media} = route.params; const [aspectRatio, setAspectRatio] = useState(1); // Stores the coordinates of the cropped image const [x0, setX0] = useState(); const [x1, setX1] = useState(); const [y0, setY0] = useState(); const [y1, setY1] = useState(); // Removes bottom navigation bar on current screen and add it back when navigating away useFocusEffect( useCallback(() => { navigation.dangerouslyGetParent()?.setOptions({ tabBarVisible: false, }); return () => { navigation.dangerouslyGetParent()?.setOptions({ tabBarVisible: true, }); }; }, [navigation]), ); // Setting original aspect ratio of image useEffect(() => { if (media.uri) { Image.getSize( media.uri, (w, h) => { setAspectRatio(w / h); }, (err) => console.log(err), ); } }, []); // Crops original image based of (x0, y0) and (x1, y1) coordinates const handleNext = () => { if ( x0 !== undefined && x1 !== undefined && y0 !== undefined && y1 !== undefined ) { PhotoManipulator.crop(media.uri, { x: x0, y: y1, width: Math.abs(x0 - x1), height: Math.abs(y0 - y1), }) .then((croppedURL) => { navigation.navigate('CaptionScreen', { screenType, title: title, media: { filename: media.filename, uri: croppedURL, isVideo: false, }, }); }) .catch((err) => console.log('err: ', err)); } else if ( x0 === undefined && x1 === undefined && y0 === undefined && y1 === undefined ) { navigation.navigate('CaptionScreen', { screenType, title: title, media, }); } }; /* Records (x0, y0) and (x1, y1) coordinates used later for cropping, * based on(x, y) - the center of the image and scale of zoom */ const onMove = (position: IOnMove) => { Image.getSize( media.uri, (w, h) => { const x = position.positionX; const y = position.positionY; const scale = position.scale; const screen_ratio = SCREEN_HEIGHT / SCREEN_WIDTH; let tempx0 = w / 2 - x * (w / SCREEN_WIDTH) - w / 2 / scale; let tempx1 = w / 2 - x * (w / SCREEN_WIDTH) + w / 2 / scale; if (tempx0 < 0) { tempx0 = 0; } if (tempx1 > w) { tempx1 = w; } const x_distance = Math.abs(tempx1 - tempx0); const y_distance = screen_ratio * x_distance; let tempy0 = h / 2 - y * (h / SCREEN_HEIGHT) + y_distance / 2; let tempy1 = h / 2 - y * (h / SCREEN_HEIGHT) - y_distance / 2; if (tempy0 > h) { tempy0 = h; } if (tempy1 < 0) { tempy1 = 0; } setX0(tempx0); setX1(tempx1); setY0(tempy0); setY1(tempy1); }, (err) => console.log(err), ); }; return ( <> navigation.goBack()}> ); }; const styles = StyleSheet.create({ closeButton: { position: 'absolute', top: 0, paddingTop: HeaderHeight, zIndex: 1, marginLeft: '5%', }, button: { zIndex: 1, position: 'absolute', bottom: normalize(20), right: normalize(15), width: normalize(108), height: normalize(25), borderRadius: 10, }, buttonLabel: { fontWeight: '700', fontSize: normalize(15), lineHeight: normalize(17.8), letterSpacing: normalize(1.3), textAlign: 'center', }, zoomView: {backgroundColor: 'black'}, });