@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,105 +0,0 @@
1
- import { useCallback } from 'react';
2
- import { useVideoPlayerStore, mmkvStorage } from '../../store/videoPlayerStore';
3
- import type { MediaTrack } from '../../store/videoPlayer.type';
4
-
5
- export type WatchEventType =
6
- | 'VIEW_COUNT'
7
- | 'COMPLETED'
8
- | 'PROGRESS'
9
- | 'EPISODE_CHANGE'
10
- | 'VIDEO_CLOSE';
11
-
12
- export interface WatchProgressDetails {
13
- contentId: string | null;
14
- episodeId?: string | null;
15
- contentType?: MediaTrack['type'];
16
- currentTime: number;
17
- totalWatchTime: number;
18
- duration: number;
19
- isVideoCompleted: boolean;
20
- activeTrack: MediaTrack | null;
21
- }
22
-
23
- export interface ExtendedWatchProgress extends WatchProgressDetails {
24
- event?: WatchEventType;
25
- }
26
-
27
- // Internal function - not exported to avoid conflict with videoControl.countWatchTime
28
- const countWatchTime = (
29
- forceFlush = false
30
- ): {
31
- totalWatchTime: number;
32
- completed: boolean;
33
- currentTime: number;
34
- } => {
35
- const { duration, setStartWatchTime, startWatchTime } =
36
- useVideoPlayerStore.getState();
37
-
38
- const currentTimeFromStorage = Number(
39
- mmkvStorage.getItem('currentTime') || 0
40
- );
41
- const prevWatchTime = Number(mmkvStorage.getItem('current_watch_time') || 0);
42
-
43
- const completed =
44
- duration > 0 && Math.round(currentTimeFromStorage / duration) >= 0.95;
45
-
46
- let totalTimeWatched = prevWatchTime;
47
-
48
- if (startWatchTime) {
49
- const elapsedTime = (Date.now() - startWatchTime) / 1000;
50
- totalTimeWatched = prevWatchTime + elapsedTime;
51
- mmkvStorage.setItem('current_watch_time', totalTimeWatched.toString());
52
-
53
- setStartWatchTime(null);
54
- }
55
-
56
- if (forceFlush) {
57
- const latest = Number(mmkvStorage.getItem('current_watch_time') || '0');
58
- return {
59
- totalWatchTime: latest,
60
- completed,
61
- currentTime: currentTimeFromStorage,
62
- };
63
- }
64
-
65
- return {
66
- totalWatchTime: totalTimeWatched,
67
- completed,
68
- currentTime: currentTimeFromStorage,
69
- };
70
- };
71
-
72
- export const useWatchReporter = ({
73
- onWatchProgress,
74
- }: {
75
- onWatchProgress?: (progress: ExtendedWatchProgress) => void;
76
- }) => {
77
- const reportProgress = useCallback(
78
- (event: WatchEventType = 'PROGRESS', forcedCurrentTime?: number) => {
79
- const { activeTrack, duration } = useVideoPlayerStore.getState();
80
- if (!activeTrack) return;
81
-
82
- const { totalWatchTime, completed, currentTime } = countWatchTime(
83
- event === 'VIDEO_CLOSE' ||
84
- event === 'EPISODE_CHANGE' ||
85
- event === 'COMPLETED'
86
- );
87
-
88
- const progress: WatchProgressDetails = {
89
- contentId: activeTrack?.contentId || null,
90
- episodeId: activeTrack?.episodeId || null,
91
- contentType: activeTrack?.type,
92
- currentTime: forcedCurrentTime ?? currentTime,
93
- totalWatchTime,
94
- duration: duration || 0,
95
- isVideoCompleted: completed,
96
- activeTrack,
97
- };
98
-
99
- onWatchProgress?.({ ...progress, event });
100
- },
101
- [onWatchProgress]
102
- );
103
-
104
- return { reportProgress };
105
- };
@@ -1,5 +0,0 @@
1
- export * from './videoRef';
2
- export * from './videoSource';
3
- export * from './videoControl';
4
- export * from './videoResume';
5
- export { adVideoRef } from './videoRef';
@@ -1,185 +0,0 @@
1
- import { mmkvStorage, useVideoPlayerStore } from '../../store/videoPlayerStore';
2
- import type { MediaEpisode } from '../../store/videoPlayer.type';
3
-
4
- export const handlePause = () => {
5
- const { setIsPaused, startWatchTime, setStartWatchTime } =
6
- useVideoPlayerStore.getState();
7
-
8
- setIsPaused(true);
9
-
10
- if (!startWatchTime) return;
11
-
12
- const elapsedTime = (Date.now() - startWatchTime) / 1000;
13
- const storedTime = Number(mmkvStorage.getItem('current_watch_time') ?? 0);
14
-
15
- mmkvStorage.setItem(
16
- 'current_watch_time',
17
- (storedTime + elapsedTime).toString()
18
- );
19
-
20
- setStartWatchTime(null);
21
- };
22
-
23
- interface HandleNextOptions {
24
- onPressEpisode: ({ episode }: { episode: MediaEpisode }) => Promise<boolean>;
25
- autoNext?: boolean;
26
- }
27
- export const handleNext = async ({
28
- onPressEpisode,
29
- autoNext,
30
- }: HandleNextOptions): Promise<number | null> => {
31
- const {
32
- playList: playlist,
33
- currentTrackIndex,
34
- setCurrentTrackIndex,
35
- setActiveTrack,
36
- setCurrentTime,
37
- setIsPaused,
38
- setActiveSubtitle,
39
- setPlayBackRate,
40
- contentSeasons,
41
- setActiveSeason,
42
- setControlsVisible,
43
- setSelectedSubtitleTrack,
44
- setSelectedVideoTrack,
45
- setMaxBitRate,
46
- setDuration,
47
- } = useVideoPlayerStore.getState();
48
-
49
- if (!playlist?.length) return null;
50
-
51
- if (!autoNext) {
52
- setIsPaused(true);
53
- setControlsVisible(true);
54
- return currentTrackIndex;
55
- }
56
-
57
- let nextIndex = currentTrackIndex + 1;
58
-
59
- if (nextIndex >= playlist.length) {
60
- setIsPaused(true);
61
- setControlsVisible(true);
62
- return currentTrackIndex;
63
- }
64
-
65
- const nextTrack = playlist[nextIndex];
66
- if (!nextTrack) return currentTrackIndex;
67
-
68
- let isSuccess = true;
69
- if (onPressEpisode) {
70
- isSuccess = await onPressEpisode({
71
- episode: {
72
- id: nextTrack.episodeId || '',
73
- title: nextTrack.episodeName ?? '',
74
- contentId: nextTrack.contentId || '',
75
- sourceLink: nextTrack.sourceLink,
76
- thumbnail: nextTrack.thumbnail,
77
- nextEpisodeAt: nextTrack.nextEpisodeAt,
78
- publishDate: nextTrack.publishDate,
79
- skipIntro: nextTrack.skipIntro,
80
- description: nextTrack?.description || '',
81
- duration: nextTrack?.duration || 0,
82
- sourceType: nextTrack?.sourceType || 'HLS',
83
- episodeNumber: nextTrack?.episodeNumber || 0,
84
- subtitles: nextTrack?.subtitles ?? [],
85
- },
86
- });
87
- }
88
-
89
- if (!isSuccess) {
90
- setIsPaused(true);
91
- setControlsVisible(true);
92
- return currentTrackIndex;
93
- }
94
-
95
- setIsPaused(false);
96
- setCurrentTime(0);
97
- setDuration(0);
98
- setCurrentTrackIndex(nextIndex);
99
- setActiveTrack(nextTrack);
100
- setActiveSubtitle(null);
101
- setSelectedVideoTrack(null);
102
- setMaxBitRate(null);
103
- setPlayBackRate(1, 'Normal');
104
- setSelectedSubtitleTrack(null);
105
-
106
- if (nextTrack.seasonId) {
107
- const activeSeason = contentSeasons?.find(
108
- (s) => s.id === nextTrack.seasonId
109
- );
110
- if (activeSeason) {
111
- setActiveSeason(activeSeason);
112
- }
113
- }
114
-
115
- return nextIndex;
116
- };
117
-
118
- export const viewCount = (): boolean => {
119
- const { isViewCounted, setIsViewCounted, activeTrack } =
120
- useVideoPlayerStore.getState();
121
- if (!isViewCounted) {
122
- if (activeTrack?.id) {
123
- setIsViewCounted(true);
124
- return true;
125
- }
126
- } else {
127
- return false;
128
- }
129
- return false;
130
- };
131
-
132
- export const countWatchTime = (): {
133
- totalWatchTime: number;
134
- completed: boolean;
135
- currentTime: number;
136
- } => {
137
- const { activeTrack, duration, setStartWatchTime, startWatchTime } =
138
- useVideoPlayerStore.getState();
139
-
140
- const currentTimeFromStorage = Number(
141
- mmkvStorage.getItem('currentTime') || 0
142
- );
143
- const prevWatchTime = Number(mmkvStorage.getItem('current_watch_time') || 0);
144
-
145
- const completed =
146
- duration > 0 && Math.round(currentTimeFromStorage / duration) >= 0.95;
147
-
148
- if (!startWatchTime) {
149
- return {
150
- totalWatchTime: prevWatchTime,
151
- completed,
152
- currentTime: currentTimeFromStorage,
153
- };
154
- }
155
-
156
- const elapsedTime = (Date.now() - startWatchTime) / 1000;
157
-
158
- const totalTimeWatched = prevWatchTime + elapsedTime;
159
- mmkvStorage.setItem('current_watch_time', totalTimeWatched.toString());
160
-
161
- setStartWatchTime(null);
162
-
163
- if (totalTimeWatched < 30) {
164
- return {
165
- totalWatchTime: 0,
166
- completed: false,
167
- currentTime: currentTimeFromStorage,
168
- };
169
- }
170
-
171
- if (activeTrack?.id) {
172
- return {
173
- totalWatchTime: totalTimeWatched,
174
- completed,
175
- currentTime: currentTimeFromStorage,
176
- };
177
- }
178
-
179
- mmkvStorage.setItem('current_watch_time', '0');
180
- return {
181
- totalWatchTime: 0,
182
- completed: false,
183
- currentTime: 0,
184
- };
185
- };
@@ -1,21 +0,0 @@
1
- import { createRef } from 'react';
2
- import type { VideoRef } from 'react-native-video';
3
- import type { AdsPlayerRef } from '../../../AdsPlayer/AdsPlayer';
4
-
5
- export const hideControlsStyles = {
6
- hideForward: true,
7
- hideDuration: true,
8
- hideFullscreen: true,
9
- hidePlayPause: true,
10
- hideNavigationBarOnFullScreenMode: true,
11
- hideNotificationBarOnFullScreenMode: true,
12
- hideNext: true,
13
- hidePosition: true,
14
- hidePrevious: true,
15
- hideRewind: true,
16
- hideSeekBar: true,
17
- hideSettingButton: true,
18
- };
19
-
20
- export const videoRef = createRef<VideoRef>();
21
- export const adVideoRef = createRef<AdsPlayerRef>();
@@ -1,23 +0,0 @@
1
- import { videoRef } from './videoRef';
2
- import { useVideoPlayerStore } from '../../store/videoPlayerStore';
3
- import { useAdsPlayerStore } from '../../../AdsPlayer/store/adsPlayerStore';
4
-
5
- /**
6
- * Reusable function to resume video from ad
7
- * Handles seeking to resume time and unpausing the video
8
- */
9
- export const resumeVideoFromAd = (resumeTimeValue: number | null) => {
10
- const { setIsPaused } = useVideoPlayerStore.getState();
11
- const { setResumeTime } = useAdsPlayerStore.getState();
12
-
13
- if (videoRef.current && resumeTimeValue !== null && resumeTimeValue > 0) {
14
- setTimeout(() => {
15
- videoRef.current?.seek(resumeTimeValue);
16
- setIsPaused(false);
17
- setResumeTime(null);
18
- }, 100);
19
- } else {
20
- setIsPaused(false);
21
- setResumeTime(null);
22
- }
23
- };
@@ -1,23 +0,0 @@
1
- import type { MediaTrack } from '../../store/videoPlayer.type';
2
- import type { ReactVideoSource } from 'react-native-video';
3
-
4
- interface UrlHandlerProps {
5
- playList: MediaTrack[];
6
- currentTrackIndex: number;
7
- }
8
-
9
- export const getVideoSource = ({
10
- playList,
11
- currentTrackIndex,
12
- }: UrlHandlerProps): ReactVideoSource => {
13
- const track = playList?.[currentTrackIndex];
14
- if (!track) return { uri: '' };
15
-
16
- const uri = track.isTrailer ? track.trailerSource : track.sourceLink;
17
- return { uri: encodeURI(uri?.trim() || '') ?? '' };
18
- };
19
-
20
- export const getEpisodeIndex = (
21
- playList: MediaTrack[],
22
- episodeId: string
23
- ): number => playList.findIndex((item) => item.episodeId === episodeId);
@@ -1,181 +0,0 @@
1
- import React, { useCallback, useMemo } from 'react';
2
- import { View, StyleSheet } from 'react-native';
3
- import { type EdgeInsets } from 'react-native-safe-area-context';
4
-
5
- import VideoPlayerCore from './VideoPlayer/VideoPlayerCore';
6
- import { AdsPlayer, useAdsManager } from './AdsPlayer';
7
- import { useVideoPlayerStore } from './VideoPlayer/store/videoPlayerStore';
8
- import { useAdsPlayerStore } from './AdsPlayer/store/adsPlayerStore';
9
- import type {
10
- MediaEpisode,
11
- VideoAd,
12
- } from './VideoPlayer/store/videoPlayer.type';
13
- import type { VideoPlayerTheme } from './VideoPlayer/context';
14
- import {
15
- createPlayerEvents,
16
- useWatchReporter,
17
- adVideoRef,
18
- useAdEventHandler,
19
- usePauseVideoOnAd,
20
- useOrientationLock,
21
- resumeVideoFromAd as resumeVideoFromAdUtil,
22
- type ExtendedWatchProgress,
23
- } from './VideoPlayer/utils';
24
-
25
- export interface VideoPlayerProps {
26
- onClose?: () => void;
27
- isFocused?: boolean;
28
- seekTime?: number | null;
29
- mode?: 'fullscreen' | 'normal';
30
- autoNext?: boolean;
31
- event?: {
32
- onPressEpisode?: ({
33
- episode,
34
- }: {
35
- episode: MediaEpisode;
36
- }) => Promise<boolean>;
37
- };
38
- theme?: Partial<VideoPlayerTheme>;
39
- onWatchProgress?: (progress: ExtendedWatchProgress) => void;
40
- ads?: VideoAd[];
41
- onAdEnd?: (ad: VideoAd) => void;
42
- onAdError?: (error: Error, ad: VideoAd) => void;
43
- onAdTracking?: ({
44
- ad,
45
- trackingUrl,
46
- event,
47
- }: {
48
- ad: VideoAd;
49
- trackingUrl: string;
50
- event: string;
51
- }) => void;
52
- insets: EdgeInsets;
53
- }
54
-
55
- const VideoPlayer: React.FC<VideoPlayerProps> = ({
56
- onClose,
57
- isFocused = true,
58
- mode = 'fullscreen',
59
- seekTime,
60
- event,
61
- autoNext = true,
62
- theme,
63
- onWatchProgress,
64
- ads = [],
65
- onAdEnd,
66
- onAdError,
67
- onAdTracking,
68
- insets,
69
- }) => {
70
- const isPaused = useVideoPlayerStore((state) => state.isPaused);
71
- const activeTrack = useVideoPlayerStore((state) => state.activeTrack);
72
- const currentAd = useAdsPlayerStore((state) => state.currentAd);
73
- const isAdPlaying = useAdsPlayerStore((state) => state.isAdPlaying);
74
- const resumeTime = useAdsPlayerStore((state) => state.resumeTime);
75
-
76
- const playerEvents = useMemo(() => createPlayerEvents(), []);
77
- const { reportProgress } = useWatchReporter({ onWatchProgress });
78
- const { checkPostRollAds } = useAdsManager(ads, onAdTracking);
79
-
80
- // Handle orientation locking
81
- useOrientationLock({ isFocused, mode });
82
-
83
- // Pause main video when ads start playing
84
- usePauseVideoOnAd();
85
-
86
- const { handleAdEnd, handleAdSkip, handleAdError } = useAdEventHandler({
87
- resumeVideoFromAd: resumeVideoFromAdUtil,
88
- resumeTime,
89
- playerEvents,
90
- reportProgress,
91
- onPressEpisode: event?.onPressEpisode,
92
- autoNext,
93
- onAdEnd,
94
- onAdError,
95
- });
96
-
97
- const handleVideoEnd = useCallback(() => {
98
- // Don't show ads if it's a trailer
99
- if (activeTrack?.isTrailer) {
100
- return;
101
- }
102
- if (checkPostRollAds()) {
103
- return;
104
- }
105
- }, [checkPostRollAds, activeTrack?.isTrailer]);
106
-
107
- // Handle ad player close - reset both stores
108
- const handleAdClose = useCallback(() => {
109
- // Reset ads store
110
- const { resetAdsStore } = useAdsPlayerStore.getState();
111
- resetAdsStore();
112
-
113
- // Reset video player store
114
- const { resetStore } = useVideoPlayerStore.getState();
115
- resetStore();
116
-
117
- // Call the original onClose if provided
118
- onClose?.();
119
- }, [onClose]);
120
-
121
- const showAdsOverlay =
122
- ads.length > 0 && isAdPlaying && currentAd && !activeTrack?.isTrailer;
123
-
124
- return (
125
- <View style={styles.container}>
126
- <View
127
- style={[
128
- styles.mainPlayerWrapper,
129
- showAdsOverlay && styles.mainPlayerHidden,
130
- ]}
131
- pointerEvents={showAdsOverlay ? 'none' : 'auto'}
132
- >
133
- <VideoPlayerCore
134
- onClose={onClose}
135
- isFocused={isFocused}
136
- mode={mode}
137
- seekTime={seekTime}
138
- event={event}
139
- autoNext={autoNext}
140
- theme={theme}
141
- onWatchProgress={onWatchProgress}
142
- insets={insets}
143
- isPausedOverride={isAdPlaying ? true : isPaused}
144
- onVideoEnd={handleVideoEnd}
145
- />
146
- </View>
147
- {showAdsOverlay && (
148
- <View style={styles.adsOverlay}>
149
- <AdsPlayer
150
- ref={adVideoRef}
151
- insets={insets}
152
- onAdEnd={handleAdEnd}
153
- onAdSkip={handleAdSkip}
154
- onAdError={handleAdError}
155
- onAdTracking={onAdTracking}
156
- onClose={handleAdClose}
157
- />
158
- </View>
159
- )}
160
- </View>
161
- );
162
- };
163
-
164
- const styles = StyleSheet.create({
165
- container: {
166
- flex: 1,
167
- },
168
- mainPlayerWrapper: {
169
- flex: 1,
170
- },
171
- mainPlayerHidden: {
172
- opacity: 0,
173
- },
174
- adsOverlay: {
175
- ...StyleSheet.absoluteFillObject,
176
- zIndex: 1000,
177
- backgroundColor: 'black',
178
- },
179
- });
180
-
181
- export default React.memo(VideoPlayer);
package/src/index.tsx DELETED
@@ -1,3 +0,0 @@
1
- export * from './VideoPlayer/store';
2
- export * from './VideoPlayer/utils';
3
- export { default as VideoPlayer } from './VideoPlayer';