@applicaster/quick-brick-player 13.0.0-rc.11 → 13.0.0-rc.111

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 (43) hide show
  1. package/package.json +27 -14
  2. package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
  3. package/src/Player/AudioLayer/AudioDescription.tsx +5 -7
  4. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +174 -280
  5. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +27 -0
  6. package/src/Player/AudioLayer/Layout/Controls/index.tsx +316 -0
  7. package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +7 -25
  8. package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
  9. package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +44 -74
  10. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +230 -0
  11. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +83 -0
  12. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +25 -0
  13. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +101 -0
  14. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +26 -0
  15. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +215 -0
  16. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +223 -0
  17. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +115 -0
  18. package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
  19. package/src/Player/AudioLayer/Layout/const.ts +22 -0
  20. package/src/Player/AudioLayer/Layout/debug.ts +6 -0
  21. package/src/Player/AudioLayer/Layout/hooks/index.ts +5 -0
  22. package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
  23. package/src/Player/AudioLayer/Layout/hooks/useTabletLayoutImageSize.ts +105 -0
  24. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
  25. package/src/Player/AudioLayer/Layout/index.tsx +21 -48
  26. package/src/Player/AudioLayer/Layout/types.ts +7 -0
  27. package/src/Player/AudioLayer/SleepTimerManager.ts +119 -0
  28. package/src/Player/AudioLayer/SpeedManager.ts +52 -0
  29. package/src/Player/AudioLayer/utils.ts +27 -0
  30. package/src/Player/Const/sleepTimerOptions.ts +39 -0
  31. package/src/Player/Const/speedOptions.ts +4 -0
  32. package/src/Player/Utils/Utils.ts +0 -5
  33. package/src/Player/Utils/index.tsx +117 -0
  34. package/src/Player/hooks/useIsCasting.tsx +57 -0
  35. package/src/Player/index.tsx +39 -22
  36. package/src/QuickBrickPlayer.tsx +3 -0
  37. package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
  38. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
  39. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
  40. package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
  41. package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
  42. package/src/Player/Helpers/VideoResizeMode.ts +0 -7
  43. package/src/utils/utils.ts +0 -25
@@ -1,7 +1,13 @@
1
1
  import * as React from "react";
2
- import { ViewStyle, View } from "react-native";
2
+ import { useEffect, useState } from "react";
3
+ import {
4
+ Dimensions as ScreenDimensions,
5
+ StyleSheet,
6
+ View,
7
+ ViewStyle,
8
+ } from "react-native";
3
9
 
4
- import { SafeAreaView, Edge } from "react-native-safe-area-context";
10
+ import { Edge, SafeAreaView } from "react-native-safe-area-context";
5
11
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
6
12
  import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
7
13
  import * as R from "ramda";
@@ -15,24 +21,31 @@ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
15
21
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
16
22
  import { PlayerDetails } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/PlayerDetails";
17
23
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
18
- import { useEffect, useState } from "react";
19
- import { MagicBG } from "./MagicBG";
24
+ import { formatSpeed } from "./utils";
20
25
  import {
21
- formatSpeed,
22
- hasDatePassed,
23
- loadItemsFromStorage,
24
- NAMESPACE,
25
- } from "./utils";
26
- import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
27
- import { addQueryParam, getLiveUrl } from "../Utils";
26
+ getBottomSheetModalDefaultItemIcon,
27
+ getBottomSheetModalIconProps,
28
+ getBottomSheetModalItemProps,
29
+ getBottomSheetModalLabelProps,
30
+ getBottomSheetModalSelectedItemIcon,
31
+ } from "../Utils";
28
32
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
29
33
  import {
34
+ AnimatedScrollModal,
30
35
  AnimationComponent,
31
36
  ComponentAnimationType,
32
- AnimatedScrollModal,
33
37
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
34
- import { PADDING_HORIZONTAL } from "./Layout/defaultLayoutsConts";
38
+ import { PADDING_HORIZONTAL } from "./Layout/const";
35
39
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
40
+ import {
41
+ SLEEP_TIMER_OFF,
42
+ SleepTimerController,
43
+ SleepTimerState,
44
+ } from "./SleepTimerManager";
45
+ import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
46
+ import { openBottomSheetModal } from "@applicaster/zapp-react-native-utils/modalState";
47
+ import { getSleepTimerOptions } from "../Const/sleepTimerOptions";
48
+ import { speedOptions } from "../Const/speedOptions";
36
49
 
37
50
  const { log_debug } = createLogger({
38
51
  subsystem: "UIComponent",
@@ -48,8 +61,8 @@ type Dimensions = {
48
61
 
49
62
  type Configuration = {
50
63
  [key: string]: any;
51
- magic_background?: boolean;
52
64
  audio_player_background_image_query?: string;
65
+ audio_player_background_image_default_color?: string;
53
66
  tablet_landscape_sidebar_width?: string;
54
67
  tablet_landscape_player_container_background_color?: string;
55
68
  };
@@ -57,7 +70,6 @@ type Configuration = {
57
70
  type Props = {
58
71
  children: React.ReactNode;
59
72
  inline?: boolean;
60
- docked?: boolean;
61
73
  configuration: Configuration;
62
74
  style: ViewStyle & Dimensions;
63
75
  entry: ZappEntry;
@@ -71,57 +83,27 @@ type Props = {
71
83
  isTabletPortrait?: boolean;
72
84
  };
73
85
 
74
- export const defaultAspectRatioWidth = (height: number): number =>
75
- (height / 9) * 16;
76
-
77
- const Styles = {
78
- mainContainer: (style: ViewStyle) => {
79
- const combinedStyle: ViewStyle = {
80
- flex: 1,
81
- };
86
+ const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
82
87
 
83
- return {
84
- ...combinedStyle,
85
- ...style,
86
- };
87
- },
88
+ const Styles = StyleSheet.create({
88
89
  playerContainer: {
89
90
  flex: 1,
90
91
  },
91
92
  paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
92
-
93
- controlsMobile: {
94
- height: 50,
95
- marginHorizontal: 24,
96
- },
97
- controlsTablet: {
98
- height: 96,
99
- marginHorizontal: 24,
100
- },
101
- playerDetails: { marginTop: 60 },
102
-
103
- linearGradient: {
104
- flex: 1,
93
+ playerDetails: {
94
+ marginTop: 60,
95
+ alignSelf: "center",
96
+ width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
105
97
  },
106
- };
98
+ });
107
99
 
108
- const sleeps = [
109
- // { label: "End of episode", value: "episode" },
110
- { label: "5 minutes", value: 5 },
111
- { label: "10 minutes", value: 10 },
112
- { label: "15 minutes", value: 15 },
113
- { label: "30 minutes", value: 30 },
114
- { label: "45 minutes", value: 45 },
115
- { label: "1 hour", value: 60 },
116
- { label: "2 hours", value: 120 },
117
- ];
100
+ const edges: Edge[] = ["right", "left", "top"];
118
101
 
119
102
  export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
120
103
  const player = usePlayer();
121
104
  const playerState = usePlayerState("audio-player-wrapper");
122
105
 
123
106
  const {
124
- docked,
125
107
  configuration,
126
108
  style,
127
109
  entry,
@@ -131,40 +113,39 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
131
113
  isTabletPortrait,
132
114
  } = props;
133
115
 
134
- const speeds = [
135
- { asset: configuration["speed_0_8"], value: 0.8 },
136
- { asset: configuration["speed_1"], value: 1.0 },
137
- { asset: configuration["speed_1_2"], value: 1.2 },
138
- { asset: configuration["speed_1_5"], value: 1.5 },
139
- { asset: configuration["speed_2"], value: 2.0 },
140
- ];
141
-
142
116
  const isTablet = useIsTablet();
143
117
 
144
118
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
145
119
 
146
- // TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
147
-
148
- const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
149
-
150
120
  const { title, summary } = useTitleSummaryOverlay(
151
- feedUrl,
152
121
  entry,
153
122
  playerState?.isLive,
154
123
  configuration?.audio_live_player_update_interval
155
124
  );
156
125
 
157
- const [playbackSpeed, setPlaybackSpeed] = useState({
158
- asset: configuration["speed_1"],
159
- value: 1.0,
160
- });
126
+ const [sleepTimerManager, setSleepTimerManager] =
127
+ useState<SleepTimerController | null>(null);
161
128
 
162
- const [sleepTimer, setSleepTimer] = useState({
163
- label: "playback_sleep_off_label",
164
- value: 0,
165
- });
129
+ const [speedManager, setSpeedManager] = useState<SpeedController | null>(
130
+ null
131
+ );
132
+
133
+ useEffect(() => {
134
+ if (player) {
135
+ setSleepTimerManager(new SleepTimerController(player));
136
+ setSpeedManager(new SpeedController(player));
137
+ } else {
138
+ setSleepTimerManager(null);
139
+ setSpeedManager(null);
140
+ }
141
+ }, [player]);
166
142
 
167
- const [sleepTimerDate, setSleepTimerDate] = useState(0);
143
+ const [playbackSpeed, setPlaybackSpeed] =
144
+ useState<PlaybackSpeed>(DEFAULT_SPEED);
145
+
146
+ const [sleepTimerState, setSleepTimerState] = useState<SleepTimerState>(
147
+ new SleepTimerState(SLEEP_TIMER_OFF, 0)
148
+ );
168
149
 
169
150
  const [defaultDimensions, setDefaultDimensions] =
170
151
  React.useState<Dimensions>(undefined);
@@ -174,8 +155,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
174
155
  height: 0,
175
156
  });
176
157
 
177
- const navigator = useNavigation();
178
-
179
158
  const { maximiseVideoModal } = useNavigation();
180
159
 
181
160
  const onLayout = (event: any) => {
@@ -189,82 +168,27 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
189
168
  if (!defaultDimensions) setDefaultDimensions({ width, height });
190
169
  };
191
170
 
192
- const cancelSleepTimer = async () => {
193
- player?.cancelSleepTimer();
194
-
195
- setSleepTimer({
196
- label: "playback_sleep_off_label",
197
- value: 0,
198
- });
199
-
200
- setSleepTimerDate(0);
201
-
202
- await localStorage.removeItem("sleep", NAMESPACE);
203
- };
204
-
205
- const startSleepTimer = (timerValue: number) => {
206
- try {
207
- const currentDate = new Date();
208
- const futureDate = new Date(currentDate.getTime() + timerValue * 60000);
209
- const futureSleepDate = futureDate.getTime();
210
-
211
- player?.cancelSleepTimer();
212
-
213
- player?.startSleepTimer(futureSleepDate);
214
-
215
- return futureSleepDate;
216
- } catch (e) {
217
- return 0;
218
- }
219
- };
220
-
221
- const handleSleep = async (
222
- timerValue: number,
223
- currentFutureSleepDate = null
224
- ) => {
225
- if (currentFutureSleepDate) {
226
- if (hasDatePassed(currentFutureSleepDate)) {
227
- await cancelSleepTimer();
228
-
229
- return 0;
230
- }
231
-
232
- return currentFutureSleepDate;
233
- }
234
-
235
- if (timerValue === 0) {
236
- await cancelSleepTimer();
237
-
238
- return timerValue;
239
- }
240
-
241
- return startSleepTimer(timerValue);
242
- };
243
-
244
171
  useEffect(() => {
245
- const loadSpeed = async () => {
246
- const speed = await loadItemsFromStorage("speed");
247
-
248
- if (playerState.isReadyToPlay && speed) {
249
- setPlaybackSpeed(speed);
250
- player?.setPlaybackRate(speed.value);
251
- }
252
- };
172
+ const sleepSubscription =
173
+ sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
253
174
 
254
- const loadSleep = async () => {
255
- const sleep = await loadItemsFromStorage("sleep");
175
+ const speedSubscription =
176
+ speedManager?.playbackSpeed$.subscribe(setPlaybackSpeed);
256
177
 
257
- if (playerState.isReadyToPlay && sleep) {
258
- const { futureSleepDate, ...rest } = sleep;
259
- setSleepTimer(rest);
260
- const sleepTimerDate = await handleSleep(sleep.value, futureSleepDate);
261
- setSleepTimerDate(sleepTimerDate);
262
- }
178
+ return () => {
179
+ sleepSubscription?.unsubscribe();
180
+ speedSubscription?.unsubscribe();
263
181
  };
182
+ }, [sleepTimerManager, speedManager]);
264
183
 
265
- loadSpeed().then();
266
- loadSleep().then();
267
- }, [playerState.isReadyToPlay]);
184
+ useEffect(() => {
185
+ if (!playerState.isReadyToPlay) {
186
+ return;
187
+ }
188
+
189
+ void speedManager?.loadSpeed();
190
+ void sleepTimerManager?.loadSleep();
191
+ }, [playerState.isReadyToPlay, speedManager, sleepTimerManager]);
268
192
 
269
193
  const getValue = (key: string, stylesObj: {}) =>
270
194
  R.propOr(null, key, stylesObj);
@@ -292,7 +216,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
292
216
 
293
217
  const onPlaybackButtonPress = React.useCallback(() => {
294
218
  if (playerState.isBuffering) return;
295
- playerState.isPaused ? player?.play() : player.pause();
219
+ playerState.isPaused ? player?.play() : player?.pause();
296
220
  }, [playerState, player]);
297
221
 
298
222
  const seekDuration = toNumberWithDefault(10, value("seek_duration"));
@@ -307,57 +231,77 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
307
231
 
308
232
  const onSpeedSelect = React.useCallback(
309
233
  async (item) => {
310
- setPlaybackSpeed(item);
311
- player.setPlaybackRate(item.value);
312
- await localStorage.setItem("speed", item, NAMESPACE);
234
+ await speedManager?.setPlaybackSpeed(item);
313
235
  },
314
- [player, setPlaybackSpeed]
236
+ [speedManager]
315
237
  );
316
238
 
317
239
  const onSleepSelect = React.useCallback(
318
240
  async (item) => {
319
- setSleepTimer(item);
320
- const futureSleepDate = await handleSleep(item.value);
321
- setSleepTimerDate(futureSleepDate);
322
-
323
- await localStorage.setItem(
324
- "sleep",
325
- { ...item, futureSleepDate },
326
- NAMESPACE
327
- );
241
+ await sleepTimerManager?.setSleepTimer(item);
328
242
  },
329
- [player, setSleepTimer]
243
+ [sleepTimerManager]
330
244
  );
331
245
 
332
246
  const onSpeedButtonPress = React.useCallback(() => {
333
- navigator.openModalBottomSheet({
247
+ openBottomSheetModal({
334
248
  modalBottomSheetContentProps: {
335
- items: speeds,
249
+ items: speedOptions,
336
250
  current_selection: playbackSpeed,
337
251
  onPress: onSpeedSelect,
338
252
  title: configuration["playback_speed_title"],
253
+ itemProps: getBottomSheetModalItemProps,
254
+ iconProps: getBottomSheetModalIconProps,
255
+ labelProps: getBottomSheetModalLabelProps,
256
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
257
+ getDefaultItemIcon: getBottomSheetModalDefaultItemIcon,
258
+ iconPlacement: "right",
339
259
  },
340
260
  options: {
341
- supportedOrientations: ["portrait"],
261
+ supportedOrientations: [
262
+ "portrait",
263
+ "landscape",
264
+ "portrait-upside-down",
265
+ ],
342
266
  },
343
267
  });
344
- }, [playbackSpeed, setPlaybackSpeed]);
268
+ }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
345
269
 
346
270
  const onSleepButtonPress = React.useCallback(() => {
347
- navigator.openModalBottomSheet({
271
+ openBottomSheetModal({
348
272
  modalBottomSheetContentProps: {
349
- items: [
350
- { label: configuration["playback_sleep_off_label"], value: 0 },
351
- ].concat(sleeps),
352
- current_selection: sleepTimer,
273
+ items: getSleepTimerOptions(configuration),
274
+ current_selection: sleepTimerState.timer,
353
275
  onPress: onSleepSelect,
354
276
  title: configuration["playback_sleep_title"],
277
+ itemProps: getBottomSheetModalItemProps,
278
+ iconProps: getBottomSheetModalIconProps,
279
+ labelProps: getBottomSheetModalLabelProps,
280
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
281
+ iconPlacement: "right",
355
282
  },
356
283
  options: {
357
- supportedOrientations: ["portrait"],
284
+ supportedOrientations: [
285
+ "portrait",
286
+ "landscape",
287
+ "portrait-upside-down",
288
+ ],
358
289
  },
359
290
  });
360
- }, [sleepTimer, setSleepTimer, configuration]);
291
+ }, [
292
+ sleepTimerState.timer,
293
+ configuration["playback_sleep_title"],
294
+ configuration["playback_sleep_off_label"],
295
+ onSleepSelect,
296
+ ]);
297
+
298
+ // This method does not actually cancel the sleep timer
299
+ // (and should not to avoid race condition),
300
+ // it just performs the cleanup when timer expires
301
+ // TODO: rename it in code above
302
+ const cancelSleepTimer = React.useCallback(() => {
303
+ sleepTimerManager?.onTimerExpired();
304
+ }, [sleepTimerManager]);
361
305
 
362
306
  const onCloseVideoModal = React.useCallback(() => {
363
307
  playerManager.close();
@@ -378,111 +322,61 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
378
322
  player?.seekTo(0);
379
323
  }, [player]);
380
324
 
381
- const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
382
-
383
- const ContainerView = SafeAreaView;
384
-
385
- const MainContent = React.useMemo(() => {
386
- return (
387
- <ContainerView style={Styles.mainContainer(style)} edges={edges}>
388
- <AnimationComponent
389
- animationType={ComponentAnimationType.moveUpComponent}
390
- additionalData={{ saveArea: true }}
391
- style={Styles.playerContainer}
392
- >
393
- <AnimatedScrollModal>
394
- <View style={Styles.playerContainer} onLayout={onLayout}>
395
- <Layout
396
- entry={entry}
397
- playerState={playerState}
398
- layoutState={layoutState}
399
- value={value}
400
- onPlaybackButtonPress={onPlaybackButtonPress}
401
- onRewindButtonPress={onRewindButtonPress}
402
- onForwardButtonPress={onForwardButtonPress}
403
- onPlayerSeek={onPlayerSeek}
404
- onSkipStart={onSkipStart}
405
- onSpeedButtonPress={onSpeedButtonPress}
406
- onSleepButtonPress={onSleepButtonPress}
407
- playbackSpeedName={formatSpeed(playbackSpeed.value)}
408
- playbackSleepName={
409
- sleepTimer.value === 0 ? "sleep_timer" : "sleep_timer_active"
410
- }
411
- sleepTimerDate={sleepTimerDate}
412
- cancelSleepTimer={cancelSleepTimer}
413
- onSkipLive={onSkipLive}
414
- onCloseVideoModal={onCloseVideoModal}
415
- maximiseVideoModal={maximiseVideoModal}
416
- configuration={configuration}
417
- dimensions={dimensions}
418
- playNextData={playNextData}
419
- title={title}
420
- summary={summary}
421
- defaultDimensions={defaultDimensions}
422
- />
423
- <View style={Styles.paddingHorizontal}>
424
- {children}
425
- <AnimationComponent
426
- animationType={ComponentAnimationType.componentFade}
427
- >
428
- <PlayerDetails
429
- configuration={configuration}
430
- style={Styles.playerDetails}
431
- entry={entry}
432
- isTabletLandscape={isTabletLandscape}
433
- isAudioPlayer={true}
434
- />
435
- </AnimationComponent>
436
- </View>
437
- </View>
438
- </AnimatedScrollModal>
439
- </AnimationComponent>
440
- </ContainerView>
441
- );
442
- }, [
443
- docked,
444
- style,
445
- entry,
446
- playerState,
447
- layoutState,
448
- value,
449
- onPlaybackButtonPress,
450
- onRewindButtonPress,
451
- onForwardButtonPress,
452
- onPlayerSeek,
453
- onCloseVideoModal,
454
- maximiseVideoModal,
455
- configuration,
456
- dimensions,
457
- children,
458
- playNextData,
459
- onSkipStart,
460
- onSkipLive,
461
- sleepTimer.value,
462
- sleepTimerDate,
463
- ]);
464
-
465
- if (configuration.magic_background) {
466
- const baseUrl = entry?.extensions?.audio_player_background_image ?? "";
467
-
468
- const queryParamName =
469
- configuration.audio_player_background_image_query || "width";
470
-
471
- const queryParamValue = 15;
472
-
473
- const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
474
-
475
- return (
476
- <MagicBG
477
- image={url}
478
- fallbackUrl={baseUrl}
479
- colors={entry?.extensions?.backgroundColors}
480
- defaultColor="#000000"
325
+ return (
326
+ <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
327
+ <AnimationComponent
328
+ animationType={ComponentAnimationType.moveUpComponent}
329
+ additionalData={{ saveArea: true }}
330
+ style={Styles.playerContainer}
481
331
  >
482
- {MainContent}
483
- </MagicBG>
484
- );
485
- }
486
-
487
- return MainContent;
332
+ <AnimatedScrollModal>
333
+ <View style={Styles.playerContainer} onLayout={onLayout}>
334
+ <Layout
335
+ entry={entry}
336
+ playerState={playerState}
337
+ layoutState={layoutState}
338
+ value={value}
339
+ onPlaybackButtonPress={onPlaybackButtonPress}
340
+ onRewindButtonPress={onRewindButtonPress}
341
+ onForwardButtonPress={onForwardButtonPress}
342
+ onPlayerSeek={onPlayerSeek}
343
+ onSkipStart={onSkipStart}
344
+ onSpeedButtonPress={onSpeedButtonPress}
345
+ onSleepButtonPress={onSleepButtonPress}
346
+ playbackSpeedName={formatSpeed(playbackSpeed.value)}
347
+ playbackSleepName={
348
+ sleepTimerState.timer.value === 0
349
+ ? "sleep_timer"
350
+ : "sleep_timer_active"
351
+ }
352
+ sleepTimerDate={sleepTimerState.timerDate}
353
+ cancelSleepTimer={cancelSleepTimer}
354
+ onSkipLive={onSkipLive}
355
+ onCloseVideoModal={onCloseVideoModal}
356
+ maximiseVideoModal={maximiseVideoModal}
357
+ configuration={configuration}
358
+ dimensions={dimensions}
359
+ playNextData={playNextData}
360
+ title={title}
361
+ summary={summary}
362
+ />
363
+ <View style={Styles.paddingHorizontal}>
364
+ {children}
365
+ <AnimationComponent
366
+ animationType={ComponentAnimationType.componentFade}
367
+ >
368
+ <PlayerDetails
369
+ isAudioPlayer
370
+ configuration={configuration}
371
+ style={Styles.playerDetails}
372
+ entry={entry}
373
+ isTabletLandscape={isTabletLandscape}
374
+ />
375
+ </AnimationComponent>
376
+ </View>
377
+ </View>
378
+ </AnimatedScrollModal>
379
+ </AnimationComponent>
380
+ </SafeAreaView>
381
+ );
488
382
  };
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ import { View, StyleSheet } from "react-native";
3
+
4
+ import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
5
+
6
+ import { TABLET_VERTICAL_SEPARATOR_HEIGHT } from "../const";
7
+
8
+ import { withDebug } from "../debug";
9
+
10
+ const styles = StyleSheet.create({
11
+ flexingHeight: {
12
+ flex: 1,
13
+
14
+ ...withDebug({ backgroundColor: "red" }),
15
+ },
16
+ fixedHeight: {
17
+ height: TABLET_VERTICAL_SEPARATOR_HEIGHT,
18
+
19
+ ...withDebug({ backgroundColor: "red" }),
20
+ },
21
+ });
22
+
23
+ export const VerticalGutter = () => {
24
+ const isTablet = useIsTablet();
25
+
26
+ return <View style={isTablet ? styles.fixedHeight : styles.flexingHeight} />;
27
+ };