@applicaster/quick-brick-player 13.0.0-rc.98 → 13.0.0
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 -7
- package/src/Player/AudioLayer/AudioDescription.tsx +109 -68
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +81 -189
- package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +23 -5
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +46 -60
- package/src/Player/AudioLayer/Layout/Controls/utils.ts +5 -13
- package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +38 -19
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +35 -25
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +39 -40
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +6 -22
- 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 +37 -20
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +19 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +101 -103
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +5 -14
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +39 -13
- package/src/Player/AudioLayer/Layout/const.ts +6 -0
- package/src/Player/AudioLayer/Layout/debug.ts +1 -1
- package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -1
- package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
- package/src/Player/AudioLayer/Layout/hooks/{useImageSize.ts → useTabletLayoutImageSize.ts} +10 -5
- package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +1 -1
- package/src/Player/AudioLayer/Layout/utils.ts +7 -0
- package/src/Player/AudioLayer/SleepTimerManager.ts +22 -11
- 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/Const/sleepTimerOptions.ts +7 -5
- package/src/Player/Utils/index.tsx +6 -0
- package/src/Player/hooks/useIsCasting.tsx +57 -0
- package/src/Player/index.tsx +84 -37
- package/src/QuickBrickPlayer.tsx +3 -0
- 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/utils/utils.ts +0 -25
|
@@ -2,10 +2,12 @@ import * as React from "react";
|
|
|
2
2
|
import { StyleSheet } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useIsTablet,
|
|
7
|
+
useZStore,
|
|
8
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
6
9
|
import {
|
|
7
10
|
Controls as MobileTransportControls,
|
|
8
|
-
CountDown,
|
|
9
11
|
ProgressBar,
|
|
10
12
|
} from "@applicaster/quick-brick-mobile-transport-controls";
|
|
11
13
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
@@ -28,6 +30,7 @@ import {
|
|
|
28
30
|
sleepButton,
|
|
29
31
|
speedButton,
|
|
30
32
|
} from "./utils";
|
|
33
|
+
import { useSleepTimerModal } from "../../useSleepTimerModal";
|
|
31
34
|
|
|
32
35
|
const styles = StyleSheet.create({
|
|
33
36
|
flex: {
|
|
@@ -39,19 +42,24 @@ const styles = StyleSheet.create({
|
|
|
39
42
|
progressBar: {
|
|
40
43
|
flex: 0,
|
|
41
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
|
+
},
|
|
42
59
|
});
|
|
43
60
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
isLiveShowFullControls,
|
|
47
|
-
}: {
|
|
48
|
-
isTablet: boolean;
|
|
49
|
-
isLiveShowFullControls: boolean;
|
|
50
|
-
}) => ({
|
|
51
|
-
height: isTablet ? undefined : 50,
|
|
52
|
-
marginHorizontal: isTablet ? undefined : 10,
|
|
53
|
-
justifyContent: isLiveShowFullControls ? "space-between" : "space-evenly",
|
|
54
|
-
});
|
|
61
|
+
const getControlJustifyContent = (countOfButtons: number) =>
|
|
62
|
+
countOfButtons <= 1 ? "center" : "space-between";
|
|
55
63
|
|
|
56
64
|
type Props = {
|
|
57
65
|
entry: ZappEntry;
|
|
@@ -60,11 +68,8 @@ type Props = {
|
|
|
60
68
|
value: GetValue;
|
|
61
69
|
title: string | number;
|
|
62
70
|
summary: string | number;
|
|
63
|
-
sleepTimerDate: number;
|
|
64
|
-
cancelSleepTimer: Callback;
|
|
65
71
|
|
|
66
72
|
playbackSpeedName: string;
|
|
67
|
-
playbackSleepName: string;
|
|
68
73
|
|
|
69
74
|
onPlaybackButtonPress: Callback;
|
|
70
75
|
onRewindButtonPress: Callback;
|
|
@@ -73,7 +78,8 @@ type Props = {
|
|
|
73
78
|
onSkipStart: Callback;
|
|
74
79
|
onSkipLive: Callback;
|
|
75
80
|
onSpeedButtonPress: Callback;
|
|
76
|
-
|
|
81
|
+
|
|
82
|
+
maxWidth?: number;
|
|
77
83
|
|
|
78
84
|
docked: boolean;
|
|
79
85
|
};
|
|
@@ -86,11 +92,8 @@ export const Controls = (props: Props) => {
|
|
|
86
92
|
value,
|
|
87
93
|
title,
|
|
88
94
|
summary,
|
|
89
|
-
sleepTimerDate,
|
|
90
|
-
cancelSleepTimer,
|
|
91
95
|
|
|
92
96
|
playbackSpeedName,
|
|
93
|
-
playbackSleepName,
|
|
94
97
|
|
|
95
98
|
onPlaybackButtonPress,
|
|
96
99
|
onRewindButtonPress,
|
|
@@ -99,11 +102,26 @@ export const Controls = (props: Props) => {
|
|
|
99
102
|
onSkipStart,
|
|
100
103
|
onSkipLive,
|
|
101
104
|
onSpeedButtonPress,
|
|
102
|
-
|
|
105
|
+
maxWidth = 320,
|
|
103
106
|
|
|
104
107
|
docked,
|
|
105
108
|
} = props;
|
|
106
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
|
+
|
|
107
125
|
const isTablet = useIsTablet();
|
|
108
126
|
const controller = playerManager.getActivePlayer();
|
|
109
127
|
let showFullControls = !controller?.isAd();
|
|
@@ -117,40 +135,6 @@ export const Controls = (props: Props) => {
|
|
|
117
135
|
showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
|
|
118
136
|
}
|
|
119
137
|
|
|
120
|
-
const sleepTitle = value("playback_sleep_countdown_label");
|
|
121
|
-
|
|
122
|
-
const [timeLeft, setTimeLeft] = React.useState(
|
|
123
|
-
sleepTimerDate !== 0 ? sleepTimerDate - Date.now() : 0
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
const showCounter = React.useMemo(() => sleepTimerDate > 0, [sleepTimerDate]);
|
|
127
|
-
|
|
128
|
-
React.useEffect(() => {
|
|
129
|
-
if (showCounter && sleepTimerDate !== 0) {
|
|
130
|
-
setTimeLeft(sleepTimerDate - Date.now());
|
|
131
|
-
|
|
132
|
-
const intervalId = setInterval(() => {
|
|
133
|
-
setTimeLeft(() => {
|
|
134
|
-
const newTimeLeft = sleepTimerDate - Date.now();
|
|
135
|
-
|
|
136
|
-
if (newTimeLeft <= 0) {
|
|
137
|
-
clearInterval(intervalId);
|
|
138
|
-
|
|
139
|
-
cancelSleepTimer();
|
|
140
|
-
|
|
141
|
-
return 0;
|
|
142
|
-
} else {
|
|
143
|
-
return newTimeLeft;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}, 1000);
|
|
147
|
-
|
|
148
|
-
return () => clearInterval(intervalId);
|
|
149
|
-
} else {
|
|
150
|
-
setTimeLeft(0);
|
|
151
|
-
}
|
|
152
|
-
}, [sleepTimerDate, showCounter, cancelSleepTimer]);
|
|
153
|
-
|
|
154
138
|
const startTime = entry.extensions?.live?.start_time;
|
|
155
139
|
const endTime = entry.extensions?.live?.end_time;
|
|
156
140
|
|
|
@@ -261,6 +245,7 @@ export const Controls = (props: Props) => {
|
|
|
261
245
|
summary={summary}
|
|
262
246
|
value={value}
|
|
263
247
|
layoutState={layoutState}
|
|
248
|
+
maxWidth={maxWidth}
|
|
264
249
|
/>
|
|
265
250
|
|
|
266
251
|
<VerticalGutter />
|
|
@@ -282,12 +267,11 @@ export const Controls = (props: Props) => {
|
|
|
282
267
|
isDateBasedLiveContent={isDateBasedLiveContent}
|
|
283
268
|
onSkipLive={onSkipLive}
|
|
284
269
|
progressBarStyles={styles.progressBar}
|
|
270
|
+
thumbStyles={styles.progressBarThumbStyles}
|
|
271
|
+
thumbStylesPressed={styles.progressBarThumbStyles_pressed}
|
|
272
|
+
trackStyles={styles.progressBarTrackStyles}
|
|
285
273
|
/>
|
|
286
274
|
|
|
287
|
-
{showCounter && timeLeft >= 0 ? (
|
|
288
|
-
<CountDown timeLeft={timeLeft} value={value} title={sleepTitle} />
|
|
289
|
-
) : null}
|
|
290
|
-
|
|
291
275
|
<VerticalGutter />
|
|
292
276
|
</>
|
|
293
277
|
) : null}
|
|
@@ -297,7 +281,9 @@ export const Controls = (props: Props) => {
|
|
|
297
281
|
visible={true}
|
|
298
282
|
keepAlive={null}
|
|
299
283
|
buttons={controlButtons}
|
|
300
|
-
style={
|
|
284
|
+
style={{
|
|
285
|
+
justifyContent: getControlJustifyContent(controlButtons().length),
|
|
286
|
+
}}
|
|
301
287
|
playerState={playerState}
|
|
302
288
|
/>
|
|
303
289
|
</AnimationComponent>
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
const rewindButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
|
|
2
|
-
isTablet ? "big" : "smallMargins";
|
|
3
|
-
|
|
4
|
-
const playbackButtonSize = (isTablet: boolean): keyof ButtonSizeStyles =>
|
|
5
|
-
isTablet ? "bigExtended" : "mediumExtended";
|
|
6
|
-
|
|
7
1
|
const playbackButtonMargins = (
|
|
8
2
|
isTablet: boolean,
|
|
9
3
|
isLiveShowFullControls: boolean
|
|
10
|
-
): number =>
|
|
11
|
-
isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? undefined : 40;
|
|
4
|
+
): number => (isLiveShowFullControls ? (isTablet ? 65 : 10) : undefined);
|
|
12
5
|
|
|
13
6
|
export const playbackButton = ({
|
|
14
7
|
playerState,
|
|
@@ -30,7 +23,7 @@ export const playbackButton = ({
|
|
|
30
23
|
: "pause";
|
|
31
24
|
|
|
32
25
|
return {
|
|
33
|
-
size:
|
|
26
|
+
size: "bigExtended",
|
|
34
27
|
icon: playerState.isBuffering ? "buffering" : icon,
|
|
35
28
|
preferredFocus: true,
|
|
36
29
|
onPress,
|
|
@@ -52,10 +45,9 @@ type ButtonsByNameProps = ButtonsProps & { name?: string };
|
|
|
52
45
|
const rewindButtonByName = ({
|
|
53
46
|
name,
|
|
54
47
|
onPress,
|
|
55
|
-
isTablet,
|
|
56
48
|
style,
|
|
57
49
|
}: ButtonsByNameProps): ControlsButton => ({
|
|
58
|
-
size:
|
|
50
|
+
size: "big",
|
|
59
51
|
icon: name,
|
|
60
52
|
onPress,
|
|
61
53
|
style,
|
|
@@ -107,7 +99,7 @@ export const skipToLiveButton = (props: ButtonsProps): ControlsButton =>
|
|
|
107
99
|
skipButtonByName({ ...props, name: "skip_live" });
|
|
108
100
|
|
|
109
101
|
export const speedButton = (props: ButtonsProps): ControlsButton =>
|
|
110
|
-
speedButtonByName(
|
|
102
|
+
speedButtonByName(props);
|
|
111
103
|
|
|
112
104
|
export const sleepButton = (props: ButtonsProps): ControlsButton =>
|
|
113
|
-
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
|
+
);
|
|
@@ -24,19 +24,23 @@ import {
|
|
|
24
24
|
useModalAnimationContext,
|
|
25
25
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
26
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";
|
|
29
|
+
|
|
30
|
+
const bottomTabBarHeight = getTabBarHeight();
|
|
27
31
|
|
|
28
32
|
type Props = {
|
|
29
33
|
entry: ZappEntry;
|
|
30
34
|
layoutState: QuickBrickPlayer.LayoutState;
|
|
31
35
|
playerState: QuickBrickPlayer.PlayerState;
|
|
32
36
|
value: GetValue;
|
|
33
|
-
configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
|
|
34
37
|
dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
|
|
35
38
|
onCloseVideoModal: () => void;
|
|
36
39
|
onPlayerSeek: (targetTime: number) => void;
|
|
37
40
|
playNextData: PlayNextData;
|
|
38
41
|
title: string | number;
|
|
39
42
|
summary: string | number;
|
|
43
|
+
ImageComponent?: React.ReactNode;
|
|
40
44
|
};
|
|
41
45
|
|
|
42
46
|
const styles = StyleSheet.create({
|
|
@@ -53,6 +57,7 @@ const styles = StyleSheet.create({
|
|
|
53
57
|
touchableArea: {
|
|
54
58
|
flexShrink: 1,
|
|
55
59
|
flex: 1,
|
|
60
|
+
flexDirection: "row",
|
|
56
61
|
alignSelf: "stretch",
|
|
57
62
|
},
|
|
58
63
|
contentInfo: {
|
|
@@ -87,15 +92,11 @@ const styles = StyleSheet.create({
|
|
|
87
92
|
},
|
|
88
93
|
});
|
|
89
94
|
|
|
90
|
-
const backgroundColorStyle = (value: GetValue): ViewStyle => ({
|
|
91
|
-
backgroundColor: value("docked_player_background_color"),
|
|
92
|
-
});
|
|
93
|
-
|
|
94
95
|
const playerDimensionsStyle = (
|
|
95
96
|
minimisedHeight: number,
|
|
96
97
|
addPadding: boolean
|
|
97
98
|
): ViewStyle => ({
|
|
98
|
-
|
|
99
|
+
width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
|
|
99
100
|
});
|
|
100
101
|
|
|
101
102
|
const animatedContainerStyle = (
|
|
@@ -181,13 +182,13 @@ export const DockedControls = (props: Props) => {
|
|
|
181
182
|
layoutState,
|
|
182
183
|
playerState,
|
|
183
184
|
value,
|
|
184
|
-
configuration,
|
|
185
185
|
dimensions,
|
|
186
186
|
onCloseVideoModal,
|
|
187
187
|
onPlayerSeek,
|
|
188
188
|
playNextData,
|
|
189
189
|
title,
|
|
190
190
|
summary,
|
|
191
|
+
ImageComponent,
|
|
191
192
|
} = props;
|
|
192
193
|
|
|
193
194
|
const isTablet = useIsTablet();
|
|
@@ -207,6 +208,10 @@ export const DockedControls = (props: Props) => {
|
|
|
207
208
|
[]
|
|
208
209
|
);
|
|
209
210
|
|
|
211
|
+
const dockedBackgroundColor = value("docked_player_background_color");
|
|
212
|
+
|
|
213
|
+
const insets = useSafeAreaInsets();
|
|
214
|
+
|
|
210
215
|
if (!layoutState.docked && !startComponentsAnimation) return null;
|
|
211
216
|
|
|
212
217
|
return (
|
|
@@ -218,7 +223,9 @@ export const DockedControls = (props: Props) => {
|
|
|
218
223
|
isActiveGesture || layoutState.docked,
|
|
219
224
|
progressBarHeight
|
|
220
225
|
),
|
|
221
|
-
{
|
|
226
|
+
{
|
|
227
|
+
height: minimisedHeight + bottomTabBarHeight + insets.bottom,
|
|
228
|
+
},
|
|
222
229
|
]}
|
|
223
230
|
>
|
|
224
231
|
{!playerState.isLive &&
|
|
@@ -245,19 +252,25 @@ export const DockedControls = (props: Props) => {
|
|
|
245
252
|
)}
|
|
246
253
|
/>
|
|
247
254
|
<TouchableWithoutFeedback onPress={maximazeVideoModal}>
|
|
248
|
-
<View
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
+
)}
|
|
257
270
|
<View
|
|
258
271
|
style={[
|
|
259
272
|
styles.contentInfo,
|
|
260
|
-
|
|
273
|
+
{ backgroundColor: dockedBackgroundColor },
|
|
261
274
|
]}
|
|
262
275
|
>
|
|
263
276
|
<ContentInfo
|
|
@@ -273,7 +286,7 @@ export const DockedControls = (props: Props) => {
|
|
|
273
286
|
isTablet
|
|
274
287
|
? styles.controlsContainerForTablet
|
|
275
288
|
: styles.controlsContainerForMobile,
|
|
276
|
-
|
|
289
|
+
{ backgroundColor: dockedBackgroundColor },
|
|
277
290
|
]}
|
|
278
291
|
>
|
|
279
292
|
<Controls
|
|
@@ -295,6 +308,12 @@ export const DockedControls = (props: Props) => {
|
|
|
295
308
|
/>
|
|
296
309
|
</View>
|
|
297
310
|
</View>
|
|
311
|
+
<View
|
|
312
|
+
style={{
|
|
313
|
+
height: insets.bottom + bottomTabBarHeight,
|
|
314
|
+
backgroundColor: dockedBackgroundColor,
|
|
315
|
+
}}
|
|
316
|
+
/>
|
|
298
317
|
</AnimationComponent>
|
|
299
318
|
);
|
|
300
319
|
};
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { View, ViewStyle
|
|
2
|
+
import { StyleSheet, View, ViewStyle } from "react-native";
|
|
3
3
|
import {
|
|
4
|
-
useSafeAreaInsets,
|
|
5
4
|
useSafeAreaFrame,
|
|
5
|
+
useSafeAreaInsets,
|
|
6
6
|
} from "react-native-safe-area-context";
|
|
7
7
|
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
8
|
|
|
9
|
-
import { MOBILE } from "./const";
|
|
9
|
+
import { MOBILE, NAVBAR_HEIGHT } from "./const";
|
|
10
10
|
import { TransportInfo } from "./TransportInfo";
|
|
11
11
|
import { PlayerImage } from "./PlayerImage";
|
|
12
12
|
import { Controls } from "./Controls";
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
|
|
15
15
|
import { DockedControls } from "./DockedControls";
|
|
16
|
-
import { withDebug } from "./debug";
|
|
16
|
+
import { DEBUG, withDebug } from "./debug";
|
|
17
|
+
import {
|
|
18
|
+
BottomDebugSquare,
|
|
19
|
+
LeftDebugSquare,
|
|
20
|
+
RightDebugSquare,
|
|
21
|
+
} from "./Debug/index";
|
|
17
22
|
|
|
18
23
|
import { Props } from "./types";
|
|
19
24
|
|
|
@@ -72,15 +77,11 @@ export function MobileLayout({
|
|
|
72
77
|
onSkipStart,
|
|
73
78
|
onSkipLive,
|
|
74
79
|
onSpeedButtonPress,
|
|
75
|
-
onSleepButtonPress,
|
|
76
80
|
onCloseVideoModal,
|
|
77
81
|
playbackSpeedName,
|
|
78
|
-
playbackSleepName,
|
|
79
82
|
configuration,
|
|
80
83
|
dimensions,
|
|
81
84
|
playNextData,
|
|
82
|
-
cancelSleepTimer,
|
|
83
|
-
sleepTimerDate,
|
|
84
85
|
title,
|
|
85
86
|
summary,
|
|
86
87
|
}: Props) {
|
|
@@ -90,11 +91,27 @@ export function MobileLayout({
|
|
|
90
91
|
const { height: screenHeight } = useSafeAreaFrame();
|
|
91
92
|
const { progressBarHeight } = useModalAnimationContext();
|
|
92
93
|
|
|
93
|
-
const { imageSize
|
|
94
|
+
const { imageSize } = useMobileLayoutImageSize();
|
|
94
95
|
|
|
95
96
|
const { height: transportInfoHeight, onLayout: onTransportInfoLayout } =
|
|
96
97
|
useTransportInfoHeight();
|
|
97
98
|
|
|
99
|
+
const controlsContainerHeight = React.useMemo(() => {
|
|
100
|
+
return (
|
|
101
|
+
screenHeight -
|
|
102
|
+
topInset -
|
|
103
|
+
imageSize -
|
|
104
|
+
NAVBAR_HEIGHT -
|
|
105
|
+
MOBILE.MARGIN_BOTTOM -
|
|
106
|
+
MOBILE.MARGIN_TOP -
|
|
107
|
+
bottomInset
|
|
108
|
+
);
|
|
109
|
+
}, [screenHeight, topInset, imageSize, bottomInset]);
|
|
110
|
+
|
|
111
|
+
const verticalOffsetForImage = React.useMemo(() => {
|
|
112
|
+
return transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight;
|
|
113
|
+
}, [transportInfoHeight, progressBarHeight]);
|
|
114
|
+
|
|
98
115
|
return (
|
|
99
116
|
<View
|
|
100
117
|
style={[
|
|
@@ -107,6 +124,10 @@ export function MobileLayout({
|
|
|
107
124
|
}),
|
|
108
125
|
]}
|
|
109
126
|
>
|
|
127
|
+
{DEBUG ? <LeftDebugSquare /> : null}
|
|
128
|
+
{DEBUG ? <RightDebugSquare /> : null}
|
|
129
|
+
{DEBUG ? <BottomDebugSquare /> : null}
|
|
130
|
+
|
|
110
131
|
{/* TransportInfo */}
|
|
111
132
|
<TransportInfo
|
|
112
133
|
entry={entry}
|
|
@@ -139,7 +160,6 @@ export function MobileLayout({
|
|
|
139
160
|
}),
|
|
140
161
|
},
|
|
141
162
|
]}
|
|
142
|
-
onLayout={onLayout}
|
|
143
163
|
>
|
|
144
164
|
<PlayerImage
|
|
145
165
|
entry={entry}
|
|
@@ -155,20 +175,15 @@ export function MobileLayout({
|
|
|
155
175
|
summary={summary}
|
|
156
176
|
docked={docked}
|
|
157
177
|
imageWidth={imageSize}
|
|
158
|
-
verticalOffset={
|
|
159
|
-
transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight
|
|
160
|
-
}
|
|
178
|
+
verticalOffset={verticalOffsetForImage}
|
|
161
179
|
/>
|
|
162
180
|
</View>
|
|
163
181
|
{/* PlayerImage */}
|
|
164
182
|
|
|
165
183
|
<View
|
|
166
|
-
style={
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
marginBottom: MOBILE.MARGIN_BOTTOM,
|
|
170
|
-
},
|
|
171
|
-
]}
|
|
184
|
+
style={{
|
|
185
|
+
height: controlsContainerHeight,
|
|
186
|
+
}}
|
|
172
187
|
>
|
|
173
188
|
<Controls
|
|
174
189
|
entry={entry}
|
|
@@ -177,10 +192,7 @@ export function MobileLayout({
|
|
|
177
192
|
value={value}
|
|
178
193
|
title={title}
|
|
179
194
|
summary={summary}
|
|
180
|
-
sleepTimerDate={sleepTimerDate}
|
|
181
|
-
cancelSleepTimer={cancelSleepTimer}
|
|
182
195
|
playbackSpeedName={playbackSpeedName}
|
|
183
|
-
playbackSleepName={playbackSleepName}
|
|
184
196
|
onPlaybackButtonPress={onPlaybackButtonPress}
|
|
185
197
|
onRewindButtonPress={onRewindButtonPress}
|
|
186
198
|
onForwardButtonPress={onForwardButtonPress}
|
|
@@ -188,7 +200,6 @@ export function MobileLayout({
|
|
|
188
200
|
onSkipStart={onSkipStart}
|
|
189
201
|
onSkipLive={onSkipLive}
|
|
190
202
|
onSpeedButtonPress={onSpeedButtonPress}
|
|
191
|
-
onSleepButtonPress={onSleepButtonPress}
|
|
192
203
|
docked={docked}
|
|
193
204
|
/>
|
|
194
205
|
</View>
|
|
@@ -199,7 +210,6 @@ export function MobileLayout({
|
|
|
199
210
|
layoutState={layoutState}
|
|
200
211
|
playerState={playerState}
|
|
201
212
|
value={value}
|
|
202
|
-
configuration={configuration}
|
|
203
213
|
dimensions={dimensions}
|
|
204
214
|
onCloseVideoModal={onCloseVideoModal}
|
|
205
215
|
onPlayerSeek={onPlayerSeek}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { Image, Animated, StyleSheet, ImageStyle } from "react-native";
|
|
3
3
|
|
|
4
|
-
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
5
4
|
import {
|
|
6
5
|
useModalAnimationContext,
|
|
7
6
|
PlayerAnimationStateEnum,
|
|
8
7
|
DURATION_TO_MINIMIZE,
|
|
9
8
|
DURATION_TO_MAXIMIZE,
|
|
10
9
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
10
|
+
import { PlayerAnimationStateT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
|
|
11
|
+
import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
|
|
12
|
+
|
|
13
|
+
import { useChangePlayerState } from "./hooks";
|
|
11
14
|
|
|
12
15
|
const styles = StyleSheet.create({
|
|
13
16
|
container: {
|
|
@@ -19,47 +22,50 @@ const styles = StyleSheet.create({
|
|
|
19
22
|
|
|
20
23
|
type Props = PropsWithChildren<{
|
|
21
24
|
entry: ZappEntry;
|
|
22
|
-
style?:
|
|
23
|
-
imageStyle?: { [K: string]: any };
|
|
25
|
+
style?: ImageStyle | ImageStyle[];
|
|
24
26
|
imageWidth: number;
|
|
27
|
+
docked: boolean;
|
|
25
28
|
}>;
|
|
26
29
|
|
|
27
|
-
export const AnimatedImage = ({
|
|
28
|
-
entry,
|
|
29
|
-
style,
|
|
30
|
-
imageStyle,
|
|
31
|
-
imageWidth,
|
|
32
|
-
}: Props) => {
|
|
30
|
+
export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
33
31
|
const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
|
|
34
32
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
33
|
+
const backgroundImageSource = useBackgroundImage(entry);
|
|
34
|
+
|
|
35
|
+
const { minimisedHeight } = useModalAnimationContext();
|
|
39
36
|
|
|
40
|
-
const {
|
|
37
|
+
const changePlayerState$ = useChangePlayerState({ docked });
|
|
41
38
|
|
|
42
39
|
React.useEffect(() => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
const subscription = changePlayerState$.subscribe({
|
|
41
|
+
next: (nextPlayerState: PlayerAnimationStateT) => {
|
|
42
|
+
if (nextPlayerState === PlayerAnimationStateEnum.minimize) {
|
|
43
|
+
Animated.timing(heightAnim, {
|
|
44
|
+
toValue: minimisedHeight,
|
|
45
|
+
duration: DURATION_TO_MINIMIZE,
|
|
46
|
+
useNativeDriver: false, // width/height can't use native driver
|
|
47
|
+
}).start();
|
|
48
|
+
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (nextPlayerState === PlayerAnimationStateEnum.maximize) {
|
|
51
|
+
Animated.timing(heightAnim, {
|
|
52
|
+
toValue: imageWidth,
|
|
53
|
+
duration: DURATION_TO_MAXIMIZE,
|
|
54
|
+
useNativeDriver: false, // width/height can't use native driver
|
|
55
|
+
}).start();
|
|
56
|
+
}
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
}, [playerAnimationState, imageWidth]);
|
|
58
|
+
if (nextPlayerState === PlayerAnimationStateEnum.appear_as_docked) {
|
|
59
|
+
// minimize image immediatly
|
|
60
|
+
heightAnim.setValue(minimisedHeight);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
return () => {
|
|
66
|
+
subscription.unsubscribe();
|
|
67
|
+
};
|
|
68
|
+
}, [changePlayerState$, minimisedHeight, imageWidth]);
|
|
63
69
|
|
|
64
70
|
return (
|
|
65
71
|
<Animated.View
|
|
@@ -70,14 +76,7 @@ export const AnimatedImage = ({
|
|
|
70
76
|
},
|
|
71
77
|
]}
|
|
72
78
|
>
|
|
73
|
-
<
|
|
74
|
-
resizeMode="cover"
|
|
75
|
-
style={style}
|
|
76
|
-
imageStyle={imageStyle}
|
|
77
|
-
source={source}
|
|
78
|
-
>
|
|
79
|
-
{null}
|
|
80
|
-
</ImageBackground>
|
|
79
|
+
<Image resizeMode="cover" style={style} source={backgroundImageSource} />
|
|
81
80
|
</Animated.View>
|
|
82
81
|
);
|
|
83
82
|
};
|