@applicaster/quick-brick-player 13.0.0-rc.13 → 13.0.0-rc.131

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 (49) hide show
  1. package/package.json +27 -14
  2. package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
  3. package/src/Player/AudioLayer/AudioDescription.tsx +107 -68
  4. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +142 -295
  5. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +45 -0
  6. package/src/Player/AudioLayer/Layout/Controls/index.tsx +291 -0
  7. package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +9 -27
  8. package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
  9. package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +77 -81
  10. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +222 -0
  11. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +87 -0
  12. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +20 -0
  13. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +1 -0
  14. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +99 -0
  15. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +112 -0
  16. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +36 -0
  17. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +212 -0
  18. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +215 -0
  19. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +128 -0
  20. package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
  21. package/src/Player/AudioLayer/Layout/const.ts +26 -0
  22. package/src/Player/AudioLayer/Layout/debug.ts +6 -0
  23. package/src/Player/AudioLayer/Layout/hooks/index.ts +5 -0
  24. package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
  25. package/src/Player/AudioLayer/Layout/hooks/useTabletLayoutImageSize.ts +105 -0
  26. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
  27. package/src/Player/AudioLayer/Layout/index.tsx +21 -48
  28. package/src/Player/AudioLayer/Layout/types.ts +7 -0
  29. package/src/Player/AudioLayer/Layout/utils.ts +7 -0
  30. package/src/Player/AudioLayer/SleepTimerManager.ts +130 -0
  31. package/src/Player/AudioLayer/SpeedManager.ts +52 -0
  32. package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +66 -0
  33. package/src/Player/AudioLayer/components/SleepTimerModalHeader/index.ts +1 -0
  34. package/src/Player/AudioLayer/useSleepTimerModal.ts +109 -0
  35. package/src/Player/AudioLayer/utils.ts +27 -0
  36. package/src/Player/Const/sleepTimerOptions.ts +41 -0
  37. package/src/Player/Const/speedOptions.ts +4 -0
  38. package/src/Player/Utils/Utils.ts +0 -5
  39. package/src/Player/Utils/index.tsx +123 -0
  40. package/src/Player/hooks/useIsCasting.tsx +57 -0
  41. package/src/Player/index.tsx +106 -49
  42. package/src/QuickBrickPlayer.tsx +3 -0
  43. package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
  44. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
  45. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
  46. package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
  47. package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
  48. package/src/Player/Helpers/VideoResizeMode.ts +0 -7
  49. package/src/utils/utils.ts +0 -25
@@ -0,0 +1,291 @@
1
+ import * as React from "react";
2
+ import { StyleSheet } from "react-native";
3
+
4
+ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
5
+ import {
6
+ useIsTablet,
7
+ useZStore,
8
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
9
+ import {
10
+ Controls as MobileTransportControls,
11
+ ProgressBar,
12
+ } from "@applicaster/quick-brick-mobile-transport-controls";
13
+ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
14
+
15
+ import {
16
+ AnimationComponent,
17
+ ComponentAnimationType,
18
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
19
+
20
+ import { AudioDescription } from "../../AudioDescription";
21
+ import { isValidDate } from "../../../Utils";
22
+ import { VerticalGutter } from "./VerticalGutter";
23
+
24
+ import {
25
+ forwardButton,
26
+ playbackButton,
27
+ rewindButton,
28
+ skipToLiveButton,
29
+ skipToStartButton,
30
+ sleepButton,
31
+ speedButton,
32
+ } from "./utils";
33
+ import { useSleepTimerModal } from "../../useSleepTimerModal";
34
+
35
+ const styles = StyleSheet.create({
36
+ flex: {
37
+ flex: 1,
38
+ },
39
+ nonFlex: {
40
+ flex: 0,
41
+ },
42
+ progressBar: {
43
+ flex: 0,
44
+ },
45
+ progressBarTrackStyles: {
46
+ borderRadius: 3,
47
+ height: 6,
48
+ },
49
+ progressBarThumbStyles: {
50
+ width: 14,
51
+ height: 14,
52
+ borderRadius: 7,
53
+ },
54
+ progressBarThumbStyles_pressed: {
55
+ width: 20,
56
+ height: 20,
57
+ borderRadius: 10,
58
+ },
59
+ });
60
+
61
+ const getControlJustifyContent = (countOfButtons: number) =>
62
+ countOfButtons <= 1 ? "center" : "space-between";
63
+
64
+ type Props = {
65
+ entry: ZappEntry;
66
+ layoutState: QuickBrickPlayer.LayoutState;
67
+ playerState: QuickBrickPlayer.PlayerState;
68
+ value: GetValue;
69
+ title: string | number;
70
+ summary: string | number;
71
+
72
+ playbackSpeedName: string;
73
+
74
+ onPlaybackButtonPress: Callback;
75
+ onRewindButtonPress: Callback;
76
+ onForwardButtonPress: Callback;
77
+ onPlayerSeek: (targetTime: number) => void;
78
+ onSkipStart: Callback;
79
+ onSkipLive: Callback;
80
+ onSpeedButtonPress: Callback;
81
+
82
+ maxWidth?: number;
83
+
84
+ docked: boolean;
85
+ };
86
+
87
+ export const Controls = (props: Props) => {
88
+ const {
89
+ entry,
90
+ layoutState,
91
+ playerState,
92
+ value,
93
+ title,
94
+ summary,
95
+
96
+ playbackSpeedName,
97
+
98
+ onPlaybackButtonPress,
99
+ onRewindButtonPress,
100
+ onForwardButtonPress,
101
+ onPlayerSeek,
102
+ onSkipStart,
103
+ onSkipLive,
104
+ onSpeedButtonPress,
105
+ maxWidth = 320,
106
+
107
+ docked,
108
+ } = props;
109
+
110
+ const configuration = useZStore("playerConfiguration");
111
+
112
+ const { sleepTimerState, onSleepButtonPress } = useSleepTimerModal(
113
+ playerManager.getActivePlayer(),
114
+ configuration
115
+ );
116
+
117
+ const timerRemaining =
118
+ sleepTimerState.timerDate !== 0 && +sleepTimerState.timerDate > Date.now()
119
+ ? sleepTimerState.timerDate
120
+ : null;
121
+
122
+ const playbackSleepName =
123
+ timerRemaining === null ? "sleep_timer" : "sleep_timer_active";
124
+
125
+ const isTablet = useIsTablet();
126
+ const controller = playerManager.getActivePlayer();
127
+ let showFullControls = !controller?.isAd();
128
+ const liveButton = Boolean(value("live_badge_enabled"));
129
+
130
+ const isLiveContent = playerState.isLive;
131
+
132
+ if (isLiveContent) {
133
+ const seekEnabled = Boolean(value("liveSeekingEnabled"));
134
+
135
+ showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
136
+ }
137
+
138
+ const startTime = entry.extensions?.live?.start_time;
139
+ const endTime = entry.extensions?.live?.end_time;
140
+
141
+ const hasValidStartTime = isValidDate(startTime);
142
+ const hasValidEndTime = isValidDate(endTime);
143
+
144
+ const isDateBasedLiveContent =
145
+ isLiveContent && hasValidStartTime && hasValidEndTime;
146
+
147
+ const needsToShowProgressBar =
148
+ (isLiveContent &&
149
+ (Boolean(value("liveSeekingEnabled")) || isDateBasedLiveContent)) ||
150
+ !isLiveContent;
151
+
152
+ const startTimestamp = hasValidStartTime
153
+ ? dayjs.utc(startTime!).valueOf()
154
+ : undefined;
155
+
156
+ const endTimestamp = hasValidEndTime
157
+ ? dayjs.utc(endTime!).valueOf()
158
+ : undefined;
159
+
160
+ const isLiveShowFullControls = showFullControls && isLiveContent;
161
+
162
+ const controlButtons = React.useCallback((): Array<ControlsButton> => {
163
+ const play = playbackButton({
164
+ playerState,
165
+ liveButton,
166
+ isTablet,
167
+ isLiveShowFullControls,
168
+ onPress: onPlaybackButtonPress,
169
+ });
170
+
171
+ if (!showFullControls) {
172
+ return [play];
173
+ }
174
+
175
+ const rewind = rewindButton({
176
+ isTablet,
177
+ onPress: controller?.hasSeekableDuration?.() ? onRewindButtonPress : null,
178
+ });
179
+
180
+ const forward = forwardButton({
181
+ isTablet,
182
+ onPress: controller?.hasSeekableDuration?.()
183
+ ? onForwardButtonPress
184
+ : null,
185
+ });
186
+
187
+ const speed = speedButton({
188
+ isTablet,
189
+ onPress: onSpeedButtonPress,
190
+ name: playbackSpeedName,
191
+ });
192
+
193
+ const sleep = sleepButton({
194
+ isTablet,
195
+ onPress: onSleepButtonPress,
196
+ name: playbackSleepName,
197
+ });
198
+
199
+ if (isLiveContent) {
200
+ const skipToStart = skipToStartButton({
201
+ isTablet,
202
+ onPress: onSkipStart,
203
+ });
204
+
205
+ const skipToLive = skipToLiveButton({
206
+ isTablet,
207
+ onPress: onSkipLive,
208
+ });
209
+
210
+ return [skipToStart, rewind, play, forward, skipToLive];
211
+ }
212
+
213
+ return [speed, rewind, play, forward, sleep];
214
+ }, [
215
+ playerState,
216
+ liveButton,
217
+ isTablet,
218
+ onPlaybackButtonPress,
219
+ onRewindButtonPress,
220
+ onForwardButtonPress,
221
+ onSpeedButtonPress,
222
+ showFullControls,
223
+ onSkipStart,
224
+ onSkipLive,
225
+ isLiveContent,
226
+ playbackSpeedName,
227
+ playbackSleepName,
228
+ controller,
229
+ isLiveShowFullControls,
230
+ ]);
231
+
232
+ if (docked) {
233
+ return null;
234
+ }
235
+
236
+ return (
237
+ <AnimationComponent
238
+ animationType={ComponentAnimationType.componentFade}
239
+ style={isTablet ? styles.nonFlex : styles.flex}
240
+ >
241
+ <VerticalGutter />
242
+
243
+ <AudioDescription
244
+ title={title}
245
+ summary={summary}
246
+ value={value}
247
+ layoutState={layoutState}
248
+ maxWidth={maxWidth}
249
+ />
250
+
251
+ <VerticalGutter />
252
+
253
+ {needsToShowProgressBar ? (
254
+ <>
255
+ <ProgressBar
256
+ name={"audio-default-layout"}
257
+ content={entry}
258
+ value={value}
259
+ visible
260
+ layoutState={layoutState}
261
+ onPlayerSeek={onPlayerSeek}
262
+ playerState={playerState}
263
+ disableFullscreen
264
+ sliderStyle={2}
265
+ startTimestamp={startTimestamp}
266
+ endTimestamp={endTimestamp}
267
+ isDateBasedLiveContent={isDateBasedLiveContent}
268
+ onSkipLive={onSkipLive}
269
+ progressBarStyles={styles.progressBar}
270
+ thumbStyles={styles.progressBarThumbStyles}
271
+ thumbStylesPressed={styles.progressBarThumbStyles_pressed}
272
+ trackStyles={styles.progressBarTrackStyles}
273
+ />
274
+
275
+ <VerticalGutter />
276
+ </>
277
+ ) : null}
278
+
279
+ <MobileTransportControls
280
+ value={value}
281
+ visible={true}
282
+ keepAlive={null}
283
+ buttons={controlButtons}
284
+ style={{
285
+ justifyContent: getControlJustifyContent(controlButtons().length),
286
+ }}
287
+ playerState={playerState}
288
+ />
289
+ </AnimationComponent>
290
+ );
291
+ };
@@ -1,25 +1,7 @@
1
- type PlayerState = {
2
- currentTime: number;
3
- duration: number;
4
- seekableDuration: number;
5
- isLive: boolean;
6
- isPaused: boolean;
7
- isBuffering: boolean;
8
- };
9
-
10
- const rewindButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
11
- isTablet ? "big" : "smallMargins";
12
-
13
- const playbackButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
14
- isTablet ? "bigExtended" : "mediumExtended";
15
-
16
1
  const playbackButtonMargins = (
17
2
  isTablet: boolean,
18
3
  isLiveShowFullControls: boolean
19
- ): number =>
20
- isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? 95 : 40;
21
-
22
- export const PADDING_HORIZONTAL = 15;
4
+ ): number => (isLiveShowFullControls ? (isTablet ? 65 : 10) : undefined);
23
5
 
24
6
  export const playbackButton = ({
25
7
  playerState,
@@ -28,7 +10,7 @@ export const playbackButton = ({
28
10
  isLiveShowFullControls,
29
11
  onPress,
30
12
  }: {
31
- playerState: PlayerState;
13
+ playerState: QuickBrickPlayer.PlayerState;
32
14
  liveButton: boolean;
33
15
  isTablet: boolean;
34
16
  isLiveShowFullControls: boolean;
@@ -37,11 +19,11 @@ export const playbackButton = ({
37
19
  const icon = playerState.isPaused
38
20
  ? "play"
39
21
  : playerState.isLive && liveButton
40
- ? "stop"
41
- : "pause";
22
+ ? "stop"
23
+ : "pause";
42
24
 
43
25
  return {
44
- size: playbackButtonSize(isTablet),
26
+ size: "bigExtended",
45
27
  icon: playerState.isBuffering ? "buffering" : icon,
46
28
  preferredFocus: true,
47
29
  onPress,
@@ -57,15 +39,15 @@ type ButtonsProps = {
57
39
  style?: any;
58
40
  name?: string;
59
41
  };
42
+
60
43
  type ButtonsByNameProps = ButtonsProps & { name?: string };
61
44
 
62
45
  const rewindButtonByName = ({
63
46
  name,
64
47
  onPress,
65
- isTablet,
66
48
  style,
67
49
  }: ButtonsByNameProps): ControlsButton => ({
68
- size: rewindButtonSize(isTablet),
50
+ size: "big",
69
51
  icon: name,
70
52
  onPress,
71
53
  style,
@@ -117,7 +99,7 @@ export const skipToLiveButton = (props: ButtonsProps): ControlsButton =>
117
99
  skipButtonByName({ ...props, name: "skip_live" });
118
100
 
119
101
  export const speedButton = (props: ButtonsProps): ControlsButton =>
120
- speedButtonByName({ ...props });
102
+ speedButtonByName(props);
121
103
 
122
104
  export const sleepButton = (props: ButtonsProps): ControlsButton =>
123
- sleepButtonByName({ ...props });
105
+ sleepButtonByName(props);
@@ -0,0 +1,55 @@
1
+ /* eslint react-native/no-color-literals: off */
2
+ /* eslint react-native/no-inline-styles: off */
3
+
4
+ import * as React from "react";
5
+ import { View } from "react-native";
6
+
7
+ import { MOBILE } from "../const";
8
+
9
+ export const LeftDebugSquare = () => (
10
+ <View
11
+ style={{
12
+ position: "absolute",
13
+ top: 200,
14
+ left: 0,
15
+ width: MOBILE.MARGIN_HORIZONTAL,
16
+ height: MOBILE.MARGIN_HORIZONTAL,
17
+ backgroundColor: "blue",
18
+
19
+ borderWidth: 1,
20
+ borderColor: "yellow",
21
+ }}
22
+ />
23
+ );
24
+
25
+ export const RightDebugSquare = () => (
26
+ <View
27
+ style={{
28
+ position: "absolute",
29
+ top: 200,
30
+ right: 0,
31
+ width: MOBILE.MARGIN_HORIZONTAL,
32
+ height: MOBILE.MARGIN_HORIZONTAL,
33
+ backgroundColor: "blue",
34
+
35
+ borderWidth: 1,
36
+ borderColor: "yellow",
37
+ }}
38
+ />
39
+ );
40
+
41
+ export const BottomDebugSquare = () => (
42
+ <View
43
+ style={{
44
+ position: "absolute",
45
+ left: 170,
46
+ bottom: 0,
47
+ width: MOBILE.MARGIN_BOTTOM,
48
+ height: MOBILE.MARGIN_BOTTOM,
49
+ backgroundColor: "blue",
50
+
51
+ borderWidth: 1,
52
+ borderColor: "yellow",
53
+ }}
54
+ />
55
+ );
@@ -9,52 +9,38 @@ import * as R from "ramda";
9
9
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
10
10
 
11
11
  import {
12
+ Button,
12
13
  ContentInfo,
13
- ProgressBar,
14
14
  Controls,
15
- Button,
15
+ ProgressBar,
16
16
  } from "@applicaster/quick-brick-mobile-transport-controls";
17
17
 
18
18
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
19
+
19
20
  import {
20
- useModalAnimationContext,
21
21
  AnimationComponent,
22
22
  ComponentAnimationType,
23
23
  PlayerAnimationStateEnum,
24
+ useModalAnimationContext,
24
25
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
26
+ import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
27
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
28
+ import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
25
29
 
26
- type Dimensions = {
27
- width: number;
28
- height: number;
29
- };
30
+ const bottomTabBarHeight = getTabBarHeight();
30
31
 
31
- type LayoutProps = {
32
+ type Props = {
32
33
  entry: ZappEntry;
33
- layoutState: {
34
- inline: boolean;
35
- docked: boolean;
36
- isModal: boolean;
37
- };
38
- playerState: {
39
- currentTime: number;
40
- duration: number;
41
- seekableDuration: number;
42
- isLive: boolean;
43
- isPaused: boolean;
44
- isBuffering: boolean;
45
- };
34
+ layoutState: QuickBrickPlayer.LayoutState;
35
+ playerState: QuickBrickPlayer.PlayerState;
46
36
  value: GetValue;
47
- configuration: { [key: string]: any };
48
- onPlaybackButtonPress: () => void;
49
- onRewindButtonPress: () => void;
50
- onForwardButtonPress: () => void;
51
- onPlayerSeek: (targetTime: number) => void;
37
+ dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
52
38
  onCloseVideoModal: () => void;
53
- maximiseVideoModal: () => void;
54
- dimensions: Dimensions;
39
+ onPlayerSeek: (targetTime: number) => void;
55
40
  playNextData: PlayNextData;
56
41
  title: string | number;
57
42
  summary: string | number;
43
+ ImageComponent?: React.ReactNode;
58
44
  };
59
45
 
60
46
  const styles = StyleSheet.create({
@@ -71,6 +57,7 @@ const styles = StyleSheet.create({
71
57
  touchableArea: {
72
58
  flexShrink: 1,
73
59
  flex: 1,
60
+ flexDirection: "row",
74
61
  alignSelf: "stretch",
75
62
  },
76
63
  contentInfo: {
@@ -105,25 +92,25 @@ const styles = StyleSheet.create({
105
92
  },
106
93
  });
107
94
 
108
- const backgroundColorStyle = (value: GetValue): ViewStyle => ({
109
- backgroundColor: value("docked_player_background_color"),
110
- });
111
-
112
95
  const playerDimensionsStyle = (
113
96
  minimisedHeight: number,
114
97
  addPadding: boolean
115
98
  ): ViewStyle => ({
116
- paddingLeft: addPadding ? minimisedHeight || 100 : 0,
99
+ width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
117
100
  });
118
101
 
119
- const animatedContainerStyle = (docked: boolean): ViewStyle => ({
102
+ const animatedContainerStyle = (
103
+ docked: boolean,
104
+ progressBarHeight: number
105
+ ): ViewStyle => ({
106
+ top: progressBarHeight,
120
107
  position: "absolute",
121
108
  width: "100%",
122
109
  zIndex: docked ? 1 : -1,
123
110
  });
124
111
 
125
112
  const backgroundImageStyle = (
126
- dimensions: Dimensions,
113
+ dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"],
127
114
  minimisedHeight: number,
128
115
  isActiveGesture: boolean
129
116
  ): ViewStyle => ({
@@ -133,24 +120,11 @@ const backgroundImageStyle = (
133
120
  });
134
121
 
135
122
  const controlButtons = (
136
- isPlayNextEnabled: boolean,
137
123
  live: boolean,
138
124
  paused: boolean,
139
125
  buffering: boolean,
140
126
  playerId: string
141
127
  ): Array<ControlsButton> => {
142
- if (isPlayNextEnabled) {
143
- return [
144
- {
145
- size: "medium",
146
- name: "play_next",
147
- icon: "play_next",
148
- preferredFocus: true,
149
- style: styles.buttons,
150
- },
151
- ];
152
- }
153
-
154
128
  if (buffering) {
155
129
  return [
156
130
  {
@@ -202,24 +176,23 @@ const controlButtons = (
202
176
  ];
203
177
  };
204
178
 
205
- export default function DockedLayout(props: LayoutProps) {
179
+ export const DockedControls = (props: Props) => {
206
180
  const {
181
+ entry,
207
182
  layoutState,
183
+ playerState,
208
184
  value,
209
185
  dimensions,
210
- entry,
211
186
  onCloseVideoModal,
212
187
  onPlayerSeek,
213
- playerState,
214
- configuration,
215
188
  playNextData,
216
189
  title,
217
190
  summary,
191
+ ImageComponent,
218
192
  } = props;
219
193
 
220
194
  const isTablet = useIsTablet();
221
195
 
222
- const visible = true;
223
196
  const liveButton = Boolean(value("live_badge_enabled"));
224
197
 
225
198
  const {
@@ -227,13 +200,18 @@ export default function DockedLayout(props: LayoutProps) {
227
200
  setPlayerAnimationState,
228
201
  startComponentsAnimation,
229
202
  minimisedHeight,
203
+ progressBarHeight,
230
204
  } = useModalAnimationContext();
231
205
 
232
206
  const maximazeVideoModal = React.useCallback(
233
- () => setPlayerAnimationState(PlayerAnimationStateEnum.maximaze),
207
+ () => setPlayerAnimationState(PlayerAnimationStateEnum.maximize),
234
208
  []
235
209
  );
236
210
 
211
+ const dockedBackgroundColor = value("docked_player_background_color");
212
+
213
+ const insets = useSafeAreaInsets();
214
+
237
215
  if (!layoutState.docked && !startComponentsAnimation) return null;
238
216
 
239
217
  return (
@@ -241,22 +219,29 @@ export default function DockedLayout(props: LayoutProps) {
241
219
  animationType={ComponentAnimationType.componentAppears}
242
220
  style={[
243
221
  styles.container,
244
- animatedContainerStyle(isActiveGesture || layoutState.docked),
222
+ animatedContainerStyle(
223
+ isActiveGesture || layoutState.docked,
224
+ progressBarHeight
225
+ ),
226
+ {
227
+ height: minimisedHeight + bottomTabBarHeight + insets.bottom,
228
+ },
245
229
  ]}
246
230
  >
247
231
  {!playerState.isLive &&
248
- (layoutState.docked || startComponentsAnimation) && (
249
- <ProgressBar
250
- content={entry}
251
- value={value}
252
- visible={visible}
253
- layoutState={layoutState}
254
- onPlayerSeek={onPlayerSeek}
255
- playerState={playerState}
256
- startComponentsAnimation={startComponentsAnimation}
257
- docked
258
- />
259
- )}
232
+ (layoutState.docked || startComponentsAnimation) ? (
233
+ <ProgressBar
234
+ name={"audio-docked-layout"}
235
+ content={entry}
236
+ value={value}
237
+ visible
238
+ layoutState={layoutState}
239
+ onPlayerSeek={onPlayerSeek}
240
+ playerState={playerState}
241
+ startComponentsAnimation={startComponentsAnimation}
242
+ docked
243
+ />
244
+ ) : null}
260
245
 
261
246
  <View style={styles.content}>
262
247
  <View
@@ -267,19 +252,25 @@ export default function DockedLayout(props: LayoutProps) {
267
252
  )}
268
253
  />
269
254
  <TouchableWithoutFeedback onPress={maximazeVideoModal}>
270
- <View
271
- style={[
272
- styles.touchableArea,
273
- playerDimensionsStyle(
274
- minimisedHeight,
275
- isActiveGesture || layoutState.docked
276
- ),
277
- ]}
278
- >
255
+ <View style={styles.touchableArea}>
256
+ {isActiveGesture || layoutState.docked ? (
257
+ <View
258
+ style={{ width: toNumberWithDefault(100, minimisedHeight) }}
259
+ >
260
+ {ImageComponent || null}
261
+ </View>
262
+ ) : (
263
+ <View
264
+ style={playerDimensionsStyle(
265
+ minimisedHeight,
266
+ isActiveGesture || layoutState.docked
267
+ )}
268
+ />
269
+ )}
279
270
  <View
280
271
  style={[
281
272
  styles.contentInfo,
282
- !configuration.magic_background && backgroundColorStyle(value),
273
+ { backgroundColor: dockedBackgroundColor },
283
274
  ]}
284
275
  >
285
276
  <ContentInfo
@@ -295,14 +286,13 @@ export default function DockedLayout(props: LayoutProps) {
295
286
  isTablet
296
287
  ? styles.controlsContainerForTablet
297
288
  : styles.controlsContainerForMobile,
298
- !configuration.magic_background && backgroundColorStyle(value),
289
+ { backgroundColor: dockedBackgroundColor },
299
290
  ]}
300
291
  >
301
292
  <Controls
302
293
  value={value}
303
- visible={visible}
294
+ visible
304
295
  buttons={R.partial(controlButtons, [
305
- playNextData,
306
296
  playerState.isLive && liveButton,
307
297
  ])}
308
298
  style={styles.playPauseButton}
@@ -318,6 +308,12 @@ export default function DockedLayout(props: LayoutProps) {
318
308
  />
319
309
  </View>
320
310
  </View>
311
+ <View
312
+ style={{
313
+ height: insets.bottom + bottomTabBarHeight,
314
+ backgroundColor: dockedBackgroundColor,
315
+ }}
316
+ />
321
317
  </AnimationComponent>
322
318
  );
323
- }
319
+ };