unified video player component

This commit is contained in:
noumantahir 2022-01-23 01:11:17 +05:00
parent e8d0f67619
commit 3a99cb1034
5 changed files with 48 additions and 130 deletions

View File

@ -13,7 +13,7 @@ import { navigate } from '../../../../navigation/service';
// Constants
import { default as ROUTES } from '../../../../constants/routeNames';
import { PostHtmlRenderer, TextButton } from '../../..';
import { PostHtmlRenderer, TextButton, VideoPlayer } from '../../..';
// Styles
import styles from './commentBodyStyles';
@ -21,14 +21,12 @@ import styles from './commentBodyStyles';
// Services and Actions
import { writeToClipboard } from '../../../../utils/clipboard';
import { toastNotification } from '../../../../redux/actions/uiAction';
import VideoPlayerSheet from './videoPlayerSheet';
import { LongPressGestureHandler, State } from 'react-native-gesture-handler';
import { useCallback } from 'react';
import { OptionsModal } from '../../../atoms';
import { useAppDispatch } from '../../../../hooks';
import { isCommunity } from '../../../../utils/communityValidation';
import { GLOBAL_POST_FILTERS_VALUE } from '../../../../constants/options/filters';
import { startsWith } from 'core-js/core/string';
const WIDTH = Dimensions.get('window').width;
@ -368,7 +366,12 @@ const CommentBody = ({
setVideoUrl(null);
}}
>
<VideoPlayerSheet youtubeVideoId={youtubeVideoId} videoUrl={videoUrl} startTime={videoStartTime} />
<VideoPlayer
mode={youtubeVideoId ? 'youtube' : 'url'}
youtubeVideoId={youtubeVideoId}
videoUrl={videoUrl}
startTime={videoStartTime}
/>
</ActionsSheetView>
</Fragment>
);

View File

@ -15,11 +15,10 @@ import { toastNotification } from '../../../../redux/actions/uiAction';
// Constants
import { default as ROUTES } from '../../../../constants/routeNames';
import VideoPlayerSheet from './videoPlayerSheet';
import { OptionsModal } from '../../../atoms';
import { isCommunity } from '../../../../utils/communityValidation';
import { GLOBAL_POST_FILTERS_VALUE } from '../../../../constants/options/filters';
import { PostHtmlRenderer } from '../../..';
import { PostHtmlRenderer, VideoPlayer } from '../../..';
const WIDTH = Dimensions.get('window').width;
@ -294,7 +293,8 @@ const PostBody = ({ navigation, body, dispatch, onLoadEnd }) => {
setVideoUrl(null);
}}
>
<VideoPlayerSheet
<VideoPlayer
mode={youtubeVideoId ? 'youtube' : 'url'}
youtubeVideoId={youtubeVideoId}
videoUrl={videoUrl}
startTime={videoStartTime}

View File

@ -1,83 +0,0 @@
import React, {useState} from 'react';
import { Dimensions } from 'react-native';
import { View, StyleSheet, ActivityIndicator } from 'react-native';
import WebView from 'react-native-webview';
import YoutubeIframe, { InitialPlayerParams } from 'react-native-youtube-iframe';
interface VideoPlayerSheetProps {
youtubeVideoId?:string;
videoUrl?:string;
startTime?:number;
}
const VideoPlayerSheet = ({youtubeVideoId, videoUrl, startTime}: VideoPlayerSheetProps) => {
const PLAYER_HEIGHT = Dimensions.get('screen').width * (9/16);
const [shouldPlay, setShouldPlay] = useState(false);
const [loading, setLoading] = useState(true);
const _onReady = () => {
setLoading(false)
setShouldPlay(true);
}
const _onChangeState = (event:string) => {
setShouldPlay(!(event == 'paused' || event == 'ended'));
}
const _onError = () => {
setLoading(false)
}
const initialParams:InitialPlayerParams = {
start:startTime
}
return (
<View style={styles.container}>
{youtubeVideoId &&
<YoutubeIframe
height={PLAYER_HEIGHT}
videoId={youtubeVideoId}
initialPlayerParams={initialParams}
onReady={_onReady}
play={shouldPlay}
onChangeState={_onChangeState}
onError={_onError}
/>
}{
videoUrl &&
<View style={{height:PLAYER_HEIGHT}}>
<WebView
scalesPageToFit={true}
bounces={false}
javaScriptEnabled={true}
automaticallyAdjustContentInsets={false}
onLoadEnd={()=>{
setLoading(false);
}}
onLoadStart={()=>{
setLoading(true);
}}
source={{uri:videoUrl}}
/>
</View>
}
{loading && <ActivityIndicator style={styles.activityIndicator}/>}
</View>
);
};
export default VideoPlayerSheet;
const styles = StyleSheet.create({
container: {
paddingVertical:16,
},
activityIndicator: {
position:'absolute', alignItems:'center', justifyContent:'center', top:0, bottom:0, left:0, right:0}
});

View File

@ -218,43 +218,31 @@ export const PostHtmlRenderer = memo(
return <TDefaultRenderer {...props} />;
};
// iframe renderer for rendering iframes in body
const _iframeRenderer = function IframeRenderer(props) {
const iframeProps = useHtmlIframeProps(props);
const checkSrcRegex = /(.*?)\.(mp4|webm|ogg)$/gi;
const isVideoType = iframeProps.source.uri.match(checkSrcRegex);
const isVideoFormat = iframeProps.source.uri.match(checkSrcRegex);
const src = isVideoType
? {
html: `
<video width="100%" height="auto" controls>
<source src="${iframeProps.source.uri}" type="video/mp4">
</video>
`,
}
: {
uri: iframeProps.source.uri,
};
return (
<WebView
scalesPageToFit={true}
bounces={false}
javaScriptEnabled={true}
automaticallyAdjustContentInsets={false}
onLoadEnd={() => {
console.log('load end');
}}
onLoadStart={() => {
console.log('load start');
}}
source={src}
style={{ width: contentWidth, height: (contentWidth * 9) / 16 }}
startInLoadingState={true}
onShouldStartLoadWithRequest={() => true}
mediaPlaybackRequiresUserAction={true}
allowsInlineMediaPlayback={true}
/>
);
//this hack help avoid autoplaying fullscreened iframe videos;
const src = isVideoFormat ?
{
html: `
<video width="100%" height="auto" controls>
<source src="${iframeProps.source.uri}" type="video/mp4">
</video>`,
}:{
uri: iframeProps.source.uri,
};
return (
<VideoPlayer
mode='source'
source={src}
contentWidth={contentWidth}
/>
);
};
return (

View File

@ -1,19 +1,29 @@
import React, { useState } from 'react';
import style from './videoPlayerStyles';
import { Dimensions } from 'react-native';
import { View, StyleSheet, ActivityIndicator } from 'react-native';
import WebView from 'react-native-webview';
import YoutubeIframe, { InitialPlayerParams } from 'react-native-youtube-iframe';
import { WebViewSource } from 'react-native-webview/lib/WebViewTypes';
interface VideoPlayerProps {
mode: 'source'|'youtube'|'url';
contentWidth?: number;
youtubeVideoId?: string;
videoUrl?: string;
startTime?: number;
contentWidth?: number;
source?: WebViewSource;
}
const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: VideoPlayerProps) => {
const PLAYER_HEIGHT = Dimensions.get('screen').width * (9 / 16);
const VideoPlayer = ({
youtubeVideoId,
videoUrl,
startTime,
source,
contentWidth = Dimensions.get('screen').width,
mode
}: VideoPlayerProps) => {
const PLAYER_HEIGHT = contentWidth * (9 / 16);
const [shouldPlay, setShouldPlay] = useState(false);
const [loading, setLoading] = useState(true);
@ -40,7 +50,7 @@ const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: Vide
return (
<View style={styles.container}>
{youtubeVideoId && (
{mode === 'youtube' && youtubeVideoId && (
<View style={{ width: contentWidth, height: PLAYER_HEIGHT }}>
<YoutubeIframe
height={PLAYER_HEIGHT}
@ -53,7 +63,7 @@ const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: Vide
/>
</View>
)}
{videoUrl && (
{((mode === 'source' && source) || (mode === 'url' && videoUrl)) && (
<View style={{ height: PLAYER_HEIGHT }}>
<WebView
scalesPageToFit={true}
@ -66,8 +76,8 @@ const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: Vide
onLoadStart={() => {
setLoading(true);
}}
source={{ uri: videoUrl }}
style={{ width: contentWidth, height: (contentWidth * 9) / 16 }}
source={source || { uri: videoUrl }}
style={{ width: contentWidth, height: PLAYER_HEIGHT}}
startInLoadingState={true}
onShouldStartLoadWithRequest={() => true}
mediaPlaybackRequiresUserAction={true}