From 0e281251da135f58b71c6b279f2efd317f63a542 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Fri, 16 Jul 2021 16:20:59 -0400 Subject: Initial sidebar --- src/assets/icons/trim.svg | 14 ++++++++++++++ src/assets/icons/volume-on.svg | 9 +++++++++ src/components/comments/ZoomInCropper.tsx | 29 +++++++++++++++++++++++++++-- src/constants/api.ts | 2 +- 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/assets/icons/trim.svg create mode 100644 src/assets/icons/volume-on.svg (limited to 'src') diff --git a/src/assets/icons/trim.svg b/src/assets/icons/trim.svg new file mode 100644 index 00000000..b966c7f7 --- /dev/null +++ b/src/assets/icons/trim.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/icons/volume-on.svg b/src/assets/icons/volume-on.svg new file mode 100644 index 00000000..c3ed1693 --- /dev/null +++ b/src/assets/icons/volume-on.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/comments/ZoomInCropper.tsx b/src/components/comments/ZoomInCropper.tsx index b4333cbb..061964a8 100644 --- a/src/components/comments/ZoomInCropper.tsx +++ b/src/components/comments/ZoomInCropper.tsx @@ -1,7 +1,7 @@ import {RouteProp} from '@react-navigation/core'; import {StackNavigationProp} from '@react-navigation/stack'; import React, {useEffect, useRef, useState} from 'react'; -import {Image, StyleSheet, TouchableOpacity, View} from 'react-native'; +import {Image, StyleSheet, Text, 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'; @@ -17,6 +17,8 @@ import { import {TaggSquareButton, TaggLoadingIndicator} from '../common'; import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; import {TrimmerPlayer} from '../moments/trimmer'; +import TrimIcon from '../../assets/icons/trim.svg'; +import VolumeOnIcon from '../../assets/icons/volume-on.svg'; type ZoomInCropperRouteProps = RouteProp; type ZoomInCropperNavigationProps = StackNavigationProp< @@ -344,7 +346,14 @@ export const ZoomInCropper: React.FC = ({ )} - + {!checkIfUriImage(media.uri) && ( + + + Trim + + Volume + + )} Date: Fri, 16 Jul 2021 17:39:21 -0400 Subject: Undo api, Update volume icon --- src/assets/icons/volume-on.svg | 9 --------- src/assets/images/volume-on.png | Bin 0 -> 5479 bytes src/components/comments/ZoomInCropper.tsx | 18 ++++++++++++------ src/constants/api.ts | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 src/assets/icons/volume-on.svg create mode 100644 src/assets/images/volume-on.png (limited to 'src') diff --git a/src/assets/icons/volume-on.svg b/src/assets/icons/volume-on.svg deleted file mode 100644 index c3ed1693..00000000 --- a/src/assets/icons/volume-on.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/assets/images/volume-on.png b/src/assets/images/volume-on.png new file mode 100644 index 00000000..7cbbaa84 Binary files /dev/null and b/src/assets/images/volume-on.png differ diff --git a/src/components/comments/ZoomInCropper.tsx b/src/components/comments/ZoomInCropper.tsx index 061964a8..88f161e5 100644 --- a/src/components/comments/ZoomInCropper.tsx +++ b/src/components/comments/ZoomInCropper.tsx @@ -1,3 +1,4 @@ +import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; import {RouteProp} from '@react-navigation/core'; import {StackNavigationProp} from '@react-navigation/stack'; import React, {useEffect, useRef, useState} from 'react'; @@ -5,20 +6,18 @@ import {Image, StyleSheet, Text, 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 TrimIcon from '../../assets/icons/trim.svg'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; import {MainStackParams} from '../../routes'; import { cropVideo, - trimVideo, HeaderHeight, SCREEN_HEIGHT, SCREEN_WIDTH, + trimVideo, } from '../../utils'; -import {TaggSquareButton, TaggLoadingIndicator} from '../common'; -import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; +import {TaggLoadingIndicator, TaggSquareButton} from '../common'; import {TrimmerPlayer} from '../moments/trimmer'; -import TrimIcon from '../../assets/icons/trim.svg'; -import VolumeOnIcon from '../../assets/icons/volume-on.svg'; type ZoomInCropperRouteProps = RouteProp; type ZoomInCropperNavigationProps = StackNavigationProp< @@ -350,7 +349,10 @@ export const ZoomInCropper: React.FC = ({ Trim - + Volume )} @@ -423,4 +425,8 @@ const styles = StyleSheet.create({ backgroundColor: 'black', flex: 1, }, + volumnIcon: { + width: 25, + height: 25, + }, }); diff --git a/src/constants/api.ts b/src/constants/api.ts index ed68f14f..6dab1153 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -1,7 +1,7 @@ /* eslint-disable */ // Dev -const BASE_URL: string = 'http://192.168.0.49:8000/'; +const BASE_URL: string = 'http://127.0.0.1:8000/'; export const STREAM_CHAT_API = 'g2hvnyqx9cmv'; // Prod -- cgit v1.2.3-70-g09d2 From c3d418bc7ad3c702ed52fa522c1225dc4816c092 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 17:46:15 -0400 Subject: Refactor ZoomInCropper to be EditMedia --- src/components/comments/ZoomInCropper.tsx | 432 ------------------------------ src/routes/main/MainStackNavigator.tsx | 2 +- src/routes/main/MainStackScreen.tsx | 6 +- src/screens/index.ts | 1 + src/screens/moments/CameraScreen.tsx | 2 +- src/screens/upload/EditMedia.tsx | 431 +++++++++++++++++++++++++++++ src/screens/upload/index.ts | 1 + 7 files changed, 438 insertions(+), 437 deletions(-) delete mode 100644 src/components/comments/ZoomInCropper.tsx create mode 100644 src/screens/upload/EditMedia.tsx create mode 100644 src/screens/upload/index.ts (limited to 'src') diff --git a/src/components/comments/ZoomInCropper.tsx b/src/components/comments/ZoomInCropper.tsx deleted file mode 100644 index 88f161e5..00000000 --- a/src/components/comments/ZoomInCropper.tsx +++ /dev/null @@ -1,432 +0,0 @@ -import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; -import {RouteProp} from '@react-navigation/core'; -import {StackNavigationProp} from '@react-navigation/stack'; -import React, {useEffect, useRef, useState} from 'react'; -import {Image, StyleSheet, Text, 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 TrimIcon from '../../assets/icons/trim.svg'; -import CloseIcon from '../../assets/ionicons/close-outline.svg'; -import {MainStackParams} from '../../routes'; -import { - cropVideo, - HeaderHeight, - SCREEN_HEIGHT, - SCREEN_WIDTH, - trimVideo, -} from '../../utils'; -import {TaggLoadingIndicator, TaggSquareButton} from '../common'; -import {TrimmerPlayer} from '../moments/trimmer'; - -type ZoomInCropperRouteProps = RouteProp; -type ZoomInCropperNavigationProps = StackNavigationProp< - MainStackParams, - 'ZoomInCropper' ->; -interface ZoomInCropperProps { - route: ZoomInCropperRouteProps; - navigation: ZoomInCropperNavigationProps; -} - -export const ZoomInCropper: React.FC = ({ - route, - navigation, -}) => { - const {screenType, media, selectedCategory} = route.params; - const [aspectRatio, setAspectRatio] = useState(1); - // width and height of video, if video - const [origDimensions, setOrigDimensions] = useState([0, 0]); - const vidRef = useRef(null); - const [cropLoading, setCropLoading] = useState(false); - - // 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; - }>({}); - - // Stores the current trim endpoints - const [trimEnds, setTrimEnds] = useState<{ - end: number; - start: number; - }>({ - end: 60, - start: 0, - }); - - 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 && checkIfUriImage(media.uri)) { - Image.getSize( - media.uri, - (w, h) => { - setAspectRatio(w / h); - }, - (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 (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], - })); - } - setCropLoading(true); - trimVideo( - media.uri, - (trimmedURL: string) => - cropVideo( - trimmedURL, - (croppedURL: string) => { - setCropLoading(false); - navigation.navigate('CaptionScreen', { - screenType, - media: { - uri: croppedURL, - isVideo: true, - }, - selectedCategory, - }); - }, - videoCrop, - ), - trimEnds, - ); - } - }; - - // 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, - })); - }, - ); - } - }; - - /* 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 ( - - {cropLoading && } - 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 {width, height} = response; - setOrigDimensions([width, height]); - setAspectRatio(width / height); - }} - onChangedEndpoints={(response: {start: number; end: number}) => - setTrimEnds(response) - } - /> - - - )} - {!checkIfUriImage(media.uri) && ( - - - Trim - - Volume - - )} - - - ); -}; - -const styles = StyleSheet.create({ - container: { - backgroundColor: 'black', - height: SCREEN_HEIGHT, - width: SCREEN_WIDTH, - }, - 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', - }, - iconCarrier: { - width: SCREEN_WIDTH * 0.15, - height: SCREEN_HEIGHT * 0.2, - borderRadius: SCREEN_WIDTH * 0.1, - backgroundColor: 'rgba(0, 0, 0, 0.3)', - position: 'absolute', - right: SCREEN_WIDTH * 0.025, - top: SCREEN_HEIGHT * 0.2, - flexDirection: 'column', - justifyContent: 'space-evenly', - alignItems: 'center', - }, - iconText: { - color: 'white', - fontSize: 10, - }, - media: { - zIndex: 0, - flex: 1, - }, - videoParent: { - flex: 1, - }, - zoomView: { - backgroundColor: 'black', - flex: 1, - }, - volumnIcon: { - width: 25, - height: 25, - }, -}); diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx index c569d2d6..11e9d08d 100644 --- a/src/routes/main/MainStackNavigator.tsx +++ b/src/routes/main/MainStackNavigator.tsx @@ -39,7 +39,7 @@ export type MainStackParams = { screenType: ScreenType; selectedCategory?: string; }; - ZoomInCropper: { + EditMedia: { media: {uri: string; isVideo: boolean}; screenType: ScreenType; selectedCategory?: string; diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx index 15300c0d..064e9725 100644 --- a/src/routes/main/MainStackScreen.tsx +++ b/src/routes/main/MainStackScreen.tsx @@ -34,12 +34,12 @@ import { TagSelectionScreen, TagFriendsScreen, CameraScreen, + EditMedia, } from '../../screens'; import MutualBadgeHolders from '../../screens/suggestedPeople/MutualBadgeHolders'; import {ScreenType} from '../../types'; import {AvatarHeaderHeight, ChatHeaderHeight, SCREEN_WIDTH} from '../../utils'; import {MainStack, MainStackParams} from './MainStackNavigator'; -import {ZoomInCropper} from '../../components/comments/ZoomInCropper'; import ChoosingCategoryScreen from '../../screens/profile/ChoosingCategoryScreen'; /** @@ -336,8 +336,8 @@ const MainStackScreen: React.FC = ({route}) => { }} /> = ({route, navigation}) => { }, [mediaFromGallery]); const navigateToCropper = (uri: string) => { - navigation.navigate('ZoomInCropper', { + navigation.navigate('EditMedia', { screenType, media: { uri, diff --git a/src/screens/upload/EditMedia.tsx b/src/screens/upload/EditMedia.tsx new file mode 100644 index 00000000..ed5cd0d7 --- /dev/null +++ b/src/screens/upload/EditMedia.tsx @@ -0,0 +1,431 @@ +import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; +import {RouteProp} from '@react-navigation/core'; +import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useEffect, useRef, useState} from 'react'; +import {Image, StyleSheet, Text, 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 TrimIcon from '../../assets/icons/trim.svg'; +import CloseIcon from '../../assets/ionicons/close-outline.svg'; +import {TaggLoadingIndicator, TaggSquareButton} from '../../components/common'; +import {TrimmerPlayer} from '../../components/moments/trimmer'; +import {MainStackParams} from '../../routes'; +import { + cropVideo, + HeaderHeight, + SCREEN_HEIGHT, + SCREEN_WIDTH, + trimVideo, +} from '../../utils'; + +type EditMediaRouteProps = RouteProp; +type EditMediaNavigationProps = StackNavigationProp< + MainStackParams, + 'EditMedia' +>; +interface EditMediaProps { + route: EditMediaRouteProps; + navigation: EditMediaNavigationProps; +} + +export const EditMedia: React.FC = ({route, navigation}) => { + const {screenType, media, selectedCategory} = route.params; + const [aspectRatio, setAspectRatio] = useState(1); + // width and height of video, if video + const [origDimensions, setOrigDimensions] = useState([0, 0]); + const vidRef = useRef(null); + const [cropLoading, setCropLoading] = useState(false); + + // 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; + }>({}); + + // Stores the current trim endpoints + const [trimEnds, setTrimEnds] = useState<{ + end: number; + start: number; + }>({ + end: 60, + start: 0, + }); + + 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 && checkIfUriImage(media.uri)) { + Image.getSize( + media.uri, + (w, h) => { + setAspectRatio(w / h); + }, + (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 (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], + })); + } + setCropLoading(true); + trimVideo( + media.uri, + (trimmedURL: string) => + cropVideo( + trimmedURL, + (croppedURL: string) => { + setCropLoading(false); + navigation.navigate('CaptionScreen', { + screenType, + media: { + uri: croppedURL, + isVideo: true, + }, + selectedCategory, + }); + }, + videoCrop, + ), + trimEnds, + ); + } + }; + + // 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, + })); + }, + ); + } + }; + + /* 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 ( + + {cropLoading && } + 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 {width, height} = response; + setOrigDimensions([width, height]); + setAspectRatio(width / height); + }} + onChangedEndpoints={(response: {start: number; end: number}) => + setTrimEnds(response) + } + /> + + + )} + {!checkIfUriImage(media.uri) && ( + + + Trim + + Volume + + )} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + backgroundColor: 'black', + height: SCREEN_HEIGHT, + width: SCREEN_WIDTH, + }, + 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', + }, + iconCarrier: { + width: SCREEN_WIDTH * 0.15, + height: SCREEN_HEIGHT * 0.2, + borderRadius: SCREEN_WIDTH * 0.1, + backgroundColor: 'rgba(0, 0, 0, 0.3)', + position: 'absolute', + right: SCREEN_WIDTH * 0.025, + top: SCREEN_HEIGHT * 0.2, + flexDirection: 'column', + justifyContent: 'space-evenly', + alignItems: 'center', + }, + iconText: { + color: 'white', + fontSize: 10, + }, + media: { + zIndex: 0, + flex: 1, + }, + videoParent: { + flex: 1, + }, + zoomView: { + backgroundColor: 'black', + flex: 1, + }, + volumnIcon: { + width: 25, + height: 25, + }, +}); + +export default EditMedia; diff --git a/src/screens/upload/index.ts b/src/screens/upload/index.ts new file mode 100644 index 00000000..0dadeede --- /dev/null +++ b/src/screens/upload/index.ts @@ -0,0 +1 @@ +export {default as EditMedia} from './EditMedia'; -- cgit v1.2.3-70-g09d2 From af63a23020b64c9b20428ff14fc7a50c557b038c Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 17:54:09 -0400 Subject: Remove photo preview in camera screen --- src/screens/moments/CameraScreen.tsx | 150 +++++++++++------------------------ 1 file changed, 46 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/screens/moments/CameraScreen.tsx b/src/screens/moments/CameraScreen.tsx index cb5cd411..3c28ca22 100644 --- a/src/screens/moments/CameraScreen.tsx +++ b/src/screens/moments/CameraScreen.tsx @@ -8,16 +8,10 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native'; import {CameraType, FlashMode, RNCamera} from 'react-native-camera'; import {AnimatedCircularProgress} from 'react-native-circular-progress'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; -import { - FlashButton, - FlipButton, - GalleryIcon, - SaveButton, - TaggSquareButton, -} from '../../components'; +import {FlashButton, FlipButton, GalleryIcon} from '../../components'; import {TAGG_PURPLE} from '../../constants'; import {MainStackParams} from '../../routes'; -import {HeaderHeight, normalize, SCREEN_WIDTH} from '../../utils'; +import {HeaderHeight, SCREEN_WIDTH} from '../../utils'; import {showGIFFailureAlert, takePicture, takeVideo} from '../../utils/camera'; type CameraScreenRouteProps = RouteProp; @@ -35,9 +29,7 @@ const CameraScreen: React.FC = ({route, navigation}) => { const tabBarHeight = useBottomTabBarHeight(); const [cameraType, setCameraType] = useState('front'); const [flashMode, setFlashMode] = useState('off'); - const [mediaFromGallery, setMediaFromGallery] = useState(''); const [mostRecentPhoto, setMostRecentPhoto] = useState(''); - const [showSaveButton, setShowSaveButton] = useState(false); const [isRecording, setIsRecording] = useState(false); useFocusEffect( @@ -62,9 +54,9 @@ const CameraScreen: React.FC = ({route, navigation}) => { .catch((_err) => console.log('Unable to fetch preview photo for gallery'), ); - }, [mediaFromGallery]); + }, []); - const navigateToCropper = (uri: string) => { + const navigateToEditMedia = (uri: string) => { navigation.navigate('EditMedia', { screenType, media: { @@ -85,21 +77,11 @@ const CameraScreen: React.FC = ({route, navigation}) => { }); }; - /* - * If picture is not taken yet, exists from camera screen to profile view - * If picture is taken, exists from captured image's preview to camera - * */ const handleClose = () => { - if (showSaveButton) { - cameraRef.current?.resumePreview(); - setShowSaveButton(false); - setMediaFromGallery(''); - } else { - navigation.dangerouslyGetParent()?.setOptions({ - tabBarVisible: true, - }); - navigation.goBack(); - } + navigation.dangerouslyGetParent()?.setOptions({ + tabBarVisible: true, + }); + navigation.goBack(); }; return ( @@ -118,42 +100,31 @@ const CameraScreen: React.FC = ({route, navigation}) => { }} /> - {showSaveButton ? ( - - ) : ( - - )} - {!showSaveButton ? ( - + { + takeVideo(cameraRef, (vid) => { + navigateToCaptionScreen(true, vid.uri); + }); + setIsRecording(true); + }} + onPressOut={async () => { + if (await cameraRef.current?.isRecording()) { + cameraRef.current?.stopRecording(); + setIsRecording(false); } - activeOpacity={1} - onLongPress={() => { - takeVideo(cameraRef, (vid) => { - navigateToCaptionScreen(true, vid.uri); - }); - setIsRecording(true); - }} - onPressOut={async () => { - if (await cameraRef.current?.isRecording()) { - cameraRef.current?.stopRecording(); - setIsRecording(false); - } - }} - onPress={() => { - takePicture(cameraRef, (pic) => { - setShowSaveButton(true); - setMediaFromGallery(pic.uri); - }); - }}> - - - ) : ( - - )} + }} + onPress={() => { + takePicture(cameraRef, (pic) => navigateToEditMedia(pic.uri)); + }}> + + {isRecording && ( = ({route, navigation}) => { /> )} - {mediaFromGallery ? ( - navigateToCaptionScreen(false, mediaFromGallery)} - title={'Next'} - buttonStyle={'large'} - buttonColor={'blue'} - labelColor={'white'} - style={styles.nextButton} - labelStyle={styles.nextButtonLabel} - /> - ) : ( - { - const filename = media.filename; - if ( - filename && - (filename.endsWith('gif') || filename.endsWith('GIF')) - ) { - showGIFFailureAlert(() => navigateToCropper(media.path)); - } else { - navigateToCropper(media.path); - } - }} - /> - )} + { + const filename = media.filename; + if ( + filename && + (filename.endsWith('gif') || filename.endsWith('GIF')) + ) { + showGIFFailureAlert(() => navigateToEditMedia(media.path)); + } else { + navigateToEditMedia(media.path); + } + }} + /> @@ -221,10 +180,6 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, - captureButtonPlaceholder: { - width: 93, - height: 93, - }, captureButtonContainer: { alignSelf: 'center', backgroundColor: 'transparent', @@ -262,19 +217,6 @@ const styles = StyleSheet.create({ alignItems: 'center', width: (SCREEN_WIDTH - 100) / 2, }, - nextButton: { - zIndex: 1, - width: normalize(100), - height: normalize(37), - borderRadius: 10, - }, - nextButtonLabel: { - fontWeight: '700', - fontSize: normalize(15), - lineHeight: normalize(17.8), - letterSpacing: normalize(1.3), - textAlign: 'center', - }, }); export default CameraScreen; -- cgit v1.2.3-70-g09d2 From a5affe6d815e9a86ce4100e9a4c0709ae42a4f2b Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 17:59:52 -0400 Subject: Rename trimmer --- src/components/moments/TrimmerPlayer.tsx | 107 +++++++++++++++++++++++++++++++ src/components/moments/index.ts | 1 + src/components/moments/trimmer.tsx | 98 ---------------------------- src/screens/upload/EditMedia.tsx | 2 +- 4 files changed, 109 insertions(+), 99 deletions(-) create mode 100644 src/components/moments/TrimmerPlayer.tsx delete mode 100644 src/components/moments/trimmer.tsx (limited to 'src') diff --git a/src/components/moments/TrimmerPlayer.tsx b/src/components/moments/TrimmerPlayer.tsx new file mode 100644 index 00000000..4d6a8985 --- /dev/null +++ b/src/components/moments/TrimmerPlayer.tsx @@ -0,0 +1,107 @@ +import React, {useEffect, useRef, useState} from 'react'; +import Video from 'react-native-video'; +import {Trimmer} from 'react-native-video-processing'; +import {SCREEN_WIDTH} from '../../utils'; + +interface TrimmerPlayerProps { + source: string; + videoStyles: Object; + hideTrimmer: boolean; + handleLoad: Function; + onChangedEndpoints: Function; +} + +const TrimmerPlayer: React.FC = ({ + source, + videoStyles, + hideTrimmer, + handleLoad, + onChangedEndpoints, +}) => { + // Stores the reference to player for seeking + const playerRef = useRef ); }; @@ -447,6 +432,10 @@ const styles = StyleSheet.create({ width: 25, height: 25, }, + bottomContainer: { + width: SCREEN_WIDTH * 0.7, + justifyContent: 'space-between', + }, }); export default EditMedia; -- cgit v1.2.3-70-g09d2 From 1e0f1c0c6200af5d4f9554778341d991b47381da Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 18:47:19 -0400 Subject: Add styling --- src/components/camera/SaveButton.tsx | 7 ++++--- src/screens/upload/EditMedia.tsx | 31 ++++++++++++++++++------------- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/components/camera/SaveButton.tsx b/src/components/camera/SaveButton.tsx index 104e7c30..d1b87e65 100644 --- a/src/components/camera/SaveButton.tsx +++ b/src/components/camera/SaveButton.tsx @@ -1,18 +1,19 @@ import React from 'react'; -import {Text, TouchableOpacity} from 'react-native'; +import {StyleProp, Text, TouchableOpacity, ViewStyle} from 'react-native'; import SaveIcon from '../../assets/icons/camera/save.svg'; import {styles} from './styles'; interface SaveButtonProps { onPress: () => void; + style?: StyleProp; } /* * Appears when a picture has been taken, * On click, saves the captured image to "Recents" album on device gallery */ -export const SaveButton: React.FC = ({onPress}) => ( - +export const SaveButton: React.FC = ({onPress, style}) => ( + Save diff --git a/src/screens/upload/EditMedia.tsx b/src/screens/upload/EditMedia.tsx index 92b93888..1d42e675 100644 --- a/src/screens/upload/EditMedia.tsx +++ b/src/screens/upload/EditMedia.tsx @@ -340,8 +340,12 @@ export const EditMedia: React.FC = ({route, navigation}) => { )} - processVideo(saveImageToGallery)} /> + processVideo(saveImageToGallery)} + /> processVideo((uri) => navigation.navigate('CaptionScreen', { @@ -355,10 +359,9 @@ export const EditMedia: React.FC = ({route, navigation}) => { ) } title={'Next'} - buttonStyle={'normal'} + buttonStyle={'large'} buttonColor={'blue'} labelColor={'white'} - style={styles.button} labelStyle={styles.buttonLabel} /> @@ -379,14 +382,20 @@ const styles = StyleSheet.create({ zIndex: 1, marginLeft: '5%', }, + bottomContainer: { + width: SCREEN_WIDTH * 0.8, + justifyContent: 'space-between', + marginBottom: SCREEN_HEIGHT * 0.1, + alignItems: 'center', + alignSelf: 'center', + flexDirection: 'row', + }, + saveButton: { + width: 50, + }, button: { - zIndex: 1, - position: 'absolute', - bottom: normalize(20), - right: normalize(15), width: normalize(108), - height: normalize(25), - borderRadius: 10, + height: normalize(36), }, buttonLabel: { fontWeight: '700', @@ -432,10 +441,6 @@ const styles = StyleSheet.create({ width: 25, height: 25, }, - bottomContainer: { - width: SCREEN_WIDTH * 0.7, - justifyContent: 'space-between', - }, }); export default EditMedia; -- cgit v1.2.3-70-g09d2 From cce1f4ad7f3331ef5c111423fe46fc1d59c7638d Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 18:51:34 -0400 Subject: Clean up styles, Fix save to gallery --- src/screens/upload/EditMedia.tsx | 61 ++++++++++++++++++++++------------------ src/utils/camera.ts | 7 +++-- 2 files changed, 39 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/screens/upload/EditMedia.tsx b/src/screens/upload/EditMedia.tsx index 1d42e675..e53e2e43 100644 --- a/src/screens/upload/EditMedia.tsx +++ b/src/screens/upload/EditMedia.tsx @@ -339,32 +339,38 @@ export const EditMedia: React.FC = ({route, navigation}) => { )} - - processVideo(saveImageToGallery)} - /> - - processVideo((uri) => - navigation.navigate('CaptionScreen', { - screenType, - media: { - uri: uri, - isVideo: media.isVideo, - }, - selectedCategory, - }), - ) - } - title={'Next'} - buttonStyle={'large'} - buttonColor={'blue'} - labelColor={'white'} - labelStyle={styles.buttonLabel} - /> - + {hideTrimmer && ( + + + processVideo((uri) => + saveImageToGallery(uri, media.isVideo ? 'video' : 'photo'), + ) + } + /> + + processVideo((uri) => + navigation.navigate('CaptionScreen', { + screenType, + media: { + uri: uri, + isVideo: media.isVideo, + }, + selectedCategory, + }), + ) + } + title={'Next'} + buttonStyle={'large'} + buttonColor={'blue'} + labelColor={'white'} + labelStyle={styles.buttonLabel} + /> + + )} ); }; @@ -383,9 +389,10 @@ const styles = StyleSheet.create({ marginLeft: '5%', }, bottomContainer: { + position: 'absolute', + bottom: SCREEN_HEIGHT * 0.1, width: SCREEN_WIDTH * 0.8, justifyContent: 'space-between', - marginBottom: SCREEN_HEIGHT * 0.1, alignItems: 'center', alignSelf: 'center', flexDirection: 'row', diff --git a/src/utils/camera.ts b/src/utils/camera.ts index 5485b1ca..9d7ff67f 100644 --- a/src/utils/camera.ts +++ b/src/utils/camera.ts @@ -48,8 +48,11 @@ export const takeVideo = ( } }; -export const saveImageToGallery = (capturedImageURI: string) => { - CameraRoll.save(capturedImageURI, {album: 'Recents', type: 'photo'}) +export const saveImageToGallery = ( + capturedImageURI: string, + type: 'photo' | 'video', +) => { + CameraRoll.save(capturedImageURI, {album: 'Recents', type: type}) .then((_res) => Alert.alert('Saved to device!')) .catch((_err) => Alert.alert('Failed to save to device!')); }; -- cgit v1.2.3-70-g09d2 From 16f649033125ae7b51aa7af4115ea9190a115d6f Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 19:09:02 -0400 Subject: Rename media --- src/screens/upload/EditMedia.tsx | 75 +++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/screens/upload/EditMedia.tsx b/src/screens/upload/EditMedia.tsx index e53e2e43..6b2d6008 100644 --- a/src/screens/upload/EditMedia.tsx +++ b/src/screens/upload/EditMedia.tsx @@ -31,10 +31,15 @@ interface EditMediaProps { } export const EditMedia: React.FC = ({route, navigation}) => { - const {screenType, media, selectedCategory} = route.params; + const { + screenType, + selectedCategory, + media: {isVideo}, + } = route.params; const [aspectRatio, setAspectRatio] = useState(1); // width and height of video, if video const [origDimensions, setOrigDimensions] = useState([0, 0]); + const [mediaUri, setMediaUri] = useState(route.params.media.uri); const vidRef = useRef(null); const [cropLoading, setCropLoading] = useState(false); const [hideTrimmer, setHideTrimmer] = useState(true); @@ -64,15 +69,15 @@ export const EditMedia: React.FC = ({route, navigation}) => { // Setting original aspect ratio of image useEffect(() => { - if (media.uri && !media.isVideo) { + if (mediaUri && !isVideo) { Image.getSize( - media.uri, + mediaUri, (w, h) => { setAspectRatio(w / h); }, (err) => console.log(err), ); - } else if (media.uri && media.isVideo) { + } else if (mediaUri && isVideo) { setVideoCrop((prevState) => ({ ...prevState, cropWidth: origDimensions[0], @@ -83,7 +88,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { // Possible need to delay setting aspect ratio of video until loaded useEffect(() => { - if (media.uri && media.isVideo) { + if (mediaUri && isVideo) { setVideoCrop((prevState) => ({ ...prevState, cropWidth: origDimensions[0], @@ -94,14 +99,14 @@ export const EditMedia: React.FC = ({route, navigation}) => { // Crops original image based of (x0, y0) and (x1, y1) coordinates const processVideo = (callback: (finalUri: string) => void) => { - if (!media.isVideo) { + if (!isVideo) { if ( x0 !== undefined && x1 !== undefined && y0 !== undefined && y1 !== undefined ) { - PhotoManipulator.crop(media.uri, { + PhotoManipulator.crop(mediaUri, { x: x0, y: y1, width: Math.abs(x0 - x1), @@ -119,7 +124,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { y1 === undefined ) { // If no crop coordinates are set, then we will just pass the original image - callback(media.uri); + callback(mediaUri); } } else { if (!videoCrop.cropHeight || !videoCrop.cropWidth) { @@ -131,7 +136,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { } setCropLoading(true); trimVideo( - media.uri, + mediaUri, (trimmedURL: string) => cropVideo( trimmedURL, @@ -214,7 +219,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { */ const onMove = (position: IOnMove) => { Image.getSize( - media.uri, + mediaUri, (w, h) => { const x = position.positionX; const y = position.positionY; @@ -250,12 +255,24 @@ export const EditMedia: React.FC = ({route, navigation}) => { return ( {cropLoading && } - navigation.goBack()}> - - - {!media.isVideo ? ( + {hideTrimmer && ( + navigation.goBack()}> + + + )} + {!hideTrimmer && ( + + setHideTrimmer(true)}> + Cancel + + setHideTrimmer(true)}> + Save + + + )} + {!isVideo ? ( = ({route, navigation}) => { @@ -277,6 +294,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { zoomStep={0.5} initialZoom={1} bindToBorders={true} + zoomEnabled={hideTrimmer} onDoubleTapAfter={( _1: any, _2: any, @@ -300,7 +318,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { = ({route, navigation}) => { )} - {media.isVideo && ( + {isVideo && hideTrimmer && ( = ({route, navigation}) => { style={styles.saveButton} onPress={() => processVideo((uri) => - saveImageToGallery(uri, media.isVideo ? 'video' : 'photo'), + saveImageToGallery(uri, isVideo ? 'video' : 'photo'), ) } /> @@ -357,7 +375,7 @@ export const EditMedia: React.FC = ({route, navigation}) => { screenType, media: { uri: uri, - isVideo: media.isVideo, + isVideo: isVideo, }, selectedCategory, }), @@ -397,6 +415,21 @@ const styles = StyleSheet.create({ alignSelf: 'center', flexDirection: 'row', }, + topContainer: { + position: 'absolute', + top: SCREEN_HEIGHT * 0.1, + width: SCREEN_WIDTH * 0.9, + justifyContent: 'space-between', + alignItems: 'center', + alignSelf: 'center', + flexDirection: 'row', + zIndex: 1, + }, + bigText: { + fontSize: normalize(15), + color: 'white', + fontWeight: 'bold', + }, saveButton: { width: 50, }, -- cgit v1.2.3-70-g09d2 From 95410f705f15f0eab611400c1b9fda4830503815 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 16 Jul 2021 19:20:28 -0400 Subject: Fix trimmer logic --- src/components/moments/TrimmerPlayer.tsx | 51 ++++++++++++++++++-------------- src/screens/upload/EditMedia.tsx | 35 ++++++++++++++-------- 2 files changed, 50 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/components/moments/TrimmerPlayer.tsx b/src/components/moments/TrimmerPlayer.tsx index ef829637..b28df590 100644 --- a/src/components/moments/TrimmerPlayer.tsx +++ b/src/components/moments/TrimmerPlayer.tsx @@ -50,6 +50,10 @@ const TrimmerPlayer: React.FC = ({ // Callback so parent knows where the trimming endpts are useEffect(() => onChangedEndpoints({end, start}), [end, start]); + useEffect(() => { + playerRef.current?.seek(0); + }, [hideTrimmer]); + return ( <> -- cgit v1.2.3-70-g09d2