@applicaster/quick-brick-player 13.0.0-alpha.1240837114 → 13.0.0-alpha.1244047241

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 (41) hide show
  1. package/package.json +5 -7
  2. package/src/Player/AudioLayer/AudioDescription.tsx +107 -68
  3. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +137 -204
  4. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +45 -0
  5. package/src/Player/AudioLayer/Layout/Controls/index.tsx +320 -0
  6. package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +5 -23
  7. package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
  8. package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +59 -54
  9. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +230 -0
  10. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +70 -0
  11. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +20 -0
  12. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +108 -0
  13. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +36 -0
  14. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +220 -0
  15. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +223 -0
  16. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +128 -0
  17. package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
  18. package/src/Player/AudioLayer/Layout/const.ts +26 -0
  19. package/src/Player/AudioLayer/Layout/debug.ts +6 -0
  20. package/src/Player/AudioLayer/Layout/hooks/index.ts +5 -0
  21. package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
  22. package/src/Player/AudioLayer/Layout/hooks/useTabletLayoutImageSize.ts +105 -0
  23. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
  24. package/src/Player/AudioLayer/Layout/index.tsx +21 -48
  25. package/src/Player/AudioLayer/Layout/types.ts +7 -0
  26. package/src/Player/AudioLayer/Layout/utils.ts +7 -0
  27. package/src/Player/AudioLayer/utils.ts +6 -3
  28. package/src/Player/Const/sleepTimerOptions.ts +39 -0
  29. package/src/Player/Const/speedOptions.ts +4 -0
  30. package/src/Player/Utils/Utils.ts +0 -5
  31. package/src/Player/Utils/index.tsx +117 -0
  32. package/src/Player/hooks/useIsCasting.tsx +57 -0
  33. package/src/Player/index.tsx +14 -6
  34. package/src/QuickBrickPlayer.tsx +3 -0
  35. package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -495
  36. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
  37. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
  38. package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
  39. package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
  40. package/src/Player/Helpers/VideoResizeMode.ts +0 -7
  41. 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.1240837114",
3
+ "version": "13.0.0-alpha.1244047241",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
@@ -35,12 +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.79",
38
+ "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.120",
39
39
  "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
40
- "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.1240837114",
41
- "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.1240837114",
42
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.1240837114",
43
- "keymirror": "^0.1.1",
40
+ "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.1244047241",
41
+ "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.1244047241",
42
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.1244047241",
44
43
  "query-string": "7.1.3",
45
44
  "react-native-web-linear-gradient": "1.1.2",
46
45
  "shaka-player": "4.3.5",
@@ -53,7 +52,6 @@
53
52
  "@applicaster/applicaster-types": "*",
54
53
  "@applicaster/blur": "*",
55
54
  "@applicaster/quick-brick-xray": "*",
56
- "@applicaster/react-native-color-thief": "*",
57
55
  "@applicaster/zapp-pipes-v2-client": "*",
58
56
  "@applicaster/zapp-react-dom-ui-components": "*",
59
57
  "@applicaster/zapp-react-native-redux": "*",
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Text, TextStyle, View } 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,86 +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 containerStyles = { paddingTop: 32, paddingBottom: 12 };
17
+ const TITLE_PADDING_BOTTOM = 5;
18
+ const TITLE_LINES = 2;
19
+ const SUBTITLE_LINES = 1;
17
20
 
18
- const titleStyles = (value: GetValue, prefix: string): TextStyle => ({
19
- textAlign: "left",
20
- color: value(`${prefix}title_color`),
21
- alignSelf: "center",
22
- paddingBottom: 5,
23
- lineHeight:
24
- Number(
25
- platformSelect({
26
- ios: value(`${prefix}title_lineheight_ios`),
27
- android: value(`${prefix}title_lineheight_android`),
28
- })
29
- ) || 18,
30
- letterSpacing:
31
- Number(
32
- platformSelect({
33
- ios: value(`${prefix}title_letterspacing_ios`),
34
- android: value(`${prefix}title_letterspacing_android`),
35
- })
36
- ) || 0,
37
- fontSize:
38
- Number(
39
- platformSelect({
40
- ios: value(`${prefix}title_fontsize_ios`),
41
- android: value(`${prefix}title_fontsize_android`),
42
- })
43
- ) || 16,
44
- fontFamily: platformSelect({
45
- ios: value(`${prefix}title_font_ios`),
46
- android: value(`${prefix}title_font_android`),
47
- }),
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
+ },
48
37
  });
49
38
 
50
- const summaryStyles = (value: GetValue, prefix: string): TextStyle => ({
51
- textAlign: "left",
52
- color: value(`${prefix}subtitle_color`),
53
- alignSelf: "center",
54
- lineHeight:
55
- Number(
56
- platformSelect({
57
- ios: value(`${prefix}subtitle_lineheight_ios`),
58
- android: value(`${prefix}subtitle_lineheight_android`),
59
- })
60
- ) || 18,
61
- letterSpacing:
62
- Number(
63
- platformSelect({
64
- ios: value(`${prefix}subtitle_letterspacing_ios`),
65
- android: value(`${prefix}subtitle_letterspacing_android`),
66
- })
67
- ) || 0,
68
- fontSize:
69
- Number(
70
- platformSelect({
71
- ios: value(`${prefix}subtitle_fontsize_ios`),
72
- android: value(`${prefix}subtitle_fontsize_android`),
73
- })
74
- ) || 13,
75
- fontFamily: platformSelect({
76
- ios: value(`${prefix}subtitle_font_ios`),
77
- android: value(`${prefix}subtitle_font_android`),
78
- }),
79
- });
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;
80
101
 
81
102
  export const AudioDescription = (props: AudioDescriptionProps) => {
82
- const { title, summary, layoutState, value } = props;
103
+ const { title, summary, layoutState, value, maxWidth } = props;
83
104
  const prefix = layoutState.docked ? "docked_player_" : "";
84
105
 
106
+ const summaryStyles = getSummaryStyles(value, prefix);
107
+ const titleStyles = getTitleStyles(value, prefix);
108
+
109
+ const height = getHeight(titleStyles.lineHeight, summaryStyles.lineHeight);
110
+
85
111
  return (
86
- <View style={containerStyles}>
87
- <Text style={titleStyles(value, prefix)} numberOfLines={1}>
112
+ <View
113
+ style={[
114
+ styles.wrapper,
115
+ {
116
+ maxWidth: Math.max(maxWidth, 320),
117
+ height,
118
+ },
119
+ ]}
120
+ >
121
+ <Text style={[styles.titleText, titleStyles]} numberOfLines={TITLE_LINES}>
88
122
  {title}
89
123
  </Text>
90
- <Text style={summaryStyles(value, prefix)} numberOfLines={2}>
91
- {summary}
92
- </Text>
124
+ {summary ? (
125
+ <Text
126
+ style={[styles.summaryText, summaryStyles]}
127
+ numberOfLines={SUBTITLE_LINES}
128
+ >
129
+ {summary}
130
+ </Text>
131
+ ) : null}
93
132
  </View>
94
133
  );
95
134
  };
@@ -1,7 +1,13 @@
1
1
  import * as React from "react";
2
- import { ViewStyle, View, Dimensions as ScreenDimensions } 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,33 +21,35 @@ 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";
20
24
  import { formatSpeed } from "./utils";
21
- import { addQueryParam, getLiveUrl } from "../Utils";
25
+ import {
26
+ getBottomSheetModalDefaultItemIcon,
27
+ getBottomSheetModalIconProps,
28
+ getBottomSheetModalItemProps,
29
+ getBottomSheetModalLabelProps,
30
+ getBottomSheetModalSelectedItemIcon,
31
+ } from "../Utils";
22
32
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
23
33
  import {
34
+ AnimatedScrollModal,
24
35
  AnimationComponent,
25
36
  ComponentAnimationType,
26
- AnimatedScrollModal,
27
37
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
28
- import { PADDING_HORIZONTAL } from "./Layout/defaultLayoutsConts";
38
+ import { PADDING_HORIZONTAL } from "./Layout/const";
29
39
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
30
40
  import {
31
- speed_0_8,
32
- speed_1,
33
- speed_1_2,
34
- speed_1_5,
35
- speed_2,
36
- } from "@applicaster/quick-brick-mobile-transport-controls";
37
- import {
41
+ SLEEP_TIMER_OFF,
38
42
  SleepTimerController,
39
43
  SleepTimerState,
40
- SLEEP_TIMER_OFF,
41
44
  } from "./SleepTimerManager";
42
- import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
43
- import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
44
- import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
45
+ import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
46
+ import {
47
+ dismissModal as dismissBottomSheetModal,
48
+ openBottomSheetModal,
49
+ useModalStoreState,
50
+ } from "@applicaster/zapp-react-native-utils/modalState";
51
+ import { getSleepTimerOptions } from "../Const/sleepTimerOptions";
52
+ import { speedOptions } from "../Const/speedOptions";
45
53
 
46
54
  const { log_debug } = createLogger({
47
55
  subsystem: "UIComponent",
@@ -57,8 +65,6 @@ type Dimensions = {
57
65
 
58
66
  type Configuration = {
59
67
  [key: string]: any;
60
- magic_background?: boolean;
61
- audio_player_background_image_query?: string;
62
68
  audio_player_background_image_default_color?: string;
63
69
  tablet_landscape_sidebar_width?: string;
64
70
  tablet_landscape_player_container_background_color?: string;
@@ -67,7 +73,6 @@ type Configuration = {
67
73
  type Props = {
68
74
  children: React.ReactNode;
69
75
  inline?: boolean;
70
- docked?: boolean;
71
76
  configuration: Configuration;
72
77
  style: ViewStyle & Dimensions;
73
78
  entry: ZappEntry;
@@ -83,61 +88,27 @@ type Props = {
83
88
 
84
89
  const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
85
90
 
86
- const Styles = {
87
- mainContainer: (style: ViewStyle) => {
88
- const combinedStyle: ViewStyle = {
89
- flex: 1,
90
- };
91
-
92
- return {
93
- ...combinedStyle,
94
- ...style,
95
- };
96
- },
91
+ const Styles = StyleSheet.create({
97
92
  playerContainer: {
98
93
  flex: 1,
99
94
  },
100
95
  paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
101
-
102
- controlsMobile: {
103
- height: 50,
104
- marginHorizontal: 24,
105
- },
106
- controlsTablet: {
107
- height: 96,
108
- marginHorizontal: 24,
109
- },
110
96
  playerDetails: {
111
97
  marginTop: 60,
112
98
  alignSelf: "center",
113
99
  width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
114
100
  },
115
-
116
- linearGradient: {
117
- flex: 1,
118
- },
119
- };
120
-
121
- const sleeps = [
122
- // { label: "End of episode", value: "episode" },
123
- { label: "5 minutes", value: 5 },
124
- { label: "10 minutes", value: 10 },
125
- { label: "15 minutes", value: 15 },
126
- { label: "30 minutes", value: 30 },
127
- { label: "45 minutes", value: 45 },
128
- { label: "1 hour", value: 60 },
129
- { label: "2 hours", value: 120 },
130
- ];
101
+ });
131
102
 
132
103
  const edges: Edge[] = ["right", "left", "top"];
133
104
 
134
105
  export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
135
106
  const player = usePlayer();
136
107
  const playerState = usePlayerState("audio-player-wrapper");
137
- const theme = useTheme();
108
+
109
+ const modalBottomSheetState = useModalStoreState();
138
110
 
139
111
  const {
140
- docked,
141
112
  configuration,
142
113
  style,
143
114
  entry,
@@ -147,24 +118,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
147
118
  isTabletPortrait,
148
119
  } = props;
149
120
 
150
- const speeds = [
151
- { asset: configuration["speed_0_8"] || speed_0_8, value: 0.8 },
152
- { asset: configuration["speed_1"] || speed_1, value: 1.0 },
153
- { asset: configuration["speed_1_2"] || speed_1_2, value: 1.2 },
154
- { asset: configuration["speed_1_5"] || speed_1_5, value: 1.5 },
155
- { asset: configuration["speed_2"] || speed_2, value: 2.0 },
156
- ];
157
-
158
121
  const isTablet = useIsTablet();
159
122
 
160
123
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
161
124
 
162
- // TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
163
-
164
- const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
165
-
166
125
  const { title, summary } = useTitleSummaryOverlay(
167
- feedUrl,
168
126
  entry,
169
127
  playerState?.isLive,
170
128
  configuration?.audio_live_player_update_interval
@@ -187,6 +145,31 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
187
145
  }
188
146
  }, [player]);
189
147
 
148
+ useEffect(() => {
149
+ if (!player) return;
150
+
151
+ const unsubscribe = player.addListener({
152
+ id: "audio-player-wrapper-bottom-sheet-modal",
153
+ listener: {
154
+ onVideoEnd: () => {
155
+ // Dismiss the bottom sheet modal when the video ends to avoid audio breaks and app freeze
156
+ if (modalBottomSheetState.visible) {
157
+ dismissBottomSheetModal();
158
+ }
159
+ },
160
+ },
161
+ });
162
+
163
+ return () => unsubscribe?.();
164
+ }, [player, modalBottomSheetState.visible, sleepTimerManager]);
165
+
166
+ React.useEffect(() => {
167
+ if (playerState?.isLive) {
168
+ // Resetting a sleep timer when audio content is live (Timer not supported on live video)
169
+ sleepTimerManager.setSleepTimer(SLEEP_TIMER_OFF).catch();
170
+ }
171
+ }, [playerState?.isLive]);
172
+
190
173
  const [playbackSpeed, setPlaybackSpeed] =
191
174
  useState<PlaybackSpeed>(DEFAULT_SPEED);
192
175
 
@@ -202,8 +185,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
202
185
  height: 0,
203
186
  });
204
187
 
205
- const navigator = useNavigation();
206
-
207
188
  const { maximiseVideoModal } = useNavigation();
208
189
 
209
190
  const onLayout = (event: any) => {
@@ -293,44 +274,51 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
293
274
  );
294
275
 
295
276
  const onSpeedButtonPress = React.useCallback(() => {
296
- navigator.openModalBottomSheet({
277
+ openBottomSheetModal({
297
278
  modalBottomSheetContentProps: {
298
- items: speeds,
279
+ items: speedOptions,
299
280
  current_selection: playbackSpeed,
300
281
  onPress: onSpeedSelect,
301
282
  title: configuration["playback_speed_title"],
283
+ itemProps: getBottomSheetModalItemProps,
284
+ iconProps: getBottomSheetModalIconProps,
285
+ labelProps: getBottomSheetModalLabelProps,
286
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
287
+ getDefaultItemIcon: getBottomSheetModalDefaultItemIcon,
288
+ iconPlacement: "right",
302
289
  },
303
290
  options: {
304
- supportedOrientations: ["portrait"],
291
+ supportedOrientations: [
292
+ "portrait",
293
+ "landscape",
294
+ "portrait-upside-down",
295
+ ],
305
296
  },
306
297
  });
307
- }, [
308
- playbackSpeed,
309
- setPlaybackSpeed,
310
- navigator,
311
- onSpeedSelect,
312
- configuration["playback_speed_title"],
313
- ]);
298
+ }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
314
299
 
315
300
  const onSleepButtonPress = React.useCallback(() => {
316
- navigator.openModalBottomSheet({
301
+ openBottomSheetModal({
317
302
  modalBottomSheetContentProps: {
318
- items: [
319
- {
320
- label: configuration["playback_sleep_off_label"],
321
- value: 0,
322
- },
323
- ].concat(sleeps),
303
+ items: getSleepTimerOptions(configuration),
324
304
  current_selection: sleepTimerState.timer,
325
305
  onPress: onSleepSelect,
326
306
  title: configuration["playback_sleep_title"],
307
+ itemProps: getBottomSheetModalItemProps,
308
+ iconProps: getBottomSheetModalIconProps,
309
+ labelProps: getBottomSheetModalLabelProps,
310
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
311
+ iconPlacement: "right",
327
312
  },
328
313
  options: {
329
- supportedOrientations: ["portrait"],
314
+ supportedOrientations: [
315
+ "portrait",
316
+ "landscape",
317
+ "portrait-upside-down",
318
+ ],
330
319
  },
331
320
  });
332
321
  }, [
333
- navigator,
334
322
  sleepTimerState.timer,
335
323
  configuration["playback_sleep_title"],
336
324
  configuration["playback_sleep_off_label"],
@@ -364,116 +352,61 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
364
352
  player?.seekTo(0);
365
353
  }, [player]);
366
354
 
367
- const ContainerView = SafeAreaView;
368
-
369
- const MainContent = React.useMemo(() => {
370
- return (
371
- <ContainerView style={Styles.mainContainer(style)} edges={edges}>
372
- <AnimationComponent
373
- animationType={ComponentAnimationType.moveUpComponent}
374
- additionalData={{ saveArea: true }}
375
- style={Styles.playerContainer}
376
- >
377
- <AnimatedScrollModal>
378
- <View style={Styles.playerContainer} onLayout={onLayout}>
379
- <Layout
380
- entry={entry}
381
- playerState={playerState}
382
- layoutState={layoutState}
383
- value={value}
384
- onPlaybackButtonPress={onPlaybackButtonPress}
385
- onRewindButtonPress={onRewindButtonPress}
386
- onForwardButtonPress={onForwardButtonPress}
387
- onPlayerSeek={onPlayerSeek}
388
- onSkipStart={onSkipStart}
389
- onSpeedButtonPress={onSpeedButtonPress}
390
- onSleepButtonPress={onSleepButtonPress}
391
- playbackSpeedName={formatSpeed(playbackSpeed.value)}
392
- playbackSleepName={
393
- sleepTimerState.timer.value === 0
394
- ? "sleep_timer"
395
- : "sleep_timer_active"
396
- }
397
- sleepTimerDate={sleepTimerState.timerDate}
398
- cancelSleepTimer={cancelSleepTimer}
399
- onSkipLive={onSkipLive}
400
- onCloseVideoModal={onCloseVideoModal}
401
- maximiseVideoModal={maximiseVideoModal}
402
- configuration={configuration}
403
- dimensions={dimensions}
404
- playNextData={playNextData}
405
- title={title}
406
- summary={summary}
407
- defaultDimensions={defaultDimensions}
408
- />
409
- <View style={Styles.paddingHorizontal}>
410
- {children}
411
- <AnimationComponent
412
- animationType={ComponentAnimationType.componentFade}
413
- >
414
- <PlayerDetails
415
- configuration={configuration}
416
- style={Styles.playerDetails}
417
- entry={entry}
418
- isTabletLandscape={isTabletLandscape}
419
- isAudioPlayer={true}
420
- />
421
- </AnimationComponent>
422
- </View>
423
- </View>
424
- </AnimatedScrollModal>
425
- </AnimationComponent>
426
- </ContainerView>
427
- );
428
- }, [
429
- docked,
430
- style,
431
- entry,
432
- playerState,
433
- layoutState,
434
- value,
435
- onPlaybackButtonPress,
436
- onRewindButtonPress,
437
- onForwardButtonPress,
438
- onPlayerSeek,
439
- onCloseVideoModal,
440
- maximiseVideoModal,
441
- configuration,
442
- dimensions,
443
- children,
444
- playNextData,
445
- onSkipStart,
446
- onSkipLive,
447
- sleepTimerState.timer.value,
448
- sleepTimerState.timerDate,
449
- ]);
450
-
451
- if (configuration.magic_background) {
452
- const baseUrl = imageSrcFromMediaItem(entry, null);
453
-
454
- const queryParamName =
455
- configuration.audio_player_background_image_query || "width";
456
-
457
- const defaultBackgroundColor =
458
- configuration.audio_player_background_image_default_color ||
459
- theme?.app_background_color;
460
-
461
- const queryParamValue = 15;
462
-
463
- const url =
464
- baseUrl && addQueryParam(baseUrl, queryParamName, queryParamValue);
465
-
466
- return (
467
- <MagicBG
468
- image={url}
469
- fallbackUrl={baseUrl}
470
- colors={entry?.extensions?.backgroundColors}
471
- defaultColor={defaultBackgroundColor}
355
+ return (
356
+ <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
357
+ <AnimationComponent
358
+ animationType={ComponentAnimationType.moveUpComponent}
359
+ additionalData={{ saveArea: true }}
360
+ style={Styles.playerContainer}
472
361
  >
473
- {MainContent}
474
- </MagicBG>
475
- );
476
- }
477
-
478
- return MainContent;
362
+ <AnimatedScrollModal>
363
+ <View style={Styles.playerContainer} onLayout={onLayout}>
364
+ <Layout
365
+ entry={entry}
366
+ playerState={playerState}
367
+ layoutState={layoutState}
368
+ value={value}
369
+ onPlaybackButtonPress={onPlaybackButtonPress}
370
+ onRewindButtonPress={onRewindButtonPress}
371
+ onForwardButtonPress={onForwardButtonPress}
372
+ onPlayerSeek={onPlayerSeek}
373
+ onSkipStart={onSkipStart}
374
+ onSpeedButtonPress={onSpeedButtonPress}
375
+ onSleepButtonPress={onSleepButtonPress}
376
+ playbackSpeedName={formatSpeed(playbackSpeed.value)}
377
+ playbackSleepName={
378
+ sleepTimerState.timer.value === 0
379
+ ? "sleep_timer"
380
+ : "sleep_timer_active"
381
+ }
382
+ sleepTimerDate={sleepTimerState.timerDate}
383
+ cancelSleepTimer={cancelSleepTimer}
384
+ onSkipLive={onSkipLive}
385
+ onCloseVideoModal={onCloseVideoModal}
386
+ maximiseVideoModal={maximiseVideoModal}
387
+ configuration={configuration}
388
+ dimensions={dimensions}
389
+ playNextData={playNextData}
390
+ title={title}
391
+ summary={summary}
392
+ />
393
+ <View style={Styles.paddingHorizontal}>
394
+ {children}
395
+ <AnimationComponent
396
+ animationType={ComponentAnimationType.componentFade}
397
+ >
398
+ <PlayerDetails
399
+ isAudioPlayer
400
+ configuration={configuration}
401
+ style={Styles.playerDetails}
402
+ entry={entry}
403
+ isTabletLandscape={isTabletLandscape}
404
+ />
405
+ </AnimationComponent>
406
+ </View>
407
+ </View>
408
+ </AnimatedScrollModal>
409
+ </AnimationComponent>
410
+ </SafeAreaView>
411
+ );
479
412
  };