@zezosoft/zezo-ott-react-native-video-player 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/package.json +1 -2
  2. package/src/AdsPlayer/AdsPlayer.tsx +0 -311
  3. package/src/AdsPlayer/MediaControls/AdBottomControls.tsx +0 -191
  4. package/src/AdsPlayer/MediaControls/AdMediaControls.tsx +0 -104
  5. package/src/AdsPlayer/MediaControls/AdMediaControlsProvider.tsx +0 -62
  6. package/src/AdsPlayer/MediaControls/AdMiddleControls.tsx +0 -63
  7. package/src/AdsPlayer/MediaControls/AdTopControls.tsx +0 -191
  8. package/src/AdsPlayer/MediaControls/index.ts +0 -5
  9. package/src/AdsPlayer/components/RotatingLoader.tsx +0 -79
  10. package/src/AdsPlayer/index.ts +0 -4
  11. package/src/AdsPlayer/store/adsPlayer.type.ts +0 -29
  12. package/src/AdsPlayer/store/adsPlayerStore.ts +0 -59
  13. package/src/AdsPlayer/store/index.ts +0 -2
  14. package/src/AdsPlayer/utils/adStateReset.ts +0 -29
  15. package/src/AdsPlayer/utils/controls.ts +0 -69
  16. package/src/AdsPlayer/utils/useAdControlsAutoHide.ts +0 -32
  17. package/src/AdsPlayer/utils/useAdInitialization.ts +0 -86
  18. package/src/AdsPlayer/utils/useAdTracking.ts +0 -89
  19. package/src/AdsPlayer/utils/useAdsManager.ts +0 -215
  20. package/src/VideoPlayer/MediaControls/BottomControls.tsx +0 -210
  21. package/src/VideoPlayer/MediaControls/MediaControls.tsx +0 -30
  22. package/src/VideoPlayer/MediaControls/MediaControlsProvider.tsx +0 -104
  23. package/src/VideoPlayer/MediaControls/MiddleControls.tsx +0 -259
  24. package/src/VideoPlayer/MediaControls/TopControls.tsx +0 -100
  25. package/src/VideoPlayer/Settings/AudioAndSubtitles.tsx +0 -295
  26. package/src/VideoPlayer/Settings/Episodes.tsx +0 -297
  27. package/src/VideoPlayer/Settings/SettingModal.tsx +0 -127
  28. package/src/VideoPlayer/Settings/SpeedControls.tsx +0 -130
  29. package/src/VideoPlayer/Settings/VideoPlayerSettings.tsx +0 -141
  30. package/src/VideoPlayer/VideoPlayerCore.tsx +0 -356
  31. package/src/VideoPlayer/components/ProgressBar.tsx +0 -211
  32. package/src/VideoPlayer/components/SkipAndNextControls.tsx +0 -192
  33. package/src/VideoPlayer/components/SubtitleView.tsx +0 -53
  34. package/src/VideoPlayer/components/Toast.tsx +0 -61
  35. package/src/VideoPlayer/context/VideoPlayerConfig.tsx +0 -65
  36. package/src/VideoPlayer/context/index.ts +0 -5
  37. package/src/VideoPlayer/index.ts +0 -4
  38. package/src/VideoPlayer/store/index.ts +0 -2
  39. package/src/VideoPlayer/store/videoPlayer.type.ts +0 -214
  40. package/src/VideoPlayer/store/videoPlayerStore.ts +0 -97
  41. package/src/VideoPlayer/styles/globalStyles.ts +0 -73
  42. package/src/VideoPlayer/utils/display/Display.ts +0 -10
  43. package/src/VideoPlayer/utils/display/index.ts +0 -1
  44. package/src/VideoPlayer/utils/format/index.ts +0 -1
  45. package/src/VideoPlayer/utils/format/timeFormatter.ts +0 -44
  46. package/src/VideoPlayer/utils/hooks/index.ts +0 -5
  47. package/src/VideoPlayer/utils/hooks/useAdEventHandler.ts +0 -95
  48. package/src/VideoPlayer/utils/hooks/useOrientationLock.ts +0 -29
  49. package/src/VideoPlayer/utils/hooks/usePauseVideoOnAd.ts +0 -46
  50. package/src/VideoPlayer/utils/hooks/useVideoPlayerBack.ts +0 -66
  51. package/src/VideoPlayer/utils/hooks/useVideoResolutions.ts +0 -125
  52. package/src/VideoPlayer/utils/index.ts +0 -6
  53. package/src/VideoPlayer/utils/platform/PlatformSelector.ts +0 -13
  54. package/src/VideoPlayer/utils/platform/index.ts +0 -2
  55. package/src/VideoPlayer/utils/platform/lockOrientation.ts +0 -40
  56. package/src/VideoPlayer/utils/player/index.ts +0 -2
  57. package/src/VideoPlayer/utils/player/playerEvents.ts +0 -97
  58. package/src/VideoPlayer/utils/player/useWatchReporter.ts +0 -105
  59. package/src/VideoPlayer/utils/video/index.ts +0 -5
  60. package/src/VideoPlayer/utils/video/videoControl.ts +0 -185
  61. package/src/VideoPlayer/utils/video/videoRef.ts +0 -21
  62. package/src/VideoPlayer/utils/video/videoResume.ts +0 -23
  63. package/src/VideoPlayer/utils/video/videoSource.ts +0 -23
  64. package/src/VideoPlayer.tsx +0 -181
  65. package/src/index.tsx +0 -3
@@ -1,73 +0,0 @@
1
- import { StyleSheet } from 'react-native';
2
-
3
- const globalStyles = StyleSheet.create({
4
- centerContainer: {
5
- flex: 1,
6
- alignItems: 'center',
7
- justifyContent: 'center',
8
- },
9
- container: {
10
- flex: 1,
11
- },
12
- newContainer: {
13
- flex: 1,
14
- },
15
- flexOneJustifyContentAndAlignItemsCenter: {
16
- flex: 1,
17
- justifyContent: 'center',
18
- alignItems: 'center',
19
- },
20
- flexOneJustifyContentCenterAndAlignItemsCenter: {
21
- flex: 1,
22
- justifyContent: 'center',
23
- alignItems: 'center',
24
- },
25
- hundredPercentWidth: {
26
- width: '100%',
27
- },
28
- hundredPercentHeight: {
29
- height: '100%',
30
- },
31
- marginZeroAndPaddingZero: {
32
- margin: 0,
33
- padding: 0,
34
- },
35
- overflowHidden: {
36
- overflow: 'hidden',
37
- },
38
- flexOne: {
39
- flex: 1,
40
- },
41
- flexZero: {
42
- flex: 0,
43
- },
44
- positionAbsolute: {
45
- position: 'absolute',
46
- },
47
- twentyPercentWidth: {
48
- width: '20%',
49
- },
50
- alignItemsCenterAndJustifyContentCenter: {
51
- alignItems: 'center',
52
- justifyContent: 'center',
53
- },
54
- textAlignCenter: {
55
- textAlign: 'center',
56
- },
57
- flexRow_alignCenter_justifyBetween: {
58
- flexDirection: 'row',
59
- alignItems: 'center',
60
- justifyContent: 'space-between',
61
- },
62
- flexOneWithBlackBackground: {
63
- flex: 1,
64
- backgroundColor: 'black',
65
- },
66
- absoluteFill: StyleSheet.absoluteFillObject,
67
- controlsContainer: {
68
- flex: 1,
69
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
70
- },
71
- });
72
-
73
- export default globalStyles;
@@ -1,10 +0,0 @@
1
- import { Dimensions } from 'react-native';
2
-
3
- const { height, width } = Dimensions.get('window');
4
-
5
- const setHeight = (h: number) => (height / 100) * h;
6
- const setWidth = (w: number) => (width / 100) * w;
7
- const fullWidth = Dimensions.get('window').width;
8
- const fullHeight = Dimensions.get('window').height;
9
-
10
- export default { setHeight, setWidth, fullWidth, fullHeight };
@@ -1 +0,0 @@
1
- export { default as Display } from './Display';
@@ -1 +0,0 @@
1
- export * from './timeFormatter';
@@ -1,44 +0,0 @@
1
- export const formatDuration = (
2
- totalSeconds: number,
3
- hideSeconds = false,
4
- addSpaces = false
5
- ): string => {
6
- const hours = Math.floor(totalSeconds / 3600);
7
- const minutes = Math.floor((totalSeconds % 3600) / 60);
8
- const seconds = totalSeconds % 60;
9
-
10
- const formatUnit = (value: number, label: string) =>
11
- value ? `${value}${addSpaces ? ` ${label} ` : label}` : '';
12
-
13
- const result =
14
- formatUnit(hours, 'h') +
15
- formatUnit(minutes, 'm') +
16
- formatUnit(seconds, 's');
17
-
18
- return hideSeconds
19
- ? formatUnit(hours, 'h') + formatUnit(minutes, 'm')
20
- : result;
21
- };
22
-
23
- export const formatTime = (seconds: number) => {
24
- const h = Math.floor(seconds / 3600);
25
- const m = Math.floor((seconds % 3600) / 60);
26
- const s = Math.floor(seconds % 60);
27
- if (h > 0) {
28
- return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
29
- }
30
- return `${m}:${String(s).padStart(2, '0')}`;
31
- };
32
-
33
- export const formatTimeWithMs = (seconds: number): string => {
34
- if (isNaN(seconds) || seconds < 0) return '00:00.000';
35
- const totalMs = Math.floor(seconds * 1000);
36
- const ms = totalMs % 1000;
37
- const totalSec = Math.floor(totalMs / 1000);
38
- const min = Math.floor(totalSec / 60);
39
- const sec = totalSec % 60;
40
- return `${String(min).padStart(2, '0')}:${String(sec).padStart(
41
- 2,
42
- '0'
43
- )}.${String(ms).padStart(3, '0')}`;
44
- };
@@ -1,5 +0,0 @@
1
- export * from './useVideoPlayerBack';
2
- export * from './useVideoResolutions';
3
- export * from './useAdEventHandler';
4
- export * from './usePauseVideoOnAd';
5
- export * from './useOrientationLock';
@@ -1,95 +0,0 @@
1
- import { useCallback } from 'react';
2
- import type { VideoAd } from '../../store/videoPlayer.type';
3
- import type { ExtendedWatchProgress } from '../player/useWatchReporter';
4
- import type { MediaEpisode } from '../../store/videoPlayer.type';
5
-
6
- interface UseAdEventHandlerParams {
7
- resumeVideoFromAd: (resumeTime: number | null) => void;
8
- resumeTime: number | null;
9
- playerEvents: {
10
- onEnd: (params: {
11
- reportProgress: (event: ExtendedWatchProgress['event']) => void;
12
- onPressEpisode: ({
13
- episode,
14
- }: {
15
- episode: MediaEpisode;
16
- }) => Promise<boolean>;
17
- autoNext: boolean;
18
- }) => void;
19
- };
20
- reportProgress: (event: ExtendedWatchProgress['event']) => void;
21
- onPressEpisode?: ({ episode }: { episode: MediaEpisode }) => Promise<boolean>;
22
- autoNext: boolean;
23
- onAdEnd?: (ad: VideoAd) => void;
24
- onAdError?: (error: Error, ad: VideoAd) => void;
25
- }
26
-
27
- /**
28
- * Reusable hook for handling ad events (end, skip, error)
29
- * Consolidates duplicate logic from handleAdEnd, handleAdSkip, and handleAdError
30
- */
31
- export const useAdEventHandler = ({
32
- resumeVideoFromAd,
33
- resumeTime,
34
- playerEvents,
35
- reportProgress,
36
- onPressEpisode,
37
- autoNext,
38
- onAdEnd,
39
- onAdError,
40
- }: UseAdEventHandlerParams) => {
41
- const handlePostRollAd = useCallback(() => {
42
- playerEvents.onEnd({
43
- reportProgress,
44
- onPressEpisode: onPressEpisode ?? (async () => true),
45
- autoNext,
46
- });
47
- }, [playerEvents, reportProgress, onPressEpisode, autoNext]);
48
-
49
- const handleNonPostRollAd = useCallback(() => {
50
- resumeVideoFromAd(resumeTime);
51
- }, [resumeVideoFromAd, resumeTime]);
52
-
53
- const handleAdEnd = useCallback(
54
- (endedAd: VideoAd) => {
55
- onAdEnd?.(endedAd);
56
-
57
- if (endedAd.position === 'post') {
58
- handlePostRollAd();
59
- } else {
60
- handleNonPostRollAd();
61
- }
62
- },
63
- [onAdEnd, handlePostRollAd, handleNonPostRollAd]
64
- );
65
-
66
- const handleAdSkip = useCallback(
67
- (skippedAd: VideoAd) => {
68
- onAdEnd?.(skippedAd);
69
-
70
- if (skippedAd.position !== 'post') {
71
- handleNonPostRollAd();
72
- }
73
- },
74
- [onAdEnd, handleNonPostRollAd]
75
- );
76
-
77
- const handleAdError = useCallback(
78
- (error: Error, errorAd: VideoAd) => {
79
- onAdError?.(error, errorAd);
80
-
81
- if (errorAd.position !== 'post') {
82
- handleNonPostRollAd();
83
- } else {
84
- handlePostRollAd();
85
- }
86
- },
87
- [onAdError, handleNonPostRollAd, handlePostRollAd]
88
- );
89
-
90
- return {
91
- handleAdEnd,
92
- handleAdSkip,
93
- handleAdError,
94
- };
95
- };
@@ -1,29 +0,0 @@
1
- import { useEffect } from 'react';
2
- import { lockToLandscape, lockToPortrait } from '../platform';
3
-
4
- interface UseOrientationLockParams {
5
- isFocused: boolean;
6
- mode: 'fullscreen' | 'normal';
7
- }
8
-
9
- /**
10
- * Reusable hook for managing orientation locking
11
- * Consolidates orientation logic from VideoPlayer
12
- */
13
- export const useOrientationLock = ({
14
- isFocused,
15
- mode,
16
- }: UseOrientationLockParams) => {
17
- useEffect(() => {
18
- if (!isFocused) {
19
- lockToPortrait();
20
- return;
21
- }
22
-
23
- if (mode === 'fullscreen') {
24
- lockToLandscape();
25
- } else {
26
- lockToPortrait();
27
- }
28
- }, [isFocused, mode]);
29
- };
@@ -1,46 +0,0 @@
1
- import { useEffect, useRef } from 'react';
2
- import { useVideoPlayerStore } from '../../store/videoPlayerStore';
3
- import { useAdsPlayerStore } from '../../../AdsPlayer/store/adsPlayerStore';
4
-
5
- /**
6
- * Reusable hook to pause main video when ads start playing
7
- * Saves current time as resume time for pre-roll ads
8
- */
9
- export const usePauseVideoOnAd = () => {
10
- const { setIsPaused, currentTime, isPaused } = useVideoPlayerStore();
11
- const { currentAd, isAdPlaying, resumeTime, setResumeTime } =
12
- useAdsPlayerStore();
13
-
14
- const lastResumeTimeRef = useRef<number | null>(null);
15
-
16
- useEffect(() => {
17
- if (isAdPlaying && currentAd) {
18
- // Only pause if not already paused to prevent unnecessary updates
19
- if (!isPaused) {
20
- setIsPaused(true);
21
- }
22
-
23
- // Save current time as resume time if not already set (for pre-roll ads)
24
- // Use ref to prevent setting the same value multiple times
25
- if (
26
- resumeTime === null &&
27
- currentTime > 0 &&
28
- lastResumeTimeRef.current !== currentTime
29
- ) {
30
- lastResumeTimeRef.current = currentTime;
31
- setResumeTime(currentTime);
32
- }
33
- } else if (!isAdPlaying && !currentAd) {
34
- // Reset ref when no ad is playing
35
- lastResumeTimeRef.current = null;
36
- }
37
- }, [
38
- isAdPlaying,
39
- currentAd,
40
- isPaused,
41
- setIsPaused,
42
- currentTime,
43
- resumeTime,
44
- setResumeTime,
45
- ]);
46
- };
@@ -1,66 +0,0 @@
1
- import { useEffect, useCallback, useRef } from 'react';
2
- import {
3
- BackHandler,
4
- Platform,
5
- AppState,
6
- type AppStateStatus,
7
- } from 'react-native';
8
- import { lockToPortrait } from '../platform/lockOrientation';
9
- import { useVideoPlayerStore } from '../../store/videoPlayerStore';
10
-
11
- type UseVideoPlayerBackProps = {
12
- navigation?: any;
13
- };
14
-
15
- export const useVideoPlayerBack = ({
16
- navigation,
17
- }: UseVideoPlayerBackProps = {}) => {
18
- const { resetStore } = useVideoPlayerStore();
19
- const hasClosed = useRef(false);
20
-
21
- const handleClose = useCallback(() => {
22
- if (hasClosed.current) return;
23
- hasClosed.current = true;
24
-
25
- resetStore();
26
- lockToPortrait();
27
-
28
- if (navigation?.canGoBack()) {
29
- navigation.goBack();
30
- }
31
- }, [resetStore, navigation]);
32
-
33
- useEffect(() => {
34
- const backHandler =
35
- Platform.OS === 'android'
36
- ? BackHandler.addEventListener('hardwareBackPress', () => {
37
- handleClose();
38
- return true;
39
- })
40
- : undefined;
41
-
42
- const unsubscribe = navigation?.addListener('beforeRemove', (e: any) => {
43
- e.preventDefault();
44
- handleClose();
45
- navigation.dispatch(e.data.action);
46
- });
47
-
48
- const handleAppStateChange = (nextAppState: AppStateStatus) => {
49
- if (nextAppState === 'inactive') {
50
- handleClose();
51
- }
52
- };
53
- const appStateListener = AppState.addEventListener(
54
- 'change',
55
- handleAppStateChange
56
- );
57
-
58
- return () => {
59
- backHandler?.remove();
60
- unsubscribe?.();
61
- appStateListener.remove();
62
- };
63
- }, [handleClose, navigation]);
64
-
65
- return handleClose;
66
- };
@@ -1,125 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
- import axios from 'axios';
3
- import type { MediaTrack } from '../../store/videoPlayer.type';
4
-
5
- export interface StreamInfo {
6
- bandwidth: number;
7
- width: number | string;
8
- height: number | string;
9
- }
10
-
11
- async function getHLSBandwidthAndResolutions(
12
- m3u8Url: string,
13
- headers?: Record<string, string>
14
- ): Promise<StreamInfo[]> {
15
- try {
16
- if (!m3u8Url?.endsWith('.m3u8')) return [];
17
-
18
- const { data } = await axios.get<string>(m3u8Url, {
19
- headers: headers ?? undefined,
20
- });
21
- if (!data) return [];
22
-
23
- const lines = data.split('\n');
24
- const streams: StreamInfo[] = [];
25
-
26
- let bandwidth: number | null = null;
27
- let width: number | null = null;
28
- let height: number | null = null;
29
-
30
- for (const line of lines) {
31
- if (line.startsWith('#EXT-X-STREAM-INF')) {
32
- const bandwidthMatch = line.match(/BANDWIDTH=(\d+)/);
33
- const resolutionMatch = line.match(/RESOLUTION=(\d+)x(\d+)/);
34
-
35
- bandwidth = bandwidthMatch ? Number(bandwidthMatch[1]) : null;
36
- if (resolutionMatch) {
37
- width = Number(resolutionMatch[1]);
38
- height = Number(resolutionMatch[2]);
39
- }
40
- }
41
-
42
- if (
43
- line.trim().endsWith('.m3u8') &&
44
- bandwidth !== null &&
45
- width !== null &&
46
- height !== null
47
- ) {
48
- streams.push({ bandwidth, width, height });
49
- bandwidth = null;
50
- width = null;
51
- height = null;
52
- }
53
- }
54
-
55
- streams.sort((a, b) => (b.height as number) - (a.height as number));
56
-
57
- const autoStream: StreamInfo = {
58
- bandwidth: 0,
59
- width: 'auto',
60
- height: 'auto',
61
- };
62
-
63
- return [autoStream, ...streams];
64
- } catch {
65
- return [];
66
- }
67
- }
68
-
69
- export interface Resolution {
70
- height: number | 'auto';
71
- bandwidth: number | null;
72
- }
73
-
74
- const resolutionCache: Record<string, Resolution[]> = {};
75
-
76
- export const useVideoResolutions = (track: MediaTrack | null) => {
77
- const [resolutions, setResolutions] = useState<Resolution[]>([
78
- { height: 'auto', bandwidth: null },
79
- ]);
80
-
81
- useEffect(() => {
82
- if (!track) return;
83
-
84
- const source = track.isTrailer ? track.trailerSource : track.sourceLink;
85
- if (!source) return;
86
-
87
- if (resolutionCache[source]) {
88
- setResolutions(resolutionCache[source]);
89
- return;
90
- }
91
-
92
- let cancelled = false;
93
-
94
- const fetchResolutions = async () => {
95
- try {
96
- const data = await getHLSBandwidthAndResolutions(source);
97
- if (cancelled) return;
98
-
99
- const filteredData = data.filter(
100
- (item): item is StreamInfo & { height: number } =>
101
- typeof item.height === 'number'
102
- );
103
-
104
- const newResolutions: Resolution[] = [
105
- { height: 'auto', bandwidth: null },
106
- ...filteredData.map((item) => ({
107
- height: item.height,
108
- bandwidth: item.bandwidth,
109
- })),
110
- ];
111
-
112
- resolutionCache[source] = newResolutions;
113
- setResolutions(newResolutions);
114
- } catch {}
115
- };
116
-
117
- fetchResolutions();
118
-
119
- return () => {
120
- cancelled = true;
121
- };
122
- }, [track]);
123
-
124
- return resolutions;
125
- };
@@ -1,6 +0,0 @@
1
- export * from './video';
2
- export * from './player';
3
- export * from './platform';
4
- export * from './format';
5
- export * from './display';
6
- export * from './hooks';
@@ -1,13 +0,0 @@
1
- import { Platform } from 'react-native';
2
-
3
- class PlatformSelector {
4
- public isAndroid(): boolean {
5
- return Platform.OS === 'android';
6
- }
7
-
8
- public isIOS(): boolean {
9
- return Platform.OS === 'ios';
10
- }
11
- }
12
-
13
- export default new PlatformSelector();
@@ -1,2 +0,0 @@
1
- export * from './lockOrientation';
2
- export { default as PlatformSelector } from './PlatformSelector';
@@ -1,40 +0,0 @@
1
- import { StatusBar } from 'react-native';
2
- import Orientation from 'react-native-orientation-locker';
3
- import SystemNavigationBar from 'react-native-system-navigation-bar';
4
- import PlatformSelector from './PlatformSelector';
5
-
6
- export const lockToPortrait = () => {
7
- try {
8
- // Lock orientation immediately for fast response
9
- Orientation.lockToPortrait();
10
-
11
- // Update UI instantly without fade animation for smooth, fast rotation
12
- StatusBar.setHidden(false, 'none');
13
-
14
- if (PlatformSelector.isAndroid()) {
15
- // Execute Android-specific updates synchronously for maximum speed
16
- SystemNavigationBar.fullScreen(false);
17
- SystemNavigationBar.navigationShow();
18
- }
19
- } catch (error) {
20
- console.warn('Error locking to portrait:', error);
21
- }
22
- };
23
-
24
- export const lockToLandscape = () => {
25
- try {
26
- // Lock orientation immediately for fast response
27
- Orientation.lockToLandscape();
28
-
29
- // Update UI instantly without fade animation for smooth, fast rotation
30
- StatusBar.setHidden(true, 'none');
31
-
32
- if (PlatformSelector.isAndroid()) {
33
- // Execute Android-specific updates synchronously for maximum speed
34
- SystemNavigationBar.fullScreen(true);
35
- SystemNavigationBar.stickyImmersive();
36
- }
37
- } catch (error) {
38
- console.warn('Error locking to landscape:', error);
39
- }
40
- };
@@ -1,2 +0,0 @@
1
- export * from './playerEvents';
2
- export * from './useWatchReporter';
@@ -1,97 +0,0 @@
1
- import type {
2
- OnBufferData,
3
- OnLoadData,
4
- OnLoadStartData,
5
- OnProgressData,
6
- } from 'react-native-video';
7
- import { mmkvStorage, useVideoPlayerStore } from '../../store/videoPlayerStore';
8
-
9
- import { handleNext } from '../video/videoControl';
10
- import type { MediaEpisode } from '../../store/videoPlayer.type';
11
- import type { ExtendedWatchProgress } from './useWatchReporter';
12
-
13
- export const createPlayerEvents = () => {
14
- const onProgress = ({
15
- currentTime = 0,
16
- playableDuration = 0,
17
- }: OnProgressData) => {
18
- const store = useVideoPlayerStore.getState();
19
- store.setCurrentTime(currentTime);
20
- store.setPlayableDuration(playableDuration);
21
-
22
- try {
23
- mmkvStorage.setItem('currentTime', String(currentTime));
24
- } catch (e) {
25
- console.warn('MMKV save failed', e);
26
- }
27
-
28
- if (store.isBuffering) store.setIsBuffering(false);
29
- };
30
-
31
- const onLoad = (data: OnLoadData) => {
32
- const store = useVideoPlayerStore.getState();
33
- store.setDuration(data.duration || 0);
34
- store.setOnLoad(data);
35
-
36
- mmkvStorage.setItem('current_watch_time', '0');
37
-
38
- store.setError(null);
39
- store.setIsViewCounted(false);
40
- store.setStartWatchTime(Date.now());
41
- store.setIsNextEpisodeVisible(true);
42
- store.setIsSkipIntroVisible(true);
43
- store.setIsBuffering(false);
44
- };
45
-
46
- const onBuffer = ({ isBuffering }: OnBufferData) => {
47
- const store = useVideoPlayerStore.getState();
48
- if (isBuffering) store.setIsBuffering(true);
49
- else setTimeout(() => store.setIsBuffering(false), 150);
50
- };
51
-
52
- const onEnd = ({
53
- onPressEpisode,
54
- reportProgress,
55
- autoNext,
56
- }: {
57
- reportProgress: (event: ExtendedWatchProgress['event']) => void;
58
- onPressEpisode: ({
59
- episode,
60
- }: {
61
- episode: MediaEpisode;
62
- }) => Promise<boolean>;
63
- autoNext: boolean;
64
- }) => {
65
- reportProgress('COMPLETED');
66
- const store = useVideoPlayerStore.getState();
67
- if (!store.activeTrack?.isTrailer && store.activeTrack?.type === 'series') {
68
- handleNext({ onPressEpisode, autoNext });
69
- } else {
70
- store.setIsPaused(true);
71
- }
72
- };
73
-
74
- const onLoadStart = (_: OnLoadStartData) => {
75
- const store = useVideoPlayerStore.getState();
76
- store.setIsBuffering(true);
77
- };
78
-
79
- const LeaveVideoPlayer = () => {
80
- const store = useVideoPlayerStore.getState();
81
- store.setDuration(0);
82
- store.setCurrentTime(0);
83
- store.setPlayableDuration(0);
84
- store.setIsPaused(false);
85
- store.setSettingsModal({ isVisible: false, action: 'none' });
86
- store.setIsBuffering(false);
87
- };
88
-
89
- return {
90
- onProgress,
91
- onLoad,
92
- onBuffer,
93
- onEnd,
94
- onLoadStart,
95
- LeaveVideoPlayer,
96
- };
97
- };