import {RouteProp} from '@react-navigation/core'; import {useFocusEffect} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {Image, StyleSheet, TouchableOpacity, View} 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 { cropVideo, HeaderHeight, SCREEN_HEIGHT, SCREEN_WIDTH, numberWithCommas, } from '../../utils'; import {TaggSquareButton} from '../common'; import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; import Video from 'react-native-video'; 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); // width and height of video, if video const [origDimensions, setOrigDimensions] = useState([0, 0]); const vidRef = useRef(null); // Stores the coordinates of the cropped image const [x0, setX0] = useState(); const [x1, setX1] = useState(); const [y0, setY0] = useState(); const [y1, setY1] = useState(); // Stores crop information for video const [videoCrop, setVideoCrop] = useState<{ cropWidth?: number; cropHeight?: number; cropOffsetX?: number; cropOffsetY?: number; }>({}); const checkIfUriImage = (uri: string) => { return ( uri.endsWith('jpg') || uri.endsWith('JPG') || uri.endsWith('PNG') || uri.endsWith('png') || uri.endsWith('GIF') || uri.endsWith('gif') ); }; useFocusEffect( useCallback(() => { navigation.dangerouslyGetParent()?.setOptions({ tabBarVisible: false, }); return () => { navigation.dangerouslyGetParent()?.setOptions({ tabBarVisible: true, }); }; }, [navigation]), ); // Setting original aspect ratio of image useEffect(() => { if (media.uri && checkIfUriImage(media.uri)) { Image.getSize( media.uri, (w, h) => { setAspectRatio(w / h); }, (err) => console.log(err), ); } else if (media.uri && !checkIfUriImage(media.uri)) { const tempVideoCrop = {...videoCrop}; tempVideoCrop.cropWidth = origDimensions[0]; tempVideoCrop.cropHeight = origDimensions[1]; setVideoCrop(tempVideoCrop); } }, []); // Possible need to delay setting aspect ratio of video until loaded useEffect(() => { if (media.uri && !checkIfUriImage(media.uri)) { const tempVideoCrop = {...videoCrop}; tempVideoCrop.cropWidth = origDimensions[0]; tempVideoCrop.cropHeight = origDimensions[1]; setVideoCrop(tempVideoCrop); } }, [origDimensions]); // Crops original image based of (x0, y0) and (x1, y1) coordinates const handleNext = () => { if (checkIfUriImage(media.uri)) { 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: { 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, }); } } else { if (!videoCrop.cropHeight || !videoCrop.cropWidth) { const tempVideoCrop = {...videoCrop}; tempVideoCrop.cropWidth = origDimensions[0]; tempVideoCrop.cropHeight = origDimensions[1]; setVideoCrop(tempVideoCrop); } cropVideo( media.uri, (croppedURL: string) => { navigation.navigate('CaptionScreen', { screenType, title: title, media: { uri: croppedURL, isVideo: true, }, }); }, videoCrop, ); } }; // for whenever the video is altered by the user const onVideoMove = (zoomableEvent: any) => { const { distanceBottom, distanceLeft, distanceRight, distanceTop, lastMovePinch, lastX, lastY, lastZoomLevel, offsetX, offsetY, originalHeight, originalWidth, zoomLevel, } = zoomableEvent; // let cropWidth = origDimensions[0] / (zoomLevel * aspectRatio); // let cropOffsetX = Math.abs((origDimensions[0] - cropWidth) / 2); // let screenScale = SCREEN_HEIGHT / origDimensions[1]; // const relativeHeight = SCREEN_WIDTH / aspectRatio; // let cropHeight = origDimensions[1]; // let cropOffsetY = 0; let cropWidth = 0; let cropHeight = 0; let cropOffsetX = 0; let cropOffsetY = 0; // if (aspectRatio > 1) { // cropWidth = // originalWidth * (originalWidth - (distanceLeft + distanceRight)); // cropHeight = origDimensions[1]; // } // console.log(relativeHeight * zoomLevel, SCREEN_HEIGHT, zoomLevel); // if (cropHeight * screenScale > SCREEN_HEIGHT) { // console.log('true'); // } else { // console.log('false'); // } // console.log( // aspectRatio, // zoomLevel, // originalWidth, // originalHeight, // origDimensions[0], // origDimensions[1], // cropWidth, // cropHeight, // distanceBottom, // distanceLeft, // distanceRight, // distanceTop, // SCREEN_WIDTH * zoomLevel - SCREEN_WIDTH, // distanceBottom + distanceTop, // distanceLeft + distanceRight, // ); // console.log( // zoomLevel, // distanceBottom, // distanceLeft, // distanceRight, // distanceTop, // originalWidth / (originalWidth - (distanceLeft + distanceRight)), // ); if (vidRef !== null && vidRef.current !== null) { vidRef.current.measure( ( x: number, y: number, width: number, height: number, pageX: number, pageY: number, ) => { // width cropWidth = origDimensions[0] * (originalWidth / width); // offsetX // cropOffsetX = (origDimensions[0] - cropWidth) / 2; cropOffsetX = -1 * origDimensions[0] * (pageX / width); if (cropOffsetX < 0) { cropOffsetX = 0; } else if (cropOffsetX + cropWidth > origDimensions[0]) { cropOffsetX = origDimensions[0] - cropWidth - 1; } // height if ( height * (SCREEN_WIDTH / aspectRatio / originalHeight) > SCREEN_HEIGHT ) { const superHeight = width / aspectRatio; cropHeight = origDimensions[1] * (originalHeight / superHeight); // cropOffsetY = (origDimensions[1] - cropHeight) / 2; if (cropOffsetY < 0) { cropOffsetY = 0; } else if (cropOffsetY + cropHeight > origDimensions[1]) { cropOffsetY = origDimensions[1] - cropHeight - 1; } } else { cropHeight = origDimensions[1]; } const tempVideoCrop = {...videoCrop}; tempVideoCrop.cropWidth = cropWidth; tempVideoCrop.cropHeight = cropHeight; tempVideoCrop.cropOffsetX = cropOffsetX; tempVideoCrop.cropOffsetY = cropOffsetY; setVideoCrop(tempVideoCrop); }, ); } }; /* 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()}> {/* */} {/* */} {checkIfUriImage(media.uri) ? ( ) : ( { onVideoMove(zoomableViewEventObject); }} onShiftingAfter={(_1: any, _2: any, zoomableViewEventObject: any) => { onVideoMove(zoomableViewEventObject); }} onShiftingEnd={(_1: any, _2: any, zoomableViewEventObject: any) => { onVideoMove(zoomableViewEventObject); }} onZoomAfter={(_1: any, _2: any, zoomableViewEventObject: any) => { onVideoMove(zoomableViewEventObject); }} onZoomEnd={(_1: any, _2: any, zoomableViewEventObject: any) => { onVideoMove(zoomableViewEventObject); }} style={styles.zoomView}> )} ); }; const styles = StyleSheet.create({ container: { backgroundColor: 'black', height: SCREEN_HEIGHT, width: SCREEN_WIDTH, // flexDirection: 'column', // justifyContent: 'center', }, 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', }, media: { zIndex: 0, flex: 1, }, videoParent: { flex: 1, }, zoomView: { backgroundColor: 'black', flex: 1, // borderColor: 'pink', // borderWidth: 2, }, });