diff options
author | Ivan Chen <ivan@tagg.id> | 2021-07-16 15:48:31 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-16 15:48:31 -0400 |
commit | 6161a73ec29dbcf4ffb9ee90d86a3c4e46eb58dc (patch) | |
tree | ed8b2fb574e598f25d1db0e0204504ebe472924b /src/components | |
parent | 0838a170c84c32d502377c17825d7bf8d21300d0 (diff) | |
parent | 580774b43f2919c4fb4230308afb06cc9891a5e9 (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.tsx | 58 | ||||
-rw-r--r-- | src/components/moments/trimmer.tsx | 98 |
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); + }} + /> + </> + ); +}; |