UNPKG

@zezosoft/zezo-ott-react-native-video-player

Version:

React Native OTT Video Player for Android & iOS. Supports playlists, seasons, auto-next playback, subtitles, theming, analytics, fullscreen mode, and custom controls. 🚀 Powered by ZezoSoft.

180 lines (178 loc) • 5.88 kB
"use strict"; import React, { useCallback, useEffect } from 'react'; import { AppState, StyleSheet, View } from 'react-native'; import Video from 'react-native-video'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'; import { runOnJS } from 'react-native-reanimated'; import { videoRef } from "./utils/videoRef.js"; import { lockToLandscape, lockToPortrait } from "./utils/lockOrientation.js"; import { getVideoSource, handlePause } from "./utils/index.js"; import MediaControlsProvider from "./MediaControls/MediaControlsProvider.js"; import { useVideoPlayerStore } from "./store/videoPlayerStore.js"; import { createPlayerEvents } from "./utils/playerEvents.js"; import globalStyles from "./Styles/globalStyles.js"; import { VideoPlayerConfigProvider } from "./context/index.js"; import { useWatchReporter } from "./utils/useWatchReporter.js"; import { jsx as _jsx } from "react/jsx-runtime"; const controlsStyles = { hideForward: true, hideDuration: true, hideFullscreen: true, hidePlayPause: true, hideNavigationBarOnFullScreenMode: true, hideNotificationBarOnFullScreenMode: true, hideNext: true, hidePosition: true, hidePrevious: true, hideRewind: true, hideSeekBar: true, hideSettingButton: true }; const VideoPlayer = ({ onClose, isFocused = true, mode = 'fullscreen', seekTime, event, autoNext = true, theme, onWatchProgress }) => { const { isPaused, resizeMode, setResizeMode, setControlsVisible, controlsVisible, playBackRate, selectedAudioTrack, selectedSubtitleTrack, maxBitRate, selectedVideoTrack, setIsPaused, playList, currentTrackIndex, activeTrack, setError } = useVideoPlayerStore(); const playerEvents = createPlayerEvents(); const { reportProgress } = useWatchReporter({ onWatchProgress }); useEffect(() => { if (isFocused) { if (mode === 'fullscreen') { lockToLandscape(); } else { lockToPortrait(); } } else { lockToPortrait(); } }, [isFocused, mode]); const handleCombinedProgress = useCallback(progressEvent => { playerEvents.onProgress(progressEvent); }, [playerEvents]); useEffect(() => { if (seekTime && !activeTrack?.isTrailer && videoRef?.current) { videoRef.current?.seek(seekTime); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [seekTime, videoRef?.current]); useEffect(() => { const handleAppStateChange = nextState => { if (nextState === 'inactive' || nextState === 'background') { handlePause(); setIsPaused(true); reportProgress('PROGRESS'); } }; const sub = AppState.addEventListener('change', handleAppStateChange); return () => sub.remove(); }, [reportProgress, setIsPaused]); const trigger = type => { switch (type) { case 'Pinch': if (resizeMode === 'cover') { setResizeMode('contain'); } else { setResizeMode('cover'); } break; case 'Tap': { setControlsVisible(!controlsVisible); } } }; const composedGestures = Gesture.Race(Gesture.Pinch().onEnd(() => runOnJS(trigger)('Pinch')), Gesture.Tap().onEnd(() => runOnJS(trigger)('Tap'))); return /*#__PURE__*/_jsx(VideoPlayerConfigProvider, { theme: theme, children: /*#__PURE__*/_jsx(SafeAreaProvider, { style: globalStyles.flexOne, children: /*#__PURE__*/_jsx(GestureHandlerRootView, { style: globalStyles.flexOne, children: /*#__PURE__*/_jsx(MediaControlsProvider, { onClose: () => { reportProgress('VIDEO_CLOSE'); onClose?.(); }, onPressEpisode: async ({ episode }) => { if (event?.onPressEpisode) { return await event.onPressEpisode({ episode }); } return Promise.resolve(true); }, reportProgress: reportProgress, children: /*#__PURE__*/_jsx(GestureDetector, { gesture: composedGestures, children: /*#__PURE__*/_jsx(View, { style: globalStyles.flexOneWithBlackBackground, children: /*#__PURE__*/_jsx(Video, { ref: videoRef, source: getVideoSource({ playList, currentTrackIndex }), paused: isPaused, onProgress: handleCombinedProgress, onLoad: playerEvents.onLoad, onBuffer: playerEvents.onBuffer, onEnd: () => { playerEvents.onEnd({ reportProgress, onPressEpisode: event?.onPressEpisode ?? (async () => true), autoNext }); }, onLoadStart: playerEvents.onLoadStart, onError: () => setError("Video couldn't be loaded"), controls: false, resizeMode: resizeMode || 'contain', rate: playBackRate || 1, selectedAudioTrack: selectedAudioTrack, selectedTextTrack: selectedSubtitleTrack?.value === 'Off' ? undefined : selectedSubtitleTrack, selectedVideoTrack: selectedVideoTrack ? { type: selectedVideoTrack.type, value: selectedVideoTrack.value } : undefined, maxBitRate: maxBitRate ?? undefined, style: StyleSheet.absoluteFillObject, controlsStyles: controlsStyles }) }) }) }) }) }) }); }; export default VideoPlayer; //# sourceMappingURL=VideoPlayer.js.map