feat: add ability to define poster
props as Image type and render poster as custom component (#3972)
This commit is contained in:
@@ -34,7 +34,7 @@ import Video, {
|
||||
import styles from './styles';
|
||||
import {type AdditionalSourceInfo} from './types';
|
||||
import {bufferConfig, srcList, textTracksSelectionBy} from './constants';
|
||||
import {Overlay, toast} from './components';
|
||||
import {Overlay, toast, VideoLoader} from './components';
|
||||
|
||||
type Props = NonNullable<unknown>;
|
||||
|
||||
@@ -68,7 +68,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
const [repeat, setRepeat] = useState(false);
|
||||
const [controls, setControls] = useState(false);
|
||||
const [useCache, setUseCache] = useState(false);
|
||||
const [poster, setPoster] = useState<string | undefined>(undefined);
|
||||
const [showPoster, setShowPoster] = useState<boolean>(false);
|
||||
const [showNotificationControls, setShowNotificationControls] =
|
||||
useState(false);
|
||||
const [isSeeking, setIsSeeking] = useState(false);
|
||||
@@ -234,7 +234,6 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
paused={paused}
|
||||
volume={volume}
|
||||
muted={muted}
|
||||
fullscreen={fullscreen}
|
||||
controls={controls}
|
||||
resizeMode={resizeMode}
|
||||
onFullscreenPlayerWillDismiss={onFullScreenExit}
|
||||
@@ -264,7 +263,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
cacheSizeMB: useCache ? 200 : 0,
|
||||
}}
|
||||
preventsDisplaySleepDuringVideoPlayback={true}
|
||||
poster={poster}
|
||||
renderLoader={showPoster ? <VideoLoader /> : undefined}
|
||||
onPlaybackRateChange={onPlaybackRateChange}
|
||||
onPlaybackStateChanged={onPlaybackStateChanged}
|
||||
bufferingStrategy={BufferingStrategyType.DEFAULT}
|
||||
@@ -294,7 +293,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
paused={paused}
|
||||
volume={volume}
|
||||
setControls={setControls}
|
||||
poster={poster}
|
||||
showPoster={showPoster}
|
||||
rate={rate}
|
||||
setFullscreen={setFullscreen}
|
||||
setPaused={setPaused}
|
||||
@@ -303,7 +302,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
setIsSeeking={setIsSeeking}
|
||||
repeat={repeat}
|
||||
setRepeat={setRepeat}
|
||||
setPoster={setPoster}
|
||||
setShowPoster={setShowPoster}
|
||||
setRate={setRate}
|
||||
setResizeMode={setResizeMode}
|
||||
setShowNotificationControls={setShowNotificationControls}
|
||||
|
@@ -1,22 +1,8 @@
|
||||
import React, {FC, memo} from 'react';
|
||||
import {ActivityIndicator, View} from 'react-native';
|
||||
import styles from '../styles.tsx';
|
||||
import React, {memo} from 'react';
|
||||
import {ActivityIndicator} from 'react-native';
|
||||
|
||||
type Props = {
|
||||
isLoading: boolean;
|
||||
};
|
||||
|
||||
const _Indicator: FC<Props> = ({isLoading}) => {
|
||||
if (!isLoading) {
|
||||
return <View />;
|
||||
}
|
||||
return (
|
||||
<ActivityIndicator
|
||||
color="#3235fd"
|
||||
size="large"
|
||||
style={styles.IndicatorStyle}
|
||||
/>
|
||||
);
|
||||
const _Indicator = () => {
|
||||
return <ActivityIndicator color="#3235fd" size="large" />;
|
||||
};
|
||||
|
||||
export const Indicator = memo(_Indicator);
|
||||
|
@@ -5,19 +5,11 @@ import React, {
|
||||
type Dispatch,
|
||||
type SetStateAction,
|
||||
} from 'react';
|
||||
import {Indicator} from './Indicator.tsx';
|
||||
import {View} from 'react-native';
|
||||
import styles from '../styles.tsx';
|
||||
import ToggleControl from '../ToggleControl.tsx';
|
||||
import {
|
||||
isAndroid,
|
||||
isIos,
|
||||
samplePoster,
|
||||
textTracksSelectionBy,
|
||||
} from '../constants';
|
||||
import MultiValueControl, {
|
||||
type MultiValueControlPropType,
|
||||
} from '../MultiValueControl.tsx';
|
||||
import {isAndroid, isIos, textTracksSelectionBy} from '../constants';
|
||||
import MultiValueControl from '../MultiValueControl.tsx';
|
||||
import {
|
||||
ResizeMode,
|
||||
VideoRef,
|
||||
@@ -69,8 +61,8 @@ type Props = {
|
||||
setPaused: Dispatch<SetStateAction<boolean>>;
|
||||
repeat: boolean;
|
||||
setRepeat: Dispatch<SetStateAction<boolean>>;
|
||||
poster: string | undefined;
|
||||
setPoster: Dispatch<SetStateAction<string | undefined>>;
|
||||
showPoster: boolean;
|
||||
setShowPoster: Dispatch<SetStateAction<boolean>>;
|
||||
muted: boolean;
|
||||
setMuted: Dispatch<SetStateAction<boolean>>;
|
||||
currentTime: number;
|
||||
@@ -108,8 +100,8 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
setPaused,
|
||||
setRepeat,
|
||||
repeat,
|
||||
setPoster,
|
||||
poster,
|
||||
setShowPoster,
|
||||
showPoster,
|
||||
setMuted,
|
||||
muted,
|
||||
duration,
|
||||
@@ -217,14 +209,12 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
|
||||
const toggleRepeat = () => setRepeat(prev => !prev);
|
||||
|
||||
const togglePoster = () =>
|
||||
setPoster(prev => (prev ? undefined : samplePoster));
|
||||
const togglePoster = () => setShowPoster(prev => !prev);
|
||||
|
||||
const toggleMuted = () => setMuted(prev => !prev);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Indicator isLoading={isLoading} />
|
||||
<View style={styles.topControls}>
|
||||
<View style={styles.resizeModeControl}>
|
||||
<TopControl
|
||||
@@ -270,7 +260,7 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
<ToggleControl onPress={toggleFullscreen} text="fullscreen" />
|
||||
<ToggleControl onPress={openDecoration} text="decoration" />
|
||||
<ToggleControl
|
||||
isSelected={!!poster}
|
||||
isSelected={showPoster}
|
||||
onPress={togglePoster}
|
||||
selectedText="poster"
|
||||
unselectedText="no poster"
|
||||
|
15
examples/basic/src/components/VideoLoader.tsx
Normal file
15
examples/basic/src/components/VideoLoader.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import {Text, View} from 'react-native';
|
||||
import {Indicator} from './Indicator.tsx';
|
||||
import React, {memo} from 'react';
|
||||
import styles from '../styles.tsx';
|
||||
|
||||
const _VideoLoader = () => {
|
||||
return (
|
||||
<View style={styles.indicatorContainer}>
|
||||
<Text style={styles.indicatorText}>Loading...</Text>
|
||||
<Indicator />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export const VideoLoader = memo(_VideoLoader);
|
@@ -1,3 +1,4 @@
|
||||
export * from './VideoLoader';
|
||||
export * from './Indicator';
|
||||
export * from './Seeker';
|
||||
export * from './AudioTracksSelector';
|
||||
|
@@ -149,10 +149,6 @@ export const srcAndroidList = [
|
||||
},
|
||||
];
|
||||
|
||||
// poster which can be displayed
|
||||
export const samplePoster =
|
||||
'https://upload.wikimedia.org/wikipedia/commons/1/18/React_Native_Logo.png';
|
||||
|
||||
export const srcList: SampleVideoSource[] = srcAllPlatformList.concat(
|
||||
isAndroid ? srcAndroidList : srcIosList,
|
||||
);
|
||||
|
@@ -102,9 +102,15 @@ const styles = StyleSheet.create({
|
||||
borderWidth: 1,
|
||||
borderColor: 'red',
|
||||
},
|
||||
IndicatorStyle: {
|
||||
flex: 1,
|
||||
indicatorContainer: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: 10,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
indicatorText: {
|
||||
color: 'white',
|
||||
},
|
||||
seekbarContainer: {
|
||||
flex: 1,
|
||||
|
Reference in New Issue
Block a user