@applicaster/quick-brick-player 13.0.0-alpha.1436249127 → 13.0.0-alpha.1486614302
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 -13
- package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
- package/src/Player/AudioLayer/AudioDescription.tsx +4 -6
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +116 -136
- package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +27 -0
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +305 -0
- package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +5 -15
- package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +44 -67
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +212 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +83 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +32 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +95 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +17 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +214 -0
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +224 -0
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +109 -0
- package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
- package/src/Player/AudioLayer/Layout/const.ts +20 -0
- package/src/Player/AudioLayer/Layout/debug.ts +6 -0
- package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -0
- package/src/Player/AudioLayer/Layout/hooks/useImageSize.ts +100 -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/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 +27 -0
- package/src/Player/index.tsx +31 -19
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
- package/src/Player/Helpers/VideoResizeMode.ts +0 -7
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.1486614302",
|
|
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,12 +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-
|
|
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.
|
|
44
|
-
"keymirror": "^0.1.1",
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "13.0.0-alpha.1486614302",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.1486614302",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.1486614302",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.1486614302",
|
|
45
43
|
"query-string": "7.1.3",
|
|
46
44
|
"react-native-web-linear-gradient": "1.1.2",
|
|
47
45
|
"shaka-player": "4.3.5",
|
|
@@ -51,12 +49,28 @@
|
|
|
51
49
|
"videojs-contrib-quality-levels": "3.0.0"
|
|
52
50
|
},
|
|
53
51
|
"peerDependencies": {
|
|
52
|
+
"@applicaster/applicaster-types": "*",
|
|
53
|
+
"@applicaster/blur": "*",
|
|
54
54
|
"@applicaster/quick-brick-xray": "*",
|
|
55
55
|
"@applicaster/react-native-color-thief": "*",
|
|
56
|
-
"@
|
|
57
|
-
"@
|
|
58
|
-
"react": "
|
|
59
|
-
"react-native": "
|
|
60
|
-
"
|
|
56
|
+
"@applicaster/zapp-pipes-v2-client": "*",
|
|
57
|
+
"@applicaster/zapp-react-dom-ui-components": "*",
|
|
58
|
+
"@applicaster/zapp-react-native-redux": "*",
|
|
59
|
+
"@applicaster/zapp-react-native-tvos-ui-components": "*",
|
|
60
|
+
"@babel/runtime": "*",
|
|
61
|
+
"@react-native-community/netinfo": "*",
|
|
62
|
+
"immer": "*",
|
|
63
|
+
"react": "*",
|
|
64
|
+
"react-native": "*",
|
|
65
|
+
"react-native-fs": "*",
|
|
66
|
+
"react-native-gesture-handler": "*",
|
|
67
|
+
"react-native-linear-gradient": "*",
|
|
68
|
+
"react-native-safe-area-context": "*",
|
|
69
|
+
"react-native-svg": "*",
|
|
70
|
+
"react-native-web": "*",
|
|
71
|
+
"react-native-webview": "*",
|
|
72
|
+
"uglify-js": "*",
|
|
73
|
+
"validate-color": "*",
|
|
74
|
+
"zustand": "*"
|
|
61
75
|
}
|
|
62
76
|
}
|
|
@@ -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
|
|
2
|
+
import { Text, TextStyle } from "react-native";
|
|
3
3
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
4
|
|
|
5
5
|
type AudioDescriptionProps = {
|
|
@@ -13,8 +13,6 @@ type AudioDescriptionProps = {
|
|
|
13
13
|
value: GetValue;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const containerStyles = { paddingTop: 32, paddingBottom: 12 };
|
|
17
|
-
|
|
18
16
|
const titleStyles = (value: GetValue, prefix: string): TextStyle => ({
|
|
19
17
|
textAlign: "left",
|
|
20
18
|
color: value(`${prefix}title_color`),
|
|
@@ -83,13 +81,13 @@ export const AudioDescription = (props: AudioDescriptionProps) => {
|
|
|
83
81
|
const prefix = layoutState.docked ? "docked_player_" : "";
|
|
84
82
|
|
|
85
83
|
return (
|
|
86
|
-
|
|
84
|
+
<>
|
|
87
85
|
<Text style={titleStyles(value, prefix)} numberOfLines={1}>
|
|
88
86
|
{title}
|
|
89
87
|
</Text>
|
|
90
|
-
<Text style={summaryStyles(value, prefix)} numberOfLines={
|
|
88
|
+
<Text style={summaryStyles(value, prefix)} numberOfLines={1}>
|
|
91
89
|
{summary}
|
|
92
90
|
</Text>
|
|
93
|
-
|
|
91
|
+
</>
|
|
94
92
|
);
|
|
95
93
|
};
|
|
@@ -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,9 +25,19 @@ 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";
|
|
36
30
|
|
|
31
|
+
import {
|
|
32
|
+
SleepTimerController,
|
|
33
|
+
SleepTimerState,
|
|
34
|
+
SLEEP_TIMER_OFF,
|
|
35
|
+
} from "./SleepTimerManager";
|
|
36
|
+
import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
|
|
37
|
+
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
38
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
39
|
+
import { openBottomSheetModal } from "@applicaster/zapp-react-native-utils/modalState";
|
|
40
|
+
|
|
37
41
|
const { log_debug } = createLogger({
|
|
38
42
|
subsystem: "UIComponent",
|
|
39
43
|
category: "AudioPlayerWrapper",
|
|
@@ -50,6 +54,7 @@ type Configuration = {
|
|
|
50
54
|
[key: string]: any;
|
|
51
55
|
magic_background?: boolean;
|
|
52
56
|
audio_player_background_image_query?: string;
|
|
57
|
+
audio_player_background_image_default_color?: string;
|
|
53
58
|
tablet_landscape_sidebar_width?: string;
|
|
54
59
|
tablet_landscape_player_container_background_color?: string;
|
|
55
60
|
};
|
|
@@ -71,8 +76,7 @@ type Props = {
|
|
|
71
76
|
isTabletPortrait?: boolean;
|
|
72
77
|
};
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
(height / 9) * 16;
|
|
79
|
+
const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
|
|
76
80
|
|
|
77
81
|
const Styles = {
|
|
78
82
|
mainContainer: (style: ViewStyle) => {
|
|
@@ -98,7 +102,11 @@ const Styles = {
|
|
|
98
102
|
height: 96,
|
|
99
103
|
marginHorizontal: 24,
|
|
100
104
|
},
|
|
101
|
-
playerDetails: {
|
|
105
|
+
playerDetails: {
|
|
106
|
+
marginTop: 60,
|
|
107
|
+
alignSelf: "center",
|
|
108
|
+
width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
|
|
109
|
+
},
|
|
102
110
|
|
|
103
111
|
linearGradient: {
|
|
104
112
|
flex: 1,
|
|
@@ -116,9 +124,20 @@ const sleeps = [
|
|
|
116
124
|
{ label: "2 hours", value: 120 },
|
|
117
125
|
];
|
|
118
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
|
+
];
|
|
134
|
+
|
|
135
|
+
const edges: Edge[] = ["right", "left", "top"];
|
|
136
|
+
|
|
119
137
|
export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
120
138
|
const player = usePlayer();
|
|
121
139
|
const playerState = usePlayerState("audio-player-wrapper");
|
|
140
|
+
const theme = useTheme();
|
|
122
141
|
|
|
123
142
|
const {
|
|
124
143
|
docked,
|
|
@@ -131,14 +150,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
131
150
|
isTabletPortrait,
|
|
132
151
|
} = props;
|
|
133
152
|
|
|
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
153
|
const isTablet = useIsTablet();
|
|
143
154
|
|
|
144
155
|
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
@@ -154,17 +165,29 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
154
165
|
configuration?.audio_live_player_update_interval
|
|
155
166
|
);
|
|
156
167
|
|
|
157
|
-
const [
|
|
158
|
-
|
|
159
|
-
value: 1.0,
|
|
160
|
-
});
|
|
168
|
+
const [sleepTimerManager, setSleepTimerManager] =
|
|
169
|
+
useState<SleepTimerController | null>(null);
|
|
161
170
|
|
|
162
|
-
const [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
171
|
+
const [speedManager, setSpeedManager] = useState<SpeedController | null>(
|
|
172
|
+
null
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
if (player) {
|
|
177
|
+
setSleepTimerManager(new SleepTimerController(player));
|
|
178
|
+
setSpeedManager(new SpeedController(player));
|
|
179
|
+
} else {
|
|
180
|
+
setSleepTimerManager(null);
|
|
181
|
+
setSpeedManager(null);
|
|
182
|
+
}
|
|
183
|
+
}, [player]);
|
|
184
|
+
|
|
185
|
+
const [playbackSpeed, setPlaybackSpeed] =
|
|
186
|
+
useState<PlaybackSpeed>(DEFAULT_SPEED);
|
|
166
187
|
|
|
167
|
-
const [
|
|
188
|
+
const [sleepTimerState, setSleepTimerState] = useState<SleepTimerState>(
|
|
189
|
+
new SleepTimerState(SLEEP_TIMER_OFF, 0)
|
|
190
|
+
);
|
|
168
191
|
|
|
169
192
|
const [defaultDimensions, setDefaultDimensions] =
|
|
170
193
|
React.useState<Dimensions>(undefined);
|
|
@@ -174,8 +197,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
174
197
|
height: 0,
|
|
175
198
|
});
|
|
176
199
|
|
|
177
|
-
const navigator = useNavigation();
|
|
178
|
-
|
|
179
200
|
const { maximiseVideoModal } = useNavigation();
|
|
180
201
|
|
|
181
202
|
const onLayout = (event: any) => {
|
|
@@ -189,82 +210,27 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
189
210
|
if (!defaultDimensions) setDefaultDimensions({ width, height });
|
|
190
211
|
};
|
|
191
212
|
|
|
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
213
|
useEffect(() => {
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (playerState.isReadyToPlay && speed) {
|
|
249
|
-
setPlaybackSpeed(speed);
|
|
250
|
-
player?.setPlaybackRate(speed.value);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
214
|
+
const sleepSubscription =
|
|
215
|
+
sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
|
|
253
216
|
|
|
254
|
-
const
|
|
255
|
-
|
|
217
|
+
const speedSubscription =
|
|
218
|
+
speedManager?.playbackSpeed$.subscribe(setPlaybackSpeed);
|
|
256
219
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const sleepTimerDate = await handleSleep(sleep.value, futureSleepDate);
|
|
261
|
-
setSleepTimerDate(sleepTimerDate);
|
|
262
|
-
}
|
|
220
|
+
return () => {
|
|
221
|
+
sleepSubscription?.unsubscribe();
|
|
222
|
+
speedSubscription?.unsubscribe();
|
|
263
223
|
};
|
|
224
|
+
}, [sleepTimerManager, speedManager]);
|
|
264
225
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
if (!playerState.isReadyToPlay) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void speedManager?.loadSpeed();
|
|
232
|
+
void sleepTimerManager?.loadSleep();
|
|
233
|
+
}, [playerState.isReadyToPlay, speedManager, sleepTimerManager]);
|
|
268
234
|
|
|
269
235
|
const getValue = (key: string, stylesObj: {}) =>
|
|
270
236
|
R.propOr(null, key, stylesObj);
|
|
@@ -292,7 +258,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
292
258
|
|
|
293
259
|
const onPlaybackButtonPress = React.useCallback(() => {
|
|
294
260
|
if (playerState.isBuffering) return;
|
|
295
|
-
playerState.isPaused ? player?.play() : player
|
|
261
|
+
playerState.isPaused ? player?.play() : player?.pause();
|
|
296
262
|
}, [playerState, player]);
|
|
297
263
|
|
|
298
264
|
const seekDuration = toNumberWithDefault(10, value("seek_duration"));
|
|
@@ -307,30 +273,20 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
307
273
|
|
|
308
274
|
const onSpeedSelect = React.useCallback(
|
|
309
275
|
async (item) => {
|
|
310
|
-
setPlaybackSpeed(item);
|
|
311
|
-
player.setPlaybackRate(item.value);
|
|
312
|
-
await localStorage.setItem("speed", item, NAMESPACE);
|
|
276
|
+
await speedManager?.setPlaybackSpeed(item);
|
|
313
277
|
},
|
|
314
|
-
[
|
|
278
|
+
[speedManager]
|
|
315
279
|
);
|
|
316
280
|
|
|
317
281
|
const onSleepSelect = React.useCallback(
|
|
318
282
|
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
|
-
);
|
|
283
|
+
await sleepTimerManager?.setSleepTimer(item);
|
|
328
284
|
},
|
|
329
|
-
[
|
|
285
|
+
[sleepTimerManager]
|
|
330
286
|
);
|
|
331
287
|
|
|
332
288
|
const onSpeedButtonPress = React.useCallback(() => {
|
|
333
|
-
|
|
289
|
+
openBottomSheetModal({
|
|
334
290
|
modalBottomSheetContentProps: {
|
|
335
291
|
items: speeds,
|
|
336
292
|
current_selection: playbackSpeed,
|
|
@@ -341,15 +297,23 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
341
297
|
supportedOrientations: ["portrait"],
|
|
342
298
|
},
|
|
343
299
|
});
|
|
344
|
-
}, [
|
|
300
|
+
}, [
|
|
301
|
+
playbackSpeed,
|
|
302
|
+
setPlaybackSpeed,
|
|
303
|
+
onSpeedSelect,
|
|
304
|
+
configuration["playback_speed_title"],
|
|
305
|
+
]);
|
|
345
306
|
|
|
346
307
|
const onSleepButtonPress = React.useCallback(() => {
|
|
347
|
-
|
|
308
|
+
openBottomSheetModal({
|
|
348
309
|
modalBottomSheetContentProps: {
|
|
349
310
|
items: [
|
|
350
|
-
{
|
|
311
|
+
{
|
|
312
|
+
label: configuration["playback_sleep_off_label"],
|
|
313
|
+
value: 0,
|
|
314
|
+
},
|
|
351
315
|
].concat(sleeps),
|
|
352
|
-
current_selection:
|
|
316
|
+
current_selection: sleepTimerState.timer,
|
|
353
317
|
onPress: onSleepSelect,
|
|
354
318
|
title: configuration["playback_sleep_title"],
|
|
355
319
|
},
|
|
@@ -357,7 +321,20 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
357
321
|
supportedOrientations: ["portrait"],
|
|
358
322
|
},
|
|
359
323
|
});
|
|
360
|
-
}, [
|
|
324
|
+
}, [
|
|
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]);
|
|
361
338
|
|
|
362
339
|
const onCloseVideoModal = React.useCallback(() => {
|
|
363
340
|
playerManager.close();
|
|
@@ -378,13 +355,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
378
355
|
player?.seekTo(0);
|
|
379
356
|
}, [player]);
|
|
380
357
|
|
|
381
|
-
const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
|
|
382
|
-
|
|
383
|
-
const ContainerView = SafeAreaView;
|
|
384
|
-
|
|
385
358
|
const MainContent = React.useMemo(() => {
|
|
386
359
|
return (
|
|
387
|
-
<
|
|
360
|
+
<SafeAreaView style={Styles.mainContainer(style)} edges={edges}>
|
|
388
361
|
<AnimationComponent
|
|
389
362
|
animationType={ComponentAnimationType.moveUpComponent}
|
|
390
363
|
additionalData={{ saveArea: true }}
|
|
@@ -406,9 +379,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
406
379
|
onSleepButtonPress={onSleepButtonPress}
|
|
407
380
|
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
408
381
|
playbackSleepName={
|
|
409
|
-
|
|
382
|
+
sleepTimerState.timer.value === 0
|
|
383
|
+
? "sleep_timer"
|
|
384
|
+
: "sleep_timer_active"
|
|
410
385
|
}
|
|
411
|
-
sleepTimerDate={
|
|
386
|
+
sleepTimerDate={sleepTimerState.timerDate}
|
|
412
387
|
cancelSleepTimer={cancelSleepTimer}
|
|
413
388
|
onSkipLive={onSkipLive}
|
|
414
389
|
onCloseVideoModal={onCloseVideoModal}
|
|
@@ -437,7 +412,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
437
412
|
</View>
|
|
438
413
|
</AnimatedScrollModal>
|
|
439
414
|
</AnimationComponent>
|
|
440
|
-
</
|
|
415
|
+
</SafeAreaView>
|
|
441
416
|
);
|
|
442
417
|
}, [
|
|
443
418
|
docked,
|
|
@@ -458,26 +433,31 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
458
433
|
playNextData,
|
|
459
434
|
onSkipStart,
|
|
460
435
|
onSkipLive,
|
|
461
|
-
|
|
462
|
-
|
|
436
|
+
sleepTimerState.timer.value,
|
|
437
|
+
sleepTimerState.timerDate,
|
|
463
438
|
]);
|
|
464
439
|
|
|
465
440
|
if (configuration.magic_background) {
|
|
466
|
-
const baseUrl = entry
|
|
441
|
+
const baseUrl = imageSrcFromMediaItem(entry, null);
|
|
467
442
|
|
|
468
443
|
const queryParamName =
|
|
469
444
|
configuration.audio_player_background_image_query || "width";
|
|
470
445
|
|
|
446
|
+
const defaultBackgroundColor =
|
|
447
|
+
configuration.audio_player_background_image_default_color ||
|
|
448
|
+
theme?.app_background_color;
|
|
449
|
+
|
|
471
450
|
const queryParamValue = 15;
|
|
472
451
|
|
|
473
|
-
const url =
|
|
452
|
+
const url =
|
|
453
|
+
baseUrl && addQueryParam(baseUrl, queryParamName, queryParamValue);
|
|
474
454
|
|
|
475
455
|
return (
|
|
476
456
|
<MagicBG
|
|
477
457
|
image={url}
|
|
478
458
|
fallbackUrl={baseUrl}
|
|
479
459
|
colors={entry?.extensions?.backgroundColors}
|
|
480
|
-
defaultColor=
|
|
460
|
+
defaultColor={defaultBackgroundColor}
|
|
481
461
|
>
|
|
482
462
|
{MainContent}
|
|
483
463
|
</MagicBG>
|
|
@@ -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
|
+
};
|