aboutsummaryrefslogtreecommitdiff
path: root/src/components/comments
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/comments')
-rw-r--r--src/components/comments/ZoomInCropper.tsx290
1 files changed, 243 insertions, 47 deletions
diff --git a/src/components/comments/ZoomInCropper.tsx b/src/components/comments/ZoomInCropper.tsx
index e624c81c..6f8ff97c 100644
--- a/src/components/comments/ZoomInCropper.tsx
+++ b/src/components/comments/ZoomInCropper.tsx
@@ -1,14 +1,21 @@
import {RouteProp} from '@react-navigation/core';
import {StackNavigationProp} from '@react-navigation/stack';
-import React, {useEffect, useState} from 'react';
-import {Image, StyleSheet, TouchableOpacity} from 'react-native';
+import React, {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 {HeaderHeight, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import {
+ cropVideo,
+ HeaderHeight,
+ SCREEN_HEIGHT,
+ SCREEN_WIDTH,
+} 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<MainStackParams, 'ZoomInCropper'>;
type ZoomInCropperNavigationProps = StackNavigationProp<
@@ -26,6 +33,9 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
}) => {
const {screenType, media, selectedCategory} = route.params;
const [aspectRatio, setAspectRatio] = useState<number>(1);
+ // width and height of video, if video
+ const [origDimensions, setOrigDimensions] = useState<number[]>([0, 0]);
+ const vidRef = useRef<View>(null);
// Stores the coordinates of the cropped image
const [x0, setX0] = useState<number>();
@@ -33,9 +43,28 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
const [y0, setY0] = useState<number>();
const [y1, setY1] = useState<number>();
+ // 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')
+ );
+ };
+
// Setting original aspect ratio of image
useEffect(() => {
- if (media.uri) {
+ if (media.uri && checkIfUriImage(media.uri)) {
Image.getSize(
media.uri,
(w, h) => {
@@ -43,45 +72,146 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
},
(err) => console.log(err),
);
+ } else if (media.uri && !checkIfUriImage(media.uri)) {
+ setVideoCrop((prevState) => ({
+ ...prevState,
+ cropWidth: origDimensions[0],
+ cropHeight: origDimensions[1],
+ }));
}
}, []);
+ // Possible need to delay setting aspect ratio of video until loaded
+ useEffect(() => {
+ if (media.uri && !checkIfUriImage(media.uri)) {
+ setVideoCrop((prevState) => ({
+ ...prevState,
+ cropWidth: origDimensions[0],
+ cropHeight: origDimensions[1],
+ }));
+ }
+ }, [origDimensions]);
+
// 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) => {
+ 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,
+ 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,
+ media,
+ });
+ }
+ } else {
+ if (!videoCrop.cropHeight || !videoCrop.cropWidth) {
+ setVideoCrop((prevState) => ({
+ ...prevState,
+ cropWidth: origDimensions[0],
+ cropHeight: origDimensions[1],
+ }));
+ }
+ cropVideo(
+ media.uri,
+ (croppedURL: string) => {
navigation.navigate('CaptionScreen', {
screenType,
media: {
uri: croppedURL,
- isVideo: false,
+ isVideo: true,
},
selectedCategory,
});
- })
- .catch((err) => console.log('err: ', err));
- } else if (
- x0 === undefined &&
- x1 === undefined &&
- y0 === undefined &&
- y1 === undefined
- ) {
- navigation.navigate('CaptionScreen', {
- screenType,
- media,
- selectedCategory,
- });
+ },
+ videoCrop,
+ );
+ }
+ };
+
+ // for whenever the video is altered by the user
+ const onVideoMove = (zoomableEvent: any) => {
+ const {originalHeight, originalWidth} = zoomableEvent;
+
+ let cropWidth = 0;
+ let cropHeight = 0;
+ let cropOffsetX = 0;
+ let cropOffsetY = 0;
+
+ 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 = -1 * origDimensions[0] * (pageX / width);
+ if (cropOffsetX < 0) {
+ cropOffsetX = 0;
+ } else if (cropOffsetX + cropWidth > origDimensions[0] - 1) {
+ cropOffsetX = origDimensions[0] - cropWidth - 1;
+ }
+
+ // height
+ if (
+ height * (SCREEN_WIDTH / aspectRatio / originalHeight) >
+ SCREEN_HEIGHT
+ ) {
+ const superHeight = width / aspectRatio;
+ cropHeight = origDimensions[1] * (originalHeight / superHeight);
+
+ // offsetY
+ const topDeadZone = (height - superHeight) / 2;
+ const offsetY = topDeadZone + pageY;
+ cropOffsetY = -1 * origDimensions[1] * (offsetY / superHeight);
+ if (cropOffsetY < 0) {
+ cropOffsetY = 0;
+ } else if (cropOffsetY + cropHeight > origDimensions[1]) {
+ cropOffsetY = origDimensions[1] - cropHeight - 1;
+ }
+ } else {
+ cropHeight = origDimensions[1];
+ }
+ setVideoCrop((prevState) => ({
+ ...prevState,
+ cropWidth: cropWidth,
+ cropHeight: cropHeight,
+ cropOffsetX: cropOffsetX,
+ cropOffsetY: cropOffsetY,
+ }));
+ },
+ );
}
};
@@ -124,26 +254,77 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
};
return (
- <>
+ <View style={styles.container}>
<TouchableOpacity
style={styles.closeButton}
onPress={() => navigation.goBack()}>
<CloseIcon height={25} width={25} color={'white'} />
</TouchableOpacity>
- <ImageZoom
- style={styles.zoomView}
- cropWidth={SCREEN_WIDTH}
- cropHeight={SCREEN_HEIGHT}
- imageWidth={SCREEN_WIDTH}
- imageHeight={SCREEN_WIDTH / aspectRatio}
- onMove={onMove}>
- <Image
- style={{width: SCREEN_WIDTH, height: SCREEN_WIDTH / aspectRatio}}
- source={{
- uri: media.uri,
+ {checkIfUriImage(media.uri) ? (
+ <ImageZoom
+ style={styles.zoomView}
+ cropWidth={SCREEN_WIDTH}
+ cropHeight={SCREEN_HEIGHT}
+ imageWidth={SCREEN_WIDTH}
+ imageHeight={SCREEN_WIDTH / aspectRatio}
+ onMove={onMove}>
+ <Image
+ style={{width: SCREEN_WIDTH, height: SCREEN_WIDTH / aspectRatio}}
+ source={{
+ uri: media.uri,
+ }}
+ />
+ </ImageZoom>
+ ) : (
+ <ReactNativeZoomableView
+ maxZoom={10}
+ minZoom={1}
+ zoomStep={0.5}
+ initialZoom={1}
+ bindToBorders={true}
+ // onZoomAfter={this.logOutZoomState}
+ onDoubleTapAfter={(
+ _1: any,
+ _2: any,
+ zoomableViewEventObject: any,
+ ) => {
+ onVideoMove(zoomableViewEventObject);
+ }}
+ onShiftingAfter={(_1: any, _2: any, zoomableViewEventObject: any) => {
+ onVideoMove(zoomableViewEventObject);
+ }}
+ onShiftingEnd={(_1: any, _2: any, zoomableViewEventObject: any) => {
+ onVideoMove(zoomableViewEventObject);
}}
- />
- </ImageZoom>
+ onZoomAfter={(_1: any, _2: any, zoomableViewEventObject: any) => {
+ onVideoMove(zoomableViewEventObject);
+ }}
+ onZoomEnd={(_1: any, _2: any, zoomableViewEventObject: any) => {
+ onVideoMove(zoomableViewEventObject);
+ }}
+ style={styles.zoomView}>
+ <View style={styles.videoParent} ref={vidRef}>
+ <Video
+ source={{uri: media.uri}}
+ volume={1}
+ style={[
+ styles.media,
+ {
+ height: SCREEN_WIDTH / aspectRatio,
+ },
+ ]}
+ repeat={true}
+ resizeMode={'contain'}
+ onLoad={(response) => {
+ const {width, height} = response.naturalSize;
+ setOrigDimensions([width, height]);
+ setAspectRatio(width / height);
+ }}
+ />
+ </View>
+ </ReactNativeZoomableView>
+ )}
+
<TaggSquareButton
onPress={handleNext}
title={'Next'}
@@ -153,11 +334,16 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
style={styles.button}
labelStyle={styles.buttonLabel}
/>
- </>
+ </View>
);
};
const styles = StyleSheet.create({
+ container: {
+ backgroundColor: 'black',
+ height: SCREEN_HEIGHT,
+ width: SCREEN_WIDTH,
+ },
closeButton: {
position: 'absolute',
top: 0,
@@ -181,5 +367,15 @@ const styles = StyleSheet.create({
letterSpacing: normalize(1.3),
textAlign: 'center',
},
- zoomView: {backgroundColor: 'black'},
+ media: {
+ zIndex: 0,
+ flex: 1,
+ },
+ videoParent: {
+ flex: 1,
+ },
+ zoomView: {
+ backgroundColor: 'black',
+ flex: 1,
+ },
});