UNPKG

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

Version:

Production-ready React Native OTT video player library for Android & iOS. Features: playlists, seasons, auto-next playback, subtitles (SRT/VTT), custom theming, analytics tracking, fullscreen mode, gesture controls, ads player (pre-roll/mid-roll/post-roll

106 lines (89 loc) 2.88 kB
import { useCallback } from 'react'; import { useVideoPlayerStore, mmkvStorage } from '../../store/videoPlayerStore'; import type { MediaTrack } from '../../store/videoPlayer.type'; export type WatchEventType = | 'VIEW_COUNT' | 'COMPLETED' | 'PROGRESS' | 'EPISODE_CHANGE' | 'VIDEO_CLOSE'; export interface WatchProgressDetails { contentId: string | null; episodeId?: string | null; contentType?: MediaTrack['type']; currentTime: number; totalWatchTime: number; duration: number; isVideoCompleted: boolean; activeTrack: MediaTrack | null; } export interface ExtendedWatchProgress extends WatchProgressDetails { event?: WatchEventType; } // Internal function - not exported to avoid conflict with videoControl.countWatchTime const countWatchTime = ( forceFlush = false ): { totalWatchTime: number; completed: boolean; currentTime: number; } => { const { duration, setStartWatchTime, startWatchTime } = useVideoPlayerStore.getState(); const currentTimeFromStorage = Number( mmkvStorage.getItem('currentTime') || 0 ); const prevWatchTime = Number(mmkvStorage.getItem('current_watch_time') || 0); const completed = duration > 0 && Math.round(currentTimeFromStorage / duration) >= 0.95; let totalTimeWatched = prevWatchTime; if (startWatchTime) { const elapsedTime = (Date.now() - startWatchTime) / 1000; totalTimeWatched = prevWatchTime + elapsedTime; mmkvStorage.setItem('current_watch_time', totalTimeWatched.toString()); setStartWatchTime(null); } if (forceFlush) { const latest = Number(mmkvStorage.getItem('current_watch_time') || '0'); return { totalWatchTime: latest, completed, currentTime: currentTimeFromStorage, }; } return { totalWatchTime: totalTimeWatched, completed, currentTime: currentTimeFromStorage, }; }; export const useWatchReporter = ({ onWatchProgress, }: { onWatchProgress?: (progress: ExtendedWatchProgress) => void; }) => { const reportProgress = useCallback( (event: WatchEventType = 'PROGRESS', forcedCurrentTime?: number) => { const { activeTrack, duration } = useVideoPlayerStore.getState(); if (!activeTrack) return; const { totalWatchTime, completed, currentTime } = countWatchTime( event === 'VIDEO_CLOSE' || event === 'EPISODE_CHANGE' || event === 'COMPLETED' ); const progress: WatchProgressDetails = { contentId: activeTrack?.contentId || null, episodeId: activeTrack?.episodeId || null, contentType: activeTrack?.type, currentTime: forcedCurrentTime ?? currentTime, totalWatchTime, duration: duration || 0, isVideoCompleted: completed, activeTrack, }; onWatchProgress?.({ ...progress, event }); }, [onWatchProgress] ); return { reportProgress }; };