@applicaster/quick-brick-player 14.0.0-rc.9 → 15.0.0-alpha.1001559563
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 -11
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +25 -81
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +8 -18
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +119 -119
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +5 -38
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +3 -8
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +5 -9
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +22 -72
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +1 -58
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +0 -33
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +6 -18
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +1 -1
- package/src/Player/PlayerModal/GestureAnimatedScrollView.ts +7 -0
- package/src/Player/PlayerModal/PlayerModal.tsx +109 -0
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +271 -0
- package/src/Player/PlayerModal/consts/index.ts +34 -0
- package/src/Player/PlayerModal/context/index.ts +6 -0
- package/src/Player/PlayerModal/hooks/index.ts +193 -0
- package/src/Player/PlayerModal/index.ts +3 -0
- package/src/Player/PlayerModal/index.web.ts +5 -0
- package/src/Player/PlayerModal/styles.ts +104 -0
- package/src/Player/PlayerView/GenericTVPlayerView.tsx +42 -0
- package/src/Player/PlayerView/TVPlayerView.tsx +26 -0
- package/src/Player/PlayerView/TvOSPlayerView.tsx +51 -0
- package/src/Player/PlayerView/types.ts +42 -0
- package/src/Player/index.tsx +187 -190
- package/src/QuickBrickPlayer.tsx +16 -10
- /package/src/Player/AudioLayer/Layout/{Debug → DebugComponent}/index.tsx +0 -0
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
useSafeAreaFrame,
|
|
5
5
|
useSafeAreaInsets,
|
|
6
6
|
} from "react-native-safe-area-context";
|
|
7
|
-
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
7
|
|
|
9
8
|
import { MOBILE, NAVBAR_HEIGHT } from "./const";
|
|
10
9
|
import { TransportInfo } from "./TransportInfo";
|
|
@@ -12,13 +11,12 @@ import { PlayerImage } from "./PlayerImage";
|
|
|
12
11
|
import { Controls } from "./Controls";
|
|
13
12
|
|
|
14
13
|
import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
|
|
15
|
-
import { DockedControls } from "./DockedControls";
|
|
16
14
|
import { DEBUG, withDebug } from "./debug";
|
|
17
15
|
import {
|
|
18
16
|
BottomDebugSquare,
|
|
19
17
|
LeftDebugSquare,
|
|
20
18
|
RightDebugSquare,
|
|
21
|
-
} from "./
|
|
19
|
+
} from "./DebugComponent";
|
|
22
20
|
|
|
23
21
|
import { Props } from "./types";
|
|
24
22
|
|
|
@@ -56,6 +54,7 @@ const mobileStyles = ({
|
|
|
56
54
|
imageSize,
|
|
57
55
|
}): ViewStyle => ({
|
|
58
56
|
height: screenHeight - topInset - bottomInset,
|
|
57
|
+
width: "100%",
|
|
59
58
|
|
|
60
59
|
opacity: imageSize ? 1 : 0, // hide content until imageSize is calculated
|
|
61
60
|
|
|
@@ -77,11 +76,8 @@ export function MobileLayout({
|
|
|
77
76
|
onSkipStart,
|
|
78
77
|
onSkipLive,
|
|
79
78
|
onSpeedButtonPress,
|
|
80
|
-
onCloseVideoModal,
|
|
81
79
|
playbackSpeedName,
|
|
82
80
|
configuration,
|
|
83
|
-
dimensions,
|
|
84
|
-
playNextData,
|
|
85
81
|
title,
|
|
86
82
|
summary,
|
|
87
83
|
}: Props) {
|
|
@@ -89,12 +85,10 @@ export function MobileLayout({
|
|
|
89
85
|
|
|
90
86
|
const { bottom: bottomInset, top: topInset } = useSafeAreaInsets();
|
|
91
87
|
const { height: screenHeight } = useSafeAreaFrame();
|
|
92
|
-
const { progressBarHeight } = useModalAnimationContext();
|
|
93
88
|
|
|
94
89
|
const { imageSize } = useMobileLayoutImageSize();
|
|
95
90
|
|
|
96
|
-
const {
|
|
97
|
-
useTransportInfoHeight();
|
|
91
|
+
const { onLayout: onTransportInfoLayout } = useTransportInfoHeight();
|
|
98
92
|
|
|
99
93
|
const controlsContainerHeight = React.useMemo(() => {
|
|
100
94
|
return (
|
|
@@ -108,10 +102,6 @@ export function MobileLayout({
|
|
|
108
102
|
);
|
|
109
103
|
}, [screenHeight, topInset, imageSize, bottomInset]);
|
|
110
104
|
|
|
111
|
-
const verticalOffsetForImage = React.useMemo(() => {
|
|
112
|
-
return transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight;
|
|
113
|
-
}, [transportInfoHeight, progressBarHeight]);
|
|
114
|
-
|
|
115
105
|
return (
|
|
116
106
|
<View
|
|
117
107
|
style={[
|
|
@@ -163,19 +153,9 @@ export function MobileLayout({
|
|
|
163
153
|
>
|
|
164
154
|
<PlayerImage
|
|
165
155
|
entry={entry}
|
|
166
|
-
|
|
167
|
-
playerState={playerState}
|
|
168
|
-
value={value}
|
|
169
|
-
configuration={configuration}
|
|
170
|
-
onPlayerSeek={onPlayerSeek}
|
|
171
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
172
|
-
dimensions={dimensions}
|
|
173
|
-
playNextData={playNextData}
|
|
174
|
-
title={title}
|
|
175
|
-
summary={summary}
|
|
176
|
-
docked={docked}
|
|
156
|
+
docked={false}
|
|
177
157
|
imageWidth={imageSize}
|
|
178
|
-
|
|
158
|
+
configuration={configuration}
|
|
179
159
|
/>
|
|
180
160
|
</View>
|
|
181
161
|
{/* PlayerImage */}
|
|
@@ -204,19 +184,6 @@ export function MobileLayout({
|
|
|
204
184
|
/>
|
|
205
185
|
</View>
|
|
206
186
|
</View>
|
|
207
|
-
|
|
208
|
-
<DockedControls
|
|
209
|
-
entry={entry}
|
|
210
|
-
layoutState={layoutState}
|
|
211
|
-
playerState={playerState}
|
|
212
|
-
value={value}
|
|
213
|
-
dimensions={dimensions}
|
|
214
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
215
|
-
onPlayerSeek={onPlayerSeek}
|
|
216
|
-
playNextData={playNextData}
|
|
217
|
-
title={title}
|
|
218
|
-
summary={summary}
|
|
219
|
-
/>
|
|
220
187
|
</View>
|
|
221
188
|
);
|
|
222
189
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
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,
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
DURATION_TO_MAXIMIZE,
|
|
10
9
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
11
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
12
|
|
|
13
13
|
import { useChangePlayerState } from "./hooks";
|
|
14
14
|
|
|
@@ -30,10 +30,7 @@ type Props = PropsWithChildren<{
|
|
|
30
30
|
export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
31
31
|
const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
|
|
32
32
|
|
|
33
|
-
const
|
|
34
|
-
() => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
|
|
35
|
-
[entry]
|
|
36
|
-
);
|
|
33
|
+
const backgroundImageSource = useBackgroundImage(entry);
|
|
37
34
|
|
|
38
35
|
const { minimisedHeight } = useModalAnimationContext();
|
|
39
36
|
|
|
@@ -70,8 +67,6 @@ export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
|
70
67
|
};
|
|
71
68
|
}, [changePlayerState$, minimisedHeight, imageWidth]);
|
|
72
69
|
|
|
73
|
-
if (!source) return null;
|
|
74
|
-
|
|
75
70
|
return (
|
|
76
71
|
<Animated.View
|
|
77
72
|
style={[
|
|
@@ -81,7 +76,7 @@ export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
|
81
76
|
},
|
|
82
77
|
]}
|
|
83
78
|
>
|
|
84
|
-
<Image resizeMode="cover" style={style} source={
|
|
79
|
+
<Image resizeMode="cover" style={style} source={backgroundImageSource} />
|
|
85
80
|
</Animated.View>
|
|
86
81
|
);
|
|
87
82
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Image, ImageStyle } from "react-native";
|
|
3
|
-
|
|
4
|
-
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
3
|
+
import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
|
|
5
4
|
|
|
6
5
|
type Props = {
|
|
7
6
|
entry: ZappEntry;
|
|
@@ -9,12 +8,9 @@ type Props = {
|
|
|
9
8
|
};
|
|
10
9
|
|
|
11
10
|
export const FlexImage = ({ entry, style }: Props) => {
|
|
12
|
-
const
|
|
13
|
-
() => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
|
|
14
|
-
[entry]
|
|
15
|
-
);
|
|
11
|
+
const backgroundImageSource = useBackgroundImage(entry);
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
return (
|
|
14
|
+
<Image resizeMode="cover" style={style} source={backgroundImageSource} />
|
|
15
|
+
);
|
|
20
16
|
};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { LayoutChangeEvent, View } from "react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
AnimationComponent,
|
|
6
|
-
ComponentAnimationType,
|
|
7
|
-
useModalAnimationContext,
|
|
8
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
9
4
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
10
5
|
import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
11
6
|
|
|
@@ -13,100 +8,55 @@ import { AnimatedImage } from "./AnimatedImage";
|
|
|
13
8
|
import { FlexImage } from "./FlexImage";
|
|
14
9
|
|
|
15
10
|
import { styles } from "./styles";
|
|
16
|
-
import {
|
|
17
|
-
import { PlayNextData } from "../types";
|
|
11
|
+
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
18
12
|
|
|
19
13
|
type Props = {
|
|
20
14
|
entry: ZappEntry;
|
|
21
|
-
layoutState: QuickBrickPlayer.LayoutState;
|
|
22
|
-
playerState: QuickBrickPlayer.PlayerState;
|
|
23
|
-
value: GetValue;
|
|
24
15
|
configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
|
|
25
|
-
dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
|
|
26
|
-
onCloseVideoModal: Callback;
|
|
27
|
-
onPlayerSeek: (targetTime: number) => void;
|
|
28
|
-
playNextData: PlayNextData;
|
|
29
|
-
title: string | number;
|
|
30
|
-
summary: string | number;
|
|
31
16
|
docked: boolean;
|
|
32
17
|
imageWidth?: Option<number>;
|
|
33
|
-
verticalOffset: number;
|
|
34
18
|
onLayoutImage?: (event: LayoutChangeEvent) => void;
|
|
35
19
|
};
|
|
36
20
|
|
|
37
21
|
export const PlayerImage = (props: Props) => {
|
|
38
22
|
const {
|
|
39
23
|
entry,
|
|
40
|
-
dimensions,
|
|
41
24
|
docked,
|
|
42
|
-
verticalOffset,
|
|
43
25
|
imageWidth,
|
|
44
26
|
configuration,
|
|
45
27
|
onLayoutImage = noop,
|
|
46
28
|
} = props;
|
|
47
29
|
|
|
48
|
-
const {
|
|
49
|
-
isActiveGesture,
|
|
50
|
-
startComponentsAnimation,
|
|
51
|
-
playerAnimationState,
|
|
52
|
-
minimisedHeight,
|
|
53
|
-
} = useModalAnimationContext();
|
|
54
|
-
|
|
55
30
|
const isShadowEnabled = toBooleanWithDefaultTrue(
|
|
56
31
|
configuration?.audio_player_artwork_shadow_enabled
|
|
57
32
|
);
|
|
58
33
|
|
|
59
34
|
const shouldShowShadow = !docked && isShadowEnabled;
|
|
60
35
|
|
|
61
|
-
const borderRadius =
|
|
62
|
-
|
|
63
|
-
startComponentsAnimation,
|
|
64
|
-
isActiveGesture,
|
|
65
|
-
playerAnimationState,
|
|
66
|
-
configuration
|
|
36
|
+
const borderRadius = toNumberWithDefaultZero(
|
|
37
|
+
configuration.audio_player_artwork_border_radius
|
|
67
38
|
);
|
|
68
39
|
|
|
69
40
|
return (
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}}
|
|
75
|
-
style={styles.flex}
|
|
76
|
-
>
|
|
77
|
-
<AnimationComponent
|
|
78
|
-
animationType={ComponentAnimationType.moveComponentHorizontal}
|
|
79
|
-
additionalData={{
|
|
80
|
-
// we move image horiontally to this value due artwork is centered
|
|
81
|
-
moveValue: (dimensions.width - minimisedHeight) / 2,
|
|
82
|
-
}}
|
|
83
|
-
style={styles.alignItemsCenter}
|
|
41
|
+
<View style={styles.alignItemsCenter}>
|
|
42
|
+
<View
|
|
43
|
+
onLayout={onLayoutImage}
|
|
44
|
+
style={[shouldShowShadow ? styles.shadow : undefined, { borderRadius }]}
|
|
84
45
|
>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// we have imageSize here and now we could animate resizing of this image
|
|
101
|
-
<AnimatedImage
|
|
102
|
-
entry={entry}
|
|
103
|
-
style={[styles.backgroundImageContainer, { borderRadius }]}
|
|
104
|
-
imageWidth={imageWidth}
|
|
105
|
-
docked={docked}
|
|
106
|
-
/>
|
|
107
|
-
)}
|
|
108
|
-
</View>
|
|
109
|
-
</AnimationComponent>
|
|
110
|
-
</AnimationComponent>
|
|
46
|
+
{!imageWidth ? (
|
|
47
|
+
<View style={[styles.defaultImageWrapperView, { borderRadius }]}>
|
|
48
|
+
<FlexImage entry={entry} style={styles.backgroundImageContainer} />
|
|
49
|
+
</View>
|
|
50
|
+
) : (
|
|
51
|
+
// we have imageSize here and now we could animate resizing of this image
|
|
52
|
+
<AnimatedImage
|
|
53
|
+
entry={entry}
|
|
54
|
+
style={[styles.backgroundImageContainer, { borderRadius }]}
|
|
55
|
+
imageWidth={imageWidth}
|
|
56
|
+
docked={docked}
|
|
57
|
+
/>
|
|
58
|
+
)}
|
|
59
|
+
</View>
|
|
60
|
+
</View>
|
|
111
61
|
);
|
|
112
62
|
};
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { StyleSheet, View } from "react-native";
|
|
3
|
-
import {
|
|
4
|
-
useSafeAreaFrame,
|
|
5
|
-
useSafeAreaInsets,
|
|
6
|
-
} from "react-native-safe-area-context";
|
|
7
|
-
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
|
-
import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
|
+
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
9
4
|
|
|
10
5
|
import { TransportInfo } from "./TransportInfo";
|
|
11
6
|
import { PlayerImage } from "./PlayerImage";
|
|
12
7
|
import { Controls } from "./Controls";
|
|
13
8
|
|
|
14
|
-
import { DockedControls } from "./DockedControls";
|
|
15
9
|
import { withDebug } from "./debug";
|
|
16
10
|
|
|
17
11
|
import { Props } from "./types";
|
|
18
12
|
import { isSmallTabletHeight as getIsSmallTabletHeight } from "./utils";
|
|
19
13
|
import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "./const";
|
|
20
|
-
import { FlexImage } from "./PlayerImage/FlexImage";
|
|
21
|
-
|
|
22
|
-
const isIOS = isApplePlatform();
|
|
23
14
|
|
|
24
15
|
const MIN_WIDTH = TABLET_LANDSCAPE.MIN_WIDTH; // Minimum width for the audio player container
|
|
25
16
|
const MAX_SPACING = TABLET_LANDSCAPE.MARGIN_VERTICAL; // Maximum spacing for the audio player container
|
|
@@ -70,22 +61,6 @@ const styles = StyleSheet.create({
|
|
|
70
61
|
},
|
|
71
62
|
});
|
|
72
63
|
|
|
73
|
-
const isTabletWithHomeButton = (bottomInset: number): boolean =>
|
|
74
|
-
bottomInset === 0;
|
|
75
|
-
|
|
76
|
-
const withAdditionalOffset = ({ progressBarHeight, bottomInset }) => {
|
|
77
|
-
if (isIOS && isTabletWithHomeButton(bottomInset)) {
|
|
78
|
-
return progressBarHeight === 0 ? 8 : progressBarHeight + 2;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (isIOS && !isTabletWithHomeButton(bottomInset)) {
|
|
82
|
-
return progressBarHeight === 0 ? 4 : 1;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// android
|
|
86
|
-
return progressBarHeight === 0 ? 4 : 0.5;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
64
|
export function TabletLandscapeLayout({
|
|
90
65
|
entry,
|
|
91
66
|
layoutState,
|
|
@@ -98,21 +73,16 @@ export function TabletLandscapeLayout({
|
|
|
98
73
|
onSkipStart,
|
|
99
74
|
onSkipLive,
|
|
100
75
|
onSpeedButtonPress,
|
|
101
|
-
onCloseVideoModal,
|
|
102
76
|
playbackSpeedName,
|
|
103
77
|
configuration,
|
|
104
|
-
dimensions,
|
|
105
|
-
playNextData,
|
|
106
78
|
title,
|
|
107
79
|
summary,
|
|
108
80
|
}: Props) {
|
|
109
81
|
const [imageWidth, setImageWidth] = React.useState(0);
|
|
110
82
|
const { docked } = layoutState;
|
|
111
83
|
|
|
112
|
-
const { bottom: bottomInset } = useSafeAreaInsets();
|
|
113
84
|
const { height: screenHeight } = useSafeAreaFrame();
|
|
114
85
|
const isSmallScreen = getIsSmallTabletHeight(screenHeight);
|
|
115
|
-
const { progressBarHeight } = useModalAnimationContext();
|
|
116
86
|
|
|
117
87
|
const onLayoutImage = React.useCallback((e) => {
|
|
118
88
|
setImageWidth(e.nativeEvent.layout.width);
|
|
@@ -151,20 +121,7 @@ export function TabletLandscapeLayout({
|
|
|
151
121
|
<PlayerImage
|
|
152
122
|
docked={false}
|
|
153
123
|
entry={entry}
|
|
154
|
-
layoutState={layoutState}
|
|
155
|
-
playerState={playerState}
|
|
156
|
-
value={value}
|
|
157
124
|
configuration={configuration}
|
|
158
|
-
onPlayerSeek={onPlayerSeek}
|
|
159
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
160
|
-
dimensions={dimensions}
|
|
161
|
-
playNextData={playNextData}
|
|
162
|
-
title={title}
|
|
163
|
-
summary={summary}
|
|
164
|
-
verticalOffset={withAdditionalOffset({
|
|
165
|
-
progressBarHeight,
|
|
166
|
-
bottomInset,
|
|
167
|
-
})}
|
|
168
125
|
onLayoutImage={onLayoutImage}
|
|
169
126
|
/>
|
|
170
127
|
) : null}
|
|
@@ -193,20 +150,6 @@ export function TabletLandscapeLayout({
|
|
|
193
150
|
</View>
|
|
194
151
|
</View>
|
|
195
152
|
</View>
|
|
196
|
-
|
|
197
|
-
<DockedControls
|
|
198
|
-
ImageComponent={<FlexImage entry={entry} style={styles.flex} />}
|
|
199
|
-
entry={entry}
|
|
200
|
-
layoutState={layoutState}
|
|
201
|
-
playerState={playerState}
|
|
202
|
-
value={value}
|
|
203
|
-
dimensions={dimensions}
|
|
204
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
205
|
-
onPlayerSeek={onPlayerSeek}
|
|
206
|
-
playNextData={playNextData}
|
|
207
|
-
title={title}
|
|
208
|
-
summary={summary}
|
|
209
|
-
/>
|
|
210
153
|
</View>
|
|
211
154
|
);
|
|
212
155
|
}
|
|
@@ -4,8 +4,6 @@ import {
|
|
|
4
4
|
useSafeAreaFrame,
|
|
5
5
|
useSafeAreaInsets,
|
|
6
6
|
} from "react-native-safe-area-context";
|
|
7
|
-
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
|
-
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
9
7
|
|
|
10
8
|
import { withDebug } from "./debug";
|
|
11
9
|
import { TABLET_PORTRAIT } from "./const";
|
|
@@ -15,7 +13,6 @@ import { PlayerImage } from "./PlayerImage";
|
|
|
15
13
|
import { Controls } from "./Controls";
|
|
16
14
|
|
|
17
15
|
import { useTabletLayoutImageSize } from "./hooks";
|
|
18
|
-
import { DockedControls } from "./DockedControls";
|
|
19
16
|
import { VerticalGutter } from "./VerticalGutter";
|
|
20
17
|
|
|
21
18
|
import { Props } from "./types";
|
|
@@ -82,11 +79,8 @@ export function TabletPortraitLayout({
|
|
|
82
79
|
onSkipStart,
|
|
83
80
|
onSkipLive,
|
|
84
81
|
onSpeedButtonPress,
|
|
85
|
-
onCloseVideoModal,
|
|
86
82
|
playbackSpeedName,
|
|
87
83
|
configuration,
|
|
88
|
-
dimensions,
|
|
89
|
-
playNextData,
|
|
90
84
|
title,
|
|
91
85
|
summary,
|
|
92
86
|
}: Props) {
|
|
@@ -94,7 +88,6 @@ export function TabletPortraitLayout({
|
|
|
94
88
|
|
|
95
89
|
const { bottom: bottomInset, top: topInset } = useSafeAreaInsets();
|
|
96
90
|
const { height: screenHeight } = useSafeAreaFrame();
|
|
97
|
-
const { progressBarHeight } = useModalAnimationContext();
|
|
98
91
|
|
|
99
92
|
const {
|
|
100
93
|
imageSize,
|
|
@@ -153,21 +146,9 @@ export function TabletPortraitLayout({
|
|
|
153
146
|
>
|
|
154
147
|
<PlayerImage
|
|
155
148
|
entry={entry}
|
|
156
|
-
layoutState={layoutState}
|
|
157
|
-
playerState={playerState}
|
|
158
|
-
value={value}
|
|
159
149
|
configuration={configuration}
|
|
160
|
-
onPlayerSeek={onPlayerSeek}
|
|
161
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
162
|
-
dimensions={dimensions}
|
|
163
|
-
playNextData={playNextData}
|
|
164
|
-
title={title}
|
|
165
|
-
summary={summary}
|
|
166
150
|
docked={docked}
|
|
167
151
|
imageWidth={imageSize}
|
|
168
|
-
verticalOffset={
|
|
169
|
-
toNumberWithDefaultZero(topOffset) - progressBarHeight
|
|
170
|
-
}
|
|
171
152
|
/>
|
|
172
153
|
</View>
|
|
173
154
|
|
|
@@ -196,20 +177,6 @@ export function TabletPortraitLayout({
|
|
|
196
177
|
</View>
|
|
197
178
|
</View>
|
|
198
179
|
</View>
|
|
199
|
-
{/* PlayerImage */}
|
|
200
|
-
|
|
201
|
-
<DockedControls
|
|
202
|
-
entry={entry}
|
|
203
|
-
layoutState={layoutState}
|
|
204
|
-
playerState={playerState}
|
|
205
|
-
value={value}
|
|
206
|
-
dimensions={dimensions}
|
|
207
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
208
|
-
onPlayerSeek={onPlayerSeek}
|
|
209
|
-
playNextData={playNextData}
|
|
210
|
-
title={title}
|
|
211
|
-
summary={summary}
|
|
212
|
-
/>
|
|
213
180
|
</View>
|
|
214
181
|
);
|
|
215
182
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { compose, map, propOr, split, take, trim } from "ramda";
|
|
3
2
|
import { LayoutChangeEvent, StyleSheet, View } from "react-native";
|
|
4
3
|
|
|
5
4
|
import { TransportInfo as MobileTransportInfo } from "@applicaster/quick-brick-mobile-transport-controls";
|
|
6
5
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
7
6
|
import { useLanguageData } from "@applicaster/zapp-react-native-utils/reactHooks/player";
|
|
8
|
-
|
|
9
|
-
AnimationComponent,
|
|
10
|
-
ComponentAnimationType,
|
|
11
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
7
|
+
|
|
12
8
|
import { toPositiveNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
13
9
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
14
10
|
|
|
@@ -16,6 +12,7 @@ import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "../const";
|
|
|
16
12
|
import { withDebug } from "../debug";
|
|
17
13
|
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
18
14
|
import { isSmallTabletHeight } from "../utils";
|
|
15
|
+
import { getPlayerActionButtons } from "@applicaster/zapp-react-native-utils/playerUtils";
|
|
19
16
|
|
|
20
17
|
const styles = StyleSheet.create({
|
|
21
18
|
container: {
|
|
@@ -85,14 +82,8 @@ export const TransportInfo = ({
|
|
|
85
82
|
);
|
|
86
83
|
|
|
87
84
|
const actionButtons = React.useMemo(
|
|
88
|
-
() =>
|
|
89
|
-
|
|
90
|
-
take(2),
|
|
91
|
-
map(trim),
|
|
92
|
-
split(","),
|
|
93
|
-
propOr("", "player_action_buttons")
|
|
94
|
-
)(configuration),
|
|
95
|
-
[configuration.player_action_buttons]
|
|
85
|
+
() => getPlayerActionButtons(configuration),
|
|
86
|
+
[configuration]
|
|
96
87
|
);
|
|
97
88
|
|
|
98
89
|
return (
|
|
@@ -110,10 +101,7 @@ export const TransportInfo = ({
|
|
|
110
101
|
]}
|
|
111
102
|
onLayout={handleLayout}
|
|
112
103
|
>
|
|
113
|
-
<
|
|
114
|
-
animationType={ComponentAnimationType.componentFade}
|
|
115
|
-
style={styles.animatedContainer}
|
|
116
|
-
>
|
|
104
|
+
<View style={styles.animatedContainer}>
|
|
117
105
|
<MobileTransportInfo
|
|
118
106
|
content={entry}
|
|
119
107
|
value={value}
|
|
@@ -122,7 +110,7 @@ export const TransportInfo = ({
|
|
|
122
110
|
layoutState={layoutState}
|
|
123
111
|
actionButtons={actionButtons}
|
|
124
112
|
/>
|
|
125
|
-
</
|
|
113
|
+
</View>
|
|
126
114
|
</View>
|
|
127
115
|
);
|
|
128
116
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ModalHeader } from "@applicaster/zapp-react-native-ui-components/Components/ModalComponent/Header";
|
|
3
|
-
import { isNil } from "
|
|
3
|
+
import { isNil } from "@applicaster/zapp-react-native-utils/utils";
|
|
4
4
|
|
|
5
5
|
const formatTime = (milliseconds: number) => {
|
|
6
6
|
const totalSeconds = Math.floor(milliseconds / 1000);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { ReactElement } from "react";
|
|
2
|
+
|
|
3
|
+
import { Animated, Pressable } from "react-native";
|
|
4
|
+
import { PanGestureHandler } from "react-native-gesture-handler";
|
|
5
|
+
import { useStyles } from "./styles";
|
|
6
|
+
import { useVideoModalState } from "./hooks";
|
|
7
|
+
import { MODAL_COLLAPSE_START, MODAL_RADIUS, SCREEN_HEIGHT } from "./consts";
|
|
8
|
+
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
9
|
+
|
|
10
|
+
type AnimatedModalProps = {
|
|
11
|
+
content?: ReactElement;
|
|
12
|
+
collapsedContent?: ReactElement;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function AnimatedModal({
|
|
16
|
+
content,
|
|
17
|
+
collapsedContent,
|
|
18
|
+
}: AnimatedModalProps) {
|
|
19
|
+
const translateYRef = useModalAnimationContext().yTranslate;
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
translateY,
|
|
23
|
+
collapsed,
|
|
24
|
+
collapsedHeight,
|
|
25
|
+
gestureHandlerProps,
|
|
26
|
+
expand,
|
|
27
|
+
} = useVideoModalState(translateYRef);
|
|
28
|
+
|
|
29
|
+
const styles = useStyles({ height: collapsedHeight, type: "audio" });
|
|
30
|
+
|
|
31
|
+
// Interpolated opacities for smooth cross-fade
|
|
32
|
+
const collapsedOpacity = translateY.interpolate({
|
|
33
|
+
inputRange: [MODAL_COLLAPSE_START, SCREEN_HEIGHT - collapsedHeight],
|
|
34
|
+
outputRange: [0, 1],
|
|
35
|
+
extrapolate: "clamp",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const expandedOpacity = translateY.interpolate({
|
|
39
|
+
inputRange: [0, SCREEN_HEIGHT - collapsedHeight],
|
|
40
|
+
outputRange: [1, 0],
|
|
41
|
+
extrapolate: "clamp",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const borderTopRadiusAnimated = translateY.interpolate({
|
|
45
|
+
inputRange: [0, SCREEN_HEIGHT - collapsedHeight],
|
|
46
|
+
outputRange: [MODAL_RADIUS, 0],
|
|
47
|
+
extrapolate: "clamp",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<PanGestureHandler {...gestureHandlerProps}>
|
|
52
|
+
<Animated.View
|
|
53
|
+
pointerEvents={"auto"}
|
|
54
|
+
style={[
|
|
55
|
+
styles.modalWrapper,
|
|
56
|
+
{
|
|
57
|
+
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
58
|
+
borderTopRightRadius: borderTopRadiusAnimated,
|
|
59
|
+
transform: [{ translateY }],
|
|
60
|
+
height: SCREEN_HEIGHT,
|
|
61
|
+
},
|
|
62
|
+
]}
|
|
63
|
+
>
|
|
64
|
+
<Animated.View
|
|
65
|
+
style={[
|
|
66
|
+
styles.modal,
|
|
67
|
+
{
|
|
68
|
+
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
69
|
+
borderTopRightRadius: borderTopRadiusAnimated,
|
|
70
|
+
height: SCREEN_HEIGHT,
|
|
71
|
+
},
|
|
72
|
+
]}
|
|
73
|
+
>
|
|
74
|
+
{/* Expanded Content (fades in) */}
|
|
75
|
+
<Animated.View
|
|
76
|
+
pointerEvents={!collapsed ? "auto" : "none"}
|
|
77
|
+
style={styles.modalContent}
|
|
78
|
+
>
|
|
79
|
+
<Animated.View
|
|
80
|
+
pointerEvents={!collapsed ? "auto" : "none"}
|
|
81
|
+
style={[
|
|
82
|
+
styles.expandedContentContainer,
|
|
83
|
+
{ opacity: expandedOpacity },
|
|
84
|
+
]}
|
|
85
|
+
>
|
|
86
|
+
{content}
|
|
87
|
+
</Animated.View>
|
|
88
|
+
</Animated.View>
|
|
89
|
+
{/* Collapsed Bar (fades out) */}
|
|
90
|
+
<Animated.View
|
|
91
|
+
pointerEvents={collapsed ? "box-none" : "none"}
|
|
92
|
+
style={[
|
|
93
|
+
styles.collapsedBarContainer,
|
|
94
|
+
{ opacity: collapsedOpacity },
|
|
95
|
+
]}
|
|
96
|
+
>
|
|
97
|
+
<Pressable
|
|
98
|
+
testID="collapsedBarWrapper"
|
|
99
|
+
onPress={expand}
|
|
100
|
+
style={styles.collapsedBarWrapper}
|
|
101
|
+
>
|
|
102
|
+
{collapsedContent}
|
|
103
|
+
</Pressable>
|
|
104
|
+
</Animated.View>
|
|
105
|
+
</Animated.View>
|
|
106
|
+
</Animated.View>
|
|
107
|
+
</PanGestureHandler>
|
|
108
|
+
);
|
|
109
|
+
}
|