react-native-video-player
Version:
A <VideoPlayer /> component for React Native with controls
214 lines (212 loc) • 7.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RenderVideo = void 0;
var _react = require("react");
var _reactNativeVideo = _interopRequireDefault(require("react-native-video"));
var _Controls = require("./controls/Controls.js");
var _reactNative = require("react-native");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const RenderVideo = exports.RenderVideo = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
const {
animationDuration = 100,
autoplay = false,
controlsTimeout = 2000,
customStyles = {},
defaultMuted,
disableControlsAutoHide,
disableFullscreen,
disableSeek,
fullScreenOnLongPress,
hideControlsOnStart = false,
muted,
onEnd,
onHideControls,
onLoad,
onMutePress,
onPlayPress,
onPlaybackStateChanged,
onProgress,
onShowControls,
pauseOnPress,
paused,
repeat = false,
resizeMode = 'contain',
showDuration = false,
source,
style,
sizeStyle
} = props;
const [isPlaying, setIsPlaying] = (0, _react.useState)(autoplay);
const [isMuted, setIsMuted] = (0, _react.useState)(defaultMuted ?? false);
const [isControlsVisible, setIsControlsVisible] = (0, _react.useState)(false);
const [duration, setDuration] = (0, _react.useState)(0);
const videoRef = (0, _react.useRef)(null);
// ref to keeps progress to avoid re-rendering
const progressRef = (0, _react.useRef)(0);
// ref to pass progress to controls (in ref to avoid re-rendering) and to pass when controls wrapper should animate
const controlsRef = (0, _react.useRef)(null);
// ref to keep timeout id to clear it on unmount
const controlsTimeoutRef = (0, _react.useRef)(null);
const setProgress = (0, _react.useCallback)(progress => {
if (!isFinite(progress)) return;
progressRef.current = progress;
controlsRef.current?.onProgress(progress);
}, []);
(0, _react.useImperativeHandle)(ref, () => ({
...videoRef.current,
resume: () => {
setIsPlaying(true);
videoRef.current?.resume();
},
pause: () => {
setIsPlaying(false);
videoRef.current?.pause();
},
stop: () => {
setProgress(0);
videoRef.current?.dismissFullscreenPlayer();
},
onStart: () => {
setIsPlaying(true);
setProgress(progressRef.current >= 1 ? 0 : progressRef.current);
hideControlsOnStart ? _hideControls() : _showControls();
}
}));
const _hideControls = (0, _react.useCallback)(() => {
if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);
controlsTimeoutRef.current = setTimeout(() => {
if (onHideControls) onHideControls();
if (disableControlsAutoHide) return;
controlsRef.current?.runControlsAnimation(0.1, () => {
setIsControlsVisible(false);
setProgress(progressRef.current);
});
}, controlsTimeout);
}, [controlsTimeout, onHideControls, disableControlsAutoHide, setProgress]);
const _showControls = (0, _react.useCallback)(() => {
if (onShowControls && !isControlsVisible) onShowControls();
setIsControlsVisible(true);
_hideControls();
// force re-renders to make sure controls are mounted. ControlsRef is then available and setProgress is called correctly (It fixes the moment when controls are hidden during paused video. After clicking on the screen, controls are shown, but the current duration shows 00)
setTimeout(() => {
setProgress(progressRef.current);
controlsRef.current?.runControlsAnimation(1);
}, 0);
}, [onShowControls, isControlsVisible, _hideControls, setProgress]);
(0, _react.useEffect)(() => {
if (autoplay) _hideControls();
return () => {
if (controlsTimeoutRef.current) {
clearTimeout(controlsTimeoutRef.current);
controlsTimeoutRef.current = null;
}
};
}, [_hideControls, autoplay]);
const _onProgress = (0, _react.useCallback)(event => {
if (onProgress) onProgress(event);
if (isNaN(props?.duration || 0) && isNaN(duration)) {
throw new Error('Could not load video duration correctly, please add `duration` props');
}
setProgress(event.currentTime / (props.duration || duration));
}, [onProgress, props.duration, duration, setProgress]);
const _onEnd = (0, _react.useCallback)(() => {
if (onEnd) onEnd();
setProgress(1);
if (repeat) videoRef.current?.seek(0);
setIsPlaying(repeat);
}, [onEnd, setProgress, repeat]);
const _onLoad = (0, _react.useCallback)(event => {
if (onLoad) onLoad(event);
setDuration(event.duration);
}, [onLoad]);
const _onPlayPress = (0, _react.useCallback)(() => {
if (onPlayPress) onPlayPress();
setIsPlaying(prev => !prev);
if (progressRef.current >= 1) {
videoRef.current?.seek(0);
}
_showControls();
}, [_showControls, onPlayPress]);
const _onMutePress = (0, _react.useCallback)(() => {
const newMutedState = !isMuted;
if (onMutePress) onMutePress(newMutedState);
setIsMuted(newMutedState);
_showControls();
}, [isMuted, onMutePress, _showControls]);
const _onPlaybackStateChanged = (0, _react.useCallback)(data => {
if (onPlaybackStateChanged) onPlaybackStateChanged(data);
if (data.isPlaying !== isPlaying) setIsPlaying(data.isPlaying);
}, [isPlaying, onPlaybackStateChanged]);
const onToggleFullScreen = (0, _react.useCallback)(() => {
videoRef.current?.presentFullscreenPlayer();
}, []);
const seek = (0, _react.useCallback)(progress => {
videoRef.current?.seek(progress);
setProgress(progress / (props.duration || duration));
}, [duration, props.duration, setProgress]);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
style: [{
overflow: 'hidden'
}, customStyles.videoWrapper],
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeVideo.default, {
...props,
ref: videoRef,
style: [styles.video, sizeStyle, style, customStyles.video],
muted: muted || isMuted,
paused: paused || !isPlaying,
onProgress: _onProgress,
onEnd: _onEnd,
onLoad: _onLoad,
source: source,
resizeMode: resizeMode,
onPlaybackStateChanged: _onPlaybackStateChanged
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
style: styles.overlayButton,
onPress: () => {
_showControls();
if (pauseOnPress) _onPlayPress();
},
onLongPress: () => {
if (fullScreenOnLongPress) onToggleFullScreen();
}
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Controls.Controls, {
ref: controlsRef,
customStyles: customStyles,
showDuration: showDuration,
disableFullscreen: disableFullscreen,
duration: props.duration || duration,
isPlaying: isPlaying,
isMuted: isMuted,
onPlayPress: _onPlayPress,
onMutePress: _onMutePress,
onToggleFullScreen: onToggleFullScreen,
animationDuration: animationDuration,
showControls: _showControls,
autoplay: autoplay,
disableSeek: disableSeek,
setIsPlaying: setIsPlaying,
onSeek: seek,
controlsTimeoutId: controlsTimeoutRef.current,
isControlsVisible: isControlsVisible
})]
});
}));
const styles = _reactNative.StyleSheet.create({
video: +_reactNative.Platform.Version >= 24 ? {} : {
backgroundColor: 'black'
},
controls: {
backgroundColor: 'rgba(0, 0, 0, 0.6)',
height: 48,
marginTop: -48,
flexDirection: 'row',
alignItems: 'center'
},
overlayButton: {
..._reactNative.StyleSheet.absoluteFillObject
}
});
//# sourceMappingURL=Video.js.map