aboutsummaryrefslogtreecommitdiff
path: root/src/components/comments/ZoomInCropper.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/comments/ZoomInCropper.tsx')
-rw-r--r--src/components/comments/ZoomInCropper.tsx201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/components/comments/ZoomInCropper.tsx b/src/components/comments/ZoomInCropper.tsx
new file mode 100644
index 00000000..bca4e599
--- /dev/null
+++ b/src/components/comments/ZoomInCropper.tsx
@@ -0,0 +1,201 @@
+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<MainStackParams, 'ZoomInCropper'>;
+type ZoomInCropperNavigationProps = StackNavigationProp<
+ MainStackParams,
+ 'ZoomInCropper'
+>;
+interface ZoomInCropperProps {
+ route: ZoomInCropperRouteProps;
+ navigation: ZoomInCropperNavigationProps;
+}
+
+export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
+ route,
+ navigation,
+}) => {
+ const {screenType, title, media} = route.params;
+ const [aspectRatio, setAspectRatio] = useState<number>(1);
+
+ // Stores the coordinates of the cropped image
+ const [x0, setX0] = useState<number>();
+ const [x1, setX1] = useState<number>();
+ const [y0, setY0] = useState<number>();
+ const [y1, setY1] = useState<number>();
+
+ // 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 (
+ <>
+ <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,
+ }}
+ />
+ </ImageZoom>
+ <TaggSquareButton
+ onPress={handleNext}
+ title={'Next'}
+ buttonStyle={'normal'}
+ buttonColor={'blue'}
+ labelColor={'white'}
+ style={styles.button}
+ labelStyle={styles.buttonLabel}
+ />
+ </>
+ );
+};
+
+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'},
+});