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.

193 lines (164 loc) β€’ 4.78 kB
import { mmkvStorage, useVideoPlayerStore } from '../store/videoPlayerStore'; import type { MediaEpisode } from '../store/videoPlayer.type'; export const handlePause = () => { const { setIsPaused, startWatchTime, setStartWatchTime } = useVideoPlayerStore.getState(); setIsPaused(true); if (!startWatchTime) return; const elapsedTime = (Date.now() - startWatchTime) / 1000; const storedTime = Number(mmkvStorage.getItem('current_watch_time') ?? 0); mmkvStorage.setItem( 'current_watch_time', (storedTime + elapsedTime).toString() ); setStartWatchTime(null); }; interface HandleNextOptions { onPressEpisode: ({ episode }: { episode: MediaEpisode }) => Promise<boolean>; autoNext?: boolean; } export const handleNext = async ({ onPressEpisode, autoNext, }: HandleNextOptions): Promise<number | null> => { const { playList: playlist, currentTrackIndex, setCurrentTrackIndex, setActiveTrack, setCurrentTime, setIsPaused, setActiveSubtitle, setPlayBackRate, contentSeasons, setActiveSeason, setControlsVisible, setSelectedSubtitleTrack, setSelectedVideoTrack, setMaxBitRate, setDuration, } = useVideoPlayerStore.getState(); if (!playlist?.length) return null; // πŸ‘‰ Check autoNext if (!autoNext) { // Just pause at the end, don’t go next setIsPaused(true); setControlsVisible(true); return currentTrackIndex; } let nextIndex = currentTrackIndex + 1; // πŸ‘‰ No next episode? stop here if (nextIndex >= playlist.length) { setIsPaused(true); setControlsVisible(true); return currentTrackIndex; } const nextTrack = playlist[nextIndex]; if (!nextTrack) return currentTrackIndex; // πŸ‘‰ Trigger hook let isSuccess = true; if (onPressEpisode) { isSuccess = await onPressEpisode({ episode: { id: nextTrack.episodeId || '', title: nextTrack.episodeName ?? '', contentId: nextTrack.contentId || '', sourceLink: nextTrack.sourceLink, thumbnail: nextTrack.thumbnail, nextEpisodeAt: nextTrack.nextEpisodeAt, publishDate: nextTrack.publishDate, skipIntro: nextTrack.skipIntro, description: nextTrack?.description || '', duration: nextTrack?.duration || 0, sourceType: nextTrack?.sourceType || 'HLS', episodeNumber: nextTrack?.episodeNumber || 0, subtitles: nextTrack?.subtitles ?? [], }, }); } if (!isSuccess) { setIsPaused(true); setControlsVisible(true); return currentTrackIndex; } // πŸ‘‰ Play next episode setIsPaused(false); setCurrentTime(0); setDuration(0); setCurrentTrackIndex(nextIndex); setActiveTrack(nextTrack); setActiveSubtitle(null); setSelectedVideoTrack(null); setMaxBitRate(null); setPlayBackRate(1, 'Normal'); setSelectedSubtitleTrack(null); if (nextTrack.seasonId) { const activeSeason = contentSeasons?.find( (s) => s.id === nextTrack.seasonId ); if (activeSeason) { setActiveSeason(activeSeason); } } return nextIndex; }; export const viewCount = (): boolean => { const { isViewCounted, setIsViewCounted, activeTrack } = useVideoPlayerStore.getState(); if (!isViewCounted) { if (activeTrack?.id) { setIsViewCounted(true); return true; } } else { return false; } return false; }; export const countWatchTime = (): { totalWatchTime: number; completed: boolean; currentTime: number; } => { const { activeTrack, duration, setStartWatchTime, startWatchTime } = useVideoPlayerStore.getState(); const currentTimeFromStorage = Number( mmkvStorage.getItem('currentTime') || 0 ); const prevWatchTime = Number(mmkvStorage.getItem('current_watch_time') || 0); // βœ… Completed check (>= 95%) const completed = duration > 0 && Math.round(currentTimeFromStorage / duration) >= 0.95; // ⏱ If no start time (pause/close before resuming) if (!startWatchTime) { return { totalWatchTime: prevWatchTime, completed, currentTime: currentTimeFromStorage, }; } const elapsedTime = (Date.now() - startWatchTime) / 1000; const totalTimeWatched = prevWatchTime + elapsedTime; mmkvStorage.setItem('current_watch_time', totalTimeWatched.toString()); setStartWatchTime(null); if (totalTimeWatched < 30) { return { totalWatchTime: 0, completed: false, currentTime: currentTimeFromStorage, }; } if (activeTrack?.id) { return { totalWatchTime: totalTimeWatched, completed, currentTime: currentTimeFromStorage, }; } mmkvStorage.setItem('current_watch_time', '0'); return { totalWatchTime: 0, completed: false, currentTime: 0, }; };