@applicaster/quick-brick-player 14.0.0-alpha.3552323332 → 14.0.0-alpha.3890252181
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 -9
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +5 -6
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +4 -22
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +48 -8
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +5 -9
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +1 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +1 -42
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +0 -33
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +3 -9
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +1 -1
- package/src/Player/PlayerModal/GestureAnimatedScrollView.ts +7 -0
- package/src/Player/PlayerModal/PlayerModal.tsx +10 -11
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +21 -29
- package/src/Player/PlayerModal/consts/index.ts +20 -6
- package/src/Player/PlayerModal/hooks/index.ts +9 -16
- package/src/Player/PlayerModal/styles.ts +10 -4
- package/src/Player/PlayerView/GenericTVPlayerView.tsx +1 -2
- package/src/Player/index.tsx +2 -8
- /package/src/Player/AudioLayer/Layout/{Debug → DebugComponent}/index.tsx +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.3890252181",
|
|
4
4
|
"description": "Quick Brick Player",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -35,13 +35,12 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@applicaster/quick-brick-mobile-transport-controls": "14.0.0-
|
|
39
|
-
"@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.
|
|
40
|
-
"@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "14.0.0-alpha.
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "14.0.0-rc.34",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.34",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.3890252181",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.3890252181",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "14.0.0-alpha.3890252181",
|
|
43
43
|
"query-string": "7.1.3",
|
|
44
|
-
"react-native-web-linear-gradient": "1.1.2",
|
|
45
44
|
"shaka-player": "4.3.5",
|
|
46
45
|
"typeface-montserrat": "^0.0.54",
|
|
47
46
|
"video.js": "7.14.3",
|
|
@@ -62,11 +61,9 @@
|
|
|
62
61
|
"react": "*",
|
|
63
62
|
"react-native": "*",
|
|
64
63
|
"react-native-fs": "*",
|
|
65
|
-
"react-native-gesture-handler": "*",
|
|
66
64
|
"react-native-linear-gradient": "*",
|
|
67
65
|
"react-native-safe-area-context": "*",
|
|
68
66
|
"react-native-svg": "*",
|
|
69
|
-
"react-native-web": "*",
|
|
70
67
|
"react-native-webview": "*",
|
|
71
68
|
"uglify-js": "*",
|
|
72
69
|
"validate-color": "*",
|
|
@@ -22,6 +22,8 @@ import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks
|
|
|
22
22
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
23
23
|
import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
|
|
24
24
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
25
|
+
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
26
|
+
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
25
27
|
|
|
26
28
|
const bottomTabBarHeight = getTabBarHeight();
|
|
27
29
|
|
|
@@ -38,7 +40,6 @@ type Props = {
|
|
|
38
40
|
ImageComponent?: React.ReactNode;
|
|
39
41
|
isActiveGesture?: boolean;
|
|
40
42
|
minimisedHeight: number;
|
|
41
|
-
progressBarHeight: number;
|
|
42
43
|
aspectRatio?: number;
|
|
43
44
|
};
|
|
44
45
|
|
|
@@ -47,7 +48,7 @@ const styles = StyleSheet.create({
|
|
|
47
48
|
flex: 1,
|
|
48
49
|
flexDirection: "column",
|
|
49
50
|
alignItems: "stretch",
|
|
50
|
-
marginTop:
|
|
51
|
+
marginTop: PROGRESS_BAR_HEIGHT,
|
|
51
52
|
},
|
|
52
53
|
content: {
|
|
53
54
|
flex: 1,
|
|
@@ -160,7 +161,7 @@ export const DockedControls = (props: Props) => {
|
|
|
160
161
|
const {
|
|
161
162
|
entry,
|
|
162
163
|
layoutState,
|
|
163
|
-
onPlayerSeek,
|
|
164
|
+
onPlayerSeek = noop,
|
|
164
165
|
playNextData,
|
|
165
166
|
ImageComponent,
|
|
166
167
|
isActiveGesture = true,
|
|
@@ -210,8 +211,6 @@ export const DockedControls = (props: Props) => {
|
|
|
210
211
|
|
|
211
212
|
const liveButton = Boolean(value("live_badge_enabled"));
|
|
212
213
|
|
|
213
|
-
const startComponentsAnimation = () => {};
|
|
214
|
-
|
|
215
214
|
const dockedBackgroundColor = value("docked_player_background_color");
|
|
216
215
|
|
|
217
216
|
const insets = useSafeAreaInsets();
|
|
@@ -234,7 +233,7 @@ export const DockedControls = (props: Props) => {
|
|
|
234
233
|
layoutState={layoutState}
|
|
235
234
|
onPlayerSeek={onPlayerSeek}
|
|
236
235
|
playerState={playerState}
|
|
237
|
-
startComponentsAnimation={
|
|
236
|
+
startComponentsAnimation={noop}
|
|
238
237
|
docked
|
|
239
238
|
/>
|
|
240
239
|
) : null}
|
|
@@ -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";
|
|
@@ -17,7 +16,7 @@ import {
|
|
|
17
16
|
BottomDebugSquare,
|
|
18
17
|
LeftDebugSquare,
|
|
19
18
|
RightDebugSquare,
|
|
20
|
-
} from "./
|
|
19
|
+
} from "./DebugComponent";
|
|
21
20
|
|
|
22
21
|
import { Props } from "./types";
|
|
23
22
|
|
|
@@ -79,8 +78,6 @@ export function MobileLayout({
|
|
|
79
78
|
onSpeedButtonPress,
|
|
80
79
|
playbackSpeedName,
|
|
81
80
|
configuration,
|
|
82
|
-
dimensions,
|
|
83
|
-
playNextData,
|
|
84
81
|
title,
|
|
85
82
|
summary,
|
|
86
83
|
}: Props) {
|
|
@@ -88,12 +85,10 @@ export function MobileLayout({
|
|
|
88
85
|
|
|
89
86
|
const { bottom: bottomInset, top: topInset } = useSafeAreaInsets();
|
|
90
87
|
const { height: screenHeight } = useSafeAreaFrame();
|
|
91
|
-
const { progressBarHeight } = useModalAnimationContext();
|
|
92
88
|
|
|
93
89
|
const { imageSize } = useMobileLayoutImageSize();
|
|
94
90
|
|
|
95
|
-
const {
|
|
96
|
-
useTransportInfoHeight();
|
|
91
|
+
const { onLayout: onTransportInfoLayout } = useTransportInfoHeight();
|
|
97
92
|
|
|
98
93
|
const controlsContainerHeight = React.useMemo(() => {
|
|
99
94
|
return (
|
|
@@ -107,10 +102,6 @@ export function MobileLayout({
|
|
|
107
102
|
);
|
|
108
103
|
}, [screenHeight, topInset, imageSize, bottomInset]);
|
|
109
104
|
|
|
110
|
-
const verticalOffsetForImage = React.useMemo(() => {
|
|
111
|
-
return transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight;
|
|
112
|
-
}, [transportInfoHeight, progressBarHeight]);
|
|
113
|
-
|
|
114
105
|
return (
|
|
115
106
|
<View
|
|
116
107
|
style={[
|
|
@@ -162,18 +153,9 @@ export function MobileLayout({
|
|
|
162
153
|
>
|
|
163
154
|
<PlayerImage
|
|
164
155
|
entry={entry}
|
|
165
|
-
|
|
166
|
-
playerState={playerState}
|
|
167
|
-
value={value}
|
|
168
|
-
configuration={configuration}
|
|
169
|
-
onPlayerSeek={onPlayerSeek}
|
|
170
|
-
dimensions={dimensions}
|
|
171
|
-
playNextData={playNextData}
|
|
172
|
-
title={title}
|
|
173
|
-
summary={summary}
|
|
174
|
-
docked={docked}
|
|
156
|
+
docked={false}
|
|
175
157
|
imageWidth={imageSize}
|
|
176
|
-
|
|
158
|
+
configuration={configuration}
|
|
177
159
|
/>
|
|
178
160
|
</View>
|
|
179
161
|
{/* PlayerImage */}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
2
|
import { Image, Animated, StyleSheet, ImageStyle } from "react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useModalAnimationContext,
|
|
6
|
+
PlayerAnimationStateEnum,
|
|
7
|
+
DURATION_TO_MINIMIZE,
|
|
8
|
+
DURATION_TO_MAXIMIZE,
|
|
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";
|
|
5
14
|
|
|
6
15
|
const styles = StyleSheet.create({
|
|
7
16
|
container: {
|
|
@@ -15,17 +24,48 @@ type Props = PropsWithChildren<{
|
|
|
15
24
|
entry: ZappEntry;
|
|
16
25
|
style?: ImageStyle | ImageStyle[];
|
|
17
26
|
imageWidth: number;
|
|
27
|
+
docked: boolean;
|
|
18
28
|
}>;
|
|
19
29
|
|
|
20
|
-
export const AnimatedImage = ({ entry, style, imageWidth }: Props) => {
|
|
30
|
+
export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
21
31
|
const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
|
|
22
32
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
const backgroundImageSource = useBackgroundImage(entry);
|
|
34
|
+
|
|
35
|
+
const { minimisedHeight } = useModalAnimationContext();
|
|
36
|
+
|
|
37
|
+
const changePlayerState$ = useChangePlayerState({ docked });
|
|
38
|
+
|
|
39
|
+
React.useEffect(() => {
|
|
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
|
+
|
|
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
|
+
}
|
|
57
|
+
|
|
58
|
+
if (nextPlayerState === PlayerAnimationStateEnum.appear_as_docked) {
|
|
59
|
+
// minimize image immediatly
|
|
60
|
+
heightAnim.setValue(minimisedHeight);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|
|
27
64
|
|
|
28
|
-
|
|
65
|
+
return () => {
|
|
66
|
+
subscription.unsubscribe();
|
|
67
|
+
};
|
|
68
|
+
}, [changePlayerState$, minimisedHeight, imageWidth]);
|
|
29
69
|
|
|
30
70
|
return (
|
|
31
71
|
<Animated.View
|
|
@@ -36,7 +76,7 @@ export const AnimatedImage = ({ entry, style, imageWidth }: Props) => {
|
|
|
36
76
|
},
|
|
37
77
|
]}
|
|
38
78
|
>
|
|
39
|
-
<Image resizeMode="cover" style={style} source={
|
|
79
|
+
<Image resizeMode="cover" style={style} source={backgroundImageSource} />
|
|
40
80
|
</Animated.View>
|
|
41
81
|
);
|
|
42
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 { 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";
|
|
@@ -17,8 +12,6 @@ import { Props } from "./types";
|
|
|
17
12
|
import { isSmallTabletHeight as getIsSmallTabletHeight } from "./utils";
|
|
18
13
|
import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "./const";
|
|
19
14
|
|
|
20
|
-
const isIOS = isApplePlatform();
|
|
21
|
-
|
|
22
15
|
const MIN_WIDTH = TABLET_LANDSCAPE.MIN_WIDTH; // Minimum width for the audio player container
|
|
23
16
|
const MAX_SPACING = TABLET_LANDSCAPE.MARGIN_VERTICAL; // Maximum spacing for the audio player container
|
|
24
17
|
const MIN_SPACING = TABLET_LANDSCAPE.MARGIN_VERTICAL_S; // Minimum spacing for the audio player container
|
|
@@ -68,22 +61,6 @@ const styles = StyleSheet.create({
|
|
|
68
61
|
},
|
|
69
62
|
});
|
|
70
63
|
|
|
71
|
-
const isTabletWithHomeButton = (bottomInset: number): boolean =>
|
|
72
|
-
bottomInset === 0;
|
|
73
|
-
|
|
74
|
-
const withAdditionalOffset = ({ progressBarHeight, bottomInset }) => {
|
|
75
|
-
if (isIOS && isTabletWithHomeButton(bottomInset)) {
|
|
76
|
-
return progressBarHeight === 0 ? 8 : progressBarHeight + 2;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (isIOS && !isTabletWithHomeButton(bottomInset)) {
|
|
80
|
-
return progressBarHeight === 0 ? 4 : 1;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// android
|
|
84
|
-
return progressBarHeight === 0 ? 4 : 0.5;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
64
|
export function TabletLandscapeLayout({
|
|
88
65
|
entry,
|
|
89
66
|
layoutState,
|
|
@@ -96,21 +73,16 @@ export function TabletLandscapeLayout({
|
|
|
96
73
|
onSkipStart,
|
|
97
74
|
onSkipLive,
|
|
98
75
|
onSpeedButtonPress,
|
|
99
|
-
onCloseVideoModal,
|
|
100
76
|
playbackSpeedName,
|
|
101
77
|
configuration,
|
|
102
|
-
dimensions,
|
|
103
|
-
playNextData,
|
|
104
78
|
title,
|
|
105
79
|
summary,
|
|
106
80
|
}: Props) {
|
|
107
81
|
const [imageWidth, setImageWidth] = React.useState(0);
|
|
108
82
|
const { docked } = layoutState;
|
|
109
83
|
|
|
110
|
-
const { bottom: bottomInset } = useSafeAreaInsets();
|
|
111
84
|
const { height: screenHeight } = useSafeAreaFrame();
|
|
112
85
|
const isSmallScreen = getIsSmallTabletHeight(screenHeight);
|
|
113
|
-
const { progressBarHeight } = useModalAnimationContext();
|
|
114
86
|
|
|
115
87
|
const onLayoutImage = React.useCallback((e) => {
|
|
116
88
|
setImageWidth(e.nativeEvent.layout.width);
|
|
@@ -149,20 +121,7 @@ export function TabletLandscapeLayout({
|
|
|
149
121
|
<PlayerImage
|
|
150
122
|
docked={false}
|
|
151
123
|
entry={entry}
|
|
152
|
-
layoutState={layoutState}
|
|
153
|
-
playerState={playerState}
|
|
154
|
-
value={value}
|
|
155
124
|
configuration={configuration}
|
|
156
|
-
onPlayerSeek={onPlayerSeek}
|
|
157
|
-
onCloseVideoModal={onCloseVideoModal}
|
|
158
|
-
dimensions={dimensions}
|
|
159
|
-
playNextData={playNextData}
|
|
160
|
-
title={title}
|
|
161
|
-
summary={summary}
|
|
162
|
-
verticalOffset={withAdditionalOffset({
|
|
163
|
-
progressBarHeight,
|
|
164
|
-
bottomInset,
|
|
165
|
-
})}
|
|
166
125
|
onLayoutImage={onLayoutImage}
|
|
167
126
|
/>
|
|
168
127
|
) : null}
|
|
@@ -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,5 +1,4 @@
|
|
|
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";
|
|
@@ -13,6 +12,7 @@ import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "../const";
|
|
|
13
12
|
import { withDebug } from "../debug";
|
|
14
13
|
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
15
14
|
import { isSmallTabletHeight } from "../utils";
|
|
15
|
+
import { getPlayerActionButtons } from "@applicaster/zapp-react-native-utils/playerUtils";
|
|
16
16
|
|
|
17
17
|
const styles = StyleSheet.create({
|
|
18
18
|
container: {
|
|
@@ -82,14 +82,8 @@ export const TransportInfo = ({
|
|
|
82
82
|
);
|
|
83
83
|
|
|
84
84
|
const actionButtons = React.useMemo(
|
|
85
|
-
() =>
|
|
86
|
-
|
|
87
|
-
take(2),
|
|
88
|
-
map(trim),
|
|
89
|
-
split(","),
|
|
90
|
-
propOr("", "player_action_buttons")
|
|
91
|
-
)(configuration),
|
|
92
|
-
[configuration.player_action_buttons]
|
|
85
|
+
() => getPlayerActionButtons(configuration),
|
|
86
|
+
[configuration]
|
|
93
87
|
);
|
|
94
88
|
|
|
95
89
|
return (
|
|
@@ -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);
|
|
@@ -51,14 +51,15 @@ export function AnimatedModal({
|
|
|
51
51
|
<PanGestureHandler {...gestureHandlerProps}>
|
|
52
52
|
<Animated.View
|
|
53
53
|
pointerEvents={"auto"}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
style={[
|
|
55
|
+
styles.modalWrapper,
|
|
56
|
+
{
|
|
57
|
+
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
58
|
+
borderTopRightRadius: borderTopRadiusAnimated,
|
|
59
|
+
transform: [{ translateY }],
|
|
60
|
+
height: SCREEN_HEIGHT,
|
|
61
|
+
},
|
|
62
|
+
]}
|
|
62
63
|
>
|
|
63
64
|
<Animated.View
|
|
64
65
|
style={[
|
|
@@ -95,9 +96,7 @@ export function AnimatedModal({
|
|
|
95
96
|
>
|
|
96
97
|
<Pressable
|
|
97
98
|
testID="collapsedBarWrapper"
|
|
98
|
-
onPress={
|
|
99
|
-
expand();
|
|
100
|
-
}}
|
|
99
|
+
onPress={expand}
|
|
101
100
|
style={styles.collapsedBarWrapper}
|
|
102
101
|
>
|
|
103
102
|
{collapsedContent}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import React, { useRef, ReactElement } from "react";
|
|
2
2
|
|
|
3
3
|
import { StyleSheet, Animated, Pressable, ViewStyle } from "react-native";
|
|
4
|
-
import {
|
|
5
|
-
createNativeWrapper,
|
|
6
|
-
PanGestureHandler,
|
|
7
|
-
} from "react-native-gesture-handler";
|
|
4
|
+
import { PanGestureHandler } from "react-native-gesture-handler";
|
|
8
5
|
import { useStyles } from "./styles";
|
|
9
6
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
10
7
|
import { useVideoModalState } from "./hooks";
|
|
11
8
|
import {
|
|
12
9
|
DEFAULT_IMAGE_RATIO_VIDEO,
|
|
10
|
+
MODAL_COLLAPSE_START,
|
|
13
11
|
MODAL_RADIUS,
|
|
14
12
|
SCREEN_HEIGHT,
|
|
15
13
|
SCREEN_WIDTH,
|
|
14
|
+
VIDEO_TRANSITION_THRESHOLD,
|
|
16
15
|
} from "./consts";
|
|
17
16
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
18
17
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
19
18
|
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/useModalAnimationContext";
|
|
20
19
|
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
21
20
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
21
|
+
import { GestureAnimatedScrollView } from "./GestureAnimatedScrollView";
|
|
22
22
|
|
|
23
23
|
const orientationStyles = StyleSheet.create({
|
|
24
24
|
landscape: { flexDirection: "row" },
|
|
@@ -29,8 +29,6 @@ const directionStyles = (isLandscape: boolean): ViewStyle => {
|
|
|
29
29
|
return isLandscape ? orientationStyles.landscape : orientationStyles.portrait;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const GestureAnimatedScrollView = createNativeWrapper(Animated.ScrollView, {});
|
|
33
|
-
|
|
34
32
|
type AnimatedModalProps = {
|
|
35
33
|
enabled?: boolean;
|
|
36
34
|
pip?: boolean;
|
|
@@ -52,6 +50,8 @@ type AnimatedModalProps = {
|
|
|
52
50
|
};
|
|
53
51
|
};
|
|
54
52
|
|
|
53
|
+
const height = SCREEN_HEIGHT;
|
|
54
|
+
|
|
55
55
|
export function VideoPlayerModal({
|
|
56
56
|
enabled = true,
|
|
57
57
|
aspectRatio = DEFAULT_IMAGE_RATIO_VIDEO,
|
|
@@ -65,11 +65,9 @@ export function VideoPlayerModal({
|
|
|
65
65
|
const isTablet = useIsTablet();
|
|
66
66
|
|
|
67
67
|
let width = SCREEN_WIDTH;
|
|
68
|
-
let height = SCREEN_HEIGHT;
|
|
69
68
|
|
|
70
69
|
if (isTablet && !isTabletPortrait) {
|
|
71
70
|
width = style?.tabletLandscapeWidth || width;
|
|
72
|
-
height = SCREEN_HEIGHT; // Keep height consistent for landscape
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
@@ -91,11 +89,11 @@ export function VideoPlayerModal({
|
|
|
91
89
|
|
|
92
90
|
const SCALE_FACTOR = 1 / (width / aspectRatio / minimisedHeight); // Scale factor for expanded content
|
|
93
91
|
|
|
94
|
-
const
|
|
92
|
+
const insets = useSafeAreaInsets();
|
|
95
93
|
|
|
96
94
|
// Interpolated opacities for smooth cross-fade
|
|
97
95
|
const collapsedOpacity = translateY.interpolate({
|
|
98
|
-
inputRange: [
|
|
96
|
+
inputRange: [MODAL_COLLAPSE_START, height - collapsedHeight],
|
|
99
97
|
outputRange: [0, 1],
|
|
100
98
|
extrapolate: "clamp",
|
|
101
99
|
});
|
|
@@ -108,17 +106,12 @@ export function VideoPlayerModal({
|
|
|
108
106
|
|
|
109
107
|
const xPosition = translateY.interpolate({
|
|
110
108
|
inputRange: [height * VIDEO_TRANSITION_THRESHOLD, height - collapsedHeight],
|
|
111
|
-
outputRange: [
|
|
112
|
-
0,
|
|
113
|
-
-(width - width * SCALE_FACTOR) / 2, // Adjust this range as needed (-(width * scale_factor))
|
|
114
|
-
], // Adjust this range as needed (-(width * scale_factor))
|
|
109
|
+
outputRange: [0, -(width - width * SCALE_FACTOR) / 2],
|
|
115
110
|
extrapolate: "clamp",
|
|
116
111
|
});
|
|
117
112
|
|
|
118
113
|
const vidHeight = width / aspectRatio;
|
|
119
114
|
|
|
120
|
-
const insets = useSafeAreaInsets();
|
|
121
|
-
|
|
122
115
|
const yPosition = translateY.interpolate({
|
|
123
116
|
inputRange: [height * VIDEO_TRANSITION_THRESHOLD, height - collapsedHeight],
|
|
124
117
|
outputRange: [
|
|
@@ -135,7 +128,7 @@ export function VideoPlayerModal({
|
|
|
135
128
|
(SCREEN_WIDTH / aspectRatio) * SCALE_FACTOR) /
|
|
136
129
|
2
|
|
137
130
|
),
|
|
138
|
-
],
|
|
131
|
+
],
|
|
139
132
|
extrapolate: "clamp",
|
|
140
133
|
});
|
|
141
134
|
|
|
@@ -144,7 +137,7 @@ export function VideoPlayerModal({
|
|
|
144
137
|
SCREEN_HEIGHT * VIDEO_TRANSITION_THRESHOLD,
|
|
145
138
|
SCREEN_HEIGHT - collapsedHeight,
|
|
146
139
|
],
|
|
147
|
-
outputRange: [1, SCALE_FACTOR],
|
|
140
|
+
outputRange: [1, SCALE_FACTOR],
|
|
148
141
|
extrapolate: "clamp",
|
|
149
142
|
});
|
|
150
143
|
|
|
@@ -166,14 +159,15 @@ export function VideoPlayerModal({
|
|
|
166
159
|
>
|
|
167
160
|
<Animated.View
|
|
168
161
|
pointerEvents={"auto"}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
162
|
+
style={[
|
|
163
|
+
styles.modalWrapper,
|
|
164
|
+
{
|
|
165
|
+
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
166
|
+
borderTopRightRadius: borderTopRadiusAnimated,
|
|
167
|
+
transform: [{ translateY }],
|
|
168
|
+
height: SCREEN_HEIGHT,
|
|
169
|
+
},
|
|
170
|
+
]}
|
|
177
171
|
>
|
|
178
172
|
<Animated.View
|
|
179
173
|
pointerEvents={"auto"}
|
|
@@ -230,9 +224,7 @@ export function VideoPlayerModal({
|
|
|
230
224
|
>
|
|
231
225
|
<Pressable
|
|
232
226
|
testID="collapsedBarWrapper"
|
|
233
|
-
onPress={
|
|
234
|
-
expand();
|
|
235
|
-
}}
|
|
227
|
+
onPress={expand}
|
|
236
228
|
style={styles.collapsedBarWrapper}
|
|
237
229
|
>
|
|
238
230
|
{collapsedContent}
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isAndroidTablet } from "@applicaster/zapp-react-native-utils/reactHooks/layout/isTablet";
|
|
2
|
+
import {
|
|
3
|
+
isAndroidPlatform,
|
|
4
|
+
isAndroidVersionAtLeast,
|
|
5
|
+
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
6
|
+
import { Dimensions, StatusBar } from "react-native";
|
|
2
7
|
|
|
3
8
|
export const DOCKED_PROGRESSBAR_HEIGHT = 3; // Height of the docked progress bar plugins/mobile-transport-controls/src/ProgressBar/layouts/DockedLayout.tsx
|
|
4
9
|
|
|
5
|
-
export const
|
|
6
|
-
Dimensions.get("window");
|
|
10
|
+
export const VIDEO_TRANSITION_THRESHOLD = 0.5; // Threshold for video transition
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
const windowDimensions = Dimensions.get("window");
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
const isOldAndroidDevice =
|
|
15
|
+
isAndroidPlatform() && !isAndroidVersionAtLeast(35) && !isAndroidTablet();
|
|
11
16
|
|
|
12
|
-
export const
|
|
17
|
+
export const SCREEN_WIDTH = windowDimensions.width;
|
|
18
|
+
|
|
19
|
+
export const SCREEN_HEIGHT =
|
|
20
|
+
windowDimensions.height + (isOldAndroidDevice ? StatusBar.currentHeight : 0);
|
|
21
|
+
|
|
22
|
+
export const MODAL_COLLAPSE_START = SCREEN_HEIGHT * 0.7; // 70% of screen height
|
|
23
|
+
|
|
24
|
+
export const DRAG_TO_COLLAPSE = 0.02; // 2% to collapse
|
|
25
|
+
|
|
26
|
+
export const DRAG_TO_EXPAND = 0.02; // 2% to expand
|
|
13
27
|
|
|
14
28
|
export const DEFAULT_IMAGE_RATIO_VIDEO = 16 / 9; // Default aspect ratio for video
|
|
15
29
|
|
|
@@ -31,6 +31,8 @@ export const useVideoModalState = (
|
|
|
31
31
|
const collapsedHeight =
|
|
32
32
|
minimisedHeight + bottom + bottomTabBarHeight + PROGRESS_BAR_HEIGHT;
|
|
33
33
|
|
|
34
|
+
const translateY = translateYRef.current;
|
|
35
|
+
|
|
34
36
|
const handleExpand = useCallback(
|
|
35
37
|
(toValue: number) => {
|
|
36
38
|
return Animated.timing(translateYRef.current, {
|
|
@@ -53,17 +55,6 @@ export const useVideoModalState = (
|
|
|
53
55
|
[translateYRef]
|
|
54
56
|
);
|
|
55
57
|
|
|
56
|
-
// setup translateY if not provided
|
|
57
|
-
if (!translateYRef.current) {
|
|
58
|
-
const initialTranslateY = handleExpand
|
|
59
|
-
? 0
|
|
60
|
-
: SCREEN_HEIGHT - collapsedHeight;
|
|
61
|
-
|
|
62
|
-
translateYRef.current.setValue(initialTranslateY);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const translateY = translateYRef.current;
|
|
66
|
-
|
|
67
58
|
const offset = useRef(SCREEN_HEIGHT - collapsedHeight);
|
|
68
59
|
|
|
69
60
|
// Gesture handler for modal
|
|
@@ -91,25 +82,27 @@ export const useVideoModalState = (
|
|
|
91
82
|
newY = SCREEN_HEIGHT - collapsedHeight;
|
|
92
83
|
}
|
|
93
84
|
|
|
94
|
-
const shouldCollapse =
|
|
95
|
-
|
|
85
|
+
const shouldCollapse =
|
|
86
|
+
translationY > (SCREEN_HEIGHT - collapsedHeight) * DRAG_TO_COLLAPSE;
|
|
87
|
+
|
|
88
|
+
const shouldExpand =
|
|
89
|
+
translationY < -(SCREEN_HEIGHT - collapsedHeight) * DRAG_TO_EXPAND;
|
|
96
90
|
|
|
97
91
|
if (!collapsed && shouldCollapse) {
|
|
98
92
|
// Collapse
|
|
99
93
|
Animated.timing(translateY, {
|
|
100
94
|
toValue: SCREEN_HEIGHT - collapsedHeight,
|
|
101
|
-
duration:
|
|
95
|
+
duration: ANIMATION_DURATION,
|
|
102
96
|
useNativeDriver: true,
|
|
103
97
|
}).start(() => {
|
|
104
98
|
minimiseVideoModal();
|
|
105
99
|
offset.current = SCREEN_HEIGHT - collapsedHeight;
|
|
106
|
-
translateY.setValue(SCREEN_HEIGHT - collapsedHeight);
|
|
107
100
|
});
|
|
108
101
|
} else if (collapsed && shouldExpand) {
|
|
109
102
|
// Expand
|
|
110
103
|
Animated.timing(translateY, {
|
|
111
104
|
toValue: 0,
|
|
112
|
-
duration:
|
|
105
|
+
duration: ANIMATION_DURATION,
|
|
113
106
|
useNativeDriver: true,
|
|
114
107
|
}).start(() => {
|
|
115
108
|
maximiseVideoModal();
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable react-native/no-color-literals */
|
|
2
1
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
3
2
|
import {
|
|
4
3
|
useIsTablet,
|
|
@@ -50,6 +49,9 @@ export const useStyles = ({ height }: { height: number }) => {
|
|
|
50
49
|
|
|
51
50
|
const backgroundColor = useBackgroundColor();
|
|
52
51
|
|
|
52
|
+
const BG_COLOR_DEFAULT_BLACK = "black";
|
|
53
|
+
const BG_COLOR_DEFAULT_TRANSPARENT = "transparent";
|
|
54
|
+
|
|
53
55
|
const styles = StyleSheet.create({
|
|
54
56
|
modal: {
|
|
55
57
|
position: "absolute",
|
|
@@ -61,8 +63,11 @@ export const useStyles = ({ height }: { height: number }) => {
|
|
|
61
63
|
zIndex: 100,
|
|
62
64
|
overflow: "hidden",
|
|
63
65
|
},
|
|
66
|
+
modalWrapper: {
|
|
67
|
+
backgroundColor: BG_COLOR_DEFAULT_BLACK,
|
|
68
|
+
},
|
|
64
69
|
collapsedModalBg: {
|
|
65
|
-
backgroundColor:
|
|
70
|
+
backgroundColor: BG_COLOR_DEFAULT_BLACK,
|
|
66
71
|
},
|
|
67
72
|
modalContent: {
|
|
68
73
|
flex: 1,
|
|
@@ -70,12 +75,13 @@ export const useStyles = ({ height }: { height: number }) => {
|
|
|
70
75
|
},
|
|
71
76
|
expandedContentContainer: {
|
|
72
77
|
justifyContent: "flex-start",
|
|
73
|
-
backgroundColor:
|
|
78
|
+
backgroundColor: BG_COLOR_DEFAULT_TRANSPARENT,
|
|
74
79
|
zIndex: 1,
|
|
75
80
|
flex: 0,
|
|
76
81
|
},
|
|
77
82
|
extraContentScrollView: {
|
|
78
|
-
|
|
83
|
+
width: "100%",
|
|
84
|
+
backgroundColor: BG_COLOR_DEFAULT_TRANSPARENT,
|
|
79
85
|
},
|
|
80
86
|
collapsedBarContainer: {
|
|
81
87
|
...StyleSheet.absoluteFillObject,
|
|
@@ -13,11 +13,10 @@ export const GenericTVPlayerView: React.FC<GenericTVPlayerViewProps> = ({
|
|
|
13
13
|
audioPlayerProps,
|
|
14
14
|
transportControls,
|
|
15
15
|
entry,
|
|
16
|
-
inline,
|
|
17
16
|
}) => {
|
|
18
17
|
return (
|
|
19
18
|
<>
|
|
20
|
-
{type === "audio"
|
|
19
|
+
{type === "audio" ? (
|
|
21
20
|
<AudioPlayer
|
|
22
21
|
audio_item={entry}
|
|
23
22
|
plugin_configuration={pluginConfiguration}
|
package/src/Player/index.tsx
CHANGED
|
@@ -61,6 +61,7 @@ const styles = StyleSheet.create({
|
|
|
61
61
|
zIndex: 1,
|
|
62
62
|
},
|
|
63
63
|
playerSize: { width: "100%", height: "100%" },
|
|
64
|
+
flexImage: { height: "100%", aspectRatio: 1, flex: -1 },
|
|
64
65
|
});
|
|
65
66
|
|
|
66
67
|
const logger = createLogger({
|
|
@@ -1021,14 +1022,9 @@ export default class VideoPlayer extends React.Component<
|
|
|
1021
1022
|
entry={entry}
|
|
1022
1023
|
aspectRatio={1}
|
|
1023
1024
|
layoutState={sharedWrapperViewProps.layoutState}
|
|
1024
|
-
onPlayerSeek={() => {}}
|
|
1025
1025
|
playNextData={sharedWrapperViewProps.playNextData}
|
|
1026
|
-
progressBarHeight={4}
|
|
1027
1026
|
ImageComponent={
|
|
1028
|
-
<FlexImage
|
|
1029
|
-
entry={entry}
|
|
1030
|
-
style={{ height: "100%", aspectRatio: 1, flex: -1 }}
|
|
1031
|
-
/>
|
|
1027
|
+
<FlexImage entry={entry} style={styles.flexImage} />
|
|
1032
1028
|
}
|
|
1033
1029
|
/>
|
|
1034
1030
|
</View>
|
|
@@ -1140,9 +1136,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
1140
1136
|
entry={entry}
|
|
1141
1137
|
aspectRatio={aspectRatio}
|
|
1142
1138
|
layoutState={sharedWrapperViewProps.layoutState}
|
|
1143
|
-
onPlayerSeek={() => {}}
|
|
1144
1139
|
playNextData={sharedWrapperViewProps.playNextData}
|
|
1145
|
-
progressBarHeight={4}
|
|
1146
1140
|
/>
|
|
1147
1141
|
</View>
|
|
1148
1142
|
)
|
|
File without changes
|