fix(JS): improve loader api to allow function call instead of component (#4171)

This commit is contained in:
Olivier Bouillet 2024-09-17 15:58:47 +02:00 committed by GitHub
parent 7f6b500c82
commit 835186a321
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 68 additions and 20 deletions

View File

@ -518,14 +518,29 @@ Speed at which the media should play.
<PlatformsList types={['All']} /> <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. Allows you to create custom components to display while the video is loading.
If `renderLoader` is provided, `poster` and `posterResizeMode` will be ignored.
renderLoader is either a component or a function returning a component.
It is recommended to use the function for optimization matter.
`renderLoader` function be called with parameters of type `ReactVideoRenderLoaderProps` to be able to adapt loader
```typescript
interface ReactVideoRenderLoaderProps {
source?: ReactVideoSource; /// source of the video
style?: StyleProp<ImageStyle>; /// style to apply
resizeMode?: EnumValues<VideoResizeMode>; /// resizeMode provided to the video component
}
````
Sample:
```javascript ```javascript
<Video> <Video>
renderLoader={ renderLoader={() => (
<View> <View>
<Text>Custom Loader</Text> <Text>Custom Loader</Text>
</View> </View>)
} }
</Video> </Video>
```` ````

View File

@ -236,6 +236,18 @@ const VideoPlayer: FC<Props> = ({}) => {
Platform.OS === 'ios' && setPaused(true); Platform.OS === 'ios' && setPaused(true);
}; };
const _renderLoader = showPoster ? () => <VideoLoader /> : undefined;
const _subtitleStyle = {subtitlesFollowVideo: true};
const _controlsStyles = {
hideNavigationBarOnFullScreenMode: true,
hideNotificationBarOnFullScreenMode: true,
};
const _bufferConfig = {
...bufferConfig,
cacheSizeMB: useCache ? 200 : 0,
}
return ( return (
<View style={styles.container}> <View style={styles.container}>
<StatusBar animated={true} backgroundColor="black" hidden={false} /> <StatusBar animated={true} backgroundColor="black" hidden={false} />
@ -278,21 +290,15 @@ const VideoPlayer: FC<Props> = ({}) => {
selectedAudioTrack={selectedAudioTrack} selectedAudioTrack={selectedAudioTrack}
selectedVideoTrack={selectedVideoTrack} selectedVideoTrack={selectedVideoTrack}
playInBackground={false} playInBackground={false}
bufferConfig={{ bufferConfig={_bufferConfig}
...bufferConfig,
cacheSizeMB: useCache ? 200 : 0,
}}
preventsDisplaySleepDuringVideoPlayback={true} preventsDisplaySleepDuringVideoPlayback={true}
renderLoader={showPoster ? <VideoLoader /> : undefined} renderLoader={_renderLoader}
onPlaybackRateChange={onPlaybackRateChange} onPlaybackRateChange={onPlaybackRateChange}
onPlaybackStateChanged={onPlaybackStateChanged} onPlaybackStateChanged={onPlaybackStateChanged}
bufferingStrategy={BufferingStrategyType.DEFAULT} bufferingStrategy={BufferingStrategyType.DEFAULT}
debug={{enable: true, thread: true}} debug={{enable: true, thread: true}}
subtitleStyle={{subtitlesFollowVideo: true}} subtitleStyle={_subtitleStyle}
controlsStyles={{ controlsStyles={_controlsStyles}
hideNavigationBarOnFullScreenMode: true,
hideNotificationBarOnFullScreenMode: true,
}}
/> />
</TouchableOpacity> </TouchableOpacity>
)} )}

View File

@ -127,8 +127,18 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
const isPosterDeprecated = typeof poster === 'string'; const isPosterDeprecated = typeof poster === 'string';
const _renderLoader = useMemo(
() =>
!renderLoader
? undefined
: renderLoader instanceof Function
? renderLoader
: () => renderLoader,
[renderLoader],
);
const hasPoster = useMemo(() => { const hasPoster = useMemo(() => {
if (renderLoader) { if (_renderLoader) {
return true; return true;
} }
@ -137,7 +147,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
} }
return !!poster?.source; return !!poster?.source;
}, [isPosterDeprecated, poster, renderLoader]); }, [isPosterDeprecated, poster, _renderLoader]);
const [showPoster, setShowPoster] = useState(hasPoster); const [showPoster, setShowPoster] = useState(hasPoster);
@ -688,15 +698,23 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
} }
// render poster // render poster
if (renderLoader && (poster || posterResizeMode)) { if (_renderLoader && (poster || posterResizeMode)) {
console.warn( console.warn(
'You provided both `renderLoader` and `poster` or `posterResizeMode` props. `renderLoader` will be used.', 'You provided both `renderLoader` and `poster` or `posterResizeMode` props. `renderLoader` will be used.',
); );
} }
// render loader // render loader
if (renderLoader) { if (_renderLoader) {
return <View style={StyleSheet.absoluteFill}>{renderLoader}</View>; return (
<View style={StyleSheet.absoluteFill}>
{_renderLoader({
source: source,
style: posterStyle,
resizeMode: resizeMode,
})}
</View>
);
} }
return ( return (
@ -711,8 +729,10 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
isPosterDeprecated, isPosterDeprecated,
poster, poster,
posterResizeMode, posterResizeMode,
renderLoader, _renderLoader,
showPoster, showPoster,
source,
resizeMode,
]); ]);
const _style: StyleProp<ViewStyle> = useMemo( const _style: StyleProp<ViewStyle> = useMemo(

View File

@ -7,6 +7,7 @@ import type {
ViewStyle, ViewStyle,
ImageRequireSource, ImageRequireSource,
ImageURISource, ImageURISource,
ImageStyle,
} from 'react-native'; } from 'react-native';
import type {ReactNode} from 'react'; import type {ReactNode} from 'react';
import type VideoResizeMode from './ResizeMode'; import type VideoResizeMode from './ResizeMode';
@ -254,6 +255,12 @@ export type ControlsStyles = {
hideNotificationBarOnFullScreenMode?: boolean; hideNotificationBarOnFullScreenMode?: boolean;
}; };
export interface ReactVideoRenderLoaderProps {
source?: ReactVideoSource;
style?: StyleProp<ImageStyle>;
resizeMode?: EnumValues<VideoResizeMode>;
}
export interface ReactVideoProps extends ReactVideoEvents, ViewProps { export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
source?: ReactVideoSource; source?: ReactVideoSource;
/** @deprecated Use source.drm */ /** @deprecated Use source.drm */
@ -295,7 +302,7 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
preventsDisplaySleepDuringVideoPlayback?: boolean; preventsDisplaySleepDuringVideoPlayback?: boolean;
progressUpdateInterval?: number; progressUpdateInterval?: number;
rate?: number; rate?: number;
renderLoader?: ReactNode; renderLoader?: ReactNode | ((arg0: ReactVideoRenderLoaderProps) => ReactNode);
repeat?: boolean; repeat?: boolean;
reportBandwidth?: boolean; //Android reportBandwidth?: boolean; //Android
resizeMode?: EnumValues<VideoResizeMode>; resizeMode?: EnumValues<VideoResizeMode>;