aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/comments/ZoomInCropper.tsx58
-rw-r--r--src/components/moments/trimmer.tsx98
-rw-r--r--src/screens/profile/CaptionScreen.tsx2
-rw-r--r--src/utils/camera.ts15
4 files changed, 151 insertions, 22 deletions
diff --git a/src/components/comments/ZoomInCropper.tsx b/src/components/comments/ZoomInCropper.tsx
index 3581168d..b4333cbb 100644
--- a/src/components/comments/ZoomInCropper.tsx
+++ b/src/components/comments/ZoomInCropper.tsx
@@ -9,13 +9,14 @@ import CloseIcon from '../../assets/ionicons/close-outline.svg';
import {MainStackParams} from '../../routes';
import {
cropVideo,
+ trimVideo,
HeaderHeight,
SCREEN_HEIGHT,
SCREEN_WIDTH,
} from '../../utils';
import {TaggSquareButton, TaggLoadingIndicator} from '../common';
import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView';
-import Video from 'react-native-video';
+import {TrimmerPlayer} from '../moments/trimmer';
type ZoomInCropperRouteProps = RouteProp<MainStackParams, 'ZoomInCropper'>;
type ZoomInCropperNavigationProps = StackNavigationProp<
@@ -52,6 +53,15 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
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') ||
@@ -138,20 +148,25 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
}));
}
setCropLoading(true);
- cropVideo(
+ trimVideo(
media.uri,
- (croppedURL: string) => {
- setCropLoading(false);
- navigation.navigate('CaptionScreen', {
- screenType,
- media: {
- uri: croppedURL,
- isVideo: true,
+ (trimmedURL: string) =>
+ cropVideo(
+ trimmedURL,
+ (croppedURL: string) => {
+ setCropLoading(false);
+ navigation.navigate('CaptionScreen', {
+ screenType,
+ media: {
+ uri: croppedURL,
+ isVideo: true,
+ },
+ selectedCategory,
+ });
},
- selectedCategory,
- });
- },
- videoCrop,
+ videoCrop,
+ ),
+ trimEnds,
);
}
};
@@ -308,22 +323,23 @@ export const ZoomInCropper: React.FC<ZoomInCropperProps> = ({
}}
style={styles.zoomView}>
<View style={styles.videoParent} ref={vidRef}>
- <Video
- source={{uri: media.uri}}
- volume={1}
- style={[
+ <TrimmerPlayer
+ hideTrimmer={false}
+ source={media.uri}
+ videoStyles={[
styles.media,
{
height: SCREEN_WIDTH / aspectRatio,
},
]}
- repeat={true}
- resizeMode={'contain'}
- onLoad={(response) => {
- const {width, height} = response.naturalSize;
+ handleLoad={(response: {width: number; height: number}) => {
+ const {width, height} = response;
setOrigDimensions([width, height]);
setAspectRatio(width / height);
}}
+ onChangedEndpoints={(response: {start: number; end: number}) =>
+ setTrimEnds(response)
+ }
/>
</View>
</ReactNativeZoomableView>
diff --git a/src/components/moments/trimmer.tsx b/src/components/moments/trimmer.tsx
new file mode 100644
index 00000000..c99eaa6f
--- /dev/null
+++ b/src/components/moments/trimmer.tsx
@@ -0,0 +1,98 @@
+import React, {useEffect, useState} from 'react';
+import Video from 'react-native-video';
+import {Trimmer} from 'react-native-video-processing';
+import {useRef} from 'react';
+import {SCREEN_WIDTH} from '../../utils';
+
+export const TrimmerPlayer: React.FC<{
+ source: string;
+ videoStyles: Object;
+ hideTrimmer: boolean;
+ handleLoad: Function;
+ onChangedEndpoints: Function;
+}> = ({source, videoStyles, hideTrimmer, handleLoad, onChangedEndpoints}) => {
+ // Stores the reference to player for seeking
+ const playerRef = useRef<Video>();
+ // Stores where the video is playing (seekTime)
+ const [seekTime, setSeekTime] = useState<number>(0);
+ const [paused, setPaused] = useState<boolean>(false);
+ // Stores where the tracker is
+ const [trackerTime, setTrackerTime] = useState<number>(0);
+ // Stores start/end of desired trimmed video
+ const [end, setEnd] = useState<number>(60);
+ const [start, setStart] = useState<number>(0);
+
+ useEffect(() => {
+ playerRef.current?.seek(seekTime);
+ }, [seekTime]);
+ useEffect(() => {
+ if (!paused && (trackerTime >= end || trackerTime < start)) {
+ setTrackerTime(start);
+ playerRef.current?.seek(start);
+ }
+ }, [trackerTime]);
+ useEffect(() => {
+ setSeekTime(start);
+ setTrackerTime(start);
+ }, [start]);
+ useEffect(() => {
+ setSeekTime(end);
+ setTrackerTime(start);
+ }, [end]);
+ // Callback so parent knows where the trimming endpts are
+ useEffect(() => onChangedEndpoints({end, start}), [end, start]);
+
+ return (
+ <>
+ <Video
+ // link to descr and use of props of video player ->
+ // https://github.com/react-native-video/react-native-video
+ ref={(ref) => {
+ playerRef.current = ref || undefined;
+ }}
+ source={{uri: source}}
+ rate={1.0}
+ volume={1.0}
+ muted={false}
+ paused={paused}
+ resizeMode={'contain'}
+ repeat={true}
+ onLoad={(payload) => {
+ console.log(payload, source);
+ setEnd(payload.duration);
+ handleLoad(payload.naturalSize);
+ }}
+ onProgress={(e) => {
+ if (!paused) {
+ setTrackerTime(e.currentTime);
+ }
+ }} // Callback every ~250ms with currentTime
+ style={videoStyles}
+ onTouchEnd={() => {
+ setPaused((state) => !state);
+ }}
+ />
+ <Trimmer
+ // link to descr and use of props for trimmer ->
+ // https://github.com/shahen94/react-native-video-processing
+ source={source}
+ height={hideTrimmer ? 0 : 75}
+ width={hideTrimmer ? 0 : SCREEN_WIDTH}
+ borderWidth={hideTrimmer ? 0 : 100}
+ onTrackerMove={(e: {currentTime: number}) => {
+ setPaused(true);
+ setSeekTime(e.currentTime);
+ }}
+ currentTime={trackerTime}
+ themeColor={'white'}
+ thumbWidth={10}
+ trackerColor={'white'}
+ onChange={(e: {endTime: number; startTime: number}) => {
+ setPaused(true);
+ setEnd(e.endTime);
+ setStart(e.startTime);
+ }}
+ />
+ </>
+ );
+};
diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx
index 6bcf0e24..eba3e4bf 100644
--- a/src/screens/profile/CaptionScreen.tsx
+++ b/src/screens/profile/CaptionScreen.tsx
@@ -49,7 +49,6 @@ import {RootState} from '../../store/rootReducer';
import {MomentTagType} from '../../types';
import {isIPhoneX, normalize, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
import {mentionPartTypes} from '../../utils/comments';
-
/**
* Upload Screen to allow users to upload posts to Tagg
*/
@@ -362,6 +361,7 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
</SearchBackground>
);
};
+
const styles = StyleSheet.create({
contentContainer: {
paddingTop: StatusBarHeight,
diff --git a/src/utils/camera.ts b/src/utils/camera.ts
index c0b0c6bf..5485b1ca 100644
--- a/src/utils/camera.ts
+++ b/src/utils/camera.ts
@@ -103,6 +103,21 @@ export const showGIFFailureAlert = (onSuccess: () => void) =>
},
);
+export const trimVideo = (
+ sourceUri: string,
+ handleData: (data: any) => any,
+ ends: {
+ start: number;
+ end: number;
+ },
+) => {
+ ProcessingManager.trim(sourceUri, {
+ startTime: ends.start / 2, //needed divide by 2 for bug in module
+ endTime: ends.end,
+ quality: 'passthrough',
+ }).then((data: any) => handleData(data));
+};
+
export const cropVideo = (
sourceUri: string,
handleData: (data: any) => any,