mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-22 21:01:31 +03:00
unified video player component
This commit is contained in:
parent
e8d0f67619
commit
3a99cb1034
@ -13,7 +13,7 @@ import { navigate } from '../../../../navigation/service';
|
|||||||
// Constants
|
// Constants
|
||||||
import { default as ROUTES } from '../../../../constants/routeNames';
|
import { default as ROUTES } from '../../../../constants/routeNames';
|
||||||
|
|
||||||
import { PostHtmlRenderer, TextButton } from '../../..';
|
import { PostHtmlRenderer, TextButton, VideoPlayer } from '../../..';
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
import styles from './commentBodyStyles';
|
import styles from './commentBodyStyles';
|
||||||
@ -21,14 +21,12 @@ import styles from './commentBodyStyles';
|
|||||||
// Services and Actions
|
// Services and Actions
|
||||||
import { writeToClipboard } from '../../../../utils/clipboard';
|
import { writeToClipboard } from '../../../../utils/clipboard';
|
||||||
import { toastNotification } from '../../../../redux/actions/uiAction';
|
import { toastNotification } from '../../../../redux/actions/uiAction';
|
||||||
import VideoPlayerSheet from './videoPlayerSheet';
|
|
||||||
import { LongPressGestureHandler, State } from 'react-native-gesture-handler';
|
import { LongPressGestureHandler, State } from 'react-native-gesture-handler';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { OptionsModal } from '../../../atoms';
|
import { OptionsModal } from '../../../atoms';
|
||||||
import { useAppDispatch } from '../../../../hooks';
|
import { useAppDispatch } from '../../../../hooks';
|
||||||
import { isCommunity } from '../../../../utils/communityValidation';
|
import { isCommunity } from '../../../../utils/communityValidation';
|
||||||
import { GLOBAL_POST_FILTERS_VALUE } from '../../../../constants/options/filters';
|
import { GLOBAL_POST_FILTERS_VALUE } from '../../../../constants/options/filters';
|
||||||
import { startsWith } from 'core-js/core/string';
|
|
||||||
|
|
||||||
const WIDTH = Dimensions.get('window').width;
|
const WIDTH = Dimensions.get('window').width;
|
||||||
|
|
||||||
@ -368,7 +366,12 @@ const CommentBody = ({
|
|||||||
setVideoUrl(null);
|
setVideoUrl(null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<VideoPlayerSheet youtubeVideoId={youtubeVideoId} videoUrl={videoUrl} startTime={videoStartTime} />
|
<VideoPlayer
|
||||||
|
mode={youtubeVideoId ? 'youtube' : 'url'}
|
||||||
|
youtubeVideoId={youtubeVideoId}
|
||||||
|
videoUrl={videoUrl}
|
||||||
|
startTime={videoStartTime}
|
||||||
|
/>
|
||||||
</ActionsSheetView>
|
</ActionsSheetView>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -15,11 +15,10 @@ import { toastNotification } from '../../../../redux/actions/uiAction';
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { default as ROUTES } from '../../../../constants/routeNames';
|
import { default as ROUTES } from '../../../../constants/routeNames';
|
||||||
import VideoPlayerSheet from './videoPlayerSheet';
|
|
||||||
import { OptionsModal } from '../../../atoms';
|
import { OptionsModal } from '../../../atoms';
|
||||||
import { isCommunity } from '../../../../utils/communityValidation';
|
import { isCommunity } from '../../../../utils/communityValidation';
|
||||||
import { GLOBAL_POST_FILTERS_VALUE } from '../../../../constants/options/filters';
|
import { GLOBAL_POST_FILTERS_VALUE } from '../../../../constants/options/filters';
|
||||||
import { PostHtmlRenderer } from '../../..';
|
import { PostHtmlRenderer, VideoPlayer } from '../../..';
|
||||||
|
|
||||||
const WIDTH = Dimensions.get('window').width;
|
const WIDTH = Dimensions.get('window').width;
|
||||||
|
|
||||||
@ -294,7 +293,8 @@ const PostBody = ({ navigation, body, dispatch, onLoadEnd }) => {
|
|||||||
setVideoUrl(null);
|
setVideoUrl(null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<VideoPlayerSheet
|
<VideoPlayer
|
||||||
|
mode={youtubeVideoId ? 'youtube' : 'url'}
|
||||||
youtubeVideoId={youtubeVideoId}
|
youtubeVideoId={youtubeVideoId}
|
||||||
videoUrl={videoUrl}
|
videoUrl={videoUrl}
|
||||||
startTime={videoStartTime}
|
startTime={videoStartTime}
|
||||||
|
@ -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}
|
|
||||||
});
|
|
@ -218,43 +218,31 @@ export const PostHtmlRenderer = memo(
|
|||||||
return <TDefaultRenderer {...props} />;
|
return <TDefaultRenderer {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// iframe renderer for rendering iframes in body
|
// iframe renderer for rendering iframes in body
|
||||||
const _iframeRenderer = function IframeRenderer(props) {
|
const _iframeRenderer = function IframeRenderer(props) {
|
||||||
const iframeProps = useHtmlIframeProps(props);
|
const iframeProps = useHtmlIframeProps(props);
|
||||||
const checkSrcRegex = /(.*?)\.(mp4|webm|ogg)$/gi;
|
const checkSrcRegex = /(.*?)\.(mp4|webm|ogg)$/gi;
|
||||||
const isVideoType = iframeProps.source.uri.match(checkSrcRegex);
|
const isVideoFormat = iframeProps.source.uri.match(checkSrcRegex);
|
||||||
|
|
||||||
const src = isVideoType
|
//this hack help avoid autoplaying fullscreened iframe videos;
|
||||||
? {
|
const src = isVideoFormat ?
|
||||||
html: `
|
{
|
||||||
<video width="100%" height="auto" controls>
|
html: `
|
||||||
<source src="${iframeProps.source.uri}" type="video/mp4">
|
<video width="100%" height="auto" controls>
|
||||||
</video>
|
<source src="${iframeProps.source.uri}" type="video/mp4">
|
||||||
`,
|
</video>`,
|
||||||
}
|
}:{
|
||||||
: {
|
uri: iframeProps.source.uri,
|
||||||
uri: iframeProps.source.uri,
|
};
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<WebView
|
<VideoPlayer
|
||||||
scalesPageToFit={true}
|
mode='source'
|
||||||
bounces={false}
|
source={src}
|
||||||
javaScriptEnabled={true}
|
contentWidth={contentWidth}
|
||||||
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}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import style from './videoPlayerStyles';
|
|
||||||
import { Dimensions } from 'react-native';
|
import { Dimensions } from 'react-native';
|
||||||
import { View, StyleSheet, ActivityIndicator } from 'react-native';
|
import { View, StyleSheet, ActivityIndicator } from 'react-native';
|
||||||
import WebView from 'react-native-webview';
|
import WebView from 'react-native-webview';
|
||||||
import YoutubeIframe, { InitialPlayerParams } from 'react-native-youtube-iframe';
|
import YoutubeIframe, { InitialPlayerParams } from 'react-native-youtube-iframe';
|
||||||
|
import { WebViewSource } from 'react-native-webview/lib/WebViewTypes';
|
||||||
|
|
||||||
interface VideoPlayerProps {
|
interface VideoPlayerProps {
|
||||||
|
mode: 'source'|'youtube'|'url';
|
||||||
|
contentWidth?: number;
|
||||||
youtubeVideoId?: string;
|
youtubeVideoId?: string;
|
||||||
videoUrl?: string;
|
videoUrl?: string;
|
||||||
startTime?: number;
|
startTime?: number;
|
||||||
contentWidth?: number;
|
source?: WebViewSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: VideoPlayerProps) => {
|
const VideoPlayer = ({
|
||||||
const PLAYER_HEIGHT = Dimensions.get('screen').width * (9 / 16);
|
youtubeVideoId,
|
||||||
|
videoUrl,
|
||||||
|
startTime,
|
||||||
|
source,
|
||||||
|
contentWidth = Dimensions.get('screen').width,
|
||||||
|
mode
|
||||||
|
}: VideoPlayerProps) => {
|
||||||
|
|
||||||
|
const PLAYER_HEIGHT = contentWidth * (9 / 16);
|
||||||
|
|
||||||
const [shouldPlay, setShouldPlay] = useState(false);
|
const [shouldPlay, setShouldPlay] = useState(false);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@ -40,7 +50,7 @@ const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: Vide
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{youtubeVideoId && (
|
{mode === 'youtube' && youtubeVideoId && (
|
||||||
<View style={{ width: contentWidth, height: PLAYER_HEIGHT }}>
|
<View style={{ width: contentWidth, height: PLAYER_HEIGHT }}>
|
||||||
<YoutubeIframe
|
<YoutubeIframe
|
||||||
height={PLAYER_HEIGHT}
|
height={PLAYER_HEIGHT}
|
||||||
@ -53,7 +63,7 @@ const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: Vide
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{videoUrl && (
|
{((mode === 'source' && source) || (mode === 'url' && videoUrl)) && (
|
||||||
<View style={{ height: PLAYER_HEIGHT }}>
|
<View style={{ height: PLAYER_HEIGHT }}>
|
||||||
<WebView
|
<WebView
|
||||||
scalesPageToFit={true}
|
scalesPageToFit={true}
|
||||||
@ -66,8 +76,8 @@ const VideoPlayer = ({ youtubeVideoId, videoUrl, startTime, contentWidth }: Vide
|
|||||||
onLoadStart={() => {
|
onLoadStart={() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
}}
|
}}
|
||||||
source={{ uri: videoUrl }}
|
source={source || { uri: videoUrl }}
|
||||||
style={{ width: contentWidth, height: (contentWidth * 9) / 16 }}
|
style={{ width: contentWidth, height: PLAYER_HEIGHT}}
|
||||||
startInLoadingState={true}
|
startInLoadingState={true}
|
||||||
onShouldStartLoadWithRequest={() => true}
|
onShouldStartLoadWithRequest={() => true}
|
||||||
mediaPlaybackRequiresUserAction={true}
|
mediaPlaybackRequiresUserAction={true}
|
||||||
|
Loading…
Reference in New Issue
Block a user