Skip to content

Commit

Permalink
fix(JS): improve loader api to allow function call instead of compone…
Browse files Browse the repository at this point in the history
…nt (#4171)
  • Loading branch information
freeboub authored Sep 17, 2024
1 parent 7f6b500 commit 835186a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 20 deletions.
21 changes: 18 additions & 3 deletions docs/pages/component/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
````
Expand Down
26 changes: 16 additions & 10 deletions examples/basic/src/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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} />
Expand Down Expand Up @@ -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>
)}
Expand Down
32 changes: 26 additions & 6 deletions src/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -137,7 +147,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
}

return !!poster?.source;
}, [isPosterDeprecated, poster, renderLoader]);
}, [isPosterDeprecated, poster, _renderLoader]);

const [showPoster, setShowPoster] = useState(hasPoster);

Expand Down Expand Up @@ -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 (
Expand All @@ -711,8 +729,10 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
isPosterDeprecated,
poster,
posterResizeMode,
renderLoader,
_renderLoader,
showPoster,
source,
resizeMode,
]);

const _style: StyleProp<ViewStyle> = useMemo(
Expand Down
9 changes: 8 additions & 1 deletion src/types/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
ViewStyle,
ImageRequireSource,
ImageURISource,
ImageStyle,
} from 'react-native';
import type {ReactNode} from 'react';
import type VideoResizeMode from './ResizeMode';
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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>;
Expand Down

0 comments on commit 835186a

Please sign in to comment.