feat: add ability to define poster props as Image type and render poster as custom component (#3972)
				
					
				
			This commit is contained in:
		@@ -437,13 +437,26 @@ Determine whether the media should continue playing when notifications or the Co
 | 
			
		||||
### `poster`
 | 
			
		||||
 | 
			
		||||
<PlatformsList types={['All']} />
 | 
			
		||||
> [!WARNING]
 | 
			
		||||
> Value: string with a URL for the poster is deprecated, use `poster` as object instead
 | 
			
		||||
 | 
			
		||||
An image to display while the video is loading
 | 
			
		||||
 | 
			
		||||
Value: string with a URL for the poster, e.g. "https://baconmockup.com/300/200/"
 | 
			
		||||
Value: Props for the `Image` component. The poster is visible when the source attribute is provided.
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
<Video>
 | 
			
		||||
  poster={{
 | 
			
		||||
    source: { uri: "https://baconmockup.com/300/200/" },
 | 
			
		||||
    resizeMode: "cover",
 | 
			
		||||
    // ...
 | 
			
		||||
  }}
 | 
			
		||||
</Video>
 | 
			
		||||
````
 | 
			
		||||
 | 
			
		||||
### `posterResizeMode`
 | 
			
		||||
 | 
			
		||||
> [!WARNING]
 | 
			
		||||
> deprecated, use `poster` with `resizeMode` key instead
 | 
			
		||||
<PlatformsList types={['All']} />
 | 
			
		||||
 | 
			
		||||
Determines how to resize the poster image when the frame doesn't match the raw video dimensions.
 | 
			
		||||
@@ -489,6 +502,22 @@ Speed at which the media should play.
 | 
			
		||||
- **1.0** - Play at normal speed (default)
 | 
			
		||||
- **Other values** - Slow down or speed up playback
 | 
			
		||||
 | 
			
		||||
### `renderLoader`
 | 
			
		||||
 | 
			
		||||
<PlatformsList types={['All']} />
 | 
			
		||||
 | 
			
		||||
Allows you to create custom components to display while the video is loading. If `renderLoader` is provided, `poster` and `posterResizeMode` will be ignored.
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
<Video>
 | 
			
		||||
  renderLoader={
 | 
			
		||||
    <View>
 | 
			
		||||
      <Text>Custom Loader</Text>
 | 
			
		||||
    </View>
 | 
			
		||||
  }
 | 
			
		||||
</Video>
 | 
			
		||||
````
 | 
			
		||||
 | 
			
		||||
### `repeat`
 | 
			
		||||
 | 
			
		||||
<PlatformsList types={['All']} />
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								src/Video.tsx
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/Video.tsx
									
									
									
									
									
								
							@@ -8,7 +8,13 @@ import React, {
 | 
			
		||||
} from 'react';
 | 
			
		||||
import type {ElementRef} from 'react';
 | 
			
		||||
import {View, StyleSheet, Image, Platform, processColor} from 'react-native';
 | 
			
		||||
import type {StyleProp, ImageStyle, NativeSyntheticEvent} from 'react-native';
 | 
			
		||||
import type {
 | 
			
		||||
  StyleProp,
 | 
			
		||||
  ImageStyle,
 | 
			
		||||
  NativeSyntheticEvent,
 | 
			
		||||
  ViewStyle,
 | 
			
		||||
  ImageResizeMode,
 | 
			
		||||
} from 'react-native';
 | 
			
		||||
 | 
			
		||||
import NativeVideoComponent from './specs/VideoNativeComponent';
 | 
			
		||||
import type {
 | 
			
		||||
@@ -67,8 +73,9 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
 | 
			
		||||
      source,
 | 
			
		||||
      style,
 | 
			
		||||
      resizeMode,
 | 
			
		||||
      posterResizeMode,
 | 
			
		||||
      poster,
 | 
			
		||||
      posterResizeMode,
 | 
			
		||||
      renderLoader,
 | 
			
		||||
      drm,
 | 
			
		||||
      textTracks,
 | 
			
		||||
      selectedVideoTrack,
 | 
			
		||||
@@ -113,25 +120,28 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
 | 
			
		||||
    ref,
 | 
			
		||||
  ) => {
 | 
			
		||||
    const nativeRef = useRef<ElementRef<typeof NativeVideoComponent>>(null);
 | 
			
		||||
    const [showPoster, setShowPoster] = useState(!!poster);
 | 
			
		||||
 | 
			
		||||
    const isPosterDeprecated = typeof poster === 'string';
 | 
			
		||||
 | 
			
		||||
    const hasPoster = useMemo(() => {
 | 
			
		||||
      if (renderLoader) {
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (isPosterDeprecated) {
 | 
			
		||||
        return !!poster;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return !!poster?.source;
 | 
			
		||||
    }, [isPosterDeprecated, poster, renderLoader]);
 | 
			
		||||
 | 
			
		||||
    const [showPoster, setShowPoster] = useState(hasPoster);
 | 
			
		||||
 | 
			
		||||
    const [
 | 
			
		||||
      _restoreUserInterfaceForPIPStopCompletionHandler,
 | 
			
		||||
      setRestoreUserInterfaceForPIPStopCompletionHandler,
 | 
			
		||||
    ] = useState<boolean | undefined>();
 | 
			
		||||
 | 
			
		||||
    const hasPoster = !!poster;
 | 
			
		||||
 | 
			
		||||
    const posterStyle = useMemo<StyleProp<ImageStyle>>(
 | 
			
		||||
      () => ({
 | 
			
		||||
        ...StyleSheet.absoluteFillObject,
 | 
			
		||||
        resizeMode:
 | 
			
		||||
          posterResizeMode && posterResizeMode !== 'none'
 | 
			
		||||
            ? posterResizeMode
 | 
			
		||||
            : 'contain',
 | 
			
		||||
      }),
 | 
			
		||||
      [posterResizeMode],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const src = useMemo<VideoSrc | undefined>(() => {
 | 
			
		||||
      if (!source) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
@@ -598,13 +608,78 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
 | 
			
		||||
        : ViewType.SURFACE;
 | 
			
		||||
    }, [drm, useSecureView, useTextureView, viewType]);
 | 
			
		||||
 | 
			
		||||
    const _renderPoster = useCallback(() => {
 | 
			
		||||
      if (!hasPoster || !showPoster) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // poster resize mode
 | 
			
		||||
      let _posterResizeMode: ImageResizeMode = 'contain';
 | 
			
		||||
 | 
			
		||||
      if (!isPosterDeprecated && poster?.resizeMode) {
 | 
			
		||||
        _posterResizeMode = poster.resizeMode;
 | 
			
		||||
      } else if (posterResizeMode && posterResizeMode !== 'none') {
 | 
			
		||||
        _posterResizeMode = posterResizeMode;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // poster style
 | 
			
		||||
      const baseStyle: StyleProp<ImageStyle> = {
 | 
			
		||||
        ...StyleSheet.absoluteFillObject,
 | 
			
		||||
        resizeMode: _posterResizeMode,
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      let posterStyle: StyleProp<ImageStyle> = baseStyle;
 | 
			
		||||
 | 
			
		||||
      if (!isPosterDeprecated && poster?.style) {
 | 
			
		||||
        const styles = Array.isArray(poster.style)
 | 
			
		||||
          ? poster.style
 | 
			
		||||
          : [poster.style];
 | 
			
		||||
        posterStyle = [baseStyle, ...styles];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // render poster
 | 
			
		||||
      if (renderLoader && (poster || posterResizeMode)) {
 | 
			
		||||
        console.warn(
 | 
			
		||||
          'You provided both `renderLoader` and `poster` or `posterResizeMode` props. `renderLoader` will be used.',
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // render loader
 | 
			
		||||
      if (renderLoader) {
 | 
			
		||||
        return <View style={StyleSheet.absoluteFill}>{renderLoader}</View>;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return (
 | 
			
		||||
        <Image
 | 
			
		||||
          {...(isPosterDeprecated ? {} : poster)}
 | 
			
		||||
          source={isPosterDeprecated ? {uri: poster} : poster?.source}
 | 
			
		||||
          style={posterStyle}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
    }, [
 | 
			
		||||
      hasPoster,
 | 
			
		||||
      isPosterDeprecated,
 | 
			
		||||
      poster,
 | 
			
		||||
      posterResizeMode,
 | 
			
		||||
      renderLoader,
 | 
			
		||||
      showPoster,
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    const _style: StyleProp<ViewStyle> = useMemo(
 | 
			
		||||
      () => ({
 | 
			
		||||
        ...StyleSheet.absoluteFillObject,
 | 
			
		||||
        ...(showPoster ? {display: 'none'} : {}),
 | 
			
		||||
      }),
 | 
			
		||||
      [showPoster],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <View style={style}>
 | 
			
		||||
        <NativeVideoComponent
 | 
			
		||||
          ref={nativeRef}
 | 
			
		||||
          {...rest}
 | 
			
		||||
          src={src}
 | 
			
		||||
          style={StyleSheet.absoluteFill}
 | 
			
		||||
          style={_style}
 | 
			
		||||
          resizeMode={resizeMode}
 | 
			
		||||
          restoreUserInterfaceForPIPStopCompletionHandler={
 | 
			
		||||
            _restoreUserInterfaceForPIPStopCompletionHandler
 | 
			
		||||
@@ -679,9 +754,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
 | 
			
		||||
          }
 | 
			
		||||
          viewType={_viewType}
 | 
			
		||||
        />
 | 
			
		||||
        {hasPoster && showPoster ? (
 | 
			
		||||
          <Image style={posterStyle} source={{uri: poster}} />
 | 
			
		||||
        ) : null}
 | 
			
		||||
        {_renderPoster()}
 | 
			
		||||
      </View>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,14 @@
 | 
			
		||||
import type {ISO639_1} from './language';
 | 
			
		||||
import type {ReactVideoEvents} from './events';
 | 
			
		||||
import type {StyleProp, ViewProps, ViewStyle} from 'react-native';
 | 
			
		||||
import type {
 | 
			
		||||
  ImageProps,
 | 
			
		||||
  StyleProp,
 | 
			
		||||
  ViewProps,
 | 
			
		||||
  ViewStyle,
 | 
			
		||||
  ImageRequireSource,
 | 
			
		||||
  ImageURISource,
 | 
			
		||||
} from 'react-native';
 | 
			
		||||
import type {ReactNode} from 'react';
 | 
			
		||||
import type VideoResizeMode from './ResizeMode';
 | 
			
		||||
import type FilterType from './FilterType';
 | 
			
		||||
import type ViewType from './ViewType';
 | 
			
		||||
@@ -34,6 +42,13 @@ export type ReactVideoSource = Readonly<
 | 
			
		||||
  }
 | 
			
		||||
>;
 | 
			
		||||
 | 
			
		||||
export type ReactVideoPosterSource = ImageURISource | ImageRequireSource;
 | 
			
		||||
 | 
			
		||||
export type ReactVideoPoster = Omit<ImageProps, 'source'> & {
 | 
			
		||||
  // prevents giving source in the array
 | 
			
		||||
  source?: ReactVideoPosterSource;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type VideoMetadata = Readonly<{
 | 
			
		||||
  title?: string;
 | 
			
		||||
  subtitle?: string;
 | 
			
		||||
@@ -243,12 +258,14 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
 | 
			
		||||
  pictureInPicture?: boolean; // iOS
 | 
			
		||||
  playInBackground?: boolean;
 | 
			
		||||
  playWhenInactive?: boolean; // iOS
 | 
			
		||||
  poster?: string;
 | 
			
		||||
  poster?: string | ReactVideoPoster; // string is deprecated
 | 
			
		||||
  /** @deprecated use **resizeMode** key in **poster** props instead */
 | 
			
		||||
  posterResizeMode?: EnumValues<PosterResizeModeType>;
 | 
			
		||||
  preferredForwardBufferDuration?: number; // iOS
 | 
			
		||||
  preventsDisplaySleepDuringVideoPlayback?: boolean;
 | 
			
		||||
  progressUpdateInterval?: number;
 | 
			
		||||
  rate?: number;
 | 
			
		||||
  renderLoader?: ReactNode;
 | 
			
		||||
  repeat?: boolean;
 | 
			
		||||
  reportBandwidth?: boolean; //Android
 | 
			
		||||
  resizeMode?: EnumValues<VideoResizeMode>;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user