@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.
105 lines (88 loc) • 2.8 kB
text/typescript
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;
}
export 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 };
};