@applicaster/quick-brick-player 13.0.0-rc.11 → 13.0.0-rc.111
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 +27 -14
- package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
- package/src/Player/AudioLayer/AudioDescription.tsx +5 -7
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +174 -280
- package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +27 -0
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +316 -0
- package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +7 -25
- package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
- package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +44 -74
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +230 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +83 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +25 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +101 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +26 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +215 -0
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +223 -0
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +115 -0
- package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
- package/src/Player/AudioLayer/Layout/const.ts +22 -0
- package/src/Player/AudioLayer/Layout/debug.ts +6 -0
- package/src/Player/AudioLayer/Layout/hooks/index.ts +5 -0
- package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
- package/src/Player/AudioLayer/Layout/hooks/useTabletLayoutImageSize.ts +105 -0
- package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
- package/src/Player/AudioLayer/Layout/index.tsx +21 -48
- package/src/Player/AudioLayer/Layout/types.ts +7 -0
- package/src/Player/AudioLayer/SleepTimerManager.ts +119 -0
- package/src/Player/AudioLayer/SpeedManager.ts +52 -0
- package/src/Player/AudioLayer/utils.ts +27 -0
- 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/hooks/useIsCasting.tsx +57 -0
- package/src/Player/index.tsx +39 -22
- package/src/QuickBrickPlayer.tsx +3 -0
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
- package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
- package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
- package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
- package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
- package/src/Player/Helpers/VideoResizeMode.ts +0 -7
- package/src/utils/utils.ts +0 -25
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
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 {
|
|
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,24 +21,31 @@ 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 {
|
|
19
|
-
import { MagicBG } from "./MagicBG";
|
|
24
|
+
import { formatSpeed } from "./utils";
|
|
20
25
|
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import { addQueryParam, getLiveUrl } from "../Utils";
|
|
26
|
+
getBottomSheetModalDefaultItemIcon,
|
|
27
|
+
getBottomSheetModalIconProps,
|
|
28
|
+
getBottomSheetModalItemProps,
|
|
29
|
+
getBottomSheetModalLabelProps,
|
|
30
|
+
getBottomSheetModalSelectedItemIcon,
|
|
31
|
+
} from "../Utils";
|
|
28
32
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
29
33
|
import {
|
|
34
|
+
AnimatedScrollModal,
|
|
30
35
|
AnimationComponent,
|
|
31
36
|
ComponentAnimationType,
|
|
32
|
-
AnimatedScrollModal,
|
|
33
37
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
34
|
-
import { PADDING_HORIZONTAL } from "./Layout/
|
|
38
|
+
import { PADDING_HORIZONTAL } from "./Layout/const";
|
|
35
39
|
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
40
|
+
import {
|
|
41
|
+
SLEEP_TIMER_OFF,
|
|
42
|
+
SleepTimerController,
|
|
43
|
+
SleepTimerState,
|
|
44
|
+
} from "./SleepTimerManager";
|
|
45
|
+
import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
|
|
46
|
+
import { openBottomSheetModal } from "@applicaster/zapp-react-native-utils/modalState";
|
|
47
|
+
import { getSleepTimerOptions } from "../Const/sleepTimerOptions";
|
|
48
|
+
import { speedOptions } from "../Const/speedOptions";
|
|
36
49
|
|
|
37
50
|
const { log_debug } = createLogger({
|
|
38
51
|
subsystem: "UIComponent",
|
|
@@ -48,8 +61,8 @@ type Dimensions = {
|
|
|
48
61
|
|
|
49
62
|
type Configuration = {
|
|
50
63
|
[key: string]: any;
|
|
51
|
-
magic_background?: boolean;
|
|
52
64
|
audio_player_background_image_query?: string;
|
|
65
|
+
audio_player_background_image_default_color?: string;
|
|
53
66
|
tablet_landscape_sidebar_width?: string;
|
|
54
67
|
tablet_landscape_player_container_background_color?: string;
|
|
55
68
|
};
|
|
@@ -57,7 +70,6 @@ type Configuration = {
|
|
|
57
70
|
type Props = {
|
|
58
71
|
children: React.ReactNode;
|
|
59
72
|
inline?: boolean;
|
|
60
|
-
docked?: boolean;
|
|
61
73
|
configuration: Configuration;
|
|
62
74
|
style: ViewStyle & Dimensions;
|
|
63
75
|
entry: ZappEntry;
|
|
@@ -71,57 +83,27 @@ type Props = {
|
|
|
71
83
|
isTabletPortrait?: boolean;
|
|
72
84
|
};
|
|
73
85
|
|
|
74
|
-
|
|
75
|
-
(height / 9) * 16;
|
|
76
|
-
|
|
77
|
-
const Styles = {
|
|
78
|
-
mainContainer: (style: ViewStyle) => {
|
|
79
|
-
const combinedStyle: ViewStyle = {
|
|
80
|
-
flex: 1,
|
|
81
|
-
};
|
|
86
|
+
const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
...combinedStyle,
|
|
85
|
-
...style,
|
|
86
|
-
};
|
|
87
|
-
},
|
|
88
|
+
const Styles = StyleSheet.create({
|
|
88
89
|
playerContainer: {
|
|
89
90
|
flex: 1,
|
|
90
91
|
},
|
|
91
92
|
paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
},
|
|
97
|
-
controlsTablet: {
|
|
98
|
-
height: 96,
|
|
99
|
-
marginHorizontal: 24,
|
|
100
|
-
},
|
|
101
|
-
playerDetails: { marginTop: 60 },
|
|
102
|
-
|
|
103
|
-
linearGradient: {
|
|
104
|
-
flex: 1,
|
|
93
|
+
playerDetails: {
|
|
94
|
+
marginTop: 60,
|
|
95
|
+
alignSelf: "center",
|
|
96
|
+
width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
|
|
105
97
|
},
|
|
106
|
-
};
|
|
98
|
+
});
|
|
107
99
|
|
|
108
|
-
const
|
|
109
|
-
// { label: "End of episode", value: "episode" },
|
|
110
|
-
{ label: "5 minutes", value: 5 },
|
|
111
|
-
{ label: "10 minutes", value: 10 },
|
|
112
|
-
{ label: "15 minutes", value: 15 },
|
|
113
|
-
{ label: "30 minutes", value: 30 },
|
|
114
|
-
{ label: "45 minutes", value: 45 },
|
|
115
|
-
{ label: "1 hour", value: 60 },
|
|
116
|
-
{ label: "2 hours", value: 120 },
|
|
117
|
-
];
|
|
100
|
+
const edges: Edge[] = ["right", "left", "top"];
|
|
118
101
|
|
|
119
102
|
export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
120
103
|
const player = usePlayer();
|
|
121
104
|
const playerState = usePlayerState("audio-player-wrapper");
|
|
122
105
|
|
|
123
106
|
const {
|
|
124
|
-
docked,
|
|
125
107
|
configuration,
|
|
126
108
|
style,
|
|
127
109
|
entry,
|
|
@@ -131,40 +113,39 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
131
113
|
isTabletPortrait,
|
|
132
114
|
} = props;
|
|
133
115
|
|
|
134
|
-
const speeds = [
|
|
135
|
-
{ asset: configuration["speed_0_8"], value: 0.8 },
|
|
136
|
-
{ asset: configuration["speed_1"], value: 1.0 },
|
|
137
|
-
{ asset: configuration["speed_1_2"], value: 1.2 },
|
|
138
|
-
{ asset: configuration["speed_1_5"], value: 1.5 },
|
|
139
|
-
{ asset: configuration["speed_2"], value: 2.0 },
|
|
140
|
-
];
|
|
141
|
-
|
|
142
116
|
const isTablet = useIsTablet();
|
|
143
117
|
|
|
144
118
|
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
145
119
|
|
|
146
|
-
// TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
|
|
147
|
-
|
|
148
|
-
const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
|
|
149
|
-
|
|
150
120
|
const { title, summary } = useTitleSummaryOverlay(
|
|
151
|
-
feedUrl,
|
|
152
121
|
entry,
|
|
153
122
|
playerState?.isLive,
|
|
154
123
|
configuration?.audio_live_player_update_interval
|
|
155
124
|
);
|
|
156
125
|
|
|
157
|
-
const [
|
|
158
|
-
|
|
159
|
-
value: 1.0,
|
|
160
|
-
});
|
|
126
|
+
const [sleepTimerManager, setSleepTimerManager] =
|
|
127
|
+
useState<SleepTimerController | null>(null);
|
|
161
128
|
|
|
162
|
-
const [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
129
|
+
const [speedManager, setSpeedManager] = useState<SpeedController | null>(
|
|
130
|
+
null
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (player) {
|
|
135
|
+
setSleepTimerManager(new SleepTimerController(player));
|
|
136
|
+
setSpeedManager(new SpeedController(player));
|
|
137
|
+
} else {
|
|
138
|
+
setSleepTimerManager(null);
|
|
139
|
+
setSpeedManager(null);
|
|
140
|
+
}
|
|
141
|
+
}, [player]);
|
|
166
142
|
|
|
167
|
-
const [
|
|
143
|
+
const [playbackSpeed, setPlaybackSpeed] =
|
|
144
|
+
useState<PlaybackSpeed>(DEFAULT_SPEED);
|
|
145
|
+
|
|
146
|
+
const [sleepTimerState, setSleepTimerState] = useState<SleepTimerState>(
|
|
147
|
+
new SleepTimerState(SLEEP_TIMER_OFF, 0)
|
|
148
|
+
);
|
|
168
149
|
|
|
169
150
|
const [defaultDimensions, setDefaultDimensions] =
|
|
170
151
|
React.useState<Dimensions>(undefined);
|
|
@@ -174,8 +155,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
174
155
|
height: 0,
|
|
175
156
|
});
|
|
176
157
|
|
|
177
|
-
const navigator = useNavigation();
|
|
178
|
-
|
|
179
158
|
const { maximiseVideoModal } = useNavigation();
|
|
180
159
|
|
|
181
160
|
const onLayout = (event: any) => {
|
|
@@ -189,82 +168,27 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
189
168
|
if (!defaultDimensions) setDefaultDimensions({ width, height });
|
|
190
169
|
};
|
|
191
170
|
|
|
192
|
-
const cancelSleepTimer = async () => {
|
|
193
|
-
player?.cancelSleepTimer();
|
|
194
|
-
|
|
195
|
-
setSleepTimer({
|
|
196
|
-
label: "playback_sleep_off_label",
|
|
197
|
-
value: 0,
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
setSleepTimerDate(0);
|
|
201
|
-
|
|
202
|
-
await localStorage.removeItem("sleep", NAMESPACE);
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const startSleepTimer = (timerValue: number) => {
|
|
206
|
-
try {
|
|
207
|
-
const currentDate = new Date();
|
|
208
|
-
const futureDate = new Date(currentDate.getTime() + timerValue * 60000);
|
|
209
|
-
const futureSleepDate = futureDate.getTime();
|
|
210
|
-
|
|
211
|
-
player?.cancelSleepTimer();
|
|
212
|
-
|
|
213
|
-
player?.startSleepTimer(futureSleepDate);
|
|
214
|
-
|
|
215
|
-
return futureSleepDate;
|
|
216
|
-
} catch (e) {
|
|
217
|
-
return 0;
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
const handleSleep = async (
|
|
222
|
-
timerValue: number,
|
|
223
|
-
currentFutureSleepDate = null
|
|
224
|
-
) => {
|
|
225
|
-
if (currentFutureSleepDate) {
|
|
226
|
-
if (hasDatePassed(currentFutureSleepDate)) {
|
|
227
|
-
await cancelSleepTimer();
|
|
228
|
-
|
|
229
|
-
return 0;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return currentFutureSleepDate;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (timerValue === 0) {
|
|
236
|
-
await cancelSleepTimer();
|
|
237
|
-
|
|
238
|
-
return timerValue;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return startSleepTimer(timerValue);
|
|
242
|
-
};
|
|
243
|
-
|
|
244
171
|
useEffect(() => {
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (playerState.isReadyToPlay && speed) {
|
|
249
|
-
setPlaybackSpeed(speed);
|
|
250
|
-
player?.setPlaybackRate(speed.value);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
172
|
+
const sleepSubscription =
|
|
173
|
+
sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
|
|
253
174
|
|
|
254
|
-
const
|
|
255
|
-
|
|
175
|
+
const speedSubscription =
|
|
176
|
+
speedManager?.playbackSpeed$.subscribe(setPlaybackSpeed);
|
|
256
177
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const sleepTimerDate = await handleSleep(sleep.value, futureSleepDate);
|
|
261
|
-
setSleepTimerDate(sleepTimerDate);
|
|
262
|
-
}
|
|
178
|
+
return () => {
|
|
179
|
+
sleepSubscription?.unsubscribe();
|
|
180
|
+
speedSubscription?.unsubscribe();
|
|
263
181
|
};
|
|
182
|
+
}, [sleepTimerManager, speedManager]);
|
|
264
183
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
if (!playerState.isReadyToPlay) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
void speedManager?.loadSpeed();
|
|
190
|
+
void sleepTimerManager?.loadSleep();
|
|
191
|
+
}, [playerState.isReadyToPlay, speedManager, sleepTimerManager]);
|
|
268
192
|
|
|
269
193
|
const getValue = (key: string, stylesObj: {}) =>
|
|
270
194
|
R.propOr(null, key, stylesObj);
|
|
@@ -292,7 +216,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
292
216
|
|
|
293
217
|
const onPlaybackButtonPress = React.useCallback(() => {
|
|
294
218
|
if (playerState.isBuffering) return;
|
|
295
|
-
playerState.isPaused ? player?.play() : player
|
|
219
|
+
playerState.isPaused ? player?.play() : player?.pause();
|
|
296
220
|
}, [playerState, player]);
|
|
297
221
|
|
|
298
222
|
const seekDuration = toNumberWithDefault(10, value("seek_duration"));
|
|
@@ -307,57 +231,77 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
307
231
|
|
|
308
232
|
const onSpeedSelect = React.useCallback(
|
|
309
233
|
async (item) => {
|
|
310
|
-
setPlaybackSpeed(item);
|
|
311
|
-
player.setPlaybackRate(item.value);
|
|
312
|
-
await localStorage.setItem("speed", item, NAMESPACE);
|
|
234
|
+
await speedManager?.setPlaybackSpeed(item);
|
|
313
235
|
},
|
|
314
|
-
[
|
|
236
|
+
[speedManager]
|
|
315
237
|
);
|
|
316
238
|
|
|
317
239
|
const onSleepSelect = React.useCallback(
|
|
318
240
|
async (item) => {
|
|
319
|
-
setSleepTimer(item);
|
|
320
|
-
const futureSleepDate = await handleSleep(item.value);
|
|
321
|
-
setSleepTimerDate(futureSleepDate);
|
|
322
|
-
|
|
323
|
-
await localStorage.setItem(
|
|
324
|
-
"sleep",
|
|
325
|
-
{ ...item, futureSleepDate },
|
|
326
|
-
NAMESPACE
|
|
327
|
-
);
|
|
241
|
+
await sleepTimerManager?.setSleepTimer(item);
|
|
328
242
|
},
|
|
329
|
-
[
|
|
243
|
+
[sleepTimerManager]
|
|
330
244
|
);
|
|
331
245
|
|
|
332
246
|
const onSpeedButtonPress = React.useCallback(() => {
|
|
333
|
-
|
|
247
|
+
openBottomSheetModal({
|
|
334
248
|
modalBottomSheetContentProps: {
|
|
335
|
-
items:
|
|
249
|
+
items: speedOptions,
|
|
336
250
|
current_selection: playbackSpeed,
|
|
337
251
|
onPress: onSpeedSelect,
|
|
338
252
|
title: configuration["playback_speed_title"],
|
|
253
|
+
itemProps: getBottomSheetModalItemProps,
|
|
254
|
+
iconProps: getBottomSheetModalIconProps,
|
|
255
|
+
labelProps: getBottomSheetModalLabelProps,
|
|
256
|
+
getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
|
|
257
|
+
getDefaultItemIcon: getBottomSheetModalDefaultItemIcon,
|
|
258
|
+
iconPlacement: "right",
|
|
339
259
|
},
|
|
340
260
|
options: {
|
|
341
|
-
supportedOrientations: [
|
|
261
|
+
supportedOrientations: [
|
|
262
|
+
"portrait",
|
|
263
|
+
"landscape",
|
|
264
|
+
"portrait-upside-down",
|
|
265
|
+
],
|
|
342
266
|
},
|
|
343
267
|
});
|
|
344
|
-
}, [playbackSpeed,
|
|
268
|
+
}, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
|
|
345
269
|
|
|
346
270
|
const onSleepButtonPress = React.useCallback(() => {
|
|
347
|
-
|
|
271
|
+
openBottomSheetModal({
|
|
348
272
|
modalBottomSheetContentProps: {
|
|
349
|
-
items:
|
|
350
|
-
|
|
351
|
-
].concat(sleeps),
|
|
352
|
-
current_selection: sleepTimer,
|
|
273
|
+
items: getSleepTimerOptions(configuration),
|
|
274
|
+
current_selection: sleepTimerState.timer,
|
|
353
275
|
onPress: onSleepSelect,
|
|
354
276
|
title: configuration["playback_sleep_title"],
|
|
277
|
+
itemProps: getBottomSheetModalItemProps,
|
|
278
|
+
iconProps: getBottomSheetModalIconProps,
|
|
279
|
+
labelProps: getBottomSheetModalLabelProps,
|
|
280
|
+
getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
|
|
281
|
+
iconPlacement: "right",
|
|
355
282
|
},
|
|
356
283
|
options: {
|
|
357
|
-
supportedOrientations: [
|
|
284
|
+
supportedOrientations: [
|
|
285
|
+
"portrait",
|
|
286
|
+
"landscape",
|
|
287
|
+
"portrait-upside-down",
|
|
288
|
+
],
|
|
358
289
|
},
|
|
359
290
|
});
|
|
360
|
-
}, [
|
|
291
|
+
}, [
|
|
292
|
+
sleepTimerState.timer,
|
|
293
|
+
configuration["playback_sleep_title"],
|
|
294
|
+
configuration["playback_sleep_off_label"],
|
|
295
|
+
onSleepSelect,
|
|
296
|
+
]);
|
|
297
|
+
|
|
298
|
+
// This method does not actually cancel the sleep timer
|
|
299
|
+
// (and should not to avoid race condition),
|
|
300
|
+
// it just performs the cleanup when timer expires
|
|
301
|
+
// TODO: rename it in code above
|
|
302
|
+
const cancelSleepTimer = React.useCallback(() => {
|
|
303
|
+
sleepTimerManager?.onTimerExpired();
|
|
304
|
+
}, [sleepTimerManager]);
|
|
361
305
|
|
|
362
306
|
const onCloseVideoModal = React.useCallback(() => {
|
|
363
307
|
playerManager.close();
|
|
@@ -378,111 +322,61 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
378
322
|
player?.seekTo(0);
|
|
379
323
|
}, [player]);
|
|
380
324
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
<ContainerView style={Styles.mainContainer(style)} edges={edges}>
|
|
388
|
-
<AnimationComponent
|
|
389
|
-
animationType={ComponentAnimationType.moveUpComponent}
|
|
390
|
-
additionalData={{ saveArea: true }}
|
|
391
|
-
style={Styles.playerContainer}
|
|
392
|
-
>
|
|
393
|
-
<AnimatedScrollModal>
|
|
394
|
-
<View style={Styles.playerContainer} onLayout={onLayout}>
|
|
395
|
-
<Layout
|
|
396
|
-
entry={entry}
|
|
397
|
-
playerState={playerState}
|
|
398
|
-
layoutState={layoutState}
|
|
399
|
-
value={value}
|
|
400
|
-
onPlaybackButtonPress={onPlaybackButtonPress}
|
|
401
|
-
onRewindButtonPress={onRewindButtonPress}
|
|
402
|
-
onForwardButtonPress={onForwardButtonPress}
|
|
403
|
-
onPlayerSeek={onPlayerSeek}
|
|
404
|
-
onSkipStart={onSkipStart}
|
|
405
|
-
onSpeedButtonPress={onSpeedButtonPress}
|
|
406
|
-
onSleepButtonPress={onSleepButtonPress}
|
|
407
|
-
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
408
|
-
playbackSleepName={
|
|
409
|
-
sleepTimer.value === 0 ? "sleep_timer" : "sleep_timer_active"
|
|
410
|
-
}
|
|
411
|
-
sleepTimerDate={sleepTimerDate}
|
|
412
|
-
cancelSleepTimer={cancelSleepTimer}
|
|
413
|
-
onSkipLive={onSkipLive}
|
|
414
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
415
|
-
maximiseVideoModal={maximiseVideoModal}
|
|
416
|
-
configuration={configuration}
|
|
417
|
-
dimensions={dimensions}
|
|
418
|
-
playNextData={playNextData}
|
|
419
|
-
title={title}
|
|
420
|
-
summary={summary}
|
|
421
|
-
defaultDimensions={defaultDimensions}
|
|
422
|
-
/>
|
|
423
|
-
<View style={Styles.paddingHorizontal}>
|
|
424
|
-
{children}
|
|
425
|
-
<AnimationComponent
|
|
426
|
-
animationType={ComponentAnimationType.componentFade}
|
|
427
|
-
>
|
|
428
|
-
<PlayerDetails
|
|
429
|
-
configuration={configuration}
|
|
430
|
-
style={Styles.playerDetails}
|
|
431
|
-
entry={entry}
|
|
432
|
-
isTabletLandscape={isTabletLandscape}
|
|
433
|
-
isAudioPlayer={true}
|
|
434
|
-
/>
|
|
435
|
-
</AnimationComponent>
|
|
436
|
-
</View>
|
|
437
|
-
</View>
|
|
438
|
-
</AnimatedScrollModal>
|
|
439
|
-
</AnimationComponent>
|
|
440
|
-
</ContainerView>
|
|
441
|
-
);
|
|
442
|
-
}, [
|
|
443
|
-
docked,
|
|
444
|
-
style,
|
|
445
|
-
entry,
|
|
446
|
-
playerState,
|
|
447
|
-
layoutState,
|
|
448
|
-
value,
|
|
449
|
-
onPlaybackButtonPress,
|
|
450
|
-
onRewindButtonPress,
|
|
451
|
-
onForwardButtonPress,
|
|
452
|
-
onPlayerSeek,
|
|
453
|
-
onCloseVideoModal,
|
|
454
|
-
maximiseVideoModal,
|
|
455
|
-
configuration,
|
|
456
|
-
dimensions,
|
|
457
|
-
children,
|
|
458
|
-
playNextData,
|
|
459
|
-
onSkipStart,
|
|
460
|
-
onSkipLive,
|
|
461
|
-
sleepTimer.value,
|
|
462
|
-
sleepTimerDate,
|
|
463
|
-
]);
|
|
464
|
-
|
|
465
|
-
if (configuration.magic_background) {
|
|
466
|
-
const baseUrl = entry?.extensions?.audio_player_background_image ?? "";
|
|
467
|
-
|
|
468
|
-
const queryParamName =
|
|
469
|
-
configuration.audio_player_background_image_query || "width";
|
|
470
|
-
|
|
471
|
-
const queryParamValue = 15;
|
|
472
|
-
|
|
473
|
-
const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
|
|
474
|
-
|
|
475
|
-
return (
|
|
476
|
-
<MagicBG
|
|
477
|
-
image={url}
|
|
478
|
-
fallbackUrl={baseUrl}
|
|
479
|
-
colors={entry?.extensions?.backgroundColors}
|
|
480
|
-
defaultColor="#000000"
|
|
325
|
+
return (
|
|
326
|
+
<SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
|
|
327
|
+
<AnimationComponent
|
|
328
|
+
animationType={ComponentAnimationType.moveUpComponent}
|
|
329
|
+
additionalData={{ saveArea: true }}
|
|
330
|
+
style={Styles.playerContainer}
|
|
481
331
|
>
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
332
|
+
<AnimatedScrollModal>
|
|
333
|
+
<View style={Styles.playerContainer} onLayout={onLayout}>
|
|
334
|
+
<Layout
|
|
335
|
+
entry={entry}
|
|
336
|
+
playerState={playerState}
|
|
337
|
+
layoutState={layoutState}
|
|
338
|
+
value={value}
|
|
339
|
+
onPlaybackButtonPress={onPlaybackButtonPress}
|
|
340
|
+
onRewindButtonPress={onRewindButtonPress}
|
|
341
|
+
onForwardButtonPress={onForwardButtonPress}
|
|
342
|
+
onPlayerSeek={onPlayerSeek}
|
|
343
|
+
onSkipStart={onSkipStart}
|
|
344
|
+
onSpeedButtonPress={onSpeedButtonPress}
|
|
345
|
+
onSleepButtonPress={onSleepButtonPress}
|
|
346
|
+
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
347
|
+
playbackSleepName={
|
|
348
|
+
sleepTimerState.timer.value === 0
|
|
349
|
+
? "sleep_timer"
|
|
350
|
+
: "sleep_timer_active"
|
|
351
|
+
}
|
|
352
|
+
sleepTimerDate={sleepTimerState.timerDate}
|
|
353
|
+
cancelSleepTimer={cancelSleepTimer}
|
|
354
|
+
onSkipLive={onSkipLive}
|
|
355
|
+
onCloseVideoModal={onCloseVideoModal}
|
|
356
|
+
maximiseVideoModal={maximiseVideoModal}
|
|
357
|
+
configuration={configuration}
|
|
358
|
+
dimensions={dimensions}
|
|
359
|
+
playNextData={playNextData}
|
|
360
|
+
title={title}
|
|
361
|
+
summary={summary}
|
|
362
|
+
/>
|
|
363
|
+
<View style={Styles.paddingHorizontal}>
|
|
364
|
+
{children}
|
|
365
|
+
<AnimationComponent
|
|
366
|
+
animationType={ComponentAnimationType.componentFade}
|
|
367
|
+
>
|
|
368
|
+
<PlayerDetails
|
|
369
|
+
isAudioPlayer
|
|
370
|
+
configuration={configuration}
|
|
371
|
+
style={Styles.playerDetails}
|
|
372
|
+
entry={entry}
|
|
373
|
+
isTabletLandscape={isTabletLandscape}
|
|
374
|
+
/>
|
|
375
|
+
</AnimationComponent>
|
|
376
|
+
</View>
|
|
377
|
+
</View>
|
|
378
|
+
</AnimatedScrollModal>
|
|
379
|
+
</AnimationComponent>
|
|
380
|
+
</SafeAreaView>
|
|
381
|
+
);
|
|
488
382
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
|
+
|
|
6
|
+
import { TABLET_VERTICAL_SEPARATOR_HEIGHT } from "../const";
|
|
7
|
+
|
|
8
|
+
import { withDebug } from "../debug";
|
|
9
|
+
|
|
10
|
+
const styles = StyleSheet.create({
|
|
11
|
+
flexingHeight: {
|
|
12
|
+
flex: 1,
|
|
13
|
+
|
|
14
|
+
...withDebug({ backgroundColor: "red" }),
|
|
15
|
+
},
|
|
16
|
+
fixedHeight: {
|
|
17
|
+
height: TABLET_VERTICAL_SEPARATOR_HEIGHT,
|
|
18
|
+
|
|
19
|
+
...withDebug({ backgroundColor: "red" }),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const VerticalGutter = () => {
|
|
24
|
+
const isTablet = useIsTablet();
|
|
25
|
+
|
|
26
|
+
return <View style={isTablet ? styles.fixedHeight : styles.flexingHeight} />;
|
|
27
|
+
};
|