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` | ### `poster` | ||||||
|  |  | ||||||
| <PlatformsList types={['All']} /> | <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 | 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` | ### `posterResizeMode` | ||||||
|  | > [!WARNING] | ||||||
|  | > deprecated, use `poster` with `resizeMode` key instead | ||||||
| <PlatformsList types={['All']} /> | <PlatformsList types={['All']} /> | ||||||
|  |  | ||||||
| Determines how to resize the poster image when the frame doesn't match the raw video dimensions. | 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) | - **1.0** - Play at normal speed (default) | ||||||
| - **Other values** - Slow down or speed up playback | - **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` | ### `repeat` | ||||||
|  |  | ||||||
| <PlatformsList types={['All']} /> | <PlatformsList types={['All']} /> | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ import Video, { | |||||||
| import styles from './styles'; | import styles from './styles'; | ||||||
| import {type AdditionalSourceInfo} from './types'; | import {type AdditionalSourceInfo} from './types'; | ||||||
| import {bufferConfig, srcList, textTracksSelectionBy} from './constants'; | import {bufferConfig, srcList, textTracksSelectionBy} from './constants'; | ||||||
| import {Overlay, toast} from './components'; | import {Overlay, toast, VideoLoader} from './components'; | ||||||
|  |  | ||||||
| type Props = NonNullable<unknown>; | type Props = NonNullable<unknown>; | ||||||
|  |  | ||||||
| @@ -68,7 +68,7 @@ const VideoPlayer: FC<Props> = ({}) => { | |||||||
|   const [repeat, setRepeat] = useState(false); |   const [repeat, setRepeat] = useState(false); | ||||||
|   const [controls, setControls] = useState(false); |   const [controls, setControls] = useState(false); | ||||||
|   const [useCache, setUseCache] = useState(false); |   const [useCache, setUseCache] = useState(false); | ||||||
|   const [poster, setPoster] = useState<string | undefined>(undefined); |   const [showPoster, setShowPoster] = useState<boolean>(false); | ||||||
|   const [showNotificationControls, setShowNotificationControls] = |   const [showNotificationControls, setShowNotificationControls] = | ||||||
|     useState(false); |     useState(false); | ||||||
|   const [isSeeking, setIsSeeking] = useState(false); |   const [isSeeking, setIsSeeking] = useState(false); | ||||||
| @@ -234,7 +234,6 @@ const VideoPlayer: FC<Props> = ({}) => { | |||||||
|             paused={paused} |             paused={paused} | ||||||
|             volume={volume} |             volume={volume} | ||||||
|             muted={muted} |             muted={muted} | ||||||
|             fullscreen={fullscreen} |  | ||||||
|             controls={controls} |             controls={controls} | ||||||
|             resizeMode={resizeMode} |             resizeMode={resizeMode} | ||||||
|             onFullscreenPlayerWillDismiss={onFullScreenExit} |             onFullscreenPlayerWillDismiss={onFullScreenExit} | ||||||
| @@ -264,7 +263,7 @@ const VideoPlayer: FC<Props> = ({}) => { | |||||||
|               cacheSizeMB: useCache ? 200 : 0, |               cacheSizeMB: useCache ? 200 : 0, | ||||||
|             }} |             }} | ||||||
|             preventsDisplaySleepDuringVideoPlayback={true} |             preventsDisplaySleepDuringVideoPlayback={true} | ||||||
|             poster={poster} |             renderLoader={showPoster ? <VideoLoader /> : undefined} | ||||||
|             onPlaybackRateChange={onPlaybackRateChange} |             onPlaybackRateChange={onPlaybackRateChange} | ||||||
|             onPlaybackStateChanged={onPlaybackStateChanged} |             onPlaybackStateChanged={onPlaybackStateChanged} | ||||||
|             bufferingStrategy={BufferingStrategyType.DEFAULT} |             bufferingStrategy={BufferingStrategyType.DEFAULT} | ||||||
| @@ -294,7 +293,7 @@ const VideoPlayer: FC<Props> = ({}) => { | |||||||
|         paused={paused} |         paused={paused} | ||||||
|         volume={volume} |         volume={volume} | ||||||
|         setControls={setControls} |         setControls={setControls} | ||||||
|         poster={poster} |         showPoster={showPoster} | ||||||
|         rate={rate} |         rate={rate} | ||||||
|         setFullscreen={setFullscreen} |         setFullscreen={setFullscreen} | ||||||
|         setPaused={setPaused} |         setPaused={setPaused} | ||||||
| @@ -303,7 +302,7 @@ const VideoPlayer: FC<Props> = ({}) => { | |||||||
|         setIsSeeking={setIsSeeking} |         setIsSeeking={setIsSeeking} | ||||||
|         repeat={repeat} |         repeat={repeat} | ||||||
|         setRepeat={setRepeat} |         setRepeat={setRepeat} | ||||||
|         setPoster={setPoster} |         setShowPoster={setShowPoster} | ||||||
|         setRate={setRate} |         setRate={setRate} | ||||||
|         setResizeMode={setResizeMode} |         setResizeMode={setResizeMode} | ||||||
|         setShowNotificationControls={setShowNotificationControls} |         setShowNotificationControls={setShowNotificationControls} | ||||||
|   | |||||||
| @@ -1,22 +1,8 @@ | |||||||
| import React, {FC, memo} from 'react'; | import React, {memo} from 'react'; | ||||||
| import {ActivityIndicator, View} from 'react-native'; | import {ActivityIndicator} from 'react-native'; | ||||||
| import styles from '../styles.tsx'; |  | ||||||
|  |  | ||||||
| type Props = { | const _Indicator = () => { | ||||||
|   isLoading: boolean; |   return <ActivityIndicator color="#3235fd" size="large" />; | ||||||
| }; |  | ||||||
|  |  | ||||||
| const _Indicator: FC<Props> = ({isLoading}) => { |  | ||||||
|   if (!isLoading) { |  | ||||||
|     return <View />; |  | ||||||
|   } |  | ||||||
|   return ( |  | ||||||
|     <ActivityIndicator |  | ||||||
|       color="#3235fd" |  | ||||||
|       size="large" |  | ||||||
|       style={styles.IndicatorStyle} |  | ||||||
|     /> |  | ||||||
|   ); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const Indicator = memo(_Indicator); | export const Indicator = memo(_Indicator); | ||||||
|   | |||||||
| @@ -5,19 +5,11 @@ import React, { | |||||||
|   type Dispatch, |   type Dispatch, | ||||||
|   type SetStateAction, |   type SetStateAction, | ||||||
| } from 'react'; | } from 'react'; | ||||||
| import {Indicator} from './Indicator.tsx'; |  | ||||||
| import {View} from 'react-native'; | import {View} from 'react-native'; | ||||||
| import styles from '../styles.tsx'; | import styles from '../styles.tsx'; | ||||||
| import ToggleControl from '../ToggleControl.tsx'; | import ToggleControl from '../ToggleControl.tsx'; | ||||||
| import { | import {isAndroid, isIos, textTracksSelectionBy} from '../constants'; | ||||||
|   isAndroid, | import MultiValueControl from '../MultiValueControl.tsx'; | ||||||
|   isIos, |  | ||||||
|   samplePoster, |  | ||||||
|   textTracksSelectionBy, |  | ||||||
| } from '../constants'; |  | ||||||
| import MultiValueControl, { |  | ||||||
|   type MultiValueControlPropType, |  | ||||||
| } from '../MultiValueControl.tsx'; |  | ||||||
| import { | import { | ||||||
|   ResizeMode, |   ResizeMode, | ||||||
|   VideoRef, |   VideoRef, | ||||||
| @@ -69,8 +61,8 @@ type Props = { | |||||||
|   setPaused: Dispatch<SetStateAction<boolean>>; |   setPaused: Dispatch<SetStateAction<boolean>>; | ||||||
|   repeat: boolean; |   repeat: boolean; | ||||||
|   setRepeat: Dispatch<SetStateAction<boolean>>; |   setRepeat: Dispatch<SetStateAction<boolean>>; | ||||||
|   poster: string | undefined; |   showPoster: boolean; | ||||||
|   setPoster: Dispatch<SetStateAction<string | undefined>>; |   setShowPoster: Dispatch<SetStateAction<boolean>>; | ||||||
|   muted: boolean; |   muted: boolean; | ||||||
|   setMuted: Dispatch<SetStateAction<boolean>>; |   setMuted: Dispatch<SetStateAction<boolean>>; | ||||||
|   currentTime: number; |   currentTime: number; | ||||||
| @@ -108,8 +100,8 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => { | |||||||
|     setPaused, |     setPaused, | ||||||
|     setRepeat, |     setRepeat, | ||||||
|     repeat, |     repeat, | ||||||
|     setPoster, |     setShowPoster, | ||||||
|     poster, |     showPoster, | ||||||
|     setMuted, |     setMuted, | ||||||
|     muted, |     muted, | ||||||
|     duration, |     duration, | ||||||
| @@ -217,14 +209,12 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => { | |||||||
|  |  | ||||||
|   const toggleRepeat = () => setRepeat(prev => !prev); |   const toggleRepeat = () => setRepeat(prev => !prev); | ||||||
|  |  | ||||||
|   const togglePoster = () => |   const togglePoster = () => setShowPoster(prev => !prev); | ||||||
|     setPoster(prev => (prev ? undefined : samplePoster)); |  | ||||||
|  |  | ||||||
|   const toggleMuted = () => setMuted(prev => !prev); |   const toggleMuted = () => setMuted(prev => !prev); | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <Indicator isLoading={isLoading} /> |  | ||||||
|       <View style={styles.topControls}> |       <View style={styles.topControls}> | ||||||
|         <View style={styles.resizeModeControl}> |         <View style={styles.resizeModeControl}> | ||||||
|           <TopControl |           <TopControl | ||||||
| @@ -270,7 +260,7 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => { | |||||||
|               <ToggleControl onPress={toggleFullscreen} text="fullscreen" /> |               <ToggleControl onPress={toggleFullscreen} text="fullscreen" /> | ||||||
|               <ToggleControl onPress={openDecoration} text="decoration" /> |               <ToggleControl onPress={openDecoration} text="decoration" /> | ||||||
|               <ToggleControl |               <ToggleControl | ||||||
|                 isSelected={!!poster} |                 isSelected={showPoster} | ||||||
|                 onPress={togglePoster} |                 onPress={togglePoster} | ||||||
|                 selectedText="poster" |                 selectedText="poster" | ||||||
|                 unselectedText="no 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 './Indicator'; | ||||||
| export * from './Seeker'; | export * from './Seeker'; | ||||||
| export * from './AudioTracksSelector'; | 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( | export const srcList: SampleVideoSource[] = srcAllPlatformList.concat( | ||||||
|   isAndroid ? srcAndroidList : srcIosList, |   isAndroid ? srcAndroidList : srcIosList, | ||||||
| ); | ); | ||||||
|   | |||||||
| @@ -102,9 +102,15 @@ const styles = StyleSheet.create({ | |||||||
|     borderWidth: 1, |     borderWidth: 1, | ||||||
|     borderColor: 'red', |     borderColor: 'red', | ||||||
|   }, |   }, | ||||||
|   IndicatorStyle: { |   indicatorContainer: { | ||||||
|     flex: 1, |  | ||||||
|     justifyContent: 'center', |     justifyContent: 'center', | ||||||
|  |     alignItems: 'center', | ||||||
|  |     gap: 10, | ||||||
|  |     width: '100%', | ||||||
|  |     height: '100%', | ||||||
|  |   }, | ||||||
|  |   indicatorText: { | ||||||
|  |     color: 'white', | ||||||
|   }, |   }, | ||||||
|   seekbarContainer: { |   seekbarContainer: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|   | |||||||
							
								
								
									
										113
									
								
								src/Video.tsx
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/Video.tsx
									
									
									
									
									
								
							| @@ -8,7 +8,13 @@ import React, { | |||||||
| } from 'react'; | } from 'react'; | ||||||
| import type {ElementRef} from 'react'; | import type {ElementRef} from 'react'; | ||||||
| import {View, StyleSheet, Image, Platform, processColor} from 'react-native'; | 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 NativeVideoComponent from './specs/VideoNativeComponent'; | ||||||
| import type { | import type { | ||||||
| @@ -67,8 +73,9 @@ const Video = forwardRef<VideoRef, ReactVideoProps>( | |||||||
|       source, |       source, | ||||||
|       style, |       style, | ||||||
|       resizeMode, |       resizeMode, | ||||||
|       posterResizeMode, |  | ||||||
|       poster, |       poster, | ||||||
|  |       posterResizeMode, | ||||||
|  |       renderLoader, | ||||||
|       drm, |       drm, | ||||||
|       textTracks, |       textTracks, | ||||||
|       selectedVideoTrack, |       selectedVideoTrack, | ||||||
| @@ -113,25 +120,28 @@ const Video = forwardRef<VideoRef, ReactVideoProps>( | |||||||
|     ref, |     ref, | ||||||
|   ) => { |   ) => { | ||||||
|     const nativeRef = useRef<ElementRef<typeof NativeVideoComponent>>(null); |     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 [ |     const [ | ||||||
|       _restoreUserInterfaceForPIPStopCompletionHandler, |       _restoreUserInterfaceForPIPStopCompletionHandler, | ||||||
|       setRestoreUserInterfaceForPIPStopCompletionHandler, |       setRestoreUserInterfaceForPIPStopCompletionHandler, | ||||||
|     ] = useState<boolean | undefined>(); |     ] = 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>(() => { |     const src = useMemo<VideoSrc | undefined>(() => { | ||||||
|       if (!source) { |       if (!source) { | ||||||
|         return undefined; |         return undefined; | ||||||
| @@ -598,13 +608,78 @@ const Video = forwardRef<VideoRef, ReactVideoProps>( | |||||||
|         : ViewType.SURFACE; |         : ViewType.SURFACE; | ||||||
|     }, [drm, useSecureView, useTextureView, viewType]); |     }, [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 ( |     return ( | ||||||
|       <View style={style}> |       <View style={style}> | ||||||
|         <NativeVideoComponent |         <NativeVideoComponent | ||||||
|           ref={nativeRef} |           ref={nativeRef} | ||||||
|           {...rest} |           {...rest} | ||||||
|           src={src} |           src={src} | ||||||
|           style={StyleSheet.absoluteFill} |           style={_style} | ||||||
|           resizeMode={resizeMode} |           resizeMode={resizeMode} | ||||||
|           restoreUserInterfaceForPIPStopCompletionHandler={ |           restoreUserInterfaceForPIPStopCompletionHandler={ | ||||||
|             _restoreUserInterfaceForPIPStopCompletionHandler |             _restoreUserInterfaceForPIPStopCompletionHandler | ||||||
| @@ -679,9 +754,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>( | |||||||
|           } |           } | ||||||
|           viewType={_viewType} |           viewType={_viewType} | ||||||
|         /> |         /> | ||||||
|         {hasPoster && showPoster ? ( |         {_renderPoster()} | ||||||
|           <Image style={posterStyle} source={{uri: poster}} /> |  | ||||||
|         ) : null} |  | ||||||
|       </View> |       </View> | ||||||
|     ); |     ); | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -1,6 +1,14 @@ | |||||||
| import type {ISO639_1} from './language'; | import type {ISO639_1} from './language'; | ||||||
| import type {ReactVideoEvents} from './events'; | 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 VideoResizeMode from './ResizeMode'; | ||||||
| import type FilterType from './FilterType'; | import type FilterType from './FilterType'; | ||||||
| import type ViewType from './ViewType'; | 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<{ | export type VideoMetadata = Readonly<{ | ||||||
|   title?: string; |   title?: string; | ||||||
|   subtitle?: string; |   subtitle?: string; | ||||||
| @@ -243,12 +258,14 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps { | |||||||
|   pictureInPicture?: boolean; // iOS |   pictureInPicture?: boolean; // iOS | ||||||
|   playInBackground?: boolean; |   playInBackground?: boolean; | ||||||
|   playWhenInactive?: boolean; // iOS |   playWhenInactive?: boolean; // iOS | ||||||
|   poster?: string; |   poster?: string | ReactVideoPoster; // string is deprecated | ||||||
|  |   /** @deprecated use **resizeMode** key in **poster** props instead */ | ||||||
|   posterResizeMode?: EnumValues<PosterResizeModeType>; |   posterResizeMode?: EnumValues<PosterResizeModeType>; | ||||||
|   preferredForwardBufferDuration?: number; // iOS |   preferredForwardBufferDuration?: number; // iOS | ||||||
|   preventsDisplaySleepDuringVideoPlayback?: boolean; |   preventsDisplaySleepDuringVideoPlayback?: boolean; | ||||||
|   progressUpdateInterval?: number; |   progressUpdateInterval?: number; | ||||||
|   rate?: number; |   rate?: number; | ||||||
|  |   renderLoader?: ReactNode; | ||||||
|   repeat?: boolean; |   repeat?: boolean; | ||||||
|   reportBandwidth?: boolean; //Android |   reportBandwidth?: boolean; //Android | ||||||
|   resizeMode?: EnumValues<VideoResizeMode>; |   resizeMode?: EnumValues<VideoResizeMode>; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user