@applicaster/quick-brick-player 13.0.0-alpha.3592913150 → 13.0.0-alpha.3637360334
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 +8 -12
- package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
- package/src/Player/AudioLayer/AudioDescription.tsx +6 -4
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +118 -129
- package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +26 -0
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +307 -0
- package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +5 -13
- package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +43 -66
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +209 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/ScaledImage.tsx +83 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/StaticImage.tsx +32 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +101 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +17 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +206 -0
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +218 -0
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +103 -0
- package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
- package/src/Player/AudioLayer/Layout/const.ts +19 -0
- package/src/Player/AudioLayer/Layout/debug.ts +5 -0
- package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -0
- package/src/Player/AudioLayer/Layout/hooks/useImageSize.ts +99 -0
- package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
- package/src/Player/AudioLayer/Layout/index.tsx +34 -30
- package/src/Player/AudioLayer/Layout/types.ts +49 -0
- package/src/Player/AudioLayer/MagicBG/index.tsx +1 -1
- package/src/Player/AudioLayer/SleepTimerManager.ts +119 -0
- package/src/Player/AudioLayer/SpeedManager.ts +52 -0
- package/src/Player/AudioLayer/utils.ts +24 -0
- package/src/Player/index.tsx +27 -18
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "13.0.0-alpha.
|
|
3
|
+
"version": "13.0.0-alpha.3637360334",
|
|
4
4
|
"description": "Quick Brick Player",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "jest -w=2",
|
|
9
8
|
"build": "echo 'skipping ts build for core packages'"
|
|
10
9
|
},
|
|
11
10
|
"files": [
|
|
@@ -36,11 +35,11 @@
|
|
|
36
35
|
},
|
|
37
36
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
38
37
|
"dependencies": {
|
|
39
|
-
"@applicaster/quick-brick-mobile-transport-controls": "13.0.0-alpha.
|
|
40
|
-
"@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.
|
|
41
|
-
"@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.
|
|
43
|
-
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "13.0.0-alpha.3637360334",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.3637360334",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.3637360334",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.3637360334",
|
|
44
43
|
"keymirror": "^0.1.1",
|
|
45
44
|
"query-string": "7.1.3",
|
|
46
45
|
"react-native-web-linear-gradient": "1.1.2",
|
|
@@ -61,12 +60,9 @@
|
|
|
61
60
|
"@applicaster/zapp-react-native-tvos-ui-components": "*",
|
|
62
61
|
"@babel/runtime": "*",
|
|
63
62
|
"@react-native-community/netinfo": "*",
|
|
64
|
-
"@types/node": "*",
|
|
65
|
-
"@types/react-native": "0.69.6",
|
|
66
63
|
"immer": "*",
|
|
67
|
-
"react": "
|
|
68
|
-
"react-
|
|
69
|
-
"react-native": "0.68.6",
|
|
64
|
+
"react": "*",
|
|
65
|
+
"react-native": "*",
|
|
70
66
|
"react-native-fs": "*",
|
|
71
67
|
"react-native-gesture-handler": "*",
|
|
72
68
|
"react-native-linear-gradient": "*",
|
|
@@ -55,6 +55,11 @@ const useMuteUnmuteListeners = (playerId, player, asset, setImageUri) =>
|
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// initial state setup - show correct mute/unmute icon based on current state
|
|
59
|
+
if (player?.playerState?.isReadyToPlay) {
|
|
60
|
+
setImageUri(player.getIsMuted() ? asset.active : asset.inactive);
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
// active action = muted, inactive = unmuted
|
|
59
64
|
return player.addListener({
|
|
60
65
|
id: liveImageButtonsListenerKey,
|
|
@@ -73,10 +78,17 @@ const useMuteUnmuteListeners = (playerId, player, asset, setImageUri) =>
|
|
|
73
78
|
setImageUri(player?.getIsMuted() ? asset.active : asset.inactive);
|
|
74
79
|
},
|
|
75
80
|
onPlayerClose: () => {
|
|
76
|
-
|
|
81
|
+
if (isCurrentPlayer(playerId)) {
|
|
82
|
+
setImageUri(null);
|
|
83
|
+
}
|
|
77
84
|
},
|
|
78
85
|
onVideoEnd: () => {
|
|
79
|
-
|
|
86
|
+
if (isCurrentPlayer(playerId)) {
|
|
87
|
+
setImageUri(null);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
onPlayerResume: () => {
|
|
91
|
+
setImageUri(player?.getIsMuted() ? asset.active : asset.inactive);
|
|
80
92
|
},
|
|
81
93
|
},
|
|
82
94
|
});
|
|
@@ -93,7 +105,7 @@ const styles = StyleSheet.create({
|
|
|
93
105
|
},
|
|
94
106
|
});
|
|
95
107
|
|
|
96
|
-
|
|
108
|
+
function AssetImage(props: CellActionAssetComponentProps) {
|
|
97
109
|
const { cellUUID: playerId, asset } = props;
|
|
98
110
|
const [imageUri, setImageUri] = useState<Asset>(null);
|
|
99
111
|
|
|
@@ -108,3 +120,5 @@ export function AssetComponent(props: CellActionAssetComponentProps) {
|
|
|
108
120
|
|
|
109
121
|
return <View />;
|
|
110
122
|
}
|
|
123
|
+
|
|
124
|
+
export const AssetComponent = React.memo(AssetImage);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Text, TextStyle, View } from "react-native";
|
|
2
|
+
import { Text, TextStyle, View, StyleSheet } from "react-native";
|
|
3
3
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
4
|
|
|
5
5
|
type AudioDescriptionProps = {
|
|
@@ -13,7 +13,9 @@ type AudioDescriptionProps = {
|
|
|
13
13
|
value: GetValue;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const styles = StyleSheet.create({
|
|
17
|
+
container: {},
|
|
18
|
+
});
|
|
17
19
|
|
|
18
20
|
const titleStyles = (value: GetValue, prefix: string): TextStyle => ({
|
|
19
21
|
textAlign: "left",
|
|
@@ -83,11 +85,11 @@ export const AudioDescription = (props: AudioDescriptionProps) => {
|
|
|
83
85
|
const prefix = layoutState.docked ? "docked_player_" : "";
|
|
84
86
|
|
|
85
87
|
return (
|
|
86
|
-
<View style={
|
|
88
|
+
<View style={styles.container}>
|
|
87
89
|
<Text style={titleStyles(value, prefix)} numberOfLines={1}>
|
|
88
90
|
{title}
|
|
89
91
|
</Text>
|
|
90
|
-
<Text style={summaryStyles(value, prefix)} numberOfLines={
|
|
92
|
+
<Text style={summaryStyles(value, prefix)} numberOfLines={1}>
|
|
91
93
|
{summary}
|
|
92
94
|
</Text>
|
|
93
95
|
</View>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { ViewStyle, View } from "react-native";
|
|
2
|
+
import { ViewStyle, View, Dimensions as ScreenDimensions } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { SafeAreaView, Edge } from "react-native-safe-area-context";
|
|
5
5
|
import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
|
|
@@ -17,13 +17,7 @@ import { PlayerDetails } from "@applicaster/zapp-react-native-ui-components/Comp
|
|
|
17
17
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
18
18
|
import { useEffect, useState } from "react";
|
|
19
19
|
import { MagicBG } from "./MagicBG";
|
|
20
|
-
import {
|
|
21
|
-
formatSpeed,
|
|
22
|
-
hasDatePassed,
|
|
23
|
-
loadItemsFromStorage,
|
|
24
|
-
NAMESPACE,
|
|
25
|
-
} from "./utils";
|
|
26
|
-
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
20
|
+
import { formatSpeed } from "./utils";
|
|
27
21
|
import { addQueryParam, getLiveUrl } from "../Utils";
|
|
28
22
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
29
23
|
import {
|
|
@@ -31,8 +25,23 @@ import {
|
|
|
31
25
|
ComponentAnimationType,
|
|
32
26
|
AnimatedScrollModal,
|
|
33
27
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
34
|
-
import { PADDING_HORIZONTAL } from "./Layout/
|
|
28
|
+
import { PADDING_HORIZONTAL } from "./Layout/const";
|
|
35
29
|
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
30
|
+
import {
|
|
31
|
+
speed_0_8,
|
|
32
|
+
speed_1,
|
|
33
|
+
speed_1_2,
|
|
34
|
+
speed_1_5,
|
|
35
|
+
speed_2,
|
|
36
|
+
} from "@applicaster/quick-brick-mobile-transport-controls";
|
|
37
|
+
import {
|
|
38
|
+
SleepTimerController,
|
|
39
|
+
SleepTimerState,
|
|
40
|
+
SLEEP_TIMER_OFF,
|
|
41
|
+
} from "./SleepTimerManager";
|
|
42
|
+
import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
|
|
43
|
+
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
44
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
36
45
|
|
|
37
46
|
const { log_debug } = createLogger({
|
|
38
47
|
subsystem: "UIComponent",
|
|
@@ -50,6 +59,7 @@ type Configuration = {
|
|
|
50
59
|
[key: string]: any;
|
|
51
60
|
magic_background?: boolean;
|
|
52
61
|
audio_player_background_image_query?: string;
|
|
62
|
+
audio_player_background_image_default_color?: string;
|
|
53
63
|
tablet_landscape_sidebar_width?: string;
|
|
54
64
|
tablet_landscape_player_container_background_color?: string;
|
|
55
65
|
};
|
|
@@ -71,8 +81,7 @@ type Props = {
|
|
|
71
81
|
isTabletPortrait?: boolean;
|
|
72
82
|
};
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
(height / 9) * 16;
|
|
84
|
+
const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
|
|
76
85
|
|
|
77
86
|
const Styles = {
|
|
78
87
|
mainContainer: (style: ViewStyle) => {
|
|
@@ -98,7 +107,11 @@ const Styles = {
|
|
|
98
107
|
height: 96,
|
|
99
108
|
marginHorizontal: 24,
|
|
100
109
|
},
|
|
101
|
-
playerDetails: {
|
|
110
|
+
playerDetails: {
|
|
111
|
+
marginTop: 60,
|
|
112
|
+
alignSelf: "center",
|
|
113
|
+
width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
|
|
114
|
+
},
|
|
102
115
|
|
|
103
116
|
linearGradient: {
|
|
104
117
|
flex: 1,
|
|
@@ -116,9 +129,12 @@ const sleeps = [
|
|
|
116
129
|
{ label: "2 hours", value: 120 },
|
|
117
130
|
];
|
|
118
131
|
|
|
132
|
+
const edges: Edge[] = ["right", "left", "top"];
|
|
133
|
+
|
|
119
134
|
export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
120
135
|
const player = usePlayer();
|
|
121
136
|
const playerState = usePlayerState("audio-player-wrapper");
|
|
137
|
+
const theme = useTheme();
|
|
122
138
|
|
|
123
139
|
const {
|
|
124
140
|
docked,
|
|
@@ -132,11 +148,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
132
148
|
} = props;
|
|
133
149
|
|
|
134
150
|
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 },
|
|
151
|
+
{ asset: configuration["speed_0_8"] || speed_0_8, value: 0.8 },
|
|
152
|
+
{ asset: configuration["speed_1"] || speed_1, value: 1.0 },
|
|
153
|
+
{ asset: configuration["speed_1_2"] || speed_1_2, value: 1.2 },
|
|
154
|
+
{ asset: configuration["speed_1_5"] || speed_1_5, value: 1.5 },
|
|
155
|
+
{ asset: configuration["speed_2"] || speed_2, value: 2.0 },
|
|
140
156
|
];
|
|
141
157
|
|
|
142
158
|
const isTablet = useIsTablet();
|
|
@@ -154,17 +170,29 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
154
170
|
configuration?.audio_live_player_update_interval
|
|
155
171
|
);
|
|
156
172
|
|
|
157
|
-
const [
|
|
158
|
-
|
|
159
|
-
value: 1.0,
|
|
160
|
-
});
|
|
173
|
+
const [sleepTimerManager, setSleepTimerManager] =
|
|
174
|
+
useState<SleepTimerController | null>(null);
|
|
161
175
|
|
|
162
|
-
const [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
176
|
+
const [speedManager, setSpeedManager] = useState<SpeedController | null>(
|
|
177
|
+
null
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (player) {
|
|
182
|
+
setSleepTimerManager(new SleepTimerController(player));
|
|
183
|
+
setSpeedManager(new SpeedController(player));
|
|
184
|
+
} else {
|
|
185
|
+
setSleepTimerManager(null);
|
|
186
|
+
setSpeedManager(null);
|
|
187
|
+
}
|
|
188
|
+
}, [player]);
|
|
189
|
+
|
|
190
|
+
const [playbackSpeed, setPlaybackSpeed] =
|
|
191
|
+
useState<PlaybackSpeed>(DEFAULT_SPEED);
|
|
166
192
|
|
|
167
|
-
const [
|
|
193
|
+
const [sleepTimerState, setSleepTimerState] = useState<SleepTimerState>(
|
|
194
|
+
new SleepTimerState(SLEEP_TIMER_OFF, 0)
|
|
195
|
+
);
|
|
168
196
|
|
|
169
197
|
const [defaultDimensions, setDefaultDimensions] =
|
|
170
198
|
React.useState<Dimensions>(undefined);
|
|
@@ -189,82 +217,27 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
189
217
|
if (!defaultDimensions) setDefaultDimensions({ width, height });
|
|
190
218
|
};
|
|
191
219
|
|
|
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
220
|
useEffect(() => {
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (playerState.isReadyToPlay && speed) {
|
|
249
|
-
setPlaybackSpeed(speed);
|
|
250
|
-
player?.setPlaybackRate(speed.value);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
221
|
+
const sleepSubscription =
|
|
222
|
+
sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
|
|
253
223
|
|
|
254
|
-
const
|
|
255
|
-
|
|
224
|
+
const speedSubscription =
|
|
225
|
+
speedManager?.playbackSpeed$.subscribe(setPlaybackSpeed);
|
|
256
226
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const sleepTimerDate = await handleSleep(sleep.value, futureSleepDate);
|
|
261
|
-
setSleepTimerDate(sleepTimerDate);
|
|
262
|
-
}
|
|
227
|
+
return () => {
|
|
228
|
+
sleepSubscription?.unsubscribe();
|
|
229
|
+
speedSubscription?.unsubscribe();
|
|
263
230
|
};
|
|
231
|
+
}, [sleepTimerManager, speedManager]);
|
|
232
|
+
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
if (!playerState.isReadyToPlay) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
264
237
|
|
|
265
|
-
loadSpeed()
|
|
266
|
-
loadSleep()
|
|
267
|
-
}, [playerState.isReadyToPlay]);
|
|
238
|
+
void speedManager?.loadSpeed();
|
|
239
|
+
void sleepTimerManager?.loadSleep();
|
|
240
|
+
}, [playerState.isReadyToPlay, speedManager, sleepTimerManager]);
|
|
268
241
|
|
|
269
242
|
const getValue = (key: string, stylesObj: {}) =>
|
|
270
243
|
R.propOr(null, key, stylesObj);
|
|
@@ -292,7 +265,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
292
265
|
|
|
293
266
|
const onPlaybackButtonPress = React.useCallback(() => {
|
|
294
267
|
if (playerState.isBuffering) return;
|
|
295
|
-
playerState.isPaused ? player?.play() : player
|
|
268
|
+
playerState.isPaused ? player?.play() : player?.pause();
|
|
296
269
|
}, [playerState, player]);
|
|
297
270
|
|
|
298
271
|
const seekDuration = toNumberWithDefault(10, value("seek_duration"));
|
|
@@ -307,26 +280,16 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
307
280
|
|
|
308
281
|
const onSpeedSelect = React.useCallback(
|
|
309
282
|
async (item) => {
|
|
310
|
-
setPlaybackSpeed(item);
|
|
311
|
-
player.setPlaybackRate(item.value);
|
|
312
|
-
await localStorage.setItem("speed", item, NAMESPACE);
|
|
283
|
+
await speedManager?.setPlaybackSpeed(item);
|
|
313
284
|
},
|
|
314
|
-
[
|
|
285
|
+
[speedManager]
|
|
315
286
|
);
|
|
316
287
|
|
|
317
288
|
const onSleepSelect = React.useCallback(
|
|
318
289
|
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
|
-
);
|
|
290
|
+
await sleepTimerManager?.setSleepTimer(item);
|
|
328
291
|
},
|
|
329
|
-
[
|
|
292
|
+
[sleepTimerManager]
|
|
330
293
|
);
|
|
331
294
|
|
|
332
295
|
const onSpeedButtonPress = React.useCallback(() => {
|
|
@@ -341,15 +304,24 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
341
304
|
supportedOrientations: ["portrait"],
|
|
342
305
|
},
|
|
343
306
|
});
|
|
344
|
-
}, [
|
|
307
|
+
}, [
|
|
308
|
+
playbackSpeed,
|
|
309
|
+
setPlaybackSpeed,
|
|
310
|
+
navigator,
|
|
311
|
+
onSpeedSelect,
|
|
312
|
+
configuration["playback_speed_title"],
|
|
313
|
+
]);
|
|
345
314
|
|
|
346
315
|
const onSleepButtonPress = React.useCallback(() => {
|
|
347
316
|
navigator.openModalBottomSheet({
|
|
348
317
|
modalBottomSheetContentProps: {
|
|
349
318
|
items: [
|
|
350
|
-
{
|
|
319
|
+
{
|
|
320
|
+
label: configuration["playback_sleep_off_label"],
|
|
321
|
+
value: 0,
|
|
322
|
+
},
|
|
351
323
|
].concat(sleeps),
|
|
352
|
-
current_selection:
|
|
324
|
+
current_selection: sleepTimerState.timer,
|
|
353
325
|
onPress: onSleepSelect,
|
|
354
326
|
title: configuration["playback_sleep_title"],
|
|
355
327
|
},
|
|
@@ -357,7 +329,21 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
357
329
|
supportedOrientations: ["portrait"],
|
|
358
330
|
},
|
|
359
331
|
});
|
|
360
|
-
}, [
|
|
332
|
+
}, [
|
|
333
|
+
navigator,
|
|
334
|
+
sleepTimerState.timer,
|
|
335
|
+
configuration["playback_sleep_title"],
|
|
336
|
+
configuration["playback_sleep_off_label"],
|
|
337
|
+
onSleepSelect,
|
|
338
|
+
]);
|
|
339
|
+
|
|
340
|
+
// This method does not actually cancel the sleep timer
|
|
341
|
+
// (and should not to avoid race condition),
|
|
342
|
+
// it just performs the cleanup when timer expires
|
|
343
|
+
// TODO: rename it in code above
|
|
344
|
+
const cancelSleepTimer = React.useCallback(() => {
|
|
345
|
+
sleepTimerManager?.onTimerExpired();
|
|
346
|
+
}, [sleepTimerManager]);
|
|
361
347
|
|
|
362
348
|
const onCloseVideoModal = React.useCallback(() => {
|
|
363
349
|
playerManager.close();
|
|
@@ -378,13 +364,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
378
364
|
player?.seekTo(0);
|
|
379
365
|
}, [player]);
|
|
380
366
|
|
|
381
|
-
const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
|
|
382
|
-
|
|
383
|
-
const ContainerView = SafeAreaView;
|
|
384
|
-
|
|
385
367
|
const MainContent = React.useMemo(() => {
|
|
386
368
|
return (
|
|
387
|
-
<
|
|
369
|
+
<SafeAreaView style={Styles.mainContainer(style)} edges={edges}>
|
|
388
370
|
<AnimationComponent
|
|
389
371
|
animationType={ComponentAnimationType.moveUpComponent}
|
|
390
372
|
additionalData={{ saveArea: true }}
|
|
@@ -406,9 +388,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
406
388
|
onSleepButtonPress={onSleepButtonPress}
|
|
407
389
|
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
408
390
|
playbackSleepName={
|
|
409
|
-
|
|
391
|
+
sleepTimerState.timer.value === 0
|
|
392
|
+
? "sleep_timer"
|
|
393
|
+
: "sleep_timer_active"
|
|
410
394
|
}
|
|
411
|
-
sleepTimerDate={
|
|
395
|
+
sleepTimerDate={sleepTimerState.timerDate}
|
|
412
396
|
cancelSleepTimer={cancelSleepTimer}
|
|
413
397
|
onSkipLive={onSkipLive}
|
|
414
398
|
onCloseVideoModal={onCloseVideoModal}
|
|
@@ -437,7 +421,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
437
421
|
</View>
|
|
438
422
|
</AnimatedScrollModal>
|
|
439
423
|
</AnimationComponent>
|
|
440
|
-
</
|
|
424
|
+
</SafeAreaView>
|
|
441
425
|
);
|
|
442
426
|
}, [
|
|
443
427
|
docked,
|
|
@@ -458,26 +442,31 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
458
442
|
playNextData,
|
|
459
443
|
onSkipStart,
|
|
460
444
|
onSkipLive,
|
|
461
|
-
|
|
462
|
-
|
|
445
|
+
sleepTimerState.timer.value,
|
|
446
|
+
sleepTimerState.timerDate,
|
|
463
447
|
]);
|
|
464
448
|
|
|
465
449
|
if (configuration.magic_background) {
|
|
466
|
-
const baseUrl = entry
|
|
450
|
+
const baseUrl = imageSrcFromMediaItem(entry, null);
|
|
467
451
|
|
|
468
452
|
const queryParamName =
|
|
469
453
|
configuration.audio_player_background_image_query || "width";
|
|
470
454
|
|
|
455
|
+
const defaultBackgroundColor =
|
|
456
|
+
configuration.audio_player_background_image_default_color ||
|
|
457
|
+
theme?.app_background_color;
|
|
458
|
+
|
|
471
459
|
const queryParamValue = 15;
|
|
472
460
|
|
|
473
|
-
const url =
|
|
461
|
+
const url =
|
|
462
|
+
baseUrl && addQueryParam(baseUrl, queryParamName, queryParamValue);
|
|
474
463
|
|
|
475
464
|
return (
|
|
476
465
|
<MagicBG
|
|
477
466
|
image={url}
|
|
478
467
|
fallbackUrl={baseUrl}
|
|
479
468
|
colors={entry?.extensions?.backgroundColors}
|
|
480
|
-
defaultColor=
|
|
469
|
+
defaultColor={defaultBackgroundColor}
|
|
481
470
|
>
|
|
482
471
|
{MainContent}
|
|
483
472
|
</MagicBG>
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
...withDebug({ backgroundColor: "red" }),
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const VerticalGutter = () => {
|
|
23
|
+
const isTablet = useIsTablet();
|
|
24
|
+
|
|
25
|
+
return <View style={isTablet ? styles.fixedHeight : styles.flexingHeight} />;
|
|
26
|
+
};
|