@applicaster/quick-brick-player 13.0.0-alpha.3322736490 → 13.0.0-alpha.3332871333

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 (27) hide show
  1. package/package.json +5 -6
  2. package/src/Player/AudioLayer/AudioDescription.tsx +1 -1
  3. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +44 -69
  4. package/src/Player/AudioLayer/Layout/Controls/index.tsx +30 -19
  5. package/src/Player/AudioLayer/Layout/Controls/utils.ts +3 -11
  6. package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
  7. package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +1 -0
  8. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +33 -14
  9. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +8 -8
  10. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +2 -9
  11. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +18 -8
  12. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +9 -0
  13. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +5 -3
  14. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +3 -3
  15. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +21 -9
  16. package/src/Player/AudioLayer/Layout/const.ts +2 -0
  17. package/src/Player/AudioLayer/Layout/debug.ts +1 -1
  18. package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -1
  19. package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
  20. package/src/Player/AudioLayer/Layout/hooks/{useImageSize.ts → useTabletLayoutImageSize.ts} +10 -5
  21. package/src/Player/AudioLayer/Layout/types.ts +2 -0
  22. package/src/Player/AudioLayer/utils.ts +6 -3
  23. package/src/Player/Const/sleepTimerOptions.ts +39 -0
  24. package/src/Player/Const/speedOptions.ts +4 -0
  25. package/src/Player/Utils/Utils.ts +0 -5
  26. package/src/Player/Utils/index.tsx +117 -0
  27. package/src/Player/Helpers/VideoResizeMode.ts +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/quick-brick-player",
3
- "version": "13.0.0-alpha.3322736490",
3
+ "version": "13.0.0-alpha.3332871333",
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-alpha.3322736490",
38
+ "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.99",
39
39
  "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
40
- "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.3322736490",
41
- "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.3322736490",
42
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.3322736490",
43
- "keymirror": "^0.1.1",
40
+ "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.3332871333",
41
+ "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.3332871333",
42
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.3332871333",
44
43
  "query-string": "7.1.3",
45
44
  "react-native-web-linear-gradient": "1.1.2",
46
45
  "shaka-player": "4.3.5",
@@ -82,7 +82,7 @@ export const AudioDescription = (props: AudioDescriptionProps) => {
82
82
 
83
83
  return (
84
84
  <>
85
- <Text style={titleStyles(value, prefix)} numberOfLines={1}>
85
+ <Text style={titleStyles(value, prefix)} numberOfLines={2}>
86
86
  {title}
87
87
  </Text>
88
88
  <Text style={summaryStyles(value, prefix)} numberOfLines={1}>
@@ -1,5 +1,10 @@
1
1
  import * as React from "react";
2
- import { ViewStyle, View, Dimensions as ScreenDimensions } from "react-native";
2
+ import {
3
+ StyleSheet,
4
+ ViewStyle,
5
+ View,
6
+ Dimensions as ScreenDimensions,
7
+ } from "react-native";
3
8
 
4
9
  import { SafeAreaView, Edge } from "react-native-safe-area-context";
5
10
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
@@ -18,7 +23,14 @@ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
18
23
  import { useEffect, useState } from "react";
19
24
  import { MagicBG } from "./MagicBG";
20
25
  import { formatSpeed } from "./utils";
21
- import { addQueryParam, getLiveUrl } from "../Utils";
26
+ import {
27
+ addQueryParam,
28
+ getBottomSheetModalDefaultItemIcon,
29
+ getBottomSheetModalIconProps,
30
+ getBottomSheetModalItemProps,
31
+ getBottomSheetModalLabelProps,
32
+ getBottomSheetModalSelectedItemIcon,
33
+ } from "../Utils";
22
34
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
23
35
  import {
24
36
  AnimationComponent,
@@ -27,7 +39,6 @@ import {
27
39
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
28
40
  import { PADDING_HORIZONTAL } from "./Layout/const";
29
41
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
30
-
31
42
  import {
32
43
  SleepTimerController,
33
44
  SleepTimerState,
@@ -37,6 +48,8 @@ import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
37
48
  import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
38
49
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
39
50
  import { openBottomSheetModal } from "@applicaster/zapp-react-native-utils/modalState";
51
+ import { getSleepTimerOptions } from "../Const/sleepTimerOptions";
52
+ import { speedOptions } from "../Const/speedOptions";
40
53
 
41
54
  const { log_debug } = createLogger({
42
55
  subsystem: "UIComponent",
@@ -78,59 +91,17 @@ type Props = {
78
91
 
79
92
  const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
80
93
 
81
- const Styles = {
82
- mainContainer: (style: ViewStyle) => {
83
- const combinedStyle: ViewStyle = {
84
- flex: 1,
85
- };
86
-
87
- return {
88
- ...combinedStyle,
89
- ...style,
90
- };
91
- },
94
+ const Styles = StyleSheet.create({
92
95
  playerContainer: {
93
96
  flex: 1,
94
97
  },
95
98
  paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
96
-
97
- controlsMobile: {
98
- height: 50,
99
- marginHorizontal: 24,
100
- },
101
- controlsTablet: {
102
- height: 96,
103
- marginHorizontal: 24,
104
- },
105
99
  playerDetails: {
106
100
  marginTop: 60,
107
101
  alignSelf: "center",
108
102
  width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
109
103
  },
110
-
111
- linearGradient: {
112
- flex: 1,
113
- },
114
- };
115
-
116
- const sleeps = [
117
- // { label: "End of episode", value: "episode" },
118
- { label: "5 minutes", value: 5 },
119
- { label: "10 minutes", value: 10 },
120
- { label: "15 minutes", value: 15 },
121
- { label: "30 minutes", value: 30 },
122
- { label: "45 minutes", value: 45 },
123
- { label: "1 hour", value: 60 },
124
- { label: "2 hours", value: 120 },
125
- ];
126
-
127
- const speeds = [
128
- { label: "0.8x", value: 0.8 },
129
- { label: "1x", value: 1.0 },
130
- { label: "1.2x", value: 1.2 },
131
- { label: "1.5x", value: 1.5 },
132
- { label: "2x", value: 2.0 },
133
- ];
104
+ });
134
105
 
135
106
  const edges: Edge[] = ["right", "left", "top"];
136
107
 
@@ -154,12 +125,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
154
125
 
155
126
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
156
127
 
157
- // TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
158
-
159
- const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
160
-
161
128
  const { title, summary } = useTitleSummaryOverlay(
162
- feedUrl,
163
129
  entry,
164
130
  playerState?.isLive,
165
131
  configuration?.audio_live_player_update_interval
@@ -288,37 +254,46 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
288
254
  const onSpeedButtonPress = React.useCallback(() => {
289
255
  openBottomSheetModal({
290
256
  modalBottomSheetContentProps: {
291
- items: speeds,
257
+ items: speedOptions,
292
258
  current_selection: playbackSpeed,
293
259
  onPress: onSpeedSelect,
294
260
  title: configuration["playback_speed_title"],
261
+ itemProps: getBottomSheetModalItemProps,
262
+ iconProps: getBottomSheetModalIconProps,
263
+ labelProps: getBottomSheetModalLabelProps,
264
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
265
+ getDefaultItemIcon: getBottomSheetModalDefaultItemIcon,
266
+ iconPlacement: "right",
295
267
  },
296
268
  options: {
297
- supportedOrientations: ["portrait"],
269
+ supportedOrientations: [
270
+ "portrait",
271
+ "landscape",
272
+ "portrait-upside-down",
273
+ ],
298
274
  },
299
275
  });
300
- }, [
301
- playbackSpeed,
302
- setPlaybackSpeed,
303
- onSpeedSelect,
304
- configuration["playback_speed_title"],
305
- ]);
276
+ }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
306
277
 
307
278
  const onSleepButtonPress = React.useCallback(() => {
308
279
  openBottomSheetModal({
309
280
  modalBottomSheetContentProps: {
310
- items: [
311
- {
312
- label: configuration["playback_sleep_off_label"],
313
- value: 0,
314
- },
315
- ].concat(sleeps),
281
+ items: getSleepTimerOptions(configuration),
316
282
  current_selection: sleepTimerState.timer,
317
283
  onPress: onSleepSelect,
318
284
  title: configuration["playback_sleep_title"],
285
+ itemProps: getBottomSheetModalItemProps,
286
+ iconProps: getBottomSheetModalIconProps,
287
+ labelProps: getBottomSheetModalLabelProps,
288
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
289
+ iconPlacement: "right",
319
290
  },
320
291
  options: {
321
- supportedOrientations: ["portrait"],
292
+ supportedOrientations: [
293
+ "portrait",
294
+ "landscape",
295
+ "portrait-upside-down",
296
+ ],
322
297
  },
323
298
  });
324
299
  }, [
@@ -357,7 +332,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
357
332
 
358
333
  const MainContent = React.useMemo(() => {
359
334
  return (
360
- <SafeAreaView style={Styles.mainContainer(style)} edges={edges}>
335
+ <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
361
336
  <AnimationComponent
362
337
  animationType={ComponentAnimationType.moveUpComponent}
363
338
  additionalData={{ saveArea: true }}
@@ -401,11 +376,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
401
376
  animationType={ComponentAnimationType.componentFade}
402
377
  >
403
378
  <PlayerDetails
379
+ isAudioPlayer
404
380
  configuration={configuration}
405
381
  style={Styles.playerDetails}
406
382
  entry={entry}
407
383
  isTabletLandscape={isTabletLandscape}
408
- isAudioPlayer={true}
409
384
  />
410
385
  </AnimationComponent>
411
386
  </View>
@@ -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;
@@ -117,14 +121,19 @@ export const Controls = (props: Props) => {
117
121
  showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
118
122
  }
119
123
 
120
- const sleepTitle = value("playback_sleep_countdown_label");
121
-
122
124
  const [timeLeft, setTimeLeft] = React.useState(
123
125
  sleepTimerDate !== 0 ? sleepTimerDate - Date.now() : 0
124
126
  );
125
127
 
126
128
  const showCounter = React.useMemo(() => sleepTimerDate > 0, [sleepTimerDate]);
127
129
 
130
+ const countDownOptions = React.useMemo(() => {
131
+ return {
132
+ showCounter: showCounter && timeLeft >= 0,
133
+ timeLeft,
134
+ };
135
+ }, [showCounter, timeLeft]);
136
+
128
137
  React.useEffect(() => {
129
138
  if (showCounter && sleepTimerDate !== 0) {
130
139
  setTimeLeft(sleepTimerDate - Date.now());
@@ -282,12 +291,12 @@ export const Controls = (props: Props) => {
282
291
  isDateBasedLiveContent={isDateBasedLiveContent}
283
292
  onSkipLive={onSkipLive}
284
293
  progressBarStyles={styles.progressBar}
294
+ countDownOptions={countDownOptions}
295
+ thumbStyles={styles.progressBarThumbStyles}
296
+ thumbStylesPressed={styles.progressBarThumbStyles_pressed}
297
+ trackStyles={styles.progressBarTrackStyles}
285
298
  />
286
299
 
287
- {showCounter && timeLeft >= 0 ? (
288
- <CountDown timeLeft={timeLeft} value={value} title={sleepTitle} />
289
- ) : null}
290
-
291
300
  <VerticalGutter />
292
301
  </>
293
302
  ) : null}
@@ -297,7 +306,9 @@ export const Controls = (props: Props) => {
297
306
  visible={true}
298
307
  keepAlive={null}
299
308
  buttons={controlButtons}
300
- style={controlsStyles({ isTablet, isLiveShowFullControls })}
309
+ style={{
310
+ justifyContent: getControlJustifyContent(controlButtons().length),
311
+ }}
301
312
  playerState={playerState}
302
313
  />
303
314
  </AnimationComponent>
@@ -1,14 +1,7 @@
1
- const rewindButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
2
- isTablet ? "big" : "smallMargins";
3
-
4
- const playbackButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
5
- isTablet ? "bigExtended" : "mediumExtended";
6
-
7
1
  const playbackButtonMargins = (
8
2
  isTablet: boolean,
9
3
  isLiveShowFullControls: boolean
10
- ): number =>
11
- isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? undefined : 40;
4
+ ): number => (isLiveShowFullControls ? (isTablet ? 65 : 10) : undefined);
12
5
 
13
6
  export const playbackButton = ({
14
7
  playerState,
@@ -30,7 +23,7 @@ export const playbackButton = ({
30
23
  : "pause";
31
24
 
32
25
  return {
33
- size: playbackButtonSize(isTablet),
26
+ size: "bigExtended",
34
27
  icon: playerState.isBuffering ? "buffering" : icon,
35
28
  preferredFocus: true,
36
29
  onPress,
@@ -52,10 +45,9 @@ type ButtonsByNameProps = ButtonsProps & { name?: string };
52
45
  const rewindButtonByName = ({
53
46
  name,
54
47
  onPress,
55
- isTablet,
56
48
  style,
57
49
  }: ButtonsByNameProps): ControlsButton => ({
58
- size: rewindButtonSize(isTablet),
50
+ size: "big",
59
51
  icon: name,
60
52
  onPress,
61
53
  style,
@@ -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
+ );
@@ -218,6 +218,7 @@ export const DockedControls = (props: Props) => {
218
218
  isActiveGesture || layoutState.docked,
219
219
  progressBarHeight
220
220
  ),
221
+ { height: minimisedHeight },
221
222
  ]}
222
223
  >
223
224
  {!playerState.isLive &&
@@ -6,14 +6,19 @@ import {
6
6
  } from "react-native-safe-area-context";
7
7
  import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
8
 
9
- import { MOBILE } from "./const";
9
+ import { MOBILE, NAVBAR_HEIGHT } from "./const";
10
10
  import { TransportInfo } from "./TransportInfo";
11
11
  import { PlayerImage } from "./PlayerImage";
12
12
  import { Controls } from "./Controls";
13
13
 
14
- import { useImageSize, useTransportInfoHeight } from "./hooks";
14
+ import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
15
15
  import { DockedControls } from "./DockedControls";
16
- import { withDebug } from "./debug";
16
+ import { withDebug, DEBUG } from "./debug";
17
+ import {
18
+ LeftDebugSquare,
19
+ RightDebugSquare,
20
+ BottomDebugSquare,
21
+ } from "./Debug/index";
17
22
 
18
23
  import { Props } from "./types";
19
24
 
@@ -90,11 +95,27 @@ export function MobileLayout({
90
95
  const { height: screenHeight } = useSafeAreaFrame();
91
96
  const { progressBarHeight } = useModalAnimationContext();
92
97
 
93
- const { imageSize, onLayout } = useImageSize({ isPortraitMode: true });
98
+ const { imageSize } = useMobileLayoutImageSize();
94
99
 
95
100
  const { height: transportInfoHeight, onLayout: onTransportInfoLayout } =
96
101
  useTransportInfoHeight();
97
102
 
103
+ const controlsContainerHeight = React.useMemo(() => {
104
+ return (
105
+ screenHeight -
106
+ topInset -
107
+ imageSize -
108
+ NAVBAR_HEIGHT -
109
+ MOBILE.MARGIN_BOTTOM -
110
+ MOBILE.MARGIN_TOP -
111
+ bottomInset
112
+ );
113
+ }, [screenHeight, topInset, imageSize, bottomInset]);
114
+
115
+ const verticalOffsetForImage = React.useMemo(() => {
116
+ return transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight;
117
+ }, [transportInfoHeight, progressBarHeight]);
118
+
98
119
  return (
99
120
  <View
100
121
  style={[
@@ -107,6 +128,10 @@ export function MobileLayout({
107
128
  }),
108
129
  ]}
109
130
  >
131
+ {DEBUG ? <LeftDebugSquare /> : null}
132
+ {DEBUG ? <RightDebugSquare /> : null}
133
+ {DEBUG ? <BottomDebugSquare /> : null}
134
+
110
135
  {/* TransportInfo */}
111
136
  <TransportInfo
112
137
  entry={entry}
@@ -139,7 +164,6 @@ export function MobileLayout({
139
164
  }),
140
165
  },
141
166
  ]}
142
- onLayout={onLayout}
143
167
  >
144
168
  <PlayerImage
145
169
  entry={entry}
@@ -155,20 +179,15 @@ export function MobileLayout({
155
179
  summary={summary}
156
180
  docked={docked}
157
181
  imageWidth={imageSize}
158
- verticalOffset={
159
- transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight
160
- }
182
+ verticalOffset={verticalOffsetForImage}
161
183
  />
162
184
  </View>
163
185
  {/* PlayerImage */}
164
186
 
165
187
  <View
166
- style={[
167
- styles.flex,
168
- {
169
- marginBottom: MOBILE.MARGIN_BOTTOM,
170
- },
171
- ]}
188
+ style={{
189
+ height: controlsContainerHeight,
190
+ }}
172
191
  >
173
192
  <Controls
174
193
  entry={entry}
@@ -1,5 +1,5 @@
1
1
  import React, { PropsWithChildren } from "react";
2
- import { ImageBackground, Animated, StyleSheet } from "react-native";
2
+ import { Image, Animated, StyleSheet, ViewStyle } from "react-native";
3
3
 
4
4
  import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
5
5
  import {
@@ -14,6 +14,7 @@ const styles = StyleSheet.create({
14
14
  // we have to specify flex:0 and dimensions to make animation work
15
15
  flex: 0,
16
16
  aspectRatio: 1,
17
+ overflow: "hidden",
17
18
  },
18
19
  });
19
20
 
@@ -21,6 +22,7 @@ type Props = PropsWithChildren<{
21
22
  entry: ZappEntry;
22
23
  style?: { [K: string]: any };
23
24
  imageStyle?: { [K: string]: any };
25
+ wrapperViewStyle?: ViewStyle;
24
26
  imageWidth: number;
25
27
  }>;
26
28
 
@@ -28,6 +30,7 @@ export const AnimatedImage = ({
28
30
  entry,
29
31
  style,
30
32
  imageStyle,
33
+ wrapperViewStyle,
31
34
  imageWidth,
32
35
  }: Props) => {
33
36
  const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
@@ -65,19 +68,16 @@ export const AnimatedImage = ({
65
68
  <Animated.View
66
69
  style={[
67
70
  styles.container,
71
+ wrapperViewStyle,
72
+ imageStyle,
68
73
  {
69
74
  width: heightAnim,
70
75
  },
71
76
  ]}
72
77
  >
73
- <ImageBackground
74
- resizeMode="cover"
75
- style={style}
76
- imageStyle={imageStyle}
77
- source={source}
78
- >
78
+ <Image resizeMode="cover" style={style} source={source}>
79
79
  {null}
80
- </ImageBackground>
80
+ </Image>
81
81
  </Animated.View>
82
82
  );
83
83
  };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { ImageBackground } from "react-native";
2
+ import { Image } from "react-native";
3
3
 
4
4
  import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
5
5
 
@@ -20,13 +20,6 @@ export const FlexImage = ({ entry, imageStyle }: Props) => {
20
20
  if (!source) return null;
21
21
 
22
22
  return (
23
- <ImageBackground
24
- resizeMode="cover"
25
- style={style}
26
- source={source}
27
- imageStyle={imageStyle}
28
- >
29
- {null}
30
- </ImageBackground>
23
+ <Image resizeMode="cover" style={[style, imageStyle]} source={source} />
31
24
  );
32
25
  };
@@ -1,7 +1,5 @@
1
1
  import * as React from "react";
2
2
 
3
- import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
4
-
5
3
  import {
6
4
  AnimationComponent,
7
5
  ComponentAnimationType,
@@ -13,6 +11,7 @@ import { FlexImage } from "./FlexImage";
13
11
 
14
12
  import { styles } from "./styles";
15
13
  import { calculateBorderRadius } from "../../utils";
14
+ import { PlayNextData } from "../types";
16
15
 
17
16
  type Props = {
18
17
  entry: ZappEntry;
@@ -23,7 +22,7 @@ type Props = {
23
22
  dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
24
23
  onCloseVideoModal: Callback;
25
24
  onPlayerSeek: (targetTime: number) => void;
26
- playNextData: QuickBrickPlayer.AudioPlayerProps["playNextData"];
25
+ playNextData: PlayNextData;
27
26
  title: string | number;
28
27
  summary: string | number;
29
28
  docked: boolean;
@@ -32,9 +31,14 @@ type Props = {
32
31
  };
33
32
 
34
33
  export const PlayerImage = (props: Props) => {
35
- const { entry, dimensions, docked, imageWidth, verticalOffset } = props;
36
-
37
- const isTablet = useIsTablet();
34
+ const {
35
+ entry,
36
+ dimensions,
37
+ docked,
38
+ imageWidth,
39
+ verticalOffset,
40
+ configuration,
41
+ } = props;
38
42
 
39
43
  const {
40
44
  isActiveGesture,
@@ -43,12 +47,17 @@ export const PlayerImage = (props: Props) => {
43
47
  minimisedHeight,
44
48
  } = useModalAnimationContext();
45
49
 
50
+ const isShadowEnabled =
51
+ configuration?.audio_player_artwork_shadow_enabled ?? true;
52
+
53
+ const shouldShowShadow = !docked && isShadowEnabled;
54
+
46
55
  const borderRadius = calculateBorderRadius(
47
- isTablet,
48
56
  docked,
49
57
  startComponentsAnimation,
50
58
  isActiveGesture,
51
- playerAnimationState
59
+ playerAnimationState,
60
+ configuration
52
61
  );
53
62
 
54
63
  return (
@@ -83,6 +92,7 @@ export const PlayerImage = (props: Props) => {
83
92
  style={styles.backgroundImageContainer}
84
93
  imageStyle={{ borderRadius }}
85
94
  imageWidth={imageWidth}
95
+ wrapperViewStyle={shouldShowShadow ? styles.shadow : undefined}
86
96
  />
87
97
  ) : null}
88
98
  </AnimationComponent>
@@ -1,5 +1,7 @@
1
1
  import { StyleSheet } from "react-native";
2
2
 
3
+ const SHADOW_COLOR = "rgba(0, 0, 0, 1)";
4
+
3
5
  export const styles = StyleSheet.create({
4
6
  backgroundImageContainer: {
5
7
  flex: 1,
@@ -14,4 +16,11 @@ export const styles = StyleSheet.create({
14
16
  flex: {
15
17
  flex: 1,
16
18
  },
19
+ shadow: {
20
+ shadowColor: SHADOW_COLOR,
21
+ shadowOffset: { width: 0, height: 24 },
22
+ shadowOpacity: 0.2,
23
+ shadowRadius: 32,
24
+ elevation: 12,
25
+ },
17
26
  });
@@ -12,7 +12,7 @@ import { TransportInfo } from "./TransportInfo";
12
12
  import { PlayerImage } from "./PlayerImage";
13
13
  import { Controls } from "./Controls";
14
14
 
15
- import { useImageSize, useTransportInfoHeight } from "./hooks";
15
+ import { useTabletLayoutImageSize, useTransportInfoHeight } from "./hooks";
16
16
  import { DockedControls } from "./DockedControls";
17
17
  import { withDebug } from "./debug";
18
18
 
@@ -71,7 +71,7 @@ const withAdditionalOffset = ({ progressBarHeight, bottomInset }) => {
71
71
  }
72
72
 
73
73
  // android
74
- return progressBarHeight === 0 ? 4 : 2;
74
+ return progressBarHeight === 0 ? 4 : 0.5;
75
75
  };
76
76
 
77
77
  export function TabletLandscapeLayout({
@@ -104,7 +104,9 @@ export function TabletLandscapeLayout({
104
104
  const { height: screenHeight } = useSafeAreaFrame();
105
105
  const { progressBarHeight } = useModalAnimationContext();
106
106
 
107
- const { imageSize, onLayout } = useImageSize({ isPortraitMode: false });
107
+ const { imageSize, onLayout } = useTabletLayoutImageSize({
108
+ isPortraitMode: false,
109
+ });
108
110
 
109
111
  const { height: transportInfoHeight, onLayout: onTransportInfoLayout } =
110
112
  useTransportInfoHeight();
@@ -14,7 +14,7 @@ import { TransportInfo } from "./TransportInfo";
14
14
  import { PlayerImage } from "./PlayerImage";
15
15
  import { Controls } from "./Controls";
16
16
 
17
- import { useImageSize } from "./hooks";
17
+ import { useTabletLayoutImageSize } from "./hooks";
18
18
  import { DockedControls } from "./DockedControls";
19
19
  import { VerticalGutter } from "./VerticalGutter";
20
20
 
@@ -36,7 +36,7 @@ const styles = StyleSheet.create({
36
36
 
37
37
  fillContainer: {
38
38
  ...StyleSheet.absoluteFillObject,
39
-
39
+ alignItems: "center",
40
40
  ...withDebug({
41
41
  borderWidth: 2,
42
42
  borderColor: "red",
@@ -104,7 +104,7 @@ export function TabletPortraitLayout({
104
104
  imageSize,
105
105
  offsetY: topOffset,
106
106
  onLayout,
107
- } = useImageSize({ isPortraitMode: true });
107
+ } = useTabletLayoutImageSize({ isPortraitMode: true });
108
108
 
109
109
  return (
110
110
  <View
@@ -12,14 +12,23 @@ import {
12
12
  import { toPositiveNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
13
13
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
14
14
 
15
- import { TABLET_LANDSCAPE } from "../const";
15
+ import { TABLET_LANDSCAPE, NAVBAR_HEIGHT } from "../const";
16
16
  import { withDebug } from "../debug";
17
17
 
18
18
  const styles = StyleSheet.create({
19
19
  container: {
20
+ height: NAVBAR_HEIGHT,
21
+ justifyContent: "center",
22
+ },
23
+ animatedContainer: {
20
24
  width: "100%",
21
25
  alignItems: "center",
22
26
  justifyContent: "space-between",
27
+
28
+ ...withDebug({
29
+ borderWidth: 2,
30
+ borderColor: "yellow",
31
+ }),
23
32
  },
24
33
  });
25
34
 
@@ -74,19 +83,22 @@ export const TransportInfo = ({
74
83
 
75
84
  return (
76
85
  <View
77
- style={{
78
- marginBottom: applyMarginBottom({ isTablet, marginBottom }),
86
+ style={[
87
+ styles.container,
88
+ {
89
+ marginBottom: applyMarginBottom({ isTablet, marginBottom }),
79
90
 
80
- ...withDebug({
81
- borderWidth: 2,
82
- borderColor: "red",
83
- }),
84
- }}
91
+ ...withDebug({
92
+ borderWidth: 2,
93
+ borderColor: "red",
94
+ }),
95
+ },
96
+ ]}
85
97
  onLayout={handleLayout}
86
98
  >
87
99
  <AnimationComponent
88
100
  animationType={ComponentAnimationType.componentFade}
89
- style={styles.container}
101
+ style={styles.animatedContainer}
90
102
  >
91
103
  <MobileTransportInfo
92
104
  content={entry}
@@ -18,3 +18,5 @@ export const MOBILE = {
18
18
  MARGIN_TOP: 10,
19
19
  MIN_HEIGHT: 458,
20
20
  };
21
+
22
+ export const NAVBAR_HEIGHT = 60;
@@ -1,5 +1,5 @@
1
1
  // use this variable to activate borders on AudioPlayer. It will help you to fix layout if needed.
2
- const DEBUG = false;
2
+ export const DEBUG = false;
3
3
 
4
4
  export const withDebug = (style) => {
5
5
  return DEBUG ? style : {};
@@ -1,3 +1,5 @@
1
- export { useImageSize } from "./useImageSize";
1
+ export { useTabletLayoutImageSize } from "./useTabletLayoutImageSize";
2
+
3
+ export { useMobileLayoutImageSize } from "./useMobileLayoutImageSize";
2
4
 
3
5
  export { useTransportInfoHeight } from "./useTransportInfoHeight";
@@ -0,0 +1,14 @@
1
+ import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
2
+ import { MOBILE } from "../const";
3
+
4
+ type Return = {
5
+ imageSize: Option<number>;
6
+ };
7
+
8
+ export const useMobileLayoutImageSize = (): Return => {
9
+ const { width } = useDimensions("screen");
10
+
11
+ return {
12
+ imageSize: width - 2 * MOBILE.MARGIN_HORIZONTAL,
13
+ };
14
+ };
@@ -3,9 +3,11 @@ import { LayoutChangeEvent } from "react-native";
3
3
 
4
4
  import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
5
5
  import { Subject } from "rxjs";
6
- import { take, last } from "rxjs/operators";
6
+ import { first, debounceTime, filter } from "rxjs/operators";
7
7
  import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
8
8
 
9
+ const TIMEOUT = 200; // ms
10
+
9
11
  type Layout = {
10
12
  x: number;
11
13
  y: number;
@@ -36,7 +38,7 @@ type Return = {
36
38
  onLayout: (event: LayoutChangeEvent) => void;
37
39
  };
38
40
 
39
- export const useImageSize = ({ isPortraitMode }: Props): Return => {
41
+ export const useTabletLayoutImageSize = ({ isPortraitMode }: Props): Return => {
40
42
  const [imageSize, setImageSize] = React.useState(undefined);
41
43
  const [offsetY, setOffsetY] = React.useState(undefined);
42
44
 
@@ -45,7 +47,7 @@ export const useImageSize = ({ isPortraitMode }: Props): Return => {
45
47
  React.useEffect(() => {
46
48
  const subscription = layoutRef.current.layoutChange$
47
49
  // for landscape layout we need to wait the second layout change in order to get proper size of image
48
- .pipe(take(isPortraitMode ? 1 : 2), last())
50
+ .pipe(debounceTime(TIMEOUT), first())
49
51
  .subscribe({
50
52
  next: (layout: Layout) => {
51
53
  const size = isPortraitMode
@@ -63,8 +65,11 @@ export const useImageSize = ({ isPortraitMode }: Props): Return => {
63
65
 
64
66
  React.useEffect(() => {
65
67
  const subscription = layoutRef.current.layoutChange$
66
- // wait the second layout change in order to get proper offsetY
67
- .pipe(take(2), last())
68
+ .pipe(
69
+ filter((layout: Layout) => layout.y > 0),
70
+ debounceTime(TIMEOUT),
71
+ first()
72
+ )
68
73
  .subscribe({
69
74
  next: (layout: Layout) => {
70
75
  setOffsetY(layout.y);
@@ -3,3 +3,5 @@ import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Compo
3
3
  export type Props = QuickBrickPlayer.AudioPlayerProps & {
4
4
  playNextData: PlayNextData;
5
5
  };
6
+
7
+ export { PlayNextData };
@@ -4,6 +4,7 @@ import {
4
4
  PlayerAnimationStateT,
5
5
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
6
6
  import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
7
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
7
8
 
8
9
  export const NAMESPACE = "audio-player";
9
10
 
@@ -37,11 +38,11 @@ export const formatSpeed = (value: number) => {
37
38
  };
38
39
 
39
40
  export const calculateBorderRadius = (
40
- isTablet: boolean,
41
41
  docked: boolean,
42
42
  startComponentsAnimation: boolean,
43
43
  isActiveGesture: boolean,
44
- playerAnimationState: PlayerAnimationStateT
44
+ playerAnimationState: PlayerAnimationStateT,
45
+ configuration: Record<string, any>
45
46
  ): number => {
46
47
  const shouldRemoveBorderRadius =
47
48
  (startComponentsAnimation &&
@@ -53,5 +54,7 @@ export const calculateBorderRadius = (
53
54
  return 0;
54
55
  }
55
56
 
56
- return isTablet ? 24 : 10;
57
+ return toNumberWithDefaultZero(
58
+ configuration.audio_player_artwork_border_radius
59
+ );
57
60
  };
@@ -0,0 +1,39 @@
1
+ import { toDayJSLocaleMap } from "@applicaster/zapp-react-native-utils/appUtils/localizationsHelper";
2
+ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
3
+ import { getUILanguage } from "@applicaster/zapp-react-native-utils/localizationUtils";
4
+
5
+ const createTimerOptions = (value) => {
6
+ let label = "";
7
+
8
+ const str = dayjs
9
+ .duration(value, "minute")
10
+ .locale(toDayJSLocaleMap(getUILanguage()))
11
+ .humanize();
12
+
13
+ if (value === 60) {
14
+ /** Skipping prefix "an"/"un"/"una" for 1 hour */
15
+
16
+ if (str.includes(" ")) {
17
+ label = `1 ${str.split(" ")[1]}`; // Combine "1" with second part of the string
18
+ } else {
19
+ label = `1 ${str}`; // Use dayjs provided translation
20
+ }
21
+ } else {
22
+ label = str;
23
+ }
24
+
25
+ return {
26
+ label,
27
+ value,
28
+ };
29
+ };
30
+
31
+ export const getSleepTimerOptions = (configuration) => {
32
+ return [
33
+ {
34
+ label: configuration["playback_sleep_off_label"],
35
+ value: 0,
36
+ },
37
+ ...[5, 10, 15, 30, 45, 60, 120].map(createTimerOptions),
38
+ ];
39
+ };
@@ -0,0 +1,4 @@
1
+ export const speedOptions = [0.8, 1, 1.2, 1.5, 2].map((v) => ({
2
+ label: v + "x",
3
+ value: v,
4
+ }));
@@ -1,11 +1,6 @@
1
1
  import queryString from "query-string";
2
2
  import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
3
3
 
4
- export const getLiveUrl = (url: string) => {
5
- // Use the replace method with a regular expression to replace all instances of subClass with livePage
6
- return url.replace(new RegExp("subClass", "g"), "livePage");
7
- };
8
-
9
4
  export const addQueryParam = (
10
5
  baseUrl: string,
11
6
  paramName: string,
@@ -1 +1,118 @@
1
+ import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
2
+
1
3
  export * from "./Utils";
4
+
5
+ export const getBottomSheetModalIconProps = (theme) => ({
6
+ height: theme["audio_modal_bottom_sheet_item_icon_height"],
7
+ width: theme["audio_modal_bottom_sheet_item_icon_width"],
8
+ marginBottom: theme["audio_modal_bottom_sheet_item_icon_margin_bottom"],
9
+ marginLeft: theme["audio_modal_bottom_sheet_item_icon_margin_left"],
10
+ marginRight: theme["audio_modal_bottom_sheet_item_icon_margin_right"],
11
+ marginTop: theme["audio_modal_bottom_sheet_item_icon_margin_top"],
12
+ flavour: theme["modal_bottom_sheet_item_icon_flavour"],
13
+ });
14
+
15
+ export const getBottomSheetModalLabelProps = (theme, width: number) => {
16
+ const {
17
+ audio_modal_bottom_sheet_item_label_android_letter_spacing,
18
+ audio_modal_bottom_sheet_item_label_ios_letter_spacing,
19
+ audio_modal_bottom_sheet_item_label_family_ios_font_selector,
20
+ audio_modal_bottom_sheet_item_label_family_android_font_selector,
21
+ audio_modal_bottom_sheet_item_label_focus_font_color,
22
+ audio_modal_bottom_sheet_item_label_font_color,
23
+ audio_modal_bottom_sheet_item_label_selected_font_color,
24
+ audio_modal_bottom_sheet_item_label_hover_selected_font_color,
25
+ audio_modal_bottom_sheet_item_label_font_size,
26
+ audio_modal_bottom_sheet_item_label_line_height,
27
+ audio_modal_bottom_sheet_item_label_margin_bottom,
28
+ audio_modal_bottom_sheet_item_label_margin_top,
29
+ audio_modal_bottom_sheet_item_label_margin_left,
30
+ audio_modal_bottom_sheet_item_label_margin_right,
31
+ audio_modal_bottom_sheet_item_label_transform,
32
+ audio_modal_bottom_sheet_item_icon_width,
33
+ audio_modal_bottom_sheet_item_icon_margin_left,
34
+ audio_modal_bottom_sheet_item_icon_margin_right,
35
+ audio_modal_bottom_sheet_item_margin_left,
36
+ audio_modal_bottom_sheet_item_margin_right,
37
+ audio_modal_bottom_sheet_item_padding_left,
38
+ audio_modal_bottom_sheet_item_padding_right,
39
+ } = theme;
40
+
41
+ const maxWidth =
42
+ width -
43
+ (audio_modal_bottom_sheet_item_icon_width +
44
+ audio_modal_bottom_sheet_item_icon_margin_left +
45
+ audio_modal_bottom_sheet_item_icon_margin_right +
46
+ audio_modal_bottom_sheet_item_margin_left +
47
+ audio_modal_bottom_sheet_item_margin_right +
48
+ audio_modal_bottom_sheet_item_padding_left +
49
+ audio_modal_bottom_sheet_item_padding_right);
50
+
51
+ return {
52
+ fontFamily: platformSelect({
53
+ ios: audio_modal_bottom_sheet_item_label_family_ios_font_selector,
54
+ android: audio_modal_bottom_sheet_item_label_family_android_font_selector,
55
+ }),
56
+ letterSpacing: platformSelect({
57
+ ios: audio_modal_bottom_sheet_item_label_ios_letter_spacing,
58
+ android: audio_modal_bottom_sheet_item_label_android_letter_spacing,
59
+ }),
60
+ fontSize: audio_modal_bottom_sheet_item_label_font_size,
61
+ color: audio_modal_bottom_sheet_item_label_font_color,
62
+ focusColor: audio_modal_bottom_sheet_item_label_focus_font_color,
63
+ hoverSelectedColor:
64
+ audio_modal_bottom_sheet_item_label_hover_selected_font_color,
65
+ selectedColor: audio_modal_bottom_sheet_item_label_selected_font_color,
66
+ lineHeight: audio_modal_bottom_sheet_item_label_line_height,
67
+ marginBottom: audio_modal_bottom_sheet_item_label_margin_bottom,
68
+ marginTop: audio_modal_bottom_sheet_item_label_margin_top,
69
+ marginLeft: audio_modal_bottom_sheet_item_label_margin_left,
70
+ marginRight: audio_modal_bottom_sheet_item_label_margin_right,
71
+ transform: audio_modal_bottom_sheet_item_label_transform,
72
+ maxWidth,
73
+ };
74
+ };
75
+
76
+ export const getBottomSheetModalItemProps = (theme, width: number) => {
77
+ const {
78
+ audio_modal_bottom_sheet_item_background_color,
79
+ audio_modal_bottom_sheet_item_focus_background_color,
80
+ audio_modal_bottom_sheet_item_selected_background_color,
81
+ audio_modal_bottom_sheet_item_focused_selected_background_color,
82
+ audio_modal_bottom_sheet_item_corner_radius,
83
+ audio_modal_bottom_sheet_item_margin_bottom,
84
+ audio_modal_bottom_sheet_item_margin_left,
85
+ audio_modal_bottom_sheet_item_margin_right,
86
+ audio_modal_bottom_sheet_item_margin_top,
87
+ audio_modal_bottom_sheet_item_padding_bottom,
88
+ audio_modal_bottom_sheet_item_padding_left,
89
+ audio_modal_bottom_sheet_item_padding_right,
90
+ audio_modal_bottom_sheet_item_padding_top,
91
+ } = theme;
92
+
93
+ return {
94
+ backgroundColor: audio_modal_bottom_sheet_item_background_color,
95
+ focusedBackgroundColor:
96
+ audio_modal_bottom_sheet_item_focus_background_color,
97
+ selectedBackgroundColor:
98
+ audio_modal_bottom_sheet_item_selected_background_color,
99
+ focusedSelectedBackgroundColor:
100
+ audio_modal_bottom_sheet_item_focused_selected_background_color,
101
+ borderRadius: audio_modal_bottom_sheet_item_corner_radius,
102
+ marginBottom: audio_modal_bottom_sheet_item_margin_bottom,
103
+ marginTop: audio_modal_bottom_sheet_item_margin_top,
104
+ marginLeft: audio_modal_bottom_sheet_item_margin_left,
105
+ marginRight: audio_modal_bottom_sheet_item_margin_right,
106
+ paddingTop: audio_modal_bottom_sheet_item_padding_top,
107
+ paddingBottom: audio_modal_bottom_sheet_item_padding_bottom,
108
+ paddingRight: audio_modal_bottom_sheet_item_padding_right,
109
+ paddingLeft: audio_modal_bottom_sheet_item_padding_left,
110
+ maxWidth: width,
111
+ };
112
+ };
113
+
114
+ export const getBottomSheetModalSelectedItemIcon = (theme) =>
115
+ theme["audio_modal_bottom_sheet_item_selected_icon"] || null;
116
+
117
+ export const getBottomSheetModalDefaultItemIcon = (theme) =>
118
+ theme["audio_modal_bottom_sheet_item_default_icon"] || null;
@@ -1,7 +0,0 @@
1
- import keyMirror from "keymirror";
2
-
3
- export default keyMirror({
4
- contain: null,
5
- cover: null,
6
- stretch: null,
7
- });