@applicaster/quick-brick-player 13.0.0-alpha.5790181722 → 13.0.0-alpha.5814285061

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 (32) hide show
  1. package/package.json +5 -6
  2. package/src/Player/AudioLayer/AudioDescription.tsx +109 -68
  3. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +75 -133
  4. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +23 -5
  5. package/src/Player/AudioLayer/Layout/Controls/index.tsx +34 -19
  6. package/src/Player/AudioLayer/Layout/Controls/utils.ts +3 -11
  7. package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
  8. package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +21 -19
  9. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +35 -17
  10. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +8 -8
  11. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +2 -9
  12. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +37 -20
  13. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +12 -0
  14. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +75 -75
  15. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +5 -6
  16. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +39 -13
  17. package/src/Player/AudioLayer/Layout/const.ts +6 -0
  18. package/src/Player/AudioLayer/Layout/debug.ts +1 -1
  19. package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -1
  20. package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
  21. package/src/Player/AudioLayer/Layout/hooks/{useImageSize.ts → useTabletLayoutImageSize.ts} +7 -3
  22. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +1 -1
  23. package/src/Player/AudioLayer/Layout/utils.ts +7 -0
  24. package/src/Player/Const/sleepTimerOptions.ts +39 -10
  25. package/src/Player/hooks/useIsCasting.tsx +57 -0
  26. package/src/Player/index.tsx +10 -5
  27. package/src/QuickBrickPlayer.tsx +3 -0
  28. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
  29. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
  30. package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
  31. package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
  32. package/src/utils/utils.ts +0 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/quick-brick-player",
3
- "version": "13.0.0-alpha.5790181722",
3
+ "version": "13.0.0-alpha.5814285061",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
@@ -35,11 +35,11 @@
35
35
  },
36
36
  "homepage": "https://github.com/applicaster/quickbrick#readme",
37
37
  "dependencies": {
38
- "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.95",
38
+ "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.112",
39
39
  "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
40
- "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.5790181722",
41
- "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.5790181722",
42
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.5790181722",
40
+ "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.5814285061",
41
+ "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.5814285061",
42
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.5814285061",
43
43
  "query-string": "7.1.3",
44
44
  "react-native-web-linear-gradient": "1.1.2",
45
45
  "shaka-player": "4.3.5",
@@ -52,7 +52,6 @@
52
52
  "@applicaster/applicaster-types": "*",
53
53
  "@applicaster/blur": "*",
54
54
  "@applicaster/quick-brick-xray": "*",
55
- "@applicaster/react-native-color-thief": "*",
56
55
  "@applicaster/zapp-pipes-v2-client": "*",
57
56
  "@applicaster/zapp-react-dom-ui-components": "*",
58
57
  "@applicaster/zapp-react-native-redux": "*",
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Text, TextStyle } from "react-native";
2
+ import { StyleSheet, Text, TextStyle, View } from "react-native";
3
3
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
4
4
 
5
5
  type AudioDescriptionProps = {
@@ -10,84 +10,125 @@ type AudioDescriptionProps = {
10
10
  docked: boolean;
11
11
  isModal: boolean;
12
12
  };
13
+ maxWidth?: number;
13
14
  value: GetValue;
14
15
  };
15
16
 
16
- const titleStyles = (value: GetValue, prefix: string): TextStyle => ({
17
- textAlign: "left",
18
- color: value(`${prefix}title_color`),
19
- alignSelf: "center",
20
- paddingBottom: 5,
21
- lineHeight:
22
- Number(
23
- platformSelect({
24
- ios: value(`${prefix}title_lineheight_ios`),
25
- android: value(`${prefix}title_lineheight_android`),
26
- })
27
- ) || 18,
28
- letterSpacing:
29
- Number(
30
- platformSelect({
31
- ios: value(`${prefix}title_letterspacing_ios`),
32
- android: value(`${prefix}title_letterspacing_android`),
33
- })
34
- ) || 0,
35
- fontSize:
36
- Number(
37
- platformSelect({
38
- ios: value(`${prefix}title_fontsize_ios`),
39
- android: value(`${prefix}title_fontsize_android`),
40
- })
41
- ) || 16,
42
- fontFamily: platformSelect({
43
- ios: value(`${prefix}title_font_ios`),
44
- android: value(`${prefix}title_font_android`),
45
- }),
46
- });
17
+ const TITLE_PADDING_BOTTOM = 5;
18
+ const TITLE_LINES = 2;
19
+ const SUBTITLE_LINES = 1;
47
20
 
48
- const summaryStyles = (value: GetValue, prefix: string): TextStyle => ({
49
- textAlign: "left",
50
- color: value(`${prefix}subtitle_color`),
51
- alignSelf: "center",
52
- lineHeight:
53
- Number(
54
- platformSelect({
55
- ios: value(`${prefix}subtitle_lineheight_ios`),
56
- android: value(`${prefix}subtitle_lineheight_android`),
57
- })
58
- ) || 18,
59
- letterSpacing:
60
- Number(
61
- platformSelect({
62
- ios: value(`${prefix}subtitle_letterspacing_ios`),
63
- android: value(`${prefix}subtitle_letterspacing_android`),
64
- })
65
- ) || 0,
66
- fontSize:
67
- Number(
68
- platformSelect({
69
- ios: value(`${prefix}subtitle_fontsize_ios`),
70
- android: value(`${prefix}subtitle_fontsize_android`),
71
- })
72
- ) || 13,
73
- fontFamily: platformSelect({
74
- ios: value(`${prefix}subtitle_font_ios`),
75
- android: value(`${prefix}subtitle_font_android`),
76
- }),
21
+ const styles = StyleSheet.create({
22
+ wrapper: {
23
+ width: "100%",
24
+ alignSelf: "center",
25
+ alignItems: "center",
26
+ justifyContent: "center",
27
+ },
28
+ titleText: {
29
+ textAlign: "center",
30
+ alignSelf: "center",
31
+ paddingBottom: TITLE_PADDING_BOTTOM,
32
+ },
33
+ summaryText: {
34
+ textAlign: "left",
35
+ alignSelf: "center",
36
+ },
77
37
  });
78
38
 
39
+ const getTitleStyles = (value: GetValue, prefix: string) =>
40
+ ({
41
+ color: value(`${prefix}title_color`),
42
+ lineHeight:
43
+ Number(
44
+ platformSelect({
45
+ ios: value(`${prefix}title_lineheight_ios`),
46
+ android: value(`${prefix}title_lineheight_android`),
47
+ })
48
+ ) || 18,
49
+ letterSpacing:
50
+ Number(
51
+ platformSelect({
52
+ ios: value(`${prefix}title_letterspacing_ios`),
53
+ android: value(`${prefix}title_letterspacing_android`),
54
+ })
55
+ ) || 0,
56
+ fontSize:
57
+ Number(
58
+ platformSelect({
59
+ ios: value(`${prefix}title_fontsize_ios`),
60
+ android: value(`${prefix}title_fontsize_android`),
61
+ })
62
+ ) || 16,
63
+ fontFamily: platformSelect({
64
+ ios: value(`${prefix}title_font_ios`),
65
+ android: value(`${prefix}title_font_android`),
66
+ }),
67
+ }) as const;
68
+
69
+ const getSummaryStyles = (value: GetValue, prefix: string): TextStyle =>
70
+ ({
71
+ color: value(`${prefix}subtitle_color`),
72
+ lineHeight:
73
+ Number(
74
+ platformSelect({
75
+ ios: value(`${prefix}subtitle_lineheight_ios`),
76
+ android: value(`${prefix}subtitle_lineheight_android`),
77
+ })
78
+ ) || 18,
79
+ letterSpacing:
80
+ Number(
81
+ platformSelect({
82
+ ios: value(`${prefix}subtitle_letterspacing_ios`),
83
+ android: value(`${prefix}subtitle_letterspacing_android`),
84
+ })
85
+ ) || 0,
86
+ fontSize:
87
+ Number(
88
+ platformSelect({
89
+ ios: value(`${prefix}subtitle_fontsize_ios`),
90
+ android: value(`${prefix}subtitle_fontsize_android`),
91
+ })
92
+ ) || 13,
93
+ fontFamily: platformSelect({
94
+ ios: value(`${prefix}subtitle_font_ios`),
95
+ android: value(`${prefix}subtitle_font_android`),
96
+ }),
97
+ }) as const;
98
+
99
+ const getHeight = (titleLineHeight: number, subtitleLineHeight) =>
100
+ titleLineHeight * TITLE_LINES + subtitleLineHeight + TITLE_PADDING_BOTTOM;
101
+
79
102
  export const AudioDescription = (props: AudioDescriptionProps) => {
80
- const { title, summary, layoutState, value } = props;
103
+ const { title, summary, layoutState, value, maxWidth } = props;
81
104
  const prefix = layoutState.docked ? "docked_player_" : "";
82
105
 
106
+ const summaryStyles = getSummaryStyles(value, prefix);
107
+ const titleStyles = getTitleStyles(value, prefix);
108
+
109
+ const height = getHeight(titleStyles.lineHeight, summaryStyles.lineHeight);
110
+
83
111
  return (
84
- <>
85
- <Text style={titleStyles(value, prefix)} numberOfLines={1}>
112
+ <View
113
+ style={[
114
+ styles.wrapper,
115
+ {
116
+ maxWidth,
117
+ height,
118
+ },
119
+ ]}
120
+ >
121
+ <Text style={[styles.titleText, titleStyles]} numberOfLines={TITLE_LINES}>
86
122
  {title}
87
123
  </Text>
88
- <Text style={summaryStyles(value, prefix)} numberOfLines={1}>
89
- {summary}
90
- </Text>
91
- </>
124
+ {summary ? (
125
+ <Text
126
+ style={[styles.summaryText, summaryStyles]}
127
+ numberOfLines={SUBTITLE_LINES}
128
+ >
129
+ {summary}
130
+ </Text>
131
+ ) : null}
132
+ </View>
92
133
  );
93
134
  };
@@ -1,12 +1,13 @@
1
1
  import * as React from "react";
2
+ import { useEffect, useState } from "react";
2
3
  import {
4
+ Dimensions as ScreenDimensions,
3
5
  StyleSheet,
4
- ViewStyle,
5
6
  View,
6
- Dimensions as ScreenDimensions,
7
+ ViewStyle,
7
8
  } from "react-native";
8
9
 
9
- import { SafeAreaView, Edge } from "react-native-safe-area-context";
10
+ import { Edge, SafeAreaView } from "react-native-safe-area-context";
10
11
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
11
12
  import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
12
13
  import * as R from "ramda";
@@ -20,11 +21,8 @@ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
20
21
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
21
22
  import { PlayerDetails } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/PlayerDetails";
22
23
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
23
- import { useEffect, useState } from "react";
24
- import { MagicBG } from "./MagicBG";
25
24
  import { formatSpeed } from "./utils";
26
25
  import {
27
- addQueryParam,
28
26
  getBottomSheetModalDefaultItemIcon,
29
27
  getBottomSheetModalIconProps,
30
28
  getBottomSheetModalItemProps,
@@ -33,22 +31,20 @@ import {
33
31
  } from "../Utils";
34
32
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
35
33
  import {
34
+ AnimatedScrollModal,
36
35
  AnimationComponent,
37
36
  ComponentAnimationType,
38
- AnimatedScrollModal,
39
37
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
40
38
  import { PADDING_HORIZONTAL } from "./Layout/const";
41
39
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
42
40
  import {
41
+ SLEEP_TIMER_OFF,
43
42
  SleepTimerController,
44
43
  SleepTimerState,
45
- SLEEP_TIMER_OFF,
46
44
  } from "./SleepTimerManager";
47
- import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
48
- import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
49
- import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
45
+ import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
50
46
  import { openBottomSheetModal } from "@applicaster/zapp-react-native-utils/modalState";
51
- import { sleepTimerOptions } from "../Const/sleepTimerOptions";
47
+ import { getSleepTimerOptions } from "../Const/sleepTimerOptions";
52
48
  import { speedOptions } from "../Const/speedOptions";
53
49
 
54
50
  const { log_debug } = createLogger({
@@ -65,7 +61,6 @@ type Dimensions = {
65
61
 
66
62
  type Configuration = {
67
63
  [key: string]: any;
68
- magic_background?: boolean;
69
64
  audio_player_background_image_query?: string;
70
65
  audio_player_background_image_default_color?: string;
71
66
  tablet_landscape_sidebar_width?: string;
@@ -75,7 +70,6 @@ type Configuration = {
75
70
  type Props = {
76
71
  children: React.ReactNode;
77
72
  inline?: boolean;
78
- docked?: boolean;
79
73
  configuration: Configuration;
80
74
  style: ViewStyle & Dimensions;
81
75
  entry: ZappEntry;
@@ -108,10 +102,8 @@ const edges: Edge[] = ["right", "left", "top"];
108
102
  export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
109
103
  const player = usePlayer();
110
104
  const playerState = usePlayerState("audio-player-wrapper");
111
- const theme = useTheme();
112
105
 
113
106
  const {
114
- docked,
115
107
  configuration,
116
108
  style,
117
109
  entry,
@@ -266,7 +258,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
266
258
  iconPlacement: "right",
267
259
  },
268
260
  options: {
269
- supportedOrientations: ["portrait"],
261
+ supportedOrientations: [
262
+ "portrait",
263
+ "landscape",
264
+ "portrait-upside-down",
265
+ ],
270
266
  },
271
267
  });
272
268
  }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
@@ -274,12 +270,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
274
270
  const onSleepButtonPress = React.useCallback(() => {
275
271
  openBottomSheetModal({
276
272
  modalBottomSheetContentProps: {
277
- items: [
278
- {
279
- label: configuration["playback_sleep_off_label"],
280
- value: 0,
281
- },
282
- ].concat(sleepTimerOptions),
273
+ items: getSleepTimerOptions(configuration),
283
274
  current_selection: sleepTimerState.timer,
284
275
  onPress: onSleepSelect,
285
276
  title: configuration["playback_sleep_title"],
@@ -290,7 +281,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
290
281
  iconPlacement: "right",
291
282
  },
292
283
  options: {
293
- supportedOrientations: ["portrait"],
284
+ supportedOrientations: [
285
+ "portrait",
286
+ "landscape",
287
+ "portrait-upside-down",
288
+ ],
294
289
  },
295
290
  });
296
291
  }, [
@@ -327,114 +322,61 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
327
322
  player?.seekTo(0);
328
323
  }, [player]);
329
324
 
330
- const MainContent = React.useMemo(() => {
331
- return (
332
- <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
333
- <AnimationComponent
334
- animationType={ComponentAnimationType.moveUpComponent}
335
- additionalData={{ saveArea: true }}
336
- style={Styles.playerContainer}
337
- >
338
- <AnimatedScrollModal>
339
- <View style={Styles.playerContainer} onLayout={onLayout}>
340
- <Layout
341
- entry={entry}
342
- playerState={playerState}
343
- layoutState={layoutState}
344
- value={value}
345
- onPlaybackButtonPress={onPlaybackButtonPress}
346
- onRewindButtonPress={onRewindButtonPress}
347
- onForwardButtonPress={onForwardButtonPress}
348
- onPlayerSeek={onPlayerSeek}
349
- onSkipStart={onSkipStart}
350
- onSpeedButtonPress={onSpeedButtonPress}
351
- onSleepButtonPress={onSleepButtonPress}
352
- playbackSpeedName={formatSpeed(playbackSpeed.value)}
353
- playbackSleepName={
354
- sleepTimerState.timer.value === 0
355
- ? "sleep_timer"
356
- : "sleep_timer_active"
357
- }
358
- sleepTimerDate={sleepTimerState.timerDate}
359
- cancelSleepTimer={cancelSleepTimer}
360
- onSkipLive={onSkipLive}
361
- onCloseVideoModal={onCloseVideoModal}
362
- maximiseVideoModal={maximiseVideoModal}
363
- configuration={configuration}
364
- dimensions={dimensions}
365
- playNextData={playNextData}
366
- title={title}
367
- summary={summary}
368
- defaultDimensions={defaultDimensions}
369
- />
370
- <View style={Styles.paddingHorizontal}>
371
- {children}
372
- <AnimationComponent
373
- animationType={ComponentAnimationType.componentFade}
374
- >
375
- <PlayerDetails
376
- isAudioPlayer
377
- configuration={configuration}
378
- style={Styles.playerDetails}
379
- entry={entry}
380
- isTabletLandscape={isTabletLandscape}
381
- />
382
- </AnimationComponent>
383
- </View>
384
- </View>
385
- </AnimatedScrollModal>
386
- </AnimationComponent>
387
- </SafeAreaView>
388
- );
389
- }, [
390
- docked,
391
- style,
392
- entry,
393
- playerState,
394
- layoutState,
395
- value,
396
- onPlaybackButtonPress,
397
- onRewindButtonPress,
398
- onForwardButtonPress,
399
- onPlayerSeek,
400
- onCloseVideoModal,
401
- maximiseVideoModal,
402
- configuration,
403
- dimensions,
404
- children,
405
- playNextData,
406
- onSkipStart,
407
- onSkipLive,
408
- sleepTimerState.timer.value,
409
- sleepTimerState.timerDate,
410
- ]);
411
-
412
- if (configuration.magic_background) {
413
- const baseUrl = imageSrcFromMediaItem(entry, null);
414
-
415
- const queryParamName =
416
- configuration.audio_player_background_image_query || "width";
417
-
418
- const defaultBackgroundColor =
419
- configuration.audio_player_background_image_default_color ||
420
- theme?.app_background_color;
421
-
422
- const queryParamValue = 15;
423
-
424
- const url =
425
- baseUrl && addQueryParam(baseUrl, queryParamName, queryParamValue);
426
-
427
- return (
428
- <MagicBG
429
- image={url}
430
- fallbackUrl={baseUrl}
431
- colors={entry?.extensions?.backgroundColors}
432
- defaultColor={defaultBackgroundColor}
325
+ return (
326
+ <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
327
+ <AnimationComponent
328
+ animationType={ComponentAnimationType.moveUpComponent}
329
+ additionalData={{ saveArea: true }}
330
+ style={Styles.playerContainer}
433
331
  >
434
- {MainContent}
435
- </MagicBG>
436
- );
437
- }
438
-
439
- 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
+ );
440
382
  };
@@ -3,25 +3,43 @@ import { View, StyleSheet } from "react-native";
3
3
 
4
4
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
5
5
 
6
- import { TABLET_VERTICAL_SEPARATOR_HEIGHT } from "../const";
6
+ import {
7
+ TABLET_VERTICAL_SEPARATOR_HEIGHT,
8
+ TABLET_VERTICAL_SEPARATOR_HEIGHT_S,
9
+ } from "../const";
7
10
 
8
11
  import { withDebug } from "../debug";
12
+ import { useSafeAreaFrame } from "react-native-safe-area-context";
13
+ import { isSmallTabletHeight } from "../utils";
9
14
 
10
15
  const styles = StyleSheet.create({
11
16
  flexingHeight: {
12
17
  flex: 1,
13
-
14
18
  ...withDebug({ backgroundColor: "red" }),
15
19
  },
16
20
  fixedHeight: {
17
21
  height: TABLET_VERTICAL_SEPARATOR_HEIGHT,
18
-
22
+ ...withDebug({ backgroundColor: "red" }),
23
+ },
24
+ fixedHeightSmall: {
25
+ height: TABLET_VERTICAL_SEPARATOR_HEIGHT_S,
19
26
  ...withDebug({ backgroundColor: "red" }),
20
27
  },
21
28
  });
22
29
 
23
30
  export const VerticalGutter = () => {
24
31
  const isTablet = useIsTablet();
25
-
26
- return <View style={isTablet ? styles.fixedHeight : styles.flexingHeight} />;
32
+ const { height } = useSafeAreaFrame();
33
+
34
+ return (
35
+ <View
36
+ style={
37
+ isTablet
38
+ ? isSmallTabletHeight(height)
39
+ ? styles.fixedHeightSmall
40
+ : styles.fixedHeight
41
+ : styles.flexingHeight
42
+ }
43
+ />
44
+ );
27
45
  };
@@ -5,7 +5,6 @@ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
5
5
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
6
6
  import {
7
7
  Controls as MobileTransportControls,
8
- CountDown,
9
8
  ProgressBar,
10
9
  } from "@applicaster/quick-brick-mobile-transport-controls";
11
10
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
@@ -39,19 +38,24 @@ const styles = StyleSheet.create({
39
38
  progressBar: {
40
39
  flex: 0,
41
40
  },
41
+ progressBarTrackStyles: {
42
+ borderRadius: 3,
43
+ height: 6,
44
+ },
45
+ progressBarThumbStyles: {
46
+ width: 14,
47
+ height: 14,
48
+ borderRadius: 7,
49
+ },
50
+ progressBarThumbStyles_pressed: {
51
+ width: 20,
52
+ height: 20,
53
+ borderRadius: 10,
54
+ },
42
55
  });
43
56
 
44
- const controlsStyles = ({
45
- isTablet,
46
- isLiveShowFullControls,
47
- }: {
48
- isTablet: boolean;
49
- isLiveShowFullControls: boolean;
50
- }) => ({
51
- height: isTablet ? undefined : 50,
52
- marginHorizontal: isTablet ? undefined : 10,
53
- justifyContent: isLiveShowFullControls ? "space-between" : "space-evenly",
54
- });
57
+ const getControlJustifyContent = (countOfButtons: number) =>
58
+ countOfButtons <= 1 ? "center" : "space-between";
55
59
 
56
60
  type Props = {
57
61
  entry: ZappEntry;
@@ -75,6 +79,8 @@ type Props = {
75
79
  onSpeedButtonPress: Callback;
76
80
  onSleepButtonPress: Callback;
77
81
 
82
+ maxWidth?: number;
83
+
78
84
  docked: boolean;
79
85
  };
80
86
 
@@ -100,6 +106,7 @@ export const Controls = (props: Props) => {
100
106
  onSkipLive,
101
107
  onSpeedButtonPress,
102
108
  onSleepButtonPress,
109
+ maxWidth = 320,
103
110
 
104
111
  docked,
105
112
  } = props;
@@ -117,14 +124,19 @@ export const Controls = (props: Props) => {
117
124
  showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
118
125
  }
119
126
 
120
- const sleepTitle = value("playback_sleep_countdown_label");
121
-
122
127
  const [timeLeft, setTimeLeft] = React.useState(
123
128
  sleepTimerDate !== 0 ? sleepTimerDate - Date.now() : 0
124
129
  );
125
130
 
126
131
  const showCounter = React.useMemo(() => sleepTimerDate > 0, [sleepTimerDate]);
127
132
 
133
+ const countDownOptions = React.useMemo(() => {
134
+ return {
135
+ showCounter: showCounter && timeLeft >= 0,
136
+ timeLeft,
137
+ };
138
+ }, [showCounter, timeLeft]);
139
+
128
140
  React.useEffect(() => {
129
141
  if (showCounter && sleepTimerDate !== 0) {
130
142
  setTimeLeft(sleepTimerDate - Date.now());
@@ -261,6 +273,7 @@ export const Controls = (props: Props) => {
261
273
  summary={summary}
262
274
  value={value}
263
275
  layoutState={layoutState}
276
+ maxWidth={maxWidth}
264
277
  />
265
278
 
266
279
  <VerticalGutter />
@@ -282,12 +295,12 @@ export const Controls = (props: Props) => {
282
295
  isDateBasedLiveContent={isDateBasedLiveContent}
283
296
  onSkipLive={onSkipLive}
284
297
  progressBarStyles={styles.progressBar}
298
+ countDownOptions={countDownOptions}
299
+ thumbStyles={styles.progressBarThumbStyles}
300
+ thumbStylesPressed={styles.progressBarThumbStyles_pressed}
301
+ trackStyles={styles.progressBarTrackStyles}
285
302
  />
286
303
 
287
- {showCounter && timeLeft >= 0 ? (
288
- <CountDown timeLeft={timeLeft} value={value} title={sleepTitle} />
289
- ) : null}
290
-
291
304
  <VerticalGutter />
292
305
  </>
293
306
  ) : null}
@@ -297,7 +310,9 @@ export const Controls = (props: Props) => {
297
310
  visible={true}
298
311
  keepAlive={null}
299
312
  buttons={controlButtons}
300
- style={controlsStyles({ isTablet, isLiveShowFullControls })}
313
+ style={{
314
+ justifyContent: getControlJustifyContent(controlButtons().length),
315
+ }}
301
316
  playerState={playerState}
302
317
  />
303
318
  </AnimationComponent>