@applicaster/quick-brick-player 13.0.0-rc.12 → 13.0.0-rc.120
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 +107 -68
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +205 -281
- package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +45 -0
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +320 -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} +62 -83
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +230 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +70 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +20 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +108 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +36 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +220 -0
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +223 -0
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +128 -0
- package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
- package/src/Player/AudioLayer/Layout/const.ts +26 -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/Layout/utils.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
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { StyleSheet } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
|
|
5
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
6
|
+
import {
|
|
7
|
+
Controls as MobileTransportControls,
|
|
8
|
+
ProgressBar,
|
|
9
|
+
} from "@applicaster/quick-brick-mobile-transport-controls";
|
|
10
|
+
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
AnimationComponent,
|
|
14
|
+
ComponentAnimationType,
|
|
15
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
16
|
+
|
|
17
|
+
import { AudioDescription } from "../../AudioDescription";
|
|
18
|
+
import { isValidDate } from "../../../Utils";
|
|
19
|
+
import { VerticalGutter } from "./VerticalGutter";
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
forwardButton,
|
|
23
|
+
playbackButton,
|
|
24
|
+
rewindButton,
|
|
25
|
+
skipToLiveButton,
|
|
26
|
+
skipToStartButton,
|
|
27
|
+
sleepButton,
|
|
28
|
+
speedButton,
|
|
29
|
+
} from "./utils";
|
|
30
|
+
|
|
31
|
+
const styles = StyleSheet.create({
|
|
32
|
+
flex: {
|
|
33
|
+
flex: 1,
|
|
34
|
+
},
|
|
35
|
+
nonFlex: {
|
|
36
|
+
flex: 0,
|
|
37
|
+
},
|
|
38
|
+
progressBar: {
|
|
39
|
+
flex: 0,
|
|
40
|
+
},
|
|
41
|
+
progressBarTrackStyles: {
|
|
42
|
+
borderRadius: 3,
|
|
43
|
+
height: 6,
|
|
44
|
+
},
|
|
45
|
+
progressBarThumbStyles: {
|
|
46
|
+
width: 14,
|
|
47
|
+
height: 14,
|
|
48
|
+
borderRadius: 7,
|
|
49
|
+
},
|
|
50
|
+
progressBarThumbStyles_pressed: {
|
|
51
|
+
width: 20,
|
|
52
|
+
height: 20,
|
|
53
|
+
borderRadius: 10,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const getControlJustifyContent = (countOfButtons: number) =>
|
|
58
|
+
countOfButtons <= 1 ? "center" : "space-between";
|
|
59
|
+
|
|
60
|
+
type Props = {
|
|
61
|
+
entry: ZappEntry;
|
|
62
|
+
layoutState: QuickBrickPlayer.LayoutState;
|
|
63
|
+
playerState: QuickBrickPlayer.PlayerState;
|
|
64
|
+
value: GetValue;
|
|
65
|
+
title: string | number;
|
|
66
|
+
summary: string | number;
|
|
67
|
+
sleepTimerDate: number;
|
|
68
|
+
cancelSleepTimer: Callback;
|
|
69
|
+
|
|
70
|
+
playbackSpeedName: string;
|
|
71
|
+
playbackSleepName: string;
|
|
72
|
+
|
|
73
|
+
onPlaybackButtonPress: Callback;
|
|
74
|
+
onRewindButtonPress: Callback;
|
|
75
|
+
onForwardButtonPress: Callback;
|
|
76
|
+
onPlayerSeek: (targetTime: number) => void;
|
|
77
|
+
onSkipStart: Callback;
|
|
78
|
+
onSkipLive: Callback;
|
|
79
|
+
onSpeedButtonPress: Callback;
|
|
80
|
+
onSleepButtonPress: Callback;
|
|
81
|
+
|
|
82
|
+
maxWidth?: number;
|
|
83
|
+
|
|
84
|
+
docked: boolean;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const Controls = (props: Props) => {
|
|
88
|
+
const {
|
|
89
|
+
entry,
|
|
90
|
+
layoutState,
|
|
91
|
+
playerState,
|
|
92
|
+
value,
|
|
93
|
+
title,
|
|
94
|
+
summary,
|
|
95
|
+
sleepTimerDate,
|
|
96
|
+
cancelSleepTimer,
|
|
97
|
+
|
|
98
|
+
playbackSpeedName,
|
|
99
|
+
playbackSleepName,
|
|
100
|
+
|
|
101
|
+
onPlaybackButtonPress,
|
|
102
|
+
onRewindButtonPress,
|
|
103
|
+
onForwardButtonPress,
|
|
104
|
+
onPlayerSeek,
|
|
105
|
+
onSkipStart,
|
|
106
|
+
onSkipLive,
|
|
107
|
+
onSpeedButtonPress,
|
|
108
|
+
onSleepButtonPress,
|
|
109
|
+
maxWidth = 320,
|
|
110
|
+
|
|
111
|
+
docked,
|
|
112
|
+
} = props;
|
|
113
|
+
|
|
114
|
+
const isTablet = useIsTablet();
|
|
115
|
+
const controller = playerManager.getActivePlayer();
|
|
116
|
+
let showFullControls = !controller?.isAd();
|
|
117
|
+
const liveButton = Boolean(value("live_badge_enabled"));
|
|
118
|
+
|
|
119
|
+
const isLiveContent = playerState.isLive;
|
|
120
|
+
|
|
121
|
+
if (isLiveContent) {
|
|
122
|
+
const seekEnabled = Boolean(value("liveSeekingEnabled"));
|
|
123
|
+
|
|
124
|
+
showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const [timeLeft, setTimeLeft] = React.useState(
|
|
128
|
+
sleepTimerDate !== 0 ? sleepTimerDate - Date.now() : 0
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const showCounter = React.useMemo(() => sleepTimerDate > 0, [sleepTimerDate]);
|
|
132
|
+
|
|
133
|
+
const countDownOptions = React.useMemo(() => {
|
|
134
|
+
return {
|
|
135
|
+
showCounter: showCounter && timeLeft >= 0,
|
|
136
|
+
timeLeft,
|
|
137
|
+
};
|
|
138
|
+
}, [showCounter, timeLeft]);
|
|
139
|
+
|
|
140
|
+
React.useEffect(() => {
|
|
141
|
+
if (showCounter && sleepTimerDate !== 0) {
|
|
142
|
+
setTimeLeft(sleepTimerDate - Date.now());
|
|
143
|
+
|
|
144
|
+
const intervalId = setInterval(() => {
|
|
145
|
+
setTimeLeft(() => {
|
|
146
|
+
const newTimeLeft = sleepTimerDate - Date.now();
|
|
147
|
+
|
|
148
|
+
if (newTimeLeft <= 0) {
|
|
149
|
+
clearInterval(intervalId);
|
|
150
|
+
|
|
151
|
+
cancelSleepTimer();
|
|
152
|
+
|
|
153
|
+
return 0;
|
|
154
|
+
} else {
|
|
155
|
+
return newTimeLeft;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}, 1000);
|
|
159
|
+
|
|
160
|
+
return () => clearInterval(intervalId);
|
|
161
|
+
} else {
|
|
162
|
+
setTimeLeft(0);
|
|
163
|
+
}
|
|
164
|
+
}, [sleepTimerDate, showCounter, cancelSleepTimer]);
|
|
165
|
+
|
|
166
|
+
const startTime = entry.extensions?.live?.start_time;
|
|
167
|
+
const endTime = entry.extensions?.live?.end_time;
|
|
168
|
+
|
|
169
|
+
const hasValidStartTime = isValidDate(startTime);
|
|
170
|
+
const hasValidEndTime = isValidDate(endTime);
|
|
171
|
+
|
|
172
|
+
const isDateBasedLiveContent =
|
|
173
|
+
isLiveContent && hasValidStartTime && hasValidEndTime;
|
|
174
|
+
|
|
175
|
+
const needsToShowProgressBar =
|
|
176
|
+
(isLiveContent &&
|
|
177
|
+
(Boolean(value("liveSeekingEnabled")) || isDateBasedLiveContent)) ||
|
|
178
|
+
!isLiveContent;
|
|
179
|
+
|
|
180
|
+
const startTimestamp = hasValidStartTime
|
|
181
|
+
? dayjs.utc(startTime!).valueOf()
|
|
182
|
+
: undefined;
|
|
183
|
+
|
|
184
|
+
const endTimestamp = hasValidEndTime
|
|
185
|
+
? dayjs.utc(endTime!).valueOf()
|
|
186
|
+
: undefined;
|
|
187
|
+
|
|
188
|
+
const isLiveShowFullControls = showFullControls && isLiveContent;
|
|
189
|
+
|
|
190
|
+
const controlButtons = React.useCallback((): Array<ControlsButton> => {
|
|
191
|
+
const play = playbackButton({
|
|
192
|
+
playerState,
|
|
193
|
+
liveButton,
|
|
194
|
+
isTablet,
|
|
195
|
+
isLiveShowFullControls,
|
|
196
|
+
onPress: onPlaybackButtonPress,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (!showFullControls) {
|
|
200
|
+
return [play];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const rewind = rewindButton({
|
|
204
|
+
isTablet,
|
|
205
|
+
onPress: controller?.hasSeekableDuration?.() ? onRewindButtonPress : null,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const forward = forwardButton({
|
|
209
|
+
isTablet,
|
|
210
|
+
onPress: controller?.hasSeekableDuration?.()
|
|
211
|
+
? onForwardButtonPress
|
|
212
|
+
: null,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const speed = speedButton({
|
|
216
|
+
isTablet,
|
|
217
|
+
onPress: onSpeedButtonPress,
|
|
218
|
+
name: playbackSpeedName,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const sleep = sleepButton({
|
|
222
|
+
isTablet,
|
|
223
|
+
onPress: onSleepButtonPress,
|
|
224
|
+
name: playbackSleepName,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
if (isLiveContent) {
|
|
228
|
+
const skipToStart = skipToStartButton({
|
|
229
|
+
isTablet,
|
|
230
|
+
onPress: onSkipStart,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const skipToLive = skipToLiveButton({
|
|
234
|
+
isTablet,
|
|
235
|
+
onPress: onSkipLive,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
return [skipToStart, rewind, play, forward, skipToLive];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return [speed, rewind, play, forward, sleep];
|
|
242
|
+
}, [
|
|
243
|
+
playerState,
|
|
244
|
+
liveButton,
|
|
245
|
+
isTablet,
|
|
246
|
+
onPlaybackButtonPress,
|
|
247
|
+
onRewindButtonPress,
|
|
248
|
+
onForwardButtonPress,
|
|
249
|
+
onSpeedButtonPress,
|
|
250
|
+
showFullControls,
|
|
251
|
+
onSkipStart,
|
|
252
|
+
onSkipLive,
|
|
253
|
+
isLiveContent,
|
|
254
|
+
playbackSpeedName,
|
|
255
|
+
playbackSleepName,
|
|
256
|
+
controller,
|
|
257
|
+
isLiveShowFullControls,
|
|
258
|
+
]);
|
|
259
|
+
|
|
260
|
+
if (docked) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<AnimationComponent
|
|
266
|
+
animationType={ComponentAnimationType.componentFade}
|
|
267
|
+
style={isTablet ? styles.nonFlex : styles.flex}
|
|
268
|
+
>
|
|
269
|
+
<VerticalGutter />
|
|
270
|
+
|
|
271
|
+
<AudioDescription
|
|
272
|
+
title={title}
|
|
273
|
+
summary={summary}
|
|
274
|
+
value={value}
|
|
275
|
+
layoutState={layoutState}
|
|
276
|
+
maxWidth={maxWidth}
|
|
277
|
+
/>
|
|
278
|
+
|
|
279
|
+
<VerticalGutter />
|
|
280
|
+
|
|
281
|
+
{needsToShowProgressBar ? (
|
|
282
|
+
<>
|
|
283
|
+
<ProgressBar
|
|
284
|
+
name={"audio-default-layout"}
|
|
285
|
+
content={entry}
|
|
286
|
+
value={value}
|
|
287
|
+
visible
|
|
288
|
+
layoutState={layoutState}
|
|
289
|
+
onPlayerSeek={onPlayerSeek}
|
|
290
|
+
playerState={playerState}
|
|
291
|
+
disableFullscreen
|
|
292
|
+
sliderStyle={2}
|
|
293
|
+
startTimestamp={startTimestamp}
|
|
294
|
+
endTimestamp={endTimestamp}
|
|
295
|
+
isDateBasedLiveContent={isDateBasedLiveContent}
|
|
296
|
+
onSkipLive={onSkipLive}
|
|
297
|
+
progressBarStyles={styles.progressBar}
|
|
298
|
+
countDownOptions={countDownOptions}
|
|
299
|
+
thumbStyles={styles.progressBarThumbStyles}
|
|
300
|
+
thumbStylesPressed={styles.progressBarThumbStyles_pressed}
|
|
301
|
+
trackStyles={styles.progressBarTrackStyles}
|
|
302
|
+
/>
|
|
303
|
+
|
|
304
|
+
<VerticalGutter />
|
|
305
|
+
</>
|
|
306
|
+
) : null}
|
|
307
|
+
|
|
308
|
+
<MobileTransportControls
|
|
309
|
+
value={value}
|
|
310
|
+
visible={true}
|
|
311
|
+
keepAlive={null}
|
|
312
|
+
buttons={controlButtons}
|
|
313
|
+
style={{
|
|
314
|
+
justifyContent: getControlJustifyContent(controlButtons().length),
|
|
315
|
+
}}
|
|
316
|
+
playerState={playerState}
|
|
317
|
+
/>
|
|
318
|
+
</AnimationComponent>
|
|
319
|
+
);
|
|
320
|
+
};
|
|
@@ -1,25 +1,7 @@
|
|
|
1
|
-
type PlayerState = {
|
|
2
|
-
currentTime: number;
|
|
3
|
-
duration: number;
|
|
4
|
-
seekableDuration: number;
|
|
5
|
-
isLive: boolean;
|
|
6
|
-
isPaused: boolean;
|
|
7
|
-
isBuffering: boolean;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const rewindButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
|
|
11
|
-
isTablet ? "big" : "smallMargins";
|
|
12
|
-
|
|
13
|
-
const playbackButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
|
|
14
|
-
isTablet ? "bigExtended" : "mediumExtended";
|
|
15
|
-
|
|
16
1
|
const playbackButtonMargins = (
|
|
17
2
|
isTablet: boolean,
|
|
18
3
|
isLiveShowFullControls: boolean
|
|
19
|
-
): number =>
|
|
20
|
-
isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? 95 : 40;
|
|
21
|
-
|
|
22
|
-
export const PADDING_HORIZONTAL = 15;
|
|
4
|
+
): number => (isLiveShowFullControls ? (isTablet ? 65 : 10) : undefined);
|
|
23
5
|
|
|
24
6
|
export const playbackButton = ({
|
|
25
7
|
playerState,
|
|
@@ -28,7 +10,7 @@ export const playbackButton = ({
|
|
|
28
10
|
isLiveShowFullControls,
|
|
29
11
|
onPress,
|
|
30
12
|
}: {
|
|
31
|
-
playerState: PlayerState;
|
|
13
|
+
playerState: QuickBrickPlayer.PlayerState;
|
|
32
14
|
liveButton: boolean;
|
|
33
15
|
isTablet: boolean;
|
|
34
16
|
isLiveShowFullControls: boolean;
|
|
@@ -37,11 +19,11 @@ export const playbackButton = ({
|
|
|
37
19
|
const icon = playerState.isPaused
|
|
38
20
|
? "play"
|
|
39
21
|
: playerState.isLive && liveButton
|
|
40
|
-
|
|
41
|
-
|
|
22
|
+
? "stop"
|
|
23
|
+
: "pause";
|
|
42
24
|
|
|
43
25
|
return {
|
|
44
|
-
size:
|
|
26
|
+
size: "bigExtended",
|
|
45
27
|
icon: playerState.isBuffering ? "buffering" : icon,
|
|
46
28
|
preferredFocus: true,
|
|
47
29
|
onPress,
|
|
@@ -57,15 +39,15 @@ type ButtonsProps = {
|
|
|
57
39
|
style?: any;
|
|
58
40
|
name?: string;
|
|
59
41
|
};
|
|
42
|
+
|
|
60
43
|
type ButtonsByNameProps = ButtonsProps & { name?: string };
|
|
61
44
|
|
|
62
45
|
const rewindButtonByName = ({
|
|
63
46
|
name,
|
|
64
47
|
onPress,
|
|
65
|
-
isTablet,
|
|
66
48
|
style,
|
|
67
49
|
}: ButtonsByNameProps): ControlsButton => ({
|
|
68
|
-
size:
|
|
50
|
+
size: "big",
|
|
69
51
|
icon: name,
|
|
70
52
|
onPress,
|
|
71
53
|
style,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* eslint react-native/no-color-literals: off */
|
|
2
|
+
/* eslint react-native/no-inline-styles: off */
|
|
3
|
+
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { View } from "react-native";
|
|
6
|
+
|
|
7
|
+
import { MOBILE } from "../const";
|
|
8
|
+
|
|
9
|
+
export const LeftDebugSquare = () => (
|
|
10
|
+
<View
|
|
11
|
+
style={{
|
|
12
|
+
position: "absolute",
|
|
13
|
+
top: 200,
|
|
14
|
+
left: 0,
|
|
15
|
+
width: MOBILE.MARGIN_HORIZONTAL,
|
|
16
|
+
height: MOBILE.MARGIN_HORIZONTAL,
|
|
17
|
+
backgroundColor: "blue",
|
|
18
|
+
|
|
19
|
+
borderWidth: 1,
|
|
20
|
+
borderColor: "yellow",
|
|
21
|
+
}}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export const RightDebugSquare = () => (
|
|
26
|
+
<View
|
|
27
|
+
style={{
|
|
28
|
+
position: "absolute",
|
|
29
|
+
top: 200,
|
|
30
|
+
right: 0,
|
|
31
|
+
width: MOBILE.MARGIN_HORIZONTAL,
|
|
32
|
+
height: MOBILE.MARGIN_HORIZONTAL,
|
|
33
|
+
backgroundColor: "blue",
|
|
34
|
+
|
|
35
|
+
borderWidth: 1,
|
|
36
|
+
borderColor: "yellow",
|
|
37
|
+
}}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export const BottomDebugSquare = () => (
|
|
42
|
+
<View
|
|
43
|
+
style={{
|
|
44
|
+
position: "absolute",
|
|
45
|
+
left: 170,
|
|
46
|
+
bottom: 0,
|
|
47
|
+
width: MOBILE.MARGIN_BOTTOM,
|
|
48
|
+
height: MOBILE.MARGIN_BOTTOM,
|
|
49
|
+
backgroundColor: "blue",
|
|
50
|
+
|
|
51
|
+
borderWidth: 1,
|
|
52
|
+
borderColor: "yellow",
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
@@ -9,52 +9,34 @@ import * as R from "ramda";
|
|
|
9
9
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
+
Button,
|
|
12
13
|
ContentInfo,
|
|
13
|
-
ProgressBar,
|
|
14
14
|
Controls,
|
|
15
|
-
|
|
15
|
+
ProgressBar,
|
|
16
16
|
} from "@applicaster/quick-brick-mobile-transport-controls";
|
|
17
17
|
|
|
18
18
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
19
|
+
|
|
19
20
|
import {
|
|
20
|
-
useModalAnimationContext,
|
|
21
21
|
AnimationComponent,
|
|
22
22
|
ComponentAnimationType,
|
|
23
23
|
PlayerAnimationStateEnum,
|
|
24
|
+
useModalAnimationContext,
|
|
24
25
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
26
|
+
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
25
27
|
|
|
26
|
-
type
|
|
27
|
-
width: number;
|
|
28
|
-
height: number;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
type LayoutProps = {
|
|
28
|
+
type Props = {
|
|
32
29
|
entry: ZappEntry;
|
|
33
|
-
layoutState:
|
|
34
|
-
|
|
35
|
-
docked: boolean;
|
|
36
|
-
isModal: boolean;
|
|
37
|
-
};
|
|
38
|
-
playerState: {
|
|
39
|
-
currentTime: number;
|
|
40
|
-
duration: number;
|
|
41
|
-
seekableDuration: number;
|
|
42
|
-
isLive: boolean;
|
|
43
|
-
isPaused: boolean;
|
|
44
|
-
isBuffering: boolean;
|
|
45
|
-
};
|
|
30
|
+
layoutState: QuickBrickPlayer.LayoutState;
|
|
31
|
+
playerState: QuickBrickPlayer.PlayerState;
|
|
46
32
|
value: GetValue;
|
|
47
|
-
|
|
48
|
-
onPlaybackButtonPress: () => void;
|
|
49
|
-
onRewindButtonPress: () => void;
|
|
50
|
-
onForwardButtonPress: () => void;
|
|
51
|
-
onPlayerSeek: (targetTime: number) => void;
|
|
33
|
+
dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
|
|
52
34
|
onCloseVideoModal: () => void;
|
|
53
|
-
|
|
54
|
-
dimensions: Dimensions;
|
|
35
|
+
onPlayerSeek: (targetTime: number) => void;
|
|
55
36
|
playNextData: PlayNextData;
|
|
56
37
|
title: string | number;
|
|
57
38
|
summary: string | number;
|
|
39
|
+
ImageComponent?: React.ReactNode;
|
|
58
40
|
};
|
|
59
41
|
|
|
60
42
|
const styles = StyleSheet.create({
|
|
@@ -71,6 +53,7 @@ const styles = StyleSheet.create({
|
|
|
71
53
|
touchableArea: {
|
|
72
54
|
flexShrink: 1,
|
|
73
55
|
flex: 1,
|
|
56
|
+
flexDirection: "row",
|
|
74
57
|
alignSelf: "stretch",
|
|
75
58
|
},
|
|
76
59
|
contentInfo: {
|
|
@@ -113,17 +96,21 @@ const playerDimensionsStyle = (
|
|
|
113
96
|
minimisedHeight: number,
|
|
114
97
|
addPadding: boolean
|
|
115
98
|
): ViewStyle => ({
|
|
116
|
-
|
|
99
|
+
width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
|
|
117
100
|
});
|
|
118
101
|
|
|
119
|
-
const animatedContainerStyle = (
|
|
102
|
+
const animatedContainerStyle = (
|
|
103
|
+
docked: boolean,
|
|
104
|
+
progressBarHeight: number
|
|
105
|
+
): ViewStyle => ({
|
|
106
|
+
top: progressBarHeight,
|
|
120
107
|
position: "absolute",
|
|
121
108
|
width: "100%",
|
|
122
109
|
zIndex: docked ? 1 : -1,
|
|
123
110
|
});
|
|
124
111
|
|
|
125
112
|
const backgroundImageStyle = (
|
|
126
|
-
dimensions:
|
|
113
|
+
dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"],
|
|
127
114
|
minimisedHeight: number,
|
|
128
115
|
isActiveGesture: boolean
|
|
129
116
|
): ViewStyle => ({
|
|
@@ -133,24 +120,11 @@ const backgroundImageStyle = (
|
|
|
133
120
|
});
|
|
134
121
|
|
|
135
122
|
const controlButtons = (
|
|
136
|
-
isPlayNextEnabled: boolean,
|
|
137
123
|
live: boolean,
|
|
138
124
|
paused: boolean,
|
|
139
125
|
buffering: boolean,
|
|
140
126
|
playerId: string
|
|
141
127
|
): Array<ControlsButton> => {
|
|
142
|
-
if (isPlayNextEnabled) {
|
|
143
|
-
return [
|
|
144
|
-
{
|
|
145
|
-
size: "medium",
|
|
146
|
-
name: "play_next",
|
|
147
|
-
icon: "play_next",
|
|
148
|
-
preferredFocus: true,
|
|
149
|
-
style: styles.buttons,
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
}
|
|
153
|
-
|
|
154
128
|
if (buffering) {
|
|
155
129
|
return [
|
|
156
130
|
{
|
|
@@ -202,24 +176,23 @@ const controlButtons = (
|
|
|
202
176
|
];
|
|
203
177
|
};
|
|
204
178
|
|
|
205
|
-
export
|
|
179
|
+
export const DockedControls = (props: Props) => {
|
|
206
180
|
const {
|
|
181
|
+
entry,
|
|
207
182
|
layoutState,
|
|
183
|
+
playerState,
|
|
208
184
|
value,
|
|
209
185
|
dimensions,
|
|
210
|
-
entry,
|
|
211
186
|
onCloseVideoModal,
|
|
212
187
|
onPlayerSeek,
|
|
213
|
-
playerState,
|
|
214
|
-
configuration,
|
|
215
188
|
playNextData,
|
|
216
189
|
title,
|
|
217
190
|
summary,
|
|
191
|
+
ImageComponent,
|
|
218
192
|
} = props;
|
|
219
193
|
|
|
220
194
|
const isTablet = useIsTablet();
|
|
221
195
|
|
|
222
|
-
const visible = true;
|
|
223
196
|
const liveButton = Boolean(value("live_badge_enabled"));
|
|
224
197
|
|
|
225
198
|
const {
|
|
@@ -227,10 +200,11 @@ export default function DockedLayout(props: LayoutProps) {
|
|
|
227
200
|
setPlayerAnimationState,
|
|
228
201
|
startComponentsAnimation,
|
|
229
202
|
minimisedHeight,
|
|
203
|
+
progressBarHeight,
|
|
230
204
|
} = useModalAnimationContext();
|
|
231
205
|
|
|
232
206
|
const maximazeVideoModal = React.useCallback(
|
|
233
|
-
() => setPlayerAnimationState(PlayerAnimationStateEnum.
|
|
207
|
+
() => setPlayerAnimationState(PlayerAnimationStateEnum.maximize),
|
|
234
208
|
[]
|
|
235
209
|
);
|
|
236
210
|
|
|
@@ -241,22 +215,27 @@ export default function DockedLayout(props: LayoutProps) {
|
|
|
241
215
|
animationType={ComponentAnimationType.componentAppears}
|
|
242
216
|
style={[
|
|
243
217
|
styles.container,
|
|
244
|
-
animatedContainerStyle(
|
|
218
|
+
animatedContainerStyle(
|
|
219
|
+
isActiveGesture || layoutState.docked,
|
|
220
|
+
progressBarHeight
|
|
221
|
+
),
|
|
222
|
+
{ height: minimisedHeight },
|
|
245
223
|
]}
|
|
246
224
|
>
|
|
247
225
|
{!playerState.isLive &&
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
226
|
+
(layoutState.docked || startComponentsAnimation) ? (
|
|
227
|
+
<ProgressBar
|
|
228
|
+
name={"audio-docked-layout"}
|
|
229
|
+
content={entry}
|
|
230
|
+
value={value}
|
|
231
|
+
visible
|
|
232
|
+
layoutState={layoutState}
|
|
233
|
+
onPlayerSeek={onPlayerSeek}
|
|
234
|
+
playerState={playerState}
|
|
235
|
+
startComponentsAnimation={startComponentsAnimation}
|
|
236
|
+
docked
|
|
237
|
+
/>
|
|
238
|
+
) : null}
|
|
260
239
|
|
|
261
240
|
<View style={styles.content}>
|
|
262
241
|
<View
|
|
@@ -267,21 +246,22 @@ export default function DockedLayout(props: LayoutProps) {
|
|
|
267
246
|
)}
|
|
268
247
|
/>
|
|
269
248
|
<TouchableWithoutFeedback onPress={maximazeVideoModal}>
|
|
270
|
-
<View
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
249
|
+
<View style={styles.touchableArea}>
|
|
250
|
+
{isActiveGesture || layoutState.docked ? (
|
|
251
|
+
<View
|
|
252
|
+
style={{ width: toNumberWithDefault(100, minimisedHeight) }}
|
|
253
|
+
>
|
|
254
|
+
{ImageComponent || null}
|
|
255
|
+
</View>
|
|
256
|
+
) : (
|
|
257
|
+
<View
|
|
258
|
+
style={playerDimensionsStyle(
|
|
259
|
+
minimisedHeight,
|
|
260
|
+
isActiveGesture || layoutState.docked
|
|
261
|
+
)}
|
|
262
|
+
/>
|
|
263
|
+
)}
|
|
264
|
+
<View style={[styles.contentInfo, backgroundColorStyle(value)]}>
|
|
285
265
|
<ContentInfo
|
|
286
266
|
content={{ ...entry, title, summary }}
|
|
287
267
|
value={value}
|
|
@@ -295,14 +275,13 @@ export default function DockedLayout(props: LayoutProps) {
|
|
|
295
275
|
isTablet
|
|
296
276
|
? styles.controlsContainerForTablet
|
|
297
277
|
: styles.controlsContainerForMobile,
|
|
298
|
-
|
|
278
|
+
backgroundColorStyle(value),
|
|
299
279
|
]}
|
|
300
280
|
>
|
|
301
281
|
<Controls
|
|
302
282
|
value={value}
|
|
303
|
-
visible
|
|
283
|
+
visible
|
|
304
284
|
buttons={R.partial(controlButtons, [
|
|
305
|
-
playNextData,
|
|
306
285
|
playerState.isLive && liveButton,
|
|
307
286
|
])}
|
|
308
287
|
style={styles.playPauseButton}
|
|
@@ -320,4 +299,4 @@ export default function DockedLayout(props: LayoutProps) {
|
|
|
320
299
|
</View>
|
|
321
300
|
</AnimationComponent>
|
|
322
301
|
);
|
|
323
|
-
}
|
|
302
|
+
};
|