@applicaster/quick-brick-player 13.0.0-alpha.8532113155 → 13.0.0-alpha.9103242840
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 +6 -6
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +115 -94
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +2 -2
- package/src/Player/AudioLayer/Layout/defaultLayoutsConts.ts +2 -2
- package/src/Player/index.tsx +2 -2
- package/src/Player/AudioLayer/SleepTimerManager.ts +0 -119
- package/src/Player/AudioLayer/SpeedManager.ts +0 -52
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.9103242840",
|
|
4
4
|
"description": "Quick Brick Player",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@applicaster/quick-brick-mobile-transport-controls": "13.0.0-
|
|
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.
|
|
39
|
+
"@applicaster/quick-brick-mobile-transport-controls": "13.0.0-alpha.9103242840",
|
|
40
|
+
"@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.19",
|
|
41
|
+
"@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.9103242840",
|
|
42
|
+
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.9103242840",
|
|
43
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.9103242840",
|
|
44
44
|
"keymirror": "^0.1.1",
|
|
45
45
|
"query-string": "7.1.3",
|
|
46
46
|
"react-native-web-linear-gradient": "1.1.2",
|
|
@@ -17,7 +17,13 @@ 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 {
|
|
20
|
+
import {
|
|
21
|
+
formatSpeed,
|
|
22
|
+
hasDatePassed,
|
|
23
|
+
loadItemsFromStorage,
|
|
24
|
+
NAMESPACE,
|
|
25
|
+
} from "./utils";
|
|
26
|
+
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
21
27
|
import { addQueryParam, getLiveUrl } from "../Utils";
|
|
22
28
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
23
29
|
import {
|
|
@@ -27,19 +33,6 @@ import {
|
|
|
27
33
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
28
34
|
import { PADDING_HORIZONTAL } from "./Layout/defaultLayoutsConts";
|
|
29
35
|
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
36
|
|
|
44
37
|
const { log_debug } = createLogger({
|
|
45
38
|
subsystem: "UIComponent",
|
|
@@ -139,11 +132,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
139
132
|
} = props;
|
|
140
133
|
|
|
141
134
|
const speeds = [
|
|
142
|
-
{ asset: configuration["speed_0_8"]
|
|
143
|
-
{ asset: configuration["speed_1"]
|
|
144
|
-
{ asset: configuration["speed_1_2"]
|
|
145
|
-
{ asset: configuration["speed_1_5"]
|
|
146
|
-
{ asset: configuration["speed_2"]
|
|
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 },
|
|
147
140
|
];
|
|
148
141
|
|
|
149
142
|
const isTablet = useIsTablet();
|
|
@@ -161,29 +154,17 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
161
154
|
configuration?.audio_live_player_update_interval
|
|
162
155
|
);
|
|
163
156
|
|
|
164
|
-
const [
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
null
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
if (player) {
|
|
173
|
-
setSleepTimerManager(new SleepTimerController(player));
|
|
174
|
-
setSpeedManager(new SpeedController(player));
|
|
175
|
-
} else {
|
|
176
|
-
setSleepTimerManager(null);
|
|
177
|
-
setSpeedManager(null);
|
|
178
|
-
}
|
|
179
|
-
}, [player]);
|
|
157
|
+
const [playbackSpeed, setPlaybackSpeed] = useState({
|
|
158
|
+
asset: configuration["speed_1"],
|
|
159
|
+
value: 1.0,
|
|
160
|
+
});
|
|
180
161
|
|
|
181
|
-
const [
|
|
182
|
-
|
|
162
|
+
const [sleepTimer, setSleepTimer] = useState({
|
|
163
|
+
label: "playback_sleep_off_label",
|
|
164
|
+
value: 0,
|
|
165
|
+
});
|
|
183
166
|
|
|
184
|
-
const [
|
|
185
|
-
new SleepTimerState(SLEEP_TIMER_OFF, 0)
|
|
186
|
-
);
|
|
167
|
+
const [sleepTimerDate, setSleepTimerDate] = useState(0);
|
|
187
168
|
|
|
188
169
|
const [defaultDimensions, setDefaultDimensions] =
|
|
189
170
|
React.useState<Dimensions>(undefined);
|
|
@@ -208,27 +189,82 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
208
189
|
if (!defaultDimensions) setDefaultDimensions({ width, height });
|
|
209
190
|
};
|
|
210
191
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
|
|
192
|
+
const cancelSleepTimer = async () => {
|
|
193
|
+
player?.cancelSleepTimer();
|
|
214
194
|
|
|
215
|
-
|
|
216
|
-
|
|
195
|
+
setSleepTimer({
|
|
196
|
+
label: "playback_sleep_off_label",
|
|
197
|
+
value: 0,
|
|
198
|
+
});
|
|
217
199
|
|
|
218
|
-
|
|
219
|
-
sleepSubscription?.unsubscribe();
|
|
220
|
-
speedSubscription?.unsubscribe();
|
|
221
|
-
};
|
|
222
|
-
}, [sleepTimerManager, speedManager]);
|
|
200
|
+
setSleepTimerDate(0);
|
|
223
201
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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;
|
|
227
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
228
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
+
useEffect(() => {
|
|
245
|
+
const loadSpeed = async () => {
|
|
246
|
+
const speed = await loadItemsFromStorage("speed");
|
|
247
|
+
|
|
248
|
+
if (playerState.isReadyToPlay && speed) {
|
|
249
|
+
setPlaybackSpeed(speed);
|
|
250
|
+
player?.setPlaybackRate(speed.value);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const loadSleep = async () => {
|
|
255
|
+
const sleep = await loadItemsFromStorage("sleep");
|
|
256
|
+
|
|
257
|
+
if (playerState.isReadyToPlay && sleep) {
|
|
258
|
+
const { futureSleepDate, ...rest } = sleep;
|
|
259
|
+
setSleepTimer(rest);
|
|
260
|
+
const sleepTimerDate = await handleSleep(sleep.value, futureSleepDate);
|
|
261
|
+
setSleepTimerDate(sleepTimerDate);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
loadSpeed().then();
|
|
266
|
+
loadSleep().then();
|
|
267
|
+
}, [playerState.isReadyToPlay]);
|
|
232
268
|
|
|
233
269
|
const getValue = (key: string, stylesObj: {}) =>
|
|
234
270
|
R.propOr(null, key, stylesObj);
|
|
@@ -256,7 +292,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
256
292
|
|
|
257
293
|
const onPlaybackButtonPress = React.useCallback(() => {
|
|
258
294
|
if (playerState.isBuffering) return;
|
|
259
|
-
playerState.isPaused ? player?.play() : player
|
|
295
|
+
playerState.isPaused ? player?.play() : player.pause();
|
|
260
296
|
}, [playerState, player]);
|
|
261
297
|
|
|
262
298
|
const seekDuration = toNumberWithDefault(10, value("seek_duration"));
|
|
@@ -271,16 +307,26 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
271
307
|
|
|
272
308
|
const onSpeedSelect = React.useCallback(
|
|
273
309
|
async (item) => {
|
|
274
|
-
|
|
310
|
+
setPlaybackSpeed(item);
|
|
311
|
+
player.setPlaybackRate(item.value);
|
|
312
|
+
await localStorage.setItem("speed", item, NAMESPACE);
|
|
275
313
|
},
|
|
276
|
-
[
|
|
314
|
+
[player, setPlaybackSpeed]
|
|
277
315
|
);
|
|
278
316
|
|
|
279
317
|
const onSleepSelect = React.useCallback(
|
|
280
318
|
async (item) => {
|
|
281
|
-
|
|
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
|
+
);
|
|
282
328
|
},
|
|
283
|
-
[
|
|
329
|
+
[player, setSleepTimer]
|
|
284
330
|
);
|
|
285
331
|
|
|
286
332
|
const onSpeedButtonPress = React.useCallback(() => {
|
|
@@ -295,24 +341,15 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
295
341
|
supportedOrientations: ["portrait"],
|
|
296
342
|
},
|
|
297
343
|
});
|
|
298
|
-
}, [
|
|
299
|
-
playbackSpeed,
|
|
300
|
-
setPlaybackSpeed,
|
|
301
|
-
navigator,
|
|
302
|
-
onSpeedSelect,
|
|
303
|
-
configuration["playback_speed_title"],
|
|
304
|
-
]);
|
|
344
|
+
}, [playbackSpeed, setPlaybackSpeed]);
|
|
305
345
|
|
|
306
346
|
const onSleepButtonPress = React.useCallback(() => {
|
|
307
347
|
navigator.openModalBottomSheet({
|
|
308
348
|
modalBottomSheetContentProps: {
|
|
309
349
|
items: [
|
|
310
|
-
{
|
|
311
|
-
label: configuration["playback_sleep_off_label"],
|
|
312
|
-
value: 0,
|
|
313
|
-
},
|
|
350
|
+
{ label: configuration["playback_sleep_off_label"], value: 0 },
|
|
314
351
|
].concat(sleeps),
|
|
315
|
-
current_selection:
|
|
352
|
+
current_selection: sleepTimer,
|
|
316
353
|
onPress: onSleepSelect,
|
|
317
354
|
title: configuration["playback_sleep_title"],
|
|
318
355
|
},
|
|
@@ -320,21 +357,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
320
357
|
supportedOrientations: ["portrait"],
|
|
321
358
|
},
|
|
322
359
|
});
|
|
323
|
-
}, [
|
|
324
|
-
navigator,
|
|
325
|
-
sleepTimerState.timer,
|
|
326
|
-
configuration["playback_sleep_title"],
|
|
327
|
-
configuration["playback_sleep_off_label"],
|
|
328
|
-
onSleepSelect,
|
|
329
|
-
]);
|
|
330
|
-
|
|
331
|
-
// This method does not actually cancel the sleep timer
|
|
332
|
-
// (and should not to avoid race condition),
|
|
333
|
-
// it just performs the cleanup when timer expires
|
|
334
|
-
// TODO: rename it in code above
|
|
335
|
-
const cancelSleepTimer = React.useCallback(() => {
|
|
336
|
-
sleepTimerManager?.onTimerExpired();
|
|
337
|
-
}, [sleepTimerManager]);
|
|
360
|
+
}, [sleepTimer, setSleepTimer, configuration]);
|
|
338
361
|
|
|
339
362
|
const onCloseVideoModal = React.useCallback(() => {
|
|
340
363
|
playerManager.close();
|
|
@@ -383,11 +406,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
383
406
|
onSleepButtonPress={onSleepButtonPress}
|
|
384
407
|
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
385
408
|
playbackSleepName={
|
|
386
|
-
|
|
387
|
-
? "sleep_timer"
|
|
388
|
-
: "sleep_timer_active"
|
|
409
|
+
sleepTimer.value === 0 ? "sleep_timer" : "sleep_timer_active"
|
|
389
410
|
}
|
|
390
|
-
sleepTimerDate={
|
|
411
|
+
sleepTimerDate={sleepTimerDate}
|
|
391
412
|
cancelSleepTimer={cancelSleepTimer}
|
|
392
413
|
onSkipLive={onSkipLive}
|
|
393
414
|
onCloseVideoModal={onCloseVideoModal}
|
|
@@ -437,8 +458,8 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
437
458
|
playNextData,
|
|
438
459
|
onSkipStart,
|
|
439
460
|
onSkipLive,
|
|
440
|
-
|
|
441
|
-
|
|
461
|
+
sleepTimer.value,
|
|
462
|
+
sleepTimerDate,
|
|
442
463
|
]);
|
|
443
464
|
|
|
444
465
|
if (configuration.magic_background) {
|
package/src/Player/index.tsx
CHANGED
|
@@ -918,8 +918,8 @@ export default class VideoPlayer extends React.Component<
|
|
|
918
918
|
const playerContainerStyles = isApplePlatform()
|
|
919
919
|
? styles.playerContainerBlack
|
|
920
920
|
: isTV() && isAudioItem
|
|
921
|
-
|
|
922
|
-
|
|
921
|
+
? styles.playerContainerTransparent
|
|
922
|
+
: styles.playerContainerBlack;
|
|
923
923
|
|
|
924
924
|
const isInline = () => {
|
|
925
925
|
if (isTV()) {
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject } from "rxjs";
|
|
2
|
-
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
3
|
-
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
4
|
-
import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
|
|
5
|
-
import { hasDatePassed, NAMESPACE } from "./utils";
|
|
6
|
-
|
|
7
|
-
const { log_debug, log_error } = createLogger({
|
|
8
|
-
subsystem: "Player",
|
|
9
|
-
category: "SleepTimerManager",
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
export type SleepTimer = {
|
|
13
|
-
label: string;
|
|
14
|
-
// interval in minutes for UI at the moment when timer was first started
|
|
15
|
-
value: number;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const SLEEP_TIMER_OFF: SleepTimer = {
|
|
19
|
-
label: "playback_sleep_off_label",
|
|
20
|
-
value: 0,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class SleepTimerState {
|
|
24
|
-
constructor(
|
|
25
|
-
public timer: SleepTimer,
|
|
26
|
-
public timerDate: number
|
|
27
|
-
) {}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const SLEEP_PREFERENCE_KEY = "sleep";
|
|
31
|
-
|
|
32
|
-
export class SleepTimerController {
|
|
33
|
-
private sleepTimerStateSubject = new BehaviorSubject<SleepTimerState>(
|
|
34
|
-
new SleepTimerState(SLEEP_TIMER_OFF, 0)
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
constructor(private player: Player) {}
|
|
38
|
-
|
|
39
|
-
get sleepTimerState$() {
|
|
40
|
-
return this.sleepTimerStateSubject.asObservable();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private async scheduleSleep(sleepDate): Promise<boolean> {
|
|
44
|
-
log_debug(`Setting sleep interval to ${sleepDate}`);
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
this.player.cancelSleepTimer?.();
|
|
48
|
-
this.player.startSleepTimer?.(sleepDate);
|
|
49
|
-
|
|
50
|
-
return true;
|
|
51
|
-
} catch (e) {
|
|
52
|
-
log_error("Failed to start sleep timer", { error: e.message });
|
|
53
|
-
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async setSleepTimer(item: SleepTimer) {
|
|
59
|
-
// User has selected Off state
|
|
60
|
-
if (item.value === 0) {
|
|
61
|
-
log_debug("Cancelling sleep timer");
|
|
62
|
-
this.player.cancelSleepTimer?.();
|
|
63
|
-
|
|
64
|
-
return this.onTimerExpired();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
log_debug(`Starting sleep timer in ${item.value} minutes`);
|
|
68
|
-
|
|
69
|
-
const futureSleepDate = Date.now() + item.value * 60000;
|
|
70
|
-
|
|
71
|
-
if (await this.scheduleSleep(futureSleepDate)) {
|
|
72
|
-
await localStorage.setItem(
|
|
73
|
-
SLEEP_PREFERENCE_KEY,
|
|
74
|
-
{ ...item, futureSleepDate },
|
|
75
|
-
NAMESPACE
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
this.sleepTimerStateSubject.next(
|
|
79
|
-
new SleepTimerState(item, futureSleepDate)
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async onTimerExpired() {
|
|
85
|
-
await localStorage.removeItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
|
|
86
|
-
|
|
87
|
-
this.sleepTimerStateSubject.next(new SleepTimerState(SLEEP_TIMER_OFF, 0));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async loadSleep() {
|
|
91
|
-
const sleep = await localStorage.getItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
|
|
92
|
-
|
|
93
|
-
if (!sleep) return;
|
|
94
|
-
|
|
95
|
-
const { futureSleepDate, ...rest } = sleep;
|
|
96
|
-
|
|
97
|
-
if (!futureSleepDate || hasDatePassed(futureSleepDate)) {
|
|
98
|
-
log_debug("Sleep date has already passed");
|
|
99
|
-
await localStorage.removeItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
|
|
100
|
-
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (await this.scheduleSleep(futureSleepDate)) {
|
|
105
|
-
log_debug(`Sleep state restored, will go to sleep at ${futureSleepDate}`);
|
|
106
|
-
|
|
107
|
-
this.sleepTimerStateSubject.next(
|
|
108
|
-
new SleepTimerState(rest as SleepTimer, futureSleepDate)
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Will be called if user closed the player explicitly.
|
|
114
|
-
// TODO: check if it will be called on Android when we need.
|
|
115
|
-
// Probably we will have to handle it on native instead.
|
|
116
|
-
public static async onPlayerDestroy() {
|
|
117
|
-
await localStorage.removeItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject } from "rxjs";
|
|
2
|
-
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
3
|
-
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
4
|
-
import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
|
|
5
|
-
import { NAMESPACE } from "./utils";
|
|
6
|
-
|
|
7
|
-
const { log_debug } = createLogger({
|
|
8
|
-
subsystem: "Player",
|
|
9
|
-
category: "PlaybackSpeedManager",
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
export type PlaybackSpeed = {
|
|
13
|
-
asset: string;
|
|
14
|
-
value: number;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const SPEED_PREFERENCE_KEY = "speed";
|
|
18
|
-
|
|
19
|
-
export const DEFAULT_SPEED: PlaybackSpeed = {
|
|
20
|
-
asset: "speed_1",
|
|
21
|
-
value: 1.0,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// todo: should not be applied to live streams
|
|
25
|
-
export class SpeedController {
|
|
26
|
-
private playbackSpeedSubject = new BehaviorSubject<PlaybackSpeed>(
|
|
27
|
-
DEFAULT_SPEED
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
constructor(private player: Player) {}
|
|
31
|
-
|
|
32
|
-
get playbackSpeed$() {
|
|
33
|
-
return this.playbackSpeedSubject.asObservable();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async loadSpeed() {
|
|
37
|
-
const speed = await localStorage.getItem(SPEED_PREFERENCE_KEY, NAMESPACE);
|
|
38
|
-
|
|
39
|
-
// checking for value in case we will pull empty or broken object
|
|
40
|
-
if (speed && speed.value) {
|
|
41
|
-
this.playbackSpeedSubject.next(speed);
|
|
42
|
-
this.player.setPlaybackRate?.(speed.value);
|
|
43
|
-
log_debug(`Speed loaded: ${speed}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async setPlaybackSpeed(speed: PlaybackSpeed) {
|
|
48
|
-
await localStorage.setItem(SPEED_PREFERENCE_KEY, speed, NAMESPACE);
|
|
49
|
-
this.playbackSpeedSubject.next(speed);
|
|
50
|
-
this.player.setPlaybackRate?.(speed.value);
|
|
51
|
-
}
|
|
52
|
-
}
|