From 835186a321e1940932a045a59e26e43a040fa334 Mon Sep 17 00:00:00 2001
From: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>
Date: Tue, 17 Sep 2024 15:58:47 +0200
Subject: [PATCH] fix(JS): improve loader api to allow function call instead of
component (#4171)
---
docs/pages/component/props.mdx | 21 +++++++++++++++++---
examples/basic/src/VideoPlayer.tsx | 26 ++++++++++++++----------
src/Video.tsx | 32 ++++++++++++++++++++++++------
src/types/video.ts | 9 ++++++++-
4 files changed, 68 insertions(+), 20 deletions(-)
diff --git a/docs/pages/component/props.mdx b/docs/pages/component/props.mdx
index 184f7c60..21298868 100644
--- a/docs/pages/component/props.mdx
+++ b/docs/pages/component/props.mdx
@@ -518,14 +518,29 @@ Speed at which the media should play.
-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; /// style to apply
+ resizeMode?: EnumValues; /// resizeMode provided to the video component
+}
+````
+
+Sample:
```javascript
````
diff --git a/examples/basic/src/VideoPlayer.tsx b/examples/basic/src/VideoPlayer.tsx
index 71aa654e..6381f34b 100644
--- a/examples/basic/src/VideoPlayer.tsx
+++ b/examples/basic/src/VideoPlayer.tsx
@@ -236,6 +236,18 @@ const VideoPlayer: FC = ({}) => {
Platform.OS === 'ios' && setPaused(true);
};
+ const _renderLoader = showPoster ? () => : undefined;
+
+ const _subtitleStyle = {subtitlesFollowVideo: true};
+ const _controlsStyles = {
+ hideNavigationBarOnFullScreenMode: true,
+ hideNotificationBarOnFullScreenMode: true,
+ };
+ const _bufferConfig = {
+ ...bufferConfig,
+ cacheSizeMB: useCache ? 200 : 0,
+ }
+
return (
@@ -278,21 +290,15 @@ const VideoPlayer: FC = ({}) => {
selectedAudioTrack={selectedAudioTrack}
selectedVideoTrack={selectedVideoTrack}
playInBackground={false}
- bufferConfig={{
- ...bufferConfig,
- cacheSizeMB: useCache ? 200 : 0,
- }}
+ bufferConfig={_bufferConfig}
preventsDisplaySleepDuringVideoPlayback={true}
- renderLoader={showPoster ? : 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}
/>
)}
diff --git a/src/Video.tsx b/src/Video.tsx
index 66f11179..c1f251a1 100644
--- a/src/Video.tsx
+++ b/src/Video.tsx
@@ -127,8 +127,18 @@ const Video = forwardRef(
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(
}
return !!poster?.source;
- }, [isPosterDeprecated, poster, renderLoader]);
+ }, [isPosterDeprecated, poster, _renderLoader]);
const [showPoster, setShowPoster] = useState(hasPoster);
@@ -688,15 +698,23 @@ const Video = forwardRef(
}
// 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 {renderLoader};
+ if (_renderLoader) {
+ return (
+
+ {_renderLoader({
+ source: source,
+ style: posterStyle,
+ resizeMode: resizeMode,
+ })}
+
+ );
}
return (
@@ -711,8 +729,10 @@ const Video = forwardRef(
isPosterDeprecated,
poster,
posterResizeMode,
- renderLoader,
+ _renderLoader,
showPoster,
+ source,
+ resizeMode,
]);
const _style: StyleProp = useMemo(
diff --git a/src/types/video.ts b/src/types/video.ts
index 8aa9b8d8..71304080 100644
--- a/src/types/video.ts
+++ b/src/types/video.ts
@@ -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;
+ resizeMode?: EnumValues;
+}
+
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;