@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.
- package/package.json +5 -6
- package/src/Player/AudioLayer/AudioDescription.tsx +1 -1
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +44 -69
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +30 -19
- package/src/Player/AudioLayer/Layout/Controls/utils.ts +3 -11
- package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +1 -0
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +33 -14
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +8 -8
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +2 -9
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +18 -8
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +9 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +5 -3
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +3 -3
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +21 -9
- package/src/Player/AudioLayer/Layout/const.ts +2 -0
- package/src/Player/AudioLayer/Layout/debug.ts +1 -1
- package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -1
- package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
- package/src/Player/AudioLayer/Layout/hooks/{useImageSize.ts → useTabletLayoutImageSize.ts} +10 -5
- package/src/Player/AudioLayer/Layout/types.ts +2 -0
- package/src/Player/AudioLayer/utils.ts +6 -3
- package/src/Player/Const/sleepTimerOptions.ts +39 -0
- package/src/Player/Const/speedOptions.ts +4 -0
- package/src/Player/Utils/Utils.ts +0 -5
- package/src/Player/Utils/index.tsx +117 -0
- 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.
|
|
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-
|
|
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.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.
|
|
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={
|
|
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 {
|
|
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 {
|
|
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:
|
|
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: [
|
|
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: [
|
|
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.
|
|
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
|
|
45
|
-
|
|
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={
|
|
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:
|
|
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:
|
|
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
|
+
);
|
|
@@ -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 {
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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
|
-
<
|
|
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
|
-
</
|
|
80
|
+
</Image>
|
|
81
81
|
</Animated.View>
|
|
82
82
|
);
|
|
83
83
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
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
|
-
<
|
|
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:
|
|
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 {
|
|
36
|
-
|
|
37
|
-
|
|
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 {
|
|
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 :
|
|
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 } =
|
|
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 {
|
|
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
|
-
} =
|
|
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
|
-
|
|
86
|
+
style={[
|
|
87
|
+
styles.container,
|
|
88
|
+
{
|
|
89
|
+
marginBottom: applyMarginBottom({ isTablet, marginBottom }),
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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.
|
|
101
|
+
style={styles.animatedContainer}
|
|
90
102
|
>
|
|
91
103
|
<MobileTransportInfo
|
|
92
104
|
content={entry}
|
|
@@ -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 {
|
|
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
|
|
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(
|
|
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
|
-
|
|
67
|
-
|
|
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);
|
|
@@ -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
|
|
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
|
+
};
|
|
@@ -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;
|