@applicaster/quick-brick-player 14.0.0-alpha.1355728993 → 14.0.0-alpha.1428720541
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/Layout/DockedControls/index.tsx +2 -1
- 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/PlayerModal.tsx +1 -3
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +95 -81
- package/src/Player/PlayerModal/consts/index.ts +19 -5
- package/src/Player/PlayerModal/hooks/index.ts +2 -2
- package/src/Player/PlayerModal/styles.ts +1 -0
- package/src/Player/PlayerView/GenericTVPlayerView.tsx +1 -2
- package/src/Player/index.tsx +1 -0
- /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.1428720541",
|
|
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.40",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.37",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.1428720541",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.1428720541",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "14.0.0-alpha.1428720541",
|
|
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",
|
|
@@ -58,15 +57,11 @@
|
|
|
58
57
|
"@applicaster/zapp-react-native-tvos-ui-components": "*",
|
|
59
58
|
"@babel/runtime": "*",
|
|
60
59
|
"@react-native-community/netinfo": "*",
|
|
61
|
-
"immer": "*",
|
|
62
60
|
"react": "*",
|
|
63
61
|
"react-native": "*",
|
|
64
62
|
"react-native-fs": "*",
|
|
65
|
-
"react-native-gesture-handler": "*",
|
|
66
63
|
"react-native-linear-gradient": "*",
|
|
67
|
-
"react-native-safe-area-context": "*",
|
|
68
64
|
"react-native-svg": "*",
|
|
69
|
-
"react-native-web": "*",
|
|
70
65
|
"react-native-webview": "*",
|
|
71
66
|
"uglify-js": "*",
|
|
72
67
|
"validate-color": "*",
|
|
@@ -23,6 +23,7 @@ import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/app
|
|
|
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
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";
|
|
26
27
|
|
|
27
28
|
const bottomTabBarHeight = getTabBarHeight();
|
|
28
29
|
|
|
@@ -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,
|
|
@@ -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);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
MODAL_RADIUS,
|
|
12
12
|
SCREEN_HEIGHT,
|
|
13
13
|
SCREEN_WIDTH,
|
|
14
|
+
VIDEO_TRANSITION_THRESHOLD,
|
|
14
15
|
} from "./consts";
|
|
15
16
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
16
17
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
@@ -31,14 +32,15 @@ const directionStyles = (isLandscape: boolean): ViewStyle => {
|
|
|
31
32
|
type AnimatedModalProps = {
|
|
32
33
|
enabled?: boolean;
|
|
33
34
|
pip?: boolean;
|
|
35
|
+
fullscreen?: boolean;
|
|
34
36
|
content?: (
|
|
35
|
-
opacity: Animated.Value | Animated.AnimatedInterpolation
|
|
37
|
+
opacity: Animated.Value | Animated.AnimatedInterpolation<number>
|
|
36
38
|
) => ReactElement;
|
|
37
39
|
collapsedContent?: (
|
|
38
|
-
opacity: Animated.Value | Animated.AnimatedInterpolation
|
|
40
|
+
opacity: Animated.Value | Animated.AnimatedInterpolation<number>
|
|
39
41
|
) => ReactElement;
|
|
40
42
|
extraContent?: (
|
|
41
|
-
opacity: Animated.Value | Animated.AnimatedInterpolation
|
|
43
|
+
opacity: Animated.Value | Animated.AnimatedInterpolation<number>
|
|
42
44
|
) => ReactElement;
|
|
43
45
|
aspectRatio?: number;
|
|
44
46
|
isTabletPortrait?: boolean;
|
|
@@ -49,6 +51,8 @@ type AnimatedModalProps = {
|
|
|
49
51
|
};
|
|
50
52
|
};
|
|
51
53
|
|
|
54
|
+
const height = SCREEN_HEIGHT;
|
|
55
|
+
|
|
52
56
|
export function VideoPlayerModal({
|
|
53
57
|
enabled = true,
|
|
54
58
|
aspectRatio = DEFAULT_IMAGE_RATIO_VIDEO,
|
|
@@ -58,15 +62,14 @@ export function VideoPlayerModal({
|
|
|
58
62
|
isTabletPortrait,
|
|
59
63
|
style,
|
|
60
64
|
pip = false,
|
|
65
|
+
fullscreen = false,
|
|
61
66
|
}: AnimatedModalProps) {
|
|
62
67
|
const isTablet = useIsTablet();
|
|
63
68
|
|
|
64
69
|
let width = SCREEN_WIDTH;
|
|
65
|
-
let height = SCREEN_HEIGHT;
|
|
66
70
|
|
|
67
71
|
if (isTablet && !isTabletPortrait) {
|
|
68
72
|
width = style?.tabletLandscapeWidth || width;
|
|
69
|
-
height = SCREEN_HEIGHT; // Keep height consistent for landscape
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
@@ -88,69 +91,80 @@ export function VideoPlayerModal({
|
|
|
88
91
|
|
|
89
92
|
const SCALE_FACTOR = 1 / (width / aspectRatio / minimisedHeight); // Scale factor for expanded content
|
|
90
93
|
|
|
91
|
-
const VIDEO_TRANSITION_THRESHOLD = 0.5; // Threshold for video transition
|
|
92
|
-
|
|
93
94
|
const insets = useSafeAreaInsets();
|
|
94
95
|
|
|
96
|
+
const isFullScreenOrPIP = fullscreen || pip;
|
|
97
|
+
|
|
95
98
|
// Interpolated opacities for smooth cross-fade
|
|
96
|
-
const collapsedOpacity =
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
const collapsedOpacity = !isFullScreenOrPIP
|
|
100
|
+
? translateY.interpolate({
|
|
101
|
+
inputRange: [MODAL_COLLAPSE_START, height - collapsedHeight],
|
|
102
|
+
outputRange: [0, 1],
|
|
103
|
+
extrapolate: "clamp",
|
|
104
|
+
})
|
|
105
|
+
: new Animated.Value(0);
|
|
106
|
+
|
|
107
|
+
const expandedOpacity = !isFullScreenOrPIP
|
|
108
|
+
? translateY.interpolate({
|
|
109
|
+
inputRange: [0, height - collapsedHeight],
|
|
110
|
+
outputRange: [1, 0],
|
|
111
|
+
extrapolate: "clamp",
|
|
112
|
+
})
|
|
113
|
+
: new Animated.Value(1);
|
|
114
|
+
|
|
115
|
+
const xPosition = !isFullScreenOrPIP
|
|
116
|
+
? translateY.interpolate({
|
|
117
|
+
inputRange: [
|
|
118
|
+
height * VIDEO_TRANSITION_THRESHOLD,
|
|
119
|
+
height - collapsedHeight,
|
|
120
|
+
],
|
|
121
|
+
outputRange: [0, -(width - width * SCALE_FACTOR) / 2],
|
|
122
|
+
extrapolate: "clamp",
|
|
123
|
+
})
|
|
124
|
+
: new Animated.Value(0);
|
|
113
125
|
|
|
114
126
|
const vidHeight = width / aspectRatio;
|
|
115
127
|
|
|
116
|
-
const yPosition =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
128
|
+
const yPosition = !isFullScreenOrPIP
|
|
129
|
+
? translateY.interpolate({
|
|
130
|
+
inputRange: [
|
|
131
|
+
height * VIDEO_TRANSITION_THRESHOLD,
|
|
132
|
+
height - collapsedHeight,
|
|
133
|
+
],
|
|
134
|
+
outputRange: [
|
|
135
|
+
0,
|
|
136
|
+
isTablet && isTabletLandscape
|
|
137
|
+
? -((-PROGRESS_BAR_HEIGHT + height - vidHeight * SCALE_FACTOR) / 2)
|
|
138
|
+
: -(
|
|
139
|
+
PROGRESS_BAR_HEIGHT +
|
|
140
|
+
insets.top / 2 +
|
|
141
|
+
(SCREEN_WIDTH / aspectRatio -
|
|
142
|
+
(SCREEN_WIDTH / aspectRatio) * SCALE_FACTOR) /
|
|
143
|
+
2
|
|
144
|
+
),
|
|
145
|
+
],
|
|
146
|
+
extrapolate: "clamp",
|
|
147
|
+
})
|
|
148
|
+
: new Animated.Value(0);
|
|
149
|
+
|
|
150
|
+
const scalePosition = !isFullScreenOrPIP
|
|
151
|
+
? translateY.interpolate({
|
|
152
|
+
inputRange: [
|
|
153
|
+
height * VIDEO_TRANSITION_THRESHOLD,
|
|
154
|
+
height - collapsedHeight,
|
|
155
|
+
],
|
|
156
|
+
outputRange: [1, SCALE_FACTOR],
|
|
157
|
+
extrapolate: "clamp",
|
|
158
|
+
})
|
|
159
|
+
: new Animated.Value(1);
|
|
160
|
+
|
|
161
|
+
const borderTopRadiusAnimated = !isFullScreenOrPIP
|
|
162
|
+
? translateY.interpolate({
|
|
163
|
+
inputRange: [0, height - collapsedHeight],
|
|
164
|
+
outputRange: [MODAL_RADIUS, 0],
|
|
165
|
+
extrapolate: "clamp",
|
|
166
|
+
})
|
|
167
|
+
: new Animated.Value(0);
|
|
154
168
|
|
|
155
169
|
return (
|
|
156
170
|
<PanGestureHandler
|
|
@@ -165,8 +179,8 @@ export function VideoPlayerModal({
|
|
|
165
179
|
{
|
|
166
180
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
167
181
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
168
|
-
transform: [{ translateY }],
|
|
169
|
-
height:
|
|
182
|
+
transform: [{ translateY: isFullScreenOrPIP ? 0 : translateY }],
|
|
183
|
+
height: height,
|
|
170
184
|
},
|
|
171
185
|
]}
|
|
172
186
|
>
|
|
@@ -178,7 +192,7 @@ export function VideoPlayerModal({
|
|
|
178
192
|
{
|
|
179
193
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
180
194
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
181
|
-
height:
|
|
195
|
+
height: height,
|
|
182
196
|
},
|
|
183
197
|
]}
|
|
184
198
|
>
|
|
@@ -216,23 +230,23 @@ export function VideoPlayerModal({
|
|
|
216
230
|
) : null}
|
|
217
231
|
</Animated.View>
|
|
218
232
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
<Pressable
|
|
227
|
-
testID="collapsedBarWrapper"
|
|
228
|
-
onPress={() => {
|
|
229
|
-
expand();
|
|
230
|
-
}}
|
|
231
|
-
style={styles.collapsedBarWrapper}
|
|
233
|
+
{!isFullScreenOrPIP ? (
|
|
234
|
+
<Animated.View
|
|
235
|
+
pointerEvents={collapsed ? "box-none" : "none"}
|
|
236
|
+
style={[
|
|
237
|
+
styles.collapsedBarContainer,
|
|
238
|
+
{ opacity: collapsedOpacity },
|
|
239
|
+
]}
|
|
232
240
|
>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
241
|
+
<Pressable
|
|
242
|
+
testID="collapsedBarWrapper"
|
|
243
|
+
onPress={expand}
|
|
244
|
+
style={styles.collapsedBarWrapper}
|
|
245
|
+
>
|
|
246
|
+
{collapsedContent}
|
|
247
|
+
</Pressable>
|
|
248
|
+
</Animated.View>
|
|
249
|
+
) : null}
|
|
236
250
|
</Animated.View>
|
|
237
251
|
</Animated.View>
|
|
238
252
|
</PanGestureHandler>
|
|
@@ -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
|
-
|
|
10
|
+
export const VIDEO_TRANSITION_THRESHOLD = 0.5; // Threshold for video transition
|
|
11
|
+
|
|
12
|
+
const windowDimensions = Dimensions.get("window");
|
|
13
|
+
|
|
14
|
+
const isOldAndroidDevice =
|
|
15
|
+
isAndroidPlatform() && !isAndroidVersionAtLeast(35) && !isAndroidTablet();
|
|
16
|
+
|
|
17
|
+
export const SCREEN_WIDTH = windowDimensions.width;
|
|
18
|
+
|
|
19
|
+
export const SCREEN_HEIGHT =
|
|
20
|
+
windowDimensions.height + (isOldAndroidDevice ? StatusBar.currentHeight : 0);
|
|
7
21
|
|
|
8
22
|
export const MODAL_COLLAPSE_START = SCREEN_HEIGHT * 0.7; // 70% of screen height
|
|
9
23
|
|
|
10
|
-
export const DRAG_TO_COLLAPSE = 0.
|
|
24
|
+
export const DRAG_TO_COLLAPSE = 0.02; // 2% to collapse
|
|
11
25
|
|
|
12
|
-
export const DRAG_TO_EXPAND = 0.
|
|
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
|
|
|
@@ -92,7 +92,7 @@ export const useVideoModalState = (
|
|
|
92
92
|
// Collapse
|
|
93
93
|
Animated.timing(translateY, {
|
|
94
94
|
toValue: SCREEN_HEIGHT - collapsedHeight,
|
|
95
|
-
duration:
|
|
95
|
+
duration: ANIMATION_DURATION,
|
|
96
96
|
useNativeDriver: true,
|
|
97
97
|
}).start(() => {
|
|
98
98
|
minimiseVideoModal();
|
|
@@ -102,7 +102,7 @@ export const useVideoModalState = (
|
|
|
102
102
|
// Expand
|
|
103
103
|
Animated.timing(translateY, {
|
|
104
104
|
toValue: 0,
|
|
105
|
-
duration:
|
|
105
|
+
duration: ANIMATION_DURATION,
|
|
106
106
|
useNativeDriver: true,
|
|
107
107
|
}).start(() => {
|
|
108
108
|
maximiseVideoModal();
|
|
@@ -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
|
@@ -1036,6 +1036,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
1036
1036
|
isTabletPortrait={isTabletPortrait}
|
|
1037
1037
|
aspectRatio={aspectRatio}
|
|
1038
1038
|
pip={this.state.piped}
|
|
1039
|
+
fullscreen={fullscreen}
|
|
1039
1040
|
style={{
|
|
1040
1041
|
tabletLandscapeWidth: getTabletWidth(
|
|
1041
1042
|
this.getPluginConfiguration().tablet_landscape_sidebar_width,
|
|
File without changes
|