@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,356 +0,0 @@
1
- import React, {
2
- useCallback,
3
- useEffect,
4
- useMemo,
5
- useRef,
6
- useState,
7
- } from 'react';
8
- import { AppState, View, type AppStateStatus } from 'react-native';
9
- import Video, {
10
- type OnProgressData,
11
- type SelectedTrack,
12
- } from 'react-native-video';
13
- import { type EdgeInsets } from 'react-native-safe-area-context';
14
- import {
15
- Gesture,
16
- GestureDetector,
17
- GestureHandlerRootView,
18
- } from 'react-native-gesture-handler';
19
- import {
20
- runOnJS,
21
- useSharedValue,
22
- useAnimatedStyle,
23
- withTiming,
24
- } from 'react-native-reanimated';
25
-
26
- import { hideControlsStyles, videoRef } from './utils';
27
- import { getVideoSource, handlePause } from './utils';
28
- import MediaControlsProvider from './MediaControls/MediaControlsProvider';
29
- import { useVideoPlayerStore } from './store/videoPlayerStore';
30
- import { useAdsPlayerStore } from '../AdsPlayer/store/adsPlayerStore';
31
- import { createPlayerEvents } from './utils';
32
- import globalStyles from './styles/globalStyles';
33
- import { VideoPlayerConfigProvider, type VideoPlayerTheme } from './context';
34
- import { useWatchReporter, type ExtendedWatchProgress } from './utils';
35
- import type { MediaEpisode } from './store/videoPlayer.type';
36
- import Toast from './components/Toast';
37
-
38
- export interface VideoPlayerCoreProps {
39
- onClose?: () => void;
40
- isFocused?: boolean;
41
- seekTime?: number | null;
42
- mode?: 'fullscreen' | 'normal';
43
- autoNext?: boolean;
44
- event?: {
45
- onPressEpisode?: ({
46
- episode,
47
- }: {
48
- episode: MediaEpisode;
49
- }) => Promise<boolean>;
50
- };
51
- theme?: Partial<VideoPlayerTheme>;
52
- onWatchProgress?: (progress: ExtendedWatchProgress) => void;
53
- insets: EdgeInsets;
54
- isPausedOverride?: boolean;
55
- onVideoEnd?: () => void;
56
- }
57
-
58
- const VideoPlayerCore: React.FC<VideoPlayerCoreProps> = ({
59
- onClose,
60
- seekTime,
61
- event,
62
- autoNext = true,
63
- theme,
64
- onWatchProgress,
65
- insets,
66
- isPausedOverride,
67
- onVideoEnd,
68
- }) => {
69
- // Use separate selectors to avoid infinite loop (object selectors create new objects on each call)
70
- const isPaused = useVideoPlayerStore((state) => state.isPaused);
71
- const playBackRate = useVideoPlayerStore((state) => state.playBackRate);
72
- const resizeMode = useVideoPlayerStore((state) => state.resizeMode);
73
- const controlsVisible = useVideoPlayerStore((state) => state.controlsVisible);
74
- const selectedAudioTrack = useVideoPlayerStore(
75
- (state) => state.selectedAudioTrack
76
- );
77
- const selectedSubtitleTrack = useVideoPlayerStore(
78
- (state) => state.selectedSubtitleTrack
79
- );
80
- const selectedVideoTrack = useVideoPlayerStore(
81
- (state) => state.selectedVideoTrack
82
- );
83
- const maxBitRate = useVideoPlayerStore((state) => state.maxBitRate);
84
- const playList = useVideoPlayerStore((state) => state.playList);
85
- const currentTrackIndex = useVideoPlayerStore(
86
- (state) => state.currentTrackIndex
87
- );
88
- const activeTrack = useVideoPlayerStore((state) => state.activeTrack);
89
-
90
- const setResizeMode = useVideoPlayerStore((state) => state.setResizeMode);
91
- const setControlsVisible = useVideoPlayerStore(
92
- (state) => state.setControlsVisible
93
- );
94
- const setIsPaused = useVideoPlayerStore((state) => state.setIsPaused);
95
- const setError = useVideoPlayerStore((state) => state.setError);
96
-
97
- const playerEventsRef = useRef(createPlayerEvents());
98
- const playerEvents = playerEventsRef.current;
99
- const { reportProgress } = useWatchReporter({ onWatchProgress });
100
- const seekTimeRef = useRef(seekTime);
101
-
102
- // Toast state
103
- const [toastMessage, setToastMessage] = useState<string | null>(null);
104
- const toastOpacity = useSharedValue(0);
105
-
106
- // Pinch gesture state
107
- const pinchStartScale = useRef(1);
108
-
109
- useEffect(() => {
110
- seekTimeRef.current = seekTime;
111
- }, [seekTime]);
112
-
113
- const effectivePaused = useMemo(
114
- () => (isPausedOverride !== undefined ? isPausedOverride : isPaused),
115
- [isPausedOverride, isPaused]
116
- );
117
-
118
- const videoSource = useMemo(
119
- () => getVideoSource({ playList, currentTrackIndex }),
120
- [playList, currentTrackIndex]
121
- );
122
-
123
- const selectedAudioTrackMemo = useMemo(
124
- () => selectedAudioTrack as SelectedTrack,
125
- [selectedAudioTrack]
126
- );
127
-
128
- const selectedTextTrackMemo = useMemo(
129
- () =>
130
- selectedSubtitleTrack?.value === 'Off'
131
- ? undefined
132
- : (selectedSubtitleTrack as SelectedTrack),
133
- [selectedSubtitleTrack]
134
- );
135
-
136
- const selectedVideoTrackMemo = useMemo(
137
- () =>
138
- selectedVideoTrack
139
- ? {
140
- type: selectedVideoTrack.type,
141
- value: selectedVideoTrack.value,
142
- }
143
- : undefined,
144
- [selectedVideoTrack]
145
- );
146
-
147
- // Memoize video style for performance
148
- const videoStyle = useMemo(() => globalStyles.absoluteFill, []);
149
-
150
- // Memoize buffer config for performance
151
- const bufferConfig = useMemo(
152
- () => ({
153
- minBufferMs: 15000,
154
- maxBufferMs: 50000,
155
- bufferForPlaybackMs: 2500,
156
- bufferForPlaybackAfterRebufferMs: 5000,
157
- }),
158
- []
159
- );
160
-
161
- useEffect(() => {
162
- if (seekTimeRef.current && !activeTrack?.isTrailer && videoRef?.current) {
163
- videoRef.current.seek(seekTimeRef.current);
164
- }
165
- }, [seekTime, activeTrack?.isTrailer]);
166
-
167
- const handleAppStateChange = useCallback(
168
- (nextState: AppStateStatus) => {
169
- if (nextState === 'inactive' || nextState === 'background') {
170
- handlePause();
171
- setIsPaused(true);
172
- reportProgress('PROGRESS');
173
- }
174
- },
175
- [setIsPaused, reportProgress]
176
- );
177
-
178
- useEffect(() => {
179
- const sub = AppState.addEventListener('change', handleAppStateChange);
180
- return () => sub.remove();
181
- }, [handleAppStateChange]);
182
-
183
- const handleProgress = useCallback(
184
- (progressEvent: OnProgressData) => {
185
- playerEvents.onProgress(progressEvent);
186
- },
187
- [playerEvents]
188
- );
189
-
190
- const handleVideoEnd = useCallback(() => {
191
- if (onVideoEnd) {
192
- onVideoEnd();
193
- } else {
194
- playerEvents.onEnd({
195
- reportProgress,
196
- onPressEpisode: event?.onPressEpisode ?? (async () => true),
197
- autoNext,
198
- });
199
- }
200
- }, [
201
- onVideoEnd,
202
- playerEvents,
203
- reportProgress,
204
- event?.onPressEpisode,
205
- autoNext,
206
- ]);
207
-
208
- const handleError = useCallback(() => {
209
- setError("Video couldn't be loaded");
210
- }, [setError]);
211
-
212
- const handleTap = useCallback(() => {
213
- setControlsVisible(!controlsVisible);
214
- }, [controlsVisible, setControlsVisible]);
215
-
216
- const showToast = useCallback(
217
- (message: string) => {
218
- setToastMessage(message);
219
- toastOpacity.value = withTiming(1, { duration: 200 });
220
- setTimeout(() => {
221
- toastOpacity.value = withTiming(0, { duration: 200 }, () => {
222
- runOnJS(setToastMessage)(null);
223
- });
224
- }, 2000);
225
- },
226
- // eslint-disable-next-line react-hooks/exhaustive-deps
227
- []
228
- );
229
-
230
- const handlePinchEnd = useCallback(
231
- (finalScale: number) => {
232
- // Determine pinch direction based on scale change
233
- // If scale increased (pinch out) → cover (zoomed to fill)
234
- // If scale decreased (pinch in) → contain (original)
235
- const scaleChange = finalScale - pinchStartScale.current;
236
- const newMode = scaleChange > 0 ? 'cover' : 'contain';
237
- setResizeMode(newMode);
238
-
239
- // Show toast message
240
- const message = newMode === 'cover' ? 'Zoomed to Fill' : 'Original';
241
- showToast(message);
242
- },
243
- [setResizeMode, showToast]
244
- );
245
-
246
- // Animated style for toast
247
- const toastAnimatedStyle = useAnimatedStyle(() => {
248
- return {
249
- opacity: toastOpacity.value,
250
- };
251
- }, []);
252
-
253
- const pinchGesture = useMemo(
254
- () =>
255
- Gesture.Pinch()
256
- .onStart((pinchEvent) => {
257
- 'worklet';
258
- pinchStartScale.current = pinchEvent.scale;
259
- })
260
- .onEnd((pinchEvent) => {
261
- 'worklet';
262
- runOnJS(handlePinchEnd)(pinchEvent.scale);
263
- }),
264
- [handlePinchEnd]
265
- );
266
-
267
- const tapGesture = useMemo(
268
- () =>
269
- Gesture.Tap()
270
- .onEnd(() => {
271
- runOnJS(handleTap)();
272
- })
273
- .maxDuration(250),
274
- [handleTap]
275
- );
276
-
277
- const composedGestures = useMemo(
278
- () => Gesture.Race(pinchGesture, tapGesture),
279
- [pinchGesture, tapGesture]
280
- );
281
-
282
- const handleClose = useCallback(() => {
283
- reportProgress('VIDEO_CLOSE');
284
- // Reset stores after report is sent
285
- setTimeout(() => {
286
- const { resetStore } = useVideoPlayerStore.getState();
287
- const { resetAdsStore } = useAdsPlayerStore.getState();
288
- resetStore();
289
- resetAdsStore();
290
- }, 0);
291
- onClose?.();
292
- }, [reportProgress, onClose]);
293
-
294
- const handlePressEpisode = useCallback(
295
- async ({ episode }: { episode: MediaEpisode }) => {
296
- if (event?.onPressEpisode) {
297
- return await event.onPressEpisode({ episode });
298
- }
299
- return Promise.resolve(true);
300
- },
301
- [event]
302
- );
303
-
304
- return (
305
- <VideoPlayerConfigProvider theme={theme}>
306
- <GestureHandlerRootView style={globalStyles.flexOne}>
307
- <MediaControlsProvider
308
- onClose={handleClose}
309
- onPressEpisode={handlePressEpisode}
310
- reportProgress={reportProgress}
311
- insets={insets}
312
- >
313
- <GestureDetector gesture={composedGestures}>
314
- <View style={globalStyles.flexOneWithBlackBackground}>
315
- <Video
316
- ref={videoRef}
317
- source={videoSource}
318
- paused={effectivePaused}
319
- onProgress={handleProgress}
320
- onLoad={playerEvents.onLoad}
321
- onBuffer={playerEvents.onBuffer}
322
- onEnd={handleVideoEnd}
323
- onLoadStart={playerEvents.onLoadStart}
324
- onError={handleError}
325
- controls={false}
326
- resizeMode={resizeMode || 'contain'}
327
- rate={playBackRate || 1}
328
- selectedAudioTrack={selectedAudioTrackMemo}
329
- selectedTextTrack={selectedTextTrackMemo}
330
- selectedVideoTrack={selectedVideoTrackMemo}
331
- maxBitRate={maxBitRate ?? undefined}
332
- style={videoStyle}
333
- controlsStyles={hideControlsStyles}
334
- ignoreSilentSwitch="ignore"
335
- playInBackground={false}
336
- playWhenInactive={false}
337
- allowsExternalPlayback={true}
338
- bufferConfig={bufferConfig}
339
- />
340
- {toastMessage && (
341
- <Toast
342
- message={toastMessage}
343
- animatedStyle={toastAnimatedStyle}
344
- insets={insets}
345
- position="top"
346
- />
347
- )}
348
- </View>
349
- </GestureDetector>
350
- </MediaControlsProvider>
351
- </GestureHandlerRootView>
352
- </VideoPlayerConfigProvider>
353
- );
354
- };
355
-
356
- export default React.memo(VideoPlayerCore);
@@ -1,211 +0,0 @@
1
- /* eslint-disable react-hooks/exhaustive-deps */
2
- import React, { useEffect, useMemo, useCallback, useRef } from 'react';
3
- import { View, StyleSheet } from 'react-native';
4
- import { Slider } from 'react-native-awesome-slider';
5
- import { useSharedValue, withTiming, Easing } from 'react-native-reanimated';
6
- import { moderateScale } from 'react-native-size-matters';
7
- import { useVideoPlayerConfig } from '../context';
8
-
9
- interface Props {
10
- duration: number;
11
- currentTime: number;
12
- bufferedTime: number;
13
- onSeek?: (time: number) => void;
14
- showThumb?: boolean;
15
- height?: number;
16
- disabled?: boolean;
17
- adMarkers?: number[];
18
- }
19
-
20
- const SEEK_COOLDOWN_MS = 400;
21
- const PROGRESS_ANIM_DURATION = 220;
22
- const CACHE_ANIM_DURATION = 280;
23
- const SMOOTH_EASING = Easing.bezier(0.25, 0.1, 0.25, 1);
24
-
25
- const ProgressBar: React.FC<Props> = React.memo(
26
- ({
27
- duration,
28
- currentTime,
29
- bufferedTime,
30
- onSeek,
31
- showThumb = true,
32
- disabled = false,
33
- adMarkers = [],
34
- height,
35
- }) => {
36
- const { colors, metrics } = useVideoPlayerConfig();
37
- const sliderHeight = height ?? metrics.sliderHeight;
38
- const thumbSize = useMemo(() => {
39
- return sliderHeight * 3;
40
- }, [sliderHeight]);
41
-
42
- const progress = useSharedValue(currentTime);
43
- const cache = useSharedValue(bufferedTime);
44
- const min = useSharedValue(0);
45
- const max = useSharedValue(duration);
46
-
47
- const isSlidingRef = useRef(false);
48
- const seekCooldownUntilRef = useRef(0);
49
- const seekCooldownTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
50
- null
51
- );
52
-
53
- useEffect(() => {
54
- if (isSlidingRef.current) return;
55
- if (Date.now() < seekCooldownUntilRef.current) return;
56
- progress.value = withTiming(currentTime, {
57
- duration: PROGRESS_ANIM_DURATION,
58
- easing: SMOOTH_EASING,
59
- });
60
- }, [currentTime]);
61
-
62
- useEffect(() => {
63
- cache.value = withTiming(bufferedTime, {
64
- duration: CACHE_ANIM_DURATION,
65
- easing: SMOOTH_EASING,
66
- });
67
- }, [bufferedTime]);
68
-
69
- useEffect(() => {
70
- max.value = duration;
71
- }, [duration]);
72
-
73
- const adPositions = useMemo(() => {
74
- if (duration <= 0) return [];
75
- return adMarkers.map((t) => (t / duration) * 100);
76
- }, [adMarkers, duration]);
77
-
78
- const handleSeek = useCallback(
79
- (value: number) => {
80
- if (!disabled) onSeek?.(value);
81
- },
82
- [onSeek, disabled]
83
- );
84
-
85
- const handleSlidingStart = useCallback(() => {
86
- isSlidingRef.current = true;
87
- if (seekCooldownTimeoutRef.current) {
88
- clearTimeout(seekCooldownTimeoutRef.current);
89
- seekCooldownTimeoutRef.current = null;
90
- }
91
- }, []);
92
-
93
- const handleSlidingComplete = useCallback(
94
- (value: number) => {
95
- progress.value = value;
96
- seekCooldownUntilRef.current = Date.now() + SEEK_COOLDOWN_MS;
97
- seekCooldownTimeoutRef.current = setTimeout(() => {
98
- isSlidingRef.current = false;
99
- seekCooldownTimeoutRef.current = null;
100
- }, SEEK_COOLDOWN_MS);
101
- },
102
- [progress]
103
- );
104
-
105
- useEffect(() => {
106
- return () => {
107
- if (seekCooldownTimeoutRef.current) {
108
- clearTimeout(seekCooldownTimeoutRef.current);
109
- }
110
- };
111
- }, []);
112
-
113
- return (
114
- <View style={[styles.container, { height: thumbSize }]}>
115
- <Slider
116
- progress={progress}
117
- minimumValue={min}
118
- maximumValue={max}
119
- cache={cache}
120
- disable={disabled}
121
- onSlidingStart={handleSlidingStart}
122
- onSlidingComplete={handleSlidingComplete}
123
- onValueChange={handleSeek}
124
- containerStyle={[
125
- styles.sliderContainer,
126
- {
127
- borderRadius: sliderHeight / 2,
128
- height: sliderHeight,
129
- },
130
- ]}
131
- renderThumb={
132
- showThumb
133
- ? () => (
134
- <View
135
- style={{
136
- backgroundColor: colors.primary,
137
- width: thumbSize,
138
- height: thumbSize,
139
- borderRadius: thumbSize / 2,
140
- }}
141
- />
142
- )
143
- : () => null
144
- }
145
- renderBubble={() => null}
146
- thumbWidth={showThumb ? thumbSize : 0}
147
- theme={{
148
- minimumTrackTintColor: colors.primary,
149
- maximumTrackTintColor: colors.secondary,
150
- cacheTrackTintColor: colors.buffer,
151
- disableMinTrackTintColor: colors.primary,
152
- bubbleBackgroundColor: colors.white,
153
- }}
154
- />
155
-
156
- {/* Ad Markers */}
157
- {adPositions.length > 0 && (
158
- <View style={styles.adMarkersContainer} pointerEvents="none">
159
- {adPositions.map((pos, index) => (
160
- <View
161
- key={`ad-${index}`}
162
- style={[
163
- styles.adMarker,
164
- {
165
- left: `${pos}%`,
166
- backgroundColor: colors.primary,
167
- width: sliderHeight,
168
- },
169
- ]}
170
- />
171
- ))}
172
- </View>
173
- )}
174
- </View>
175
- );
176
- },
177
- (p, n) =>
178
- p.currentTime === n.currentTime &&
179
- p.bufferedTime === n.bufferedTime &&
180
- p.duration === n.duration &&
181
- p.disabled === n.disabled &&
182
- p.showThumb === n.showThumb &&
183
- p.height === n.height &&
184
- JSON.stringify(p.adMarkers) === JSON.stringify(n.adMarkers)
185
- );
186
-
187
- export default ProgressBar;
188
-
189
- const styles = StyleSheet.create({
190
- container: {
191
- position: 'relative',
192
- width: '100%',
193
- overflow: 'hidden',
194
- justifyContent: 'center',
195
- },
196
- sliderContainer: {
197
- overflow: 'hidden',
198
- },
199
- adMarkersContainer: {
200
- position: 'absolute',
201
- width: '100%',
202
- height: '100%',
203
- justifyContent: 'center',
204
- },
205
- adMarker: {
206
- position: 'absolute',
207
- aspectRatio: 1,
208
- top: '50%',
209
- transform: [{ translateY: -moderateScale(2.5) }],
210
- },
211
- });