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']} />
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
<Video>
renderLoader={
renderLoader={() => (
<View>
<Text>Custom Loader</Text>
</View>
</View>)
}
</Video>
````

View File

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

View File

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

View File

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