feat: add ability to define poster props as Image type and render poster as custom component (#3972)
This commit is contained in:
113
src/Video.tsx
113
src/Video.tsx
@@ -8,7 +8,13 @@ import React, {
|
||||
} from 'react';
|
||||
import type {ElementRef} from 'react';
|
||||
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 type {
|
||||
@@ -67,8 +73,9 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
source,
|
||||
style,
|
||||
resizeMode,
|
||||
posterResizeMode,
|
||||
poster,
|
||||
posterResizeMode,
|
||||
renderLoader,
|
||||
drm,
|
||||
textTracks,
|
||||
selectedVideoTrack,
|
||||
@@ -113,25 +120,28 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
ref,
|
||||
) => {
|
||||
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 [
|
||||
_restoreUserInterfaceForPIPStopCompletionHandler,
|
||||
setRestoreUserInterfaceForPIPStopCompletionHandler,
|
||||
] = 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>(() => {
|
||||
if (!source) {
|
||||
return undefined;
|
||||
@@ -598,13 +608,78 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
: ViewType.SURFACE;
|
||||
}, [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 (
|
||||
<View style={style}>
|
||||
<NativeVideoComponent
|
||||
ref={nativeRef}
|
||||
{...rest}
|
||||
src={src}
|
||||
style={StyleSheet.absoluteFill}
|
||||
style={_style}
|
||||
resizeMode={resizeMode}
|
||||
restoreUserInterfaceForPIPStopCompletionHandler={
|
||||
_restoreUserInterfaceForPIPStopCompletionHandler
|
||||
@@ -679,9 +754,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
}
|
||||
viewType={_viewType}
|
||||
/>
|
||||
{hasPoster && showPoster ? (
|
||||
<Image style={posterStyle} source={{uri: poster}} />
|
||||
) : null}
|
||||
{_renderPoster()}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user