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