aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-07-16 15:48:31 -0400
committerGitHub <noreply@github.com>2021-07-16 15:48:31 -0400
commit6161a73ec29dbcf4ffb9ee90d86a3c4e46eb58dc (patch)
treeed8b2fb574e598f25d1db0e0204504ebe472924b /src/components
parent0838a170c84c32d502377c17825d7bf8d21300d0 (diff)
parent580774b43f2919c4fb4230308afb06cc9891a5e9 (diff)
Merge pull request #503 from sotech117/tma954-video-trimming-component
[TMA-954] Video Trimming Component
Diffstat (limited to 'src/components')
-rw-r--r--src/components/comments/ZoomInCropper.tsx58
-rw-r--r--src/components/moments/trimmer.tsx98
2 files changed, 135 insertions, 21 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);
+ }}
+ />
+ </>
+ );
+};