@applicaster/quick-brick-player 15.0.0-alpha.6141436051 → 15.0.0-alpha.6203358875
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 -6
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +13 -7
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +25 -5
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +6 -1
- package/src/Player/PlayNextOverlay/index.tsx +2 -2
- package/src/Player/PlayerModal/PlayerModal.tsx +10 -15
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +129 -105
- package/src/Player/PlayerModal/hooks/index.ts +113 -145
- package/src/Player/PlayerModal/styles.ts +5 -0
- package/src/Player/PlayerModal/utils/index.ts +94 -12
- package/src/Player/Utils/index.tsx +9 -9
- package/src/Player/hooks/progressStates/__tests__/utils.test.ts +23 -0
- package/src/Player/hooks/progressStates/useLiveProgressState.tsx +78 -0
- package/src/Player/hooks/progressStates/useProgressState.tsx +30 -0
- package/src/Player/hooks/progressStates/useVodProgressState.tsx +115 -0
- package/src/Player/hooks/progressStates/utils.ts +33 -0
- package/src/Player/index.tsx +61 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "15.0.0-alpha.
|
|
3
|
+
"version": "15.0.0-alpha.6203358875",
|
|
4
4
|
"description": "Quick Brick Player",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@applicaster/quick-brick-mobile-transport-controls": "15.0.0-
|
|
39
|
-
"@applicaster/quick-brick-tv-transport-controls": "15.0.0-rc.
|
|
40
|
-
"@applicaster/zapp-react-native-tvos-app": "15.0.0-alpha.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "15.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "15.0.0-alpha.
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "15.0.0-rc.127",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "15.0.0-rc.116",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "15.0.0-alpha.6203358875",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "15.0.0-alpha.6203358875",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "15.0.0-alpha.6203358875",
|
|
43
43
|
"query-string": "7.1.3",
|
|
44
44
|
"shaka-player": "4.3.5",
|
|
45
45
|
"typeface-montserrat": "^0.0.54",
|
|
@@ -23,7 +23,7 @@ import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/pl
|
|
|
23
23
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
24
24
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
25
25
|
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
26
|
-
import {
|
|
26
|
+
import { isBottomTabVisible } from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
|
|
27
27
|
import { usePlugins } from "@applicaster/zapp-react-native-redux";
|
|
28
28
|
import { partial } from "@applicaster/zapp-react-native-utils/utils";
|
|
29
29
|
|
|
@@ -90,7 +90,8 @@ const styles = StyleSheet.create({
|
|
|
90
90
|
marginTop: { marginTop: PROGRESS_BAR_HEIGHT },
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
const getValue = (key: string, stylesObj:
|
|
93
|
+
const getValue = (key: string, stylesObj: Record<string, any>) =>
|
|
94
|
+
stylesObj?.[key] ?? null;
|
|
94
95
|
|
|
95
96
|
const controlButtons = (
|
|
96
97
|
live: boolean,
|
|
@@ -166,7 +167,12 @@ export const DockedControls = (props: Props) => {
|
|
|
166
167
|
const { currentRoute, screenData } = useNavigation();
|
|
167
168
|
|
|
168
169
|
const plugins = usePlugins();
|
|
169
|
-
|
|
170
|
+
|
|
171
|
+
const bottomTabsVisible = isBottomTabVisible(
|
|
172
|
+
currentRoute,
|
|
173
|
+
screenData,
|
|
174
|
+
plugins
|
|
175
|
+
);
|
|
170
176
|
|
|
171
177
|
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
172
178
|
|
|
@@ -208,7 +214,7 @@ export const DockedControls = (props: Props) => {
|
|
|
208
214
|
|
|
209
215
|
const insets = useSafeAreaInsets();
|
|
210
216
|
|
|
211
|
-
const
|
|
217
|
+
const progressBarLayoutState = React.useMemo(
|
|
212
218
|
() => ({
|
|
213
219
|
inline: layoutState.inline,
|
|
214
220
|
docked: true,
|
|
@@ -247,13 +253,13 @@ export const DockedControls = (props: Props) => {
|
|
|
247
253
|
);
|
|
248
254
|
|
|
249
255
|
const bottomSpacerStyle = React.useMemo(() => {
|
|
250
|
-
const tabBarHeight =
|
|
256
|
+
const tabBarHeight = bottomTabsVisible ? bottomTabBarHeight : 0;
|
|
251
257
|
const safeAreaBottomInset = insets.bottom || 0;
|
|
252
258
|
|
|
253
259
|
return {
|
|
254
260
|
height: safeAreaBottomInset + tabBarHeight,
|
|
255
261
|
};
|
|
256
|
-
}, [
|
|
262
|
+
}, [bottomTabsVisible, insets.bottom]);
|
|
257
263
|
|
|
258
264
|
const contentInfoContent = React.useMemo(
|
|
259
265
|
() => ({ ...entry, title, summary }),
|
|
@@ -275,7 +281,7 @@ export const DockedControls = (props: Props) => {
|
|
|
275
281
|
content={entry}
|
|
276
282
|
value={value}
|
|
277
283
|
visible
|
|
278
|
-
layoutState={
|
|
284
|
+
layoutState={progressBarLayoutState}
|
|
279
285
|
onPlayerSeek={onPlayerSeek}
|
|
280
286
|
playerState={playerState}
|
|
281
287
|
docked
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { LayoutChangeEvent, View } from "react-native";
|
|
2
|
+
import { Animated, LayoutChangeEvent, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
5
5
|
import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
@@ -8,6 +8,7 @@ import { FlexImage } from "./FlexImage";
|
|
|
8
8
|
|
|
9
9
|
import { styles } from "./styles";
|
|
10
10
|
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
11
|
+
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
11
12
|
|
|
12
13
|
type Props = {
|
|
13
14
|
entry: ZappEntry;
|
|
@@ -29,15 +30,34 @@ export const PlayerImage = (props: Props) => {
|
|
|
29
30
|
configuration.audio_player_artwork_border_radius
|
|
30
31
|
);
|
|
31
32
|
|
|
33
|
+
const { yTranslate } = useModalAnimationContext();
|
|
34
|
+
|
|
35
|
+
const isModalExpanded = yTranslate.current.interpolate({
|
|
36
|
+
inputRange: [0, 1], // this should be end with `1` only when it's in initial state ( 0pos), otherwise `0`
|
|
37
|
+
outputRange: [1, 0],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// do not use styles.shadow when isModalExpanded is 0
|
|
41
|
+
|
|
42
|
+
const animatedStyle = {
|
|
43
|
+
opacity: isModalExpanded,
|
|
44
|
+
};
|
|
45
|
+
|
|
32
46
|
return (
|
|
33
47
|
<View style={styles.alignItemsCenter}>
|
|
48
|
+
{/* Using an Animated.View to apply shadow to the image */}
|
|
49
|
+
<Animated.View
|
|
50
|
+
style={[
|
|
51
|
+
animatedStyle,
|
|
52
|
+
shouldShowShadow ? styles.shadow : undefined,
|
|
53
|
+
{ borderRadius },
|
|
54
|
+
]}
|
|
55
|
+
/>
|
|
34
56
|
<View
|
|
35
57
|
onLayout={onLayoutImage}
|
|
36
|
-
style={[
|
|
58
|
+
style={[styles.defaultImageWrapperView, { borderRadius }]}
|
|
37
59
|
>
|
|
38
|
-
<
|
|
39
|
-
<FlexImage entry={entry} style={styles.backgroundImageContainer} />
|
|
40
|
-
</View>
|
|
60
|
+
<FlexImage entry={entry} style={styles.backgroundImageContainer} />
|
|
41
61
|
</View>
|
|
42
62
|
</View>
|
|
43
63
|
);
|
|
@@ -23,7 +23,12 @@ export const styles = StyleSheet.create({
|
|
|
23
23
|
overflow: "hidden",
|
|
24
24
|
},
|
|
25
25
|
shadow: {
|
|
26
|
-
|
|
26
|
+
zIndex: 0,
|
|
27
|
+
position: "absolute",
|
|
28
|
+
top: 0,
|
|
29
|
+
left: 0,
|
|
30
|
+
right: 0,
|
|
31
|
+
bottom: 0,
|
|
27
32
|
shadowColor: SHADOW_COLOR,
|
|
28
33
|
shadowOffset: { width: 0, height: 24 },
|
|
29
34
|
shadowOpacity: platformSelect({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux";
|
|
5
5
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
6
6
|
|
|
7
7
|
type Props = {
|
|
@@ -32,7 +32,7 @@ export const PlayNextOverlay = ({
|
|
|
32
32
|
playNextData,
|
|
33
33
|
setNextVideoPreloadThresholdPercentage,
|
|
34
34
|
}: Props) => {
|
|
35
|
-
const
|
|
35
|
+
const plugins = usePlugins();
|
|
36
36
|
|
|
37
37
|
const OverlayPlugin = getOverlayPlugin(plugins);
|
|
38
38
|
|
|
@@ -5,8 +5,8 @@ import { PanGestureHandler } from "react-native-gesture-handler";
|
|
|
5
5
|
import { useStyles } from "./styles";
|
|
6
6
|
import { useVideoModalState } from "./hooks";
|
|
7
7
|
import { MODAL_COLLAPSE_RATIO, MODAL_RADIUS } from "./consts";
|
|
8
|
-
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
9
8
|
import { getWindowHeight } from "./utils";
|
|
9
|
+
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
10
10
|
|
|
11
11
|
type AnimatedModalProps = {
|
|
12
12
|
content?: ReactElement;
|
|
@@ -17,22 +17,18 @@ export function AnimatedModal({
|
|
|
17
17
|
content,
|
|
18
18
|
collapsedContent,
|
|
19
19
|
}: AnimatedModalProps) {
|
|
20
|
-
const
|
|
20
|
+
const { translateY, collapsed, gestureHandlerProps, expand, offset } =
|
|
21
|
+
useVideoModalState();
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
collapsed,
|
|
25
|
-
collapsedHeight,
|
|
26
|
-
gestureHandlerProps,
|
|
27
|
-
expand,
|
|
28
|
-
} = useVideoModalState(translateYRef);
|
|
23
|
+
const frame = useSafeAreaFrame();
|
|
24
|
+
const collapsedHeight = frame.height - offset.current;
|
|
29
25
|
|
|
30
|
-
const
|
|
26
|
+
const height = getWindowHeight();
|
|
27
|
+
const heightAboveMinimised = height - collapsedHeight;
|
|
31
28
|
|
|
32
|
-
const
|
|
33
|
-
const heightAboveMinimised = WINDOW_HEIGHT - collapsedHeight;
|
|
29
|
+
const styles = useStyles({ height: collapsedHeight, type: "audio" });
|
|
34
30
|
|
|
35
|
-
const MODAL_COLLAPSE_START =
|
|
31
|
+
const MODAL_COLLAPSE_START = height * MODAL_COLLAPSE_RATIO;
|
|
36
32
|
|
|
37
33
|
// Interpolated opacities for smooth cross-fade
|
|
38
34
|
const collapsedOpacity = translateY.interpolate({
|
|
@@ -63,7 +59,7 @@ export function AnimatedModal({
|
|
|
63
59
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
64
60
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
65
61
|
transform: [{ translateY }],
|
|
66
|
-
height:
|
|
62
|
+
height: height,
|
|
67
63
|
},
|
|
68
64
|
]}
|
|
69
65
|
>
|
|
@@ -73,7 +69,6 @@ export function AnimatedModal({
|
|
|
73
69
|
{
|
|
74
70
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
75
71
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
76
|
-
height: WINDOW_HEIGHT,
|
|
77
72
|
},
|
|
78
73
|
]}
|
|
79
74
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { ReactElement, useMemo, useRef } from "react";
|
|
2
2
|
|
|
3
|
-
import { Animated, Pressable
|
|
3
|
+
import { Animated, Pressable } from "react-native";
|
|
4
4
|
import { PanGestureHandler } from "react-native-gesture-handler";
|
|
5
5
|
import { useStyles } from "./styles";
|
|
6
6
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
@@ -12,22 +12,25 @@ import {
|
|
|
12
12
|
VIDEO_TRANSITION_THRESHOLD,
|
|
13
13
|
} from "./consts";
|
|
14
14
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
15
|
-
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
16
|
-
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/useModalAnimationContext";
|
|
17
15
|
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
18
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
SafeAreaView,
|
|
18
|
+
useSafeAreaFrame,
|
|
19
|
+
useSafeAreaInsets,
|
|
20
|
+
} from "react-native-safe-area-context";
|
|
19
21
|
import { GestureAnimatedScrollView } from "./GestureAnimatedScrollView";
|
|
20
22
|
import { PlayerDetailsWrapperHeightContext } from "./context";
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
import {
|
|
24
|
+
getInsetsOffset,
|
|
25
|
+
getWindowHeight,
|
|
26
|
+
getWindowWidth,
|
|
27
|
+
directionStyles,
|
|
28
|
+
getScaledPos,
|
|
29
|
+
getExtraContentPadding,
|
|
30
|
+
} from "./utils";
|
|
31
|
+
import { addOrientationChangeListener } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
27
32
|
|
|
28
|
-
const
|
|
29
|
-
return isLandscape ? orientationStyles.landscape : orientationStyles.portrait;
|
|
30
|
-
};
|
|
33
|
+
const AnimatedSafeAreaView = Animated.createAnimatedComponent(SafeAreaView);
|
|
31
34
|
|
|
32
35
|
type AnimatedModalProps = {
|
|
33
36
|
pip?: boolean;
|
|
@@ -59,44 +62,61 @@ export function VideoPlayerModal({
|
|
|
59
62
|
const enabled = !!modal && !fullscreen;
|
|
60
63
|
const isTablet = useIsTablet();
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
+
// remember initial width, ignore rotation changes
|
|
66
|
+
const width = useMemo(
|
|
67
|
+
() =>
|
|
68
|
+
isTablet && !isTabletPortrait
|
|
69
|
+
? style.tabletLandscapeWidth
|
|
70
|
+
: getWindowWidth(isTablet, !isTabletPortrait),
|
|
71
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
|
+
[]
|
|
73
|
+
);
|
|
65
74
|
|
|
66
|
-
|
|
75
|
+
const height = useMemo(
|
|
76
|
+
() => getWindowHeight(isTablet, !isTabletPortrait),
|
|
77
|
+
[]
|
|
78
|
+
); // remember initial height, ignore rotation changes
|
|
67
79
|
|
|
68
|
-
|
|
69
|
-
width = style?.tabletLandscapeWidth || width;
|
|
70
|
-
}
|
|
80
|
+
const MODAL_COLLAPSE_START = height * MODAL_COLLAPSE_RATIO;
|
|
71
81
|
|
|
72
82
|
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
73
83
|
const scrollViewRef = useRef<typeof Animated.ScrollView | null>(null);
|
|
74
84
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
const dummyRef = useRef(new Animated.Value(0));
|
|
85
|
+
const { translateY, collapsed, gestureHandlerProps, expand, offset } =
|
|
86
|
+
useVideoModalState();
|
|
78
87
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
collapsed,
|
|
82
|
-
collapsedHeight,
|
|
83
|
-
gestureHandlerProps,
|
|
84
|
-
expand,
|
|
85
|
-
} = useVideoModalState(modal ? translateYRef : dummyRef);
|
|
88
|
+
const frame = useSafeAreaFrame();
|
|
89
|
+
const collapsedHeight = frame.height - offset.current;
|
|
86
90
|
|
|
87
91
|
const heightAboveMinimised = height - collapsedHeight;
|
|
88
92
|
|
|
89
|
-
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
90
|
-
|
|
91
93
|
const styles = useStyles({ height: collapsedHeight });
|
|
92
94
|
|
|
93
95
|
const SCALE_FACTOR = 1 / (width / aspectRatio / minimisedHeight); // Scale factor for expanded content
|
|
94
96
|
|
|
95
97
|
const insets = useSafeAreaInsets();
|
|
96
98
|
|
|
97
|
-
const
|
|
99
|
+
const [isFullScreenMode, setFullScreenMode] = React.useState(
|
|
100
|
+
fullscreen || pip
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
React.useEffect(() => {
|
|
104
|
+
const listener = addOrientationChangeListener(({ toOrientation }) => {
|
|
105
|
+
/* ignored in collapsed mode non-PiP player */
|
|
106
|
+
if (collapsed && !pip) return;
|
|
107
|
+
setFullScreenMode(!(toOrientation === 1));
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return () => {
|
|
111
|
+
listener.remove();
|
|
112
|
+
};
|
|
113
|
+
}, [collapsed, pip]);
|
|
114
|
+
|
|
115
|
+
const isFullScreenOrPIP = isFullScreenMode;
|
|
116
|
+
|
|
117
|
+
const vidHeight = width / aspectRatio;
|
|
98
118
|
|
|
99
|
-
//
|
|
119
|
+
// animated opacity for smooth cross-fade of collapsed content
|
|
100
120
|
const collapsedOpacity = !isFullScreenOrPIP
|
|
101
121
|
? translateY.interpolate({
|
|
102
122
|
inputRange: [MODAL_COLLAPSE_START, heightAboveMinimised],
|
|
@@ -105,6 +125,7 @@ export function VideoPlayerModal({
|
|
|
105
125
|
})
|
|
106
126
|
: new Animated.Value(0);
|
|
107
127
|
|
|
128
|
+
// animated opacity for extra content
|
|
108
129
|
const expandedOpacity = !isFullScreenOrPIP
|
|
109
130
|
? translateY.interpolate({
|
|
110
131
|
inputRange: [0, heightAboveMinimised],
|
|
@@ -113,6 +134,7 @@ export function VideoPlayerModal({
|
|
|
113
134
|
})
|
|
114
135
|
: new Animated.Value(1);
|
|
115
136
|
|
|
137
|
+
// animated x position for video content
|
|
116
138
|
const xPosition = !isFullScreenOrPIP
|
|
117
139
|
? translateY.interpolate({
|
|
118
140
|
inputRange: [height * VIDEO_TRANSITION_THRESHOLD, MODAL_COLLAPSE_START],
|
|
@@ -121,27 +143,23 @@ export function VideoPlayerModal({
|
|
|
121
143
|
})
|
|
122
144
|
: new Animated.Value(0);
|
|
123
145
|
|
|
124
|
-
|
|
125
|
-
|
|
146
|
+
// animated y position for video content
|
|
126
147
|
const yPosition = !isFullScreenOrPIP
|
|
127
148
|
? translateY.interpolate({
|
|
128
149
|
inputRange: [height * VIDEO_TRANSITION_THRESHOLD, MODAL_COLLAPSE_START],
|
|
129
150
|
outputRange: [
|
|
130
151
|
0,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
(WINDOW_WIDTH / aspectRatio -
|
|
137
|
-
(WINDOW_WIDTH / aspectRatio) * SCALE_FACTOR) /
|
|
138
|
-
2
|
|
139
|
-
),
|
|
152
|
+
-(
|
|
153
|
+
PROGRESS_BAR_HEIGHT +
|
|
154
|
+
getInsetsOffset(insets, isTabletPortrait) +
|
|
155
|
+
getScaledPos(height, vidHeight, minimisedHeight, isTabletPortrait)
|
|
156
|
+
),
|
|
140
157
|
],
|
|
141
158
|
extrapolate: "clamp",
|
|
142
159
|
})
|
|
143
160
|
: new Animated.Value(0);
|
|
144
161
|
|
|
162
|
+
// animated position for video content
|
|
145
163
|
const scalePosition = !isFullScreenOrPIP
|
|
146
164
|
? translateY.interpolate({
|
|
147
165
|
inputRange: [height * VIDEO_TRANSITION_THRESHOLD, MODAL_COLLAPSE_START],
|
|
@@ -152,7 +170,7 @@ export function VideoPlayerModal({
|
|
|
152
170
|
|
|
153
171
|
const borderTopRadiusAnimated = !isFullScreenOrPIP
|
|
154
172
|
? translateY.interpolate({
|
|
155
|
-
inputRange: [0,
|
|
173
|
+
inputRange: [0, heightAboveMinimised],
|
|
156
174
|
outputRange: [MODAL_RADIUS, 0],
|
|
157
175
|
extrapolate: "clamp",
|
|
158
176
|
})
|
|
@@ -176,90 +194,96 @@ export function VideoPlayerModal({
|
|
|
176
194
|
<PanGestureHandler
|
|
177
195
|
enabled={enabled}
|
|
178
196
|
waitFor={scrollViewRef}
|
|
197
|
+
activeOffsetY={[-25, 25]}
|
|
198
|
+
activeOffsetX={[-25, 25]}
|
|
179
199
|
{...gestureHandlerProps}
|
|
180
200
|
>
|
|
181
|
-
<
|
|
182
|
-
pointerEvents={"auto"}
|
|
183
|
-
style={[
|
|
184
|
-
styles.modalWrapper,
|
|
185
|
-
{
|
|
186
|
-
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
187
|
-
borderTopRightRadius: borderTopRadiusAnimated,
|
|
188
|
-
transform: [{ translateY: isFullScreenOrPIP ? 0 : translateY }],
|
|
189
|
-
height: height,
|
|
190
|
-
},
|
|
191
|
-
]}
|
|
192
|
-
>
|
|
201
|
+
<AnimatedSafeAreaView pointerEvents="box-none" edges={["bottom"]}>
|
|
193
202
|
<Animated.View
|
|
194
203
|
pointerEvents={"auto"}
|
|
195
204
|
style={[
|
|
196
|
-
styles.
|
|
197
|
-
collapsed ? styles.collapsedModalBg : null,
|
|
205
|
+
styles.modalWrapper,
|
|
198
206
|
{
|
|
199
207
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
200
208
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
201
|
-
|
|
209
|
+
transform: [{ translateY: isFullScreenOrPIP ? 0 : translateY }],
|
|
210
|
+
height: frame.height,
|
|
202
211
|
},
|
|
203
212
|
]}
|
|
204
213
|
>
|
|
205
214
|
<Animated.View
|
|
206
|
-
pointerEvents={
|
|
207
|
-
style={[
|
|
215
|
+
pointerEvents={"auto"}
|
|
216
|
+
style={[
|
|
217
|
+
styles.modal,
|
|
218
|
+
collapsed ? styles.collapsedModalBg : null,
|
|
219
|
+
{
|
|
220
|
+
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
221
|
+
borderTopRightRadius: borderTopRadiusAnimated,
|
|
222
|
+
},
|
|
223
|
+
]}
|
|
208
224
|
>
|
|
209
225
|
<Animated.View
|
|
226
|
+
pointerEvents={!collapsed ? "auto" : "none"}
|
|
210
227
|
style={[
|
|
211
|
-
styles.
|
|
212
|
-
|
|
213
|
-
transform: [
|
|
214
|
-
{ translateX: xPosition },
|
|
215
|
-
{ translateY: yPosition },
|
|
216
|
-
{ scale: scalePosition },
|
|
217
|
-
],
|
|
218
|
-
},
|
|
228
|
+
pip ? styles.modalContentPiP : styles.modalContent,
|
|
229
|
+
directionStyles(isTabletPortrait),
|
|
219
230
|
]}
|
|
220
231
|
>
|
|
221
|
-
|
|
232
|
+
<Animated.View
|
|
233
|
+
style={[
|
|
234
|
+
styles.expandedContentContainer,
|
|
235
|
+
{
|
|
236
|
+
transform: [
|
|
237
|
+
{ translateX: xPosition },
|
|
238
|
+
{ translateY: yPosition },
|
|
239
|
+
{ scale: scalePosition },
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
]}
|
|
243
|
+
>
|
|
244
|
+
{content}
|
|
245
|
+
</Animated.View>
|
|
246
|
+
{extraContent ? (
|
|
247
|
+
<GestureAnimatedScrollView
|
|
248
|
+
ref={scrollViewRef}
|
|
249
|
+
contentContainerStyle={getExtraContentPadding(insets)}
|
|
250
|
+
bounces={false}
|
|
251
|
+
overScrollMode="never"
|
|
252
|
+
onLayout={onScrollViewLayout}
|
|
253
|
+
style={[
|
|
254
|
+
styles.extraContentScrollView,
|
|
255
|
+
{ opacity: expandedOpacity },
|
|
256
|
+
]}
|
|
257
|
+
>
|
|
258
|
+
<PlayerDetailsWrapperHeightContext.Provider
|
|
259
|
+
value={playerDetailsWrapperHeight}
|
|
260
|
+
>
|
|
261
|
+
{extraContent}
|
|
262
|
+
</PlayerDetailsWrapperHeightContext.Provider>
|
|
263
|
+
</GestureAnimatedScrollView>
|
|
264
|
+
) : null}
|
|
222
265
|
</Animated.View>
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
paddingBottom: insets.bottom,
|
|
228
|
-
}}
|
|
229
|
-
onLayout={onScrollViewLayout}
|
|
266
|
+
|
|
267
|
+
{!isFullScreenOrPIP ? (
|
|
268
|
+
<Animated.View
|
|
269
|
+
pointerEvents={collapsed ? "box-none" : "none"}
|
|
230
270
|
style={[
|
|
231
|
-
styles.
|
|
232
|
-
{ opacity:
|
|
271
|
+
styles.collapsedBarContainer,
|
|
272
|
+
{ opacity: collapsedOpacity },
|
|
233
273
|
]}
|
|
234
274
|
>
|
|
235
|
-
<
|
|
236
|
-
|
|
275
|
+
<Pressable
|
|
276
|
+
testID="collapsedBarWrapper"
|
|
277
|
+
onPress={expand}
|
|
278
|
+
style={styles.collapsedBarWrapper}
|
|
237
279
|
>
|
|
238
|
-
{
|
|
239
|
-
</
|
|
240
|
-
</
|
|
280
|
+
{collapsedContent}
|
|
281
|
+
</Pressable>
|
|
282
|
+
</Animated.View>
|
|
241
283
|
) : null}
|
|
242
284
|
</Animated.View>
|
|
243
|
-
|
|
244
|
-
{!isFullScreenOrPIP ? (
|
|
245
|
-
<Animated.View
|
|
246
|
-
pointerEvents={collapsed ? "box-none" : "none"}
|
|
247
|
-
style={[
|
|
248
|
-
styles.collapsedBarContainer,
|
|
249
|
-
{ opacity: collapsedOpacity },
|
|
250
|
-
]}
|
|
251
|
-
>
|
|
252
|
-
<Pressable
|
|
253
|
-
testID="collapsedBarWrapper"
|
|
254
|
-
onPress={expand}
|
|
255
|
-
style={styles.collapsedBarWrapper}
|
|
256
|
-
>
|
|
257
|
-
{collapsedContent}
|
|
258
|
-
</Pressable>
|
|
259
|
-
</Animated.View>
|
|
260
|
-
) : null}
|
|
261
285
|
</Animated.View>
|
|
262
|
-
</
|
|
286
|
+
</AnimatedSafeAreaView>
|
|
263
287
|
</PanGestureHandler>
|
|
264
288
|
);
|
|
265
289
|
}
|