@applicaster/quick-brick-player 12.0.0-alpha.5251355865 → 12.0.0-alpha.5335460000
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/CellPlayer/Assets/AssetsComponent.tsx +61 -50
- package/src/CellPlayer/ContextProvider.tsx +50 -1
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +89 -77
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +177 -79
- package/src/Player/AudioLayer/Layout/DockedLayout.tsx +72 -26
- package/src/Player/AudioLayer/Layout/defaultLayoutsConts.ts +2 -0
- package/src/Player/AudioLayer/Layout/index.tsx +1 -7
- package/src/Player/AudioLayer/MagicBG/index.tsx +77 -27
- package/src/Player/Utils/Utils.ts +9 -22
- package/src/Player/index.tsx +119 -71
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.5335460000",
|
|
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": "12.0.0-
|
|
40
|
-
"@applicaster/quick-brick-tv-transport-controls": "
|
|
41
|
-
"@applicaster/zapp-react-native-tvos-app": "12.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.
|
|
43
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.
|
|
39
|
+
"@applicaster/quick-brick-mobile-transport-controls": "12.0.0-rc.96",
|
|
40
|
+
"@applicaster/quick-brick-tv-transport-controls": "12.0.0-rc.100",
|
|
41
|
+
"@applicaster/zapp-react-native-tvos-app": "12.0.0-alpha.5335460000",
|
|
42
|
+
"@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.5335460000",
|
|
43
|
+
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.5335460000",
|
|
44
44
|
"keymirror": "^0.1.1",
|
|
45
45
|
"query-string": "7.1.3",
|
|
46
46
|
"react-native-web-linear-gradient": "1.1.2",
|
|
@@ -1,74 +1,85 @@
|
|
|
1
1
|
import React, { useEffect, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
3
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
4
4
|
import { MUTED_USAGE } from "../const";
|
|
5
5
|
import { LiveImageManager } from "@applicaster/zapp-react-native-ui-components/Components/VideoLive/LiveImageManager";
|
|
6
|
+
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
6
7
|
|
|
7
8
|
type Asset = string | undefined;
|
|
8
9
|
|
|
9
10
|
const isCurrentPlayer = (playerId) =>
|
|
10
11
|
LiveImageManager.instance.getCurrentlyPlaying()?.playerId === playerId;
|
|
11
12
|
|
|
13
|
+
const liveImageButtonsListenerKey = "live-image-buttons";
|
|
14
|
+
|
|
12
15
|
const usePlayPauseListeners = (playerId, player, asset, setImageUri) =>
|
|
13
16
|
useEffect(() => {
|
|
14
17
|
if (playerId && player) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
setImageUri(null);
|
|
19
|
+
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (player.playerState.isReadyToPlay) {
|
|
24
|
+
if (player.playerState.isPaused) {
|
|
25
|
+
setImageUri(asset.active);
|
|
26
|
+
} else {
|
|
27
|
+
setImageUri(asset.inactive);
|
|
21
28
|
}
|
|
29
|
+
}
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
onPlayerPause: () => {
|
|
30
|
-
setImageUri(asset.active);
|
|
31
|
-
},
|
|
32
|
-
onPlayerClose: () => {
|
|
33
|
-
setImageUri(null);
|
|
34
|
-
},
|
|
35
|
-
onLoad() {
|
|
36
|
-
setImageUri(asset.inactive);
|
|
37
|
-
},
|
|
31
|
+
return player.addListener({
|
|
32
|
+
id: liveImageButtonsListenerKey,
|
|
33
|
+
listener: {
|
|
34
|
+
onPlayerResume: () => {
|
|
35
|
+
setImageUri(asset.inactive);
|
|
38
36
|
},
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
onPlayerPause: () => {
|
|
38
|
+
setImageUri(asset.active);
|
|
39
|
+
},
|
|
40
|
+
onPlayerClose: () => {
|
|
41
|
+
setImageUri(null);
|
|
42
|
+
},
|
|
43
|
+
onLoad() {
|
|
44
|
+
setImageUri(asset.inactive);
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
});
|
|
41
48
|
}, [player, playerId, asset]);
|
|
42
49
|
|
|
43
50
|
const useMuteUnmuteListeners = (playerId, player, asset, setImageUri) =>
|
|
44
51
|
useEffect(() => {
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
listener: {
|
|
50
|
-
onPlayerMute: () => {
|
|
51
|
-
if (isCurrentPlayer(playerId)) {
|
|
52
|
-
setImageUri(asset.active);
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
onPlayerUnmute: () => {
|
|
56
|
-
if (isCurrentPlayer(playerId)) {
|
|
57
|
-
setImageUri(asset.inactive);
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
onLoad() {
|
|
61
|
-
setImageUri(player?.getIsMuted() ? asset.active : asset.inactive);
|
|
62
|
-
},
|
|
63
|
-
onPlayerClose: () => {
|
|
64
|
-
setImageUri(null);
|
|
65
|
-
},
|
|
66
|
-
onVideoEnd: () => {
|
|
67
|
-
setImageUri(null);
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
});
|
|
52
|
+
if (!player || !playerId) {
|
|
53
|
+
setImageUri(null);
|
|
54
|
+
|
|
55
|
+
return;
|
|
71
56
|
}
|
|
57
|
+
|
|
58
|
+
// active action = muted, inactive = unmuted
|
|
59
|
+
return player.addListener({
|
|
60
|
+
id: liveImageButtonsListenerKey,
|
|
61
|
+
listener: {
|
|
62
|
+
onPlayerMute: () => {
|
|
63
|
+
if (isCurrentPlayer(playerId)) {
|
|
64
|
+
setImageUri(asset.active);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
onPlayerUnmute: () => {
|
|
68
|
+
if (isCurrentPlayer(playerId)) {
|
|
69
|
+
setImageUri(asset.inactive);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
onLoad() {
|
|
73
|
+
setImageUri(player?.getIsMuted() ? asset.active : asset.inactive);
|
|
74
|
+
},
|
|
75
|
+
onPlayerClose: () => {
|
|
76
|
+
setImageUri(null);
|
|
77
|
+
},
|
|
78
|
+
onVideoEnd: () => {
|
|
79
|
+
setImageUri(null);
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
72
83
|
}, [player, playerId, asset]);
|
|
73
84
|
|
|
74
85
|
const useListeners = MUTED_USAGE
|
|
@@ -21,7 +21,7 @@ const playActionCallback = (player) => {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
const invokeAction = () => {
|
|
24
|
+
const invokeAction = (_item: ZappEntry, _object) => {
|
|
25
25
|
const actionCallback = MUTED_USAGE ? muteActionCallback : playActionCallback;
|
|
26
26
|
// We only allow one player to be present at a time
|
|
27
27
|
const player = LiveImageManager.instance.getCurrentlyPlaying()?.player;
|
|
@@ -29,6 +29,54 @@ const invokeAction = () => {
|
|
|
29
29
|
actionCallback(player);
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
// Not exported because currently the is no way
|
|
33
|
+
// to subscribe to the action availability change.
|
|
34
|
+
// We currently return a null state to disable the action.
|
|
35
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
36
|
+
const isActionAvailable = (item: ZappEntry) => {
|
|
37
|
+
return (
|
|
38
|
+
LiveImageManager.instance.getCurrentlyPlaying()?.getPlayer().entry.id ===
|
|
39
|
+
item.id
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const addListener = (
|
|
44
|
+
entryId: string,
|
|
45
|
+
listener: CellActionStateListenerFunction
|
|
46
|
+
) => {
|
|
47
|
+
const callback = (event: Record<string, any>) => {
|
|
48
|
+
if (event.entry?.id !== entryId) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const player = LiveImageManager.instance.getCurrentlyPlaying()?.getPlayer();
|
|
53
|
+
|
|
54
|
+
if (!player || player.entry?.id !== entryId) {
|
|
55
|
+
listener(null);
|
|
56
|
+
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const actionState = MUTED_USAGE ? player.getIsMuted() : player.isPaused();
|
|
61
|
+
|
|
62
|
+
listener({
|
|
63
|
+
state: actionState ? 1 : 0,
|
|
64
|
+
label: "",
|
|
65
|
+
asset: AssetComponent,
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return LiveImageManager.instance.addListener({
|
|
70
|
+
id: `cell-player-${entryId}`,
|
|
71
|
+
listener: {
|
|
72
|
+
onEnd: callback,
|
|
73
|
+
onStart: callback,
|
|
74
|
+
onError: callback,
|
|
75
|
+
onDestroy: callback,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
32
80
|
const emptyState = [];
|
|
33
81
|
|
|
34
82
|
const initialEntryState = () => ({
|
|
@@ -46,6 +94,7 @@ export function ContextProvider(Component: ReactComponent<any>) {
|
|
|
46
94
|
state: emptyState,
|
|
47
95
|
invokeAction,
|
|
48
96
|
initialEntryState,
|
|
97
|
+
addListener,
|
|
49
98
|
}),
|
|
50
99
|
[invokeAction, initialEntryState]
|
|
51
100
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { ViewStyle, View
|
|
2
|
+
import { ViewStyle, View } 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";
|
|
@@ -24,8 +24,15 @@ import {
|
|
|
24
24
|
NAMESPACE,
|
|
25
25
|
} from "./utils";
|
|
26
26
|
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
27
|
-
import { getLiveUrl } from "../Utils";
|
|
27
|
+
import { addQueryParam, getLiveUrl } from "../Utils";
|
|
28
28
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
29
|
+
import {
|
|
30
|
+
AnimationComponent,
|
|
31
|
+
ComponentAnimationType,
|
|
32
|
+
AnimatedScrollModal,
|
|
33
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
34
|
+
import { PADDING_HORIZONTAL } from "./Layout/defaultLayoutsConts";
|
|
35
|
+
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
29
36
|
|
|
30
37
|
const { log_debug } = createLogger({
|
|
31
38
|
subsystem: "UIComponent",
|
|
@@ -68,29 +75,20 @@ export const defaultAspectRatioWidth = (height: number): number =>
|
|
|
68
75
|
(height / 9) * 16;
|
|
69
76
|
|
|
70
77
|
const Styles = {
|
|
71
|
-
mainContainer: (
|
|
78
|
+
mainContainer: (style: ViewStyle) => {
|
|
72
79
|
const combinedStyle: ViewStyle = {
|
|
73
80
|
flex: 1,
|
|
74
81
|
};
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
style
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return { ...combinedStyle, ...style };
|
|
82
|
-
},
|
|
83
|
-
playerContainer: (docked: boolean, style: ViewStyle) => {
|
|
84
|
-
const combinedStyle: ViewStyle = {
|
|
85
|
-
flex: 1,
|
|
83
|
+
return {
|
|
84
|
+
...combinedStyle,
|
|
85
|
+
...style,
|
|
86
86
|
};
|
|
87
|
-
|
|
88
|
-
if (docked) {
|
|
89
|
-
combinedStyle.height = style.height;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return combinedStyle;
|
|
93
87
|
},
|
|
88
|
+
playerContainer: {
|
|
89
|
+
flex: 1,
|
|
90
|
+
},
|
|
91
|
+
paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
|
|
94
92
|
|
|
95
93
|
controlsMobile: {
|
|
96
94
|
height: 50,
|
|
@@ -168,6 +166,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
168
166
|
|
|
169
167
|
const [sleepTimerDate, setSleepTimerDate] = useState(0);
|
|
170
168
|
|
|
169
|
+
const [defaultDimensions, setDefaultDimensions] =
|
|
170
|
+
React.useState<Dimensions>(undefined);
|
|
171
|
+
|
|
171
172
|
const [dimensions, setDimensions] = React.useState<Dimensions>({
|
|
172
173
|
width: 0,
|
|
173
174
|
height: 0,
|
|
@@ -181,9 +182,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
181
182
|
const { width, height } = event.nativeEvent.layout;
|
|
182
183
|
|
|
183
184
|
setDimensions({
|
|
184
|
-
width
|
|
185
|
+
width,
|
|
185
186
|
height,
|
|
186
187
|
});
|
|
188
|
+
|
|
189
|
+
if (!defaultDimensions) setDefaultDimensions({ width, height });
|
|
187
190
|
};
|
|
188
191
|
|
|
189
192
|
const cancelSleepTimer = async () => {
|
|
@@ -195,7 +198,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
195
198
|
});
|
|
196
199
|
|
|
197
200
|
setSleepTimerDate(0);
|
|
198
|
-
player?.pause();
|
|
199
201
|
|
|
200
202
|
await localStorage.removeItem("sleep", NAMESPACE);
|
|
201
203
|
};
|
|
@@ -293,7 +295,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
293
295
|
playerState.isPaused ? player?.play() : player.pause();
|
|
294
296
|
}, [playerState, player]);
|
|
295
297
|
|
|
296
|
-
const seekDuration =
|
|
298
|
+
const seekDuration = toNumberWithDefault(10, value("seek_duration"));
|
|
297
299
|
|
|
298
300
|
const onRewindButtonPress = React.useCallback(() => {
|
|
299
301
|
player?.rewind(seekDuration);
|
|
@@ -376,58 +378,65 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
376
378
|
player?.seekTo(0);
|
|
377
379
|
}, [player]);
|
|
378
380
|
|
|
379
|
-
const edges = React.useMemo<Edge[]>(
|
|
380
|
-
() => (docked ? [] : ["right", "left", "top"]),
|
|
381
|
-
[docked]
|
|
382
|
-
);
|
|
381
|
+
const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
|
|
383
382
|
|
|
384
|
-
const ContainerView =
|
|
383
|
+
const ContainerView = SafeAreaView;
|
|
385
384
|
|
|
386
385
|
const MainContent = React.useMemo(() => {
|
|
387
386
|
return (
|
|
388
|
-
<ContainerView style={Styles.mainContainer(
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
387
|
+
<ContainerView style={Styles.mainContainer(style)} edges={edges}>
|
|
388
|
+
<AnimationComponent
|
|
389
|
+
animationType={ComponentAnimationType.moveUpComponent}
|
|
390
|
+
additionalData={{ saveArea: true }}
|
|
391
|
+
style={Styles.playerContainer}
|
|
392
392
|
>
|
|
393
|
-
<
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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>
|
|
431
440
|
</ContainerView>
|
|
432
441
|
);
|
|
433
442
|
}, [
|
|
@@ -456,17 +465,20 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
456
465
|
if (configuration.magic_background) {
|
|
457
466
|
const baseUrl = entry?.extensions?.audio_player_background_image ?? "";
|
|
458
467
|
|
|
459
|
-
|
|
468
|
+
const queryParamName =
|
|
469
|
+
configuration.audio_player_background_image_query || "width";
|
|
470
|
+
|
|
471
|
+
const queryParamValue = 15;
|
|
460
472
|
|
|
461
|
-
|
|
462
|
-
// configuration.audio_player_background_image_query || "width";
|
|
463
|
-
//
|
|
464
|
-
// const queryParamValue = 15;
|
|
465
|
-
//
|
|
466
|
-
// const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
|
|
473
|
+
const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
|
|
467
474
|
|
|
468
475
|
return (
|
|
469
|
-
<MagicBG
|
|
476
|
+
<MagicBG
|
|
477
|
+
image={url}
|
|
478
|
+
fallbackUrl={baseUrl}
|
|
479
|
+
colors={entry?.extensions?.backgroundColors}
|
|
480
|
+
defaultColor="#000000"
|
|
481
|
+
>
|
|
470
482
|
{MainContent}
|
|
471
483
|
</MagicBG>
|
|
472
484
|
);
|