@applicaster/zapp-react-native-ui-components 15.0.0-alpha.6750855753 → 15.0.0-alpha.6835718972
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/Components/AnimatedInOut/index.tsx +69 -26
- package/Components/HandlePlayable/HandlePlayable.tsx +14 -65
- package/Components/HandlePlayable/const.ts +3 -0
- package/Components/HandlePlayable/utils.ts +74 -0
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +1 -16
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +44 -26
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +3 -153
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerWrapper.tsx +14 -88
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/useModalSize.ts +10 -5
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +91 -0
- package/package.json +5 -5
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
|
@@ -46,6 +46,7 @@ jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
|
|
|
46
46
|
|
|
47
47
|
jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
|
|
48
48
|
isTV: jest.fn(() => false),
|
|
49
|
+
isAndroidPlatform: jest.fn(() => false),
|
|
49
50
|
isApplePlatform: jest.fn(() => true),
|
|
50
51
|
platformSelect: jest.fn((props) => props.android),
|
|
51
52
|
}));
|
|
@@ -33,8 +33,12 @@ const MODAL_SIZE_FOR_LANDSCAPE: Size = {
|
|
|
33
33
|
height: "100%",
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
const SAFE_AREA_BREAKING_API_VERSION = 35;
|
|
37
|
+
|
|
36
38
|
const isOldAndroidDevice =
|
|
37
|
-
isAndroidPlatform() &&
|
|
39
|
+
isAndroidPlatform() &&
|
|
40
|
+
!isAndroidVersionAtLeast(SAFE_AREA_BREAKING_API_VERSION) &&
|
|
41
|
+
!isAndroidTablet();
|
|
38
42
|
|
|
39
43
|
export const useModalSize = (): Size => {
|
|
40
44
|
const frame = useSafeAreaFrame();
|
|
@@ -42,7 +46,7 @@ export const useModalSize = (): Size => {
|
|
|
42
46
|
const [modalSize, setModalSize] = React.useState<Size>({
|
|
43
47
|
width: frame.width,
|
|
44
48
|
height: isOldAndroidDevice
|
|
45
|
-
? frame.height + StatusBar.currentHeight
|
|
49
|
+
? frame.height + (StatusBar.currentHeight ?? 0)
|
|
46
50
|
: frame.height,
|
|
47
51
|
});
|
|
48
52
|
|
|
@@ -57,9 +61,10 @@ export const useModalSize = (): Size => {
|
|
|
57
61
|
|
|
58
62
|
return {
|
|
59
63
|
width: newSize.width,
|
|
60
|
-
height:
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
height:
|
|
65
|
+
isOldAndroidDevice && newSize.height !== "100%"
|
|
66
|
+
? newSize.height + (StatusBar.currentHeight ?? 0)
|
|
67
|
+
: newSize.height,
|
|
63
68
|
};
|
|
64
69
|
});
|
|
65
70
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { StyleSheet, ViewStyle } from "react-native";
|
|
3
|
+
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
|
+
import { playerDimensionsHack } from "./utils";
|
|
6
|
+
import { getTabletWidth } from "@applicaster/zapp-react-native-utils/playerUtils";
|
|
7
|
+
import {
|
|
8
|
+
getBaseDimensions,
|
|
9
|
+
calculateAspectRatio,
|
|
10
|
+
getPlayerDimensions,
|
|
11
|
+
getContainerDimensions,
|
|
12
|
+
} from "./playerWrapperUtils";
|
|
13
|
+
|
|
14
|
+
export const defaultStyles = StyleSheet.create({
|
|
15
|
+
playerContainer: { position: "relative", alignSelf: "center", zIndex: 200 },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const useStyle = ({
|
|
19
|
+
style,
|
|
20
|
+
inline,
|
|
21
|
+
isModal,
|
|
22
|
+
isTabletPortrait,
|
|
23
|
+
configuration,
|
|
24
|
+
pip,
|
|
25
|
+
}) => {
|
|
26
|
+
const isTablet = useIsTablet();
|
|
27
|
+
|
|
28
|
+
const isInlineModal = inline && isModal;
|
|
29
|
+
|
|
30
|
+
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
31
|
+
|
|
32
|
+
const tabletWidth = getTabletWidth(
|
|
33
|
+
configuration.tablet_landscape_sidebar_width,
|
|
34
|
+
style
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const baseDimensions: ViewStyle = React.useMemo(
|
|
38
|
+
() => getBaseDimensions(isInlineModal, isTabletLandscape, tabletWidth),
|
|
39
|
+
[isInlineModal, isTabletLandscape, tabletWidth]
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const aspectRatio = React.useMemo(
|
|
43
|
+
() => calculateAspectRatio(isInlineModal, pip),
|
|
44
|
+
// ignoring insets - only initial needed
|
|
45
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
46
|
+
[isInlineModal, pip]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return React.useMemo(() => {
|
|
50
|
+
const playerDimensions: ViewStyle = getPlayerDimensions(
|
|
51
|
+
baseDimensions,
|
|
52
|
+
aspectRatio
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const containerDimensions: ViewStyle = getContainerDimensions(
|
|
56
|
+
baseDimensions,
|
|
57
|
+
aspectRatio
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const childrenStyles = {
|
|
61
|
+
...playerDimensions,
|
|
62
|
+
...playerDimensionsHack,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return StyleSheet.create({
|
|
66
|
+
containerDimensions,
|
|
67
|
+
childrenStyles,
|
|
68
|
+
});
|
|
69
|
+
}, [baseDimensions, aspectRatio]);
|
|
70
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Dimensions, DimensionValue, Platform, ViewStyle } from "react-native";
|
|
2
|
+
import { Edge } from "react-native-safe-area-context";
|
|
3
|
+
|
|
4
|
+
export type DimensionsT = {
|
|
5
|
+
width: number | string;
|
|
6
|
+
height: number | string | undefined;
|
|
7
|
+
aspectRatio?: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type Configuration = {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
tablet_landscape_sidebar_width?: string;
|
|
13
|
+
tablet_landscape_player_container_background_color?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// This is safe, remembering screen dimensions once as they do not change during runtime
|
|
17
|
+
// TODO: consider sharing screen orientation as a shared function for the app
|
|
18
|
+
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");
|
|
19
|
+
|
|
20
|
+
export const getWindowDimensions = () => {
|
|
21
|
+
const { width, height } = Dimensions.get("window");
|
|
22
|
+
|
|
23
|
+
return { width, height };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getMaxWindowDimension = () => {
|
|
27
|
+
const { width, height } = getWindowDimensions();
|
|
28
|
+
|
|
29
|
+
return Math.max(width, height);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getMinWindowDimension = () => {
|
|
33
|
+
const { width, height } = getWindowDimensions();
|
|
34
|
+
|
|
35
|
+
return Math.min(width, height);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getScreenAspectRatio = () => {
|
|
39
|
+
const longEdge = Math.max(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
40
|
+
const shortEdge = Math.min(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
41
|
+
|
|
42
|
+
return longEdge / shortEdge;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const getEdges = (
|
|
46
|
+
isTablet: boolean,
|
|
47
|
+
isInlineModal: boolean
|
|
48
|
+
): readonly Edge[] => {
|
|
49
|
+
if (isTablet) {
|
|
50
|
+
return ["top"];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!isInlineModal && Platform.OS === "android") {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return ["top"];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const getBaseDimensions = (
|
|
61
|
+
isInlineModal: boolean,
|
|
62
|
+
isTabletLandscape: boolean,
|
|
63
|
+
tabletWidth: DimensionValue
|
|
64
|
+
): ViewStyle => ({
|
|
65
|
+
width: isInlineModal && isTabletLandscape ? tabletWidth : "100%",
|
|
66
|
+
height: undefined,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const calculateAspectRatio = (
|
|
70
|
+
isInlineModal: boolean,
|
|
71
|
+
pip?: boolean
|
|
72
|
+
): number => {
|
|
73
|
+
return !isInlineModal && !pip ? getScreenAspectRatio() : 16 / 9;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const getPlayerDimensions = (
|
|
77
|
+
baseDimensions: ViewStyle,
|
|
78
|
+
aspectRatio: number
|
|
79
|
+
): ViewStyle => ({
|
|
80
|
+
...(baseDimensions as any),
|
|
81
|
+
width: baseDimensions.width,
|
|
82
|
+
aspectRatio,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export const getContainerDimensions = (
|
|
86
|
+
baseDimensions: ViewStyle,
|
|
87
|
+
aspectRatio?: string | number
|
|
88
|
+
): ViewStyle => ({
|
|
89
|
+
...baseDimensions,
|
|
90
|
+
aspectRatio,
|
|
91
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "15.0.0-alpha.
|
|
3
|
+
"version": "15.0.0-alpha.6835718972",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "15.0.0-alpha.
|
|
32
|
-
"@applicaster/zapp-react-native-bridge": "15.0.0-alpha.
|
|
33
|
-
"@applicaster/zapp-react-native-redux": "15.0.0-alpha.
|
|
34
|
-
"@applicaster/zapp-react-native-utils": "15.0.0-alpha.
|
|
31
|
+
"@applicaster/applicaster-types": "15.0.0-alpha.6835718972",
|
|
32
|
+
"@applicaster/zapp-react-native-bridge": "15.0.0-alpha.6835718972",
|
|
33
|
+
"@applicaster/zapp-react-native-redux": "15.0.0-alpha.6835718972",
|
|
34
|
+
"@applicaster/zapp-react-native-utils": "15.0.0-alpha.6835718972",
|
|
35
35
|
"promise": "^8.3.0",
|
|
36
36
|
"url": "^0.11.0",
|
|
37
37
|
"uuid": "^3.3.2"
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Animated, ViewStyle } from "react-native";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
useModalAnimationContext,
|
|
6
|
-
PlayerAnimationStateEnum,
|
|
7
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
|
-
|
|
9
|
-
type Props = {
|
|
10
|
-
style: ViewStyle[];
|
|
11
|
-
children: React.ReactNode;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const AnimatedPlayerModalWrapper = (props: Props) => {
|
|
15
|
-
const {
|
|
16
|
-
playerAnimationState,
|
|
17
|
-
animatedValues: { lastScrollY, dragScrollY, translateYOffset },
|
|
18
|
-
modalSnapPoints,
|
|
19
|
-
setStartComponentsAnimation,
|
|
20
|
-
} = useModalAnimationContext();
|
|
21
|
-
|
|
22
|
-
const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
|
|
23
|
-
() => ({
|
|
24
|
-
inputRange: modalSnapPoints,
|
|
25
|
-
outputRange: modalSnapPoints,
|
|
26
|
-
extrapolate: "clamp",
|
|
27
|
-
}),
|
|
28
|
-
[modalSnapPoints]
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
let translateY;
|
|
32
|
-
|
|
33
|
-
if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
|
|
34
|
-
translateY = translateYOffset.interpolate(interpolateConfig);
|
|
35
|
-
} else {
|
|
36
|
-
const reverseLastScrollY = Animated.multiply(
|
|
37
|
-
new Animated.Value(-1),
|
|
38
|
-
lastScrollY
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
translateY = Animated.add(
|
|
42
|
-
translateYOffset,
|
|
43
|
-
Animated.add(dragScrollY, reverseLastScrollY)
|
|
44
|
-
).interpolate(interpolateConfig);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
React.useEffect(() => {
|
|
48
|
-
(playerAnimationState === PlayerAnimationStateEnum.minimize ||
|
|
49
|
-
playerAnimationState === PlayerAnimationStateEnum.maximize) &&
|
|
50
|
-
setStartComponentsAnimation(true);
|
|
51
|
-
}, [playerAnimationState]);
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Animated.View
|
|
55
|
-
style={[props.style, { transform: [{ translateY: translateY }] }]}
|
|
56
|
-
>
|
|
57
|
-
{props.children}
|
|
58
|
-
</Animated.View>
|
|
59
|
-
);
|
|
60
|
-
};
|
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Animated, StyleSheet, View } from "react-native";
|
|
3
|
-
|
|
4
|
-
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
|
-
import {
|
|
6
|
-
NativeViewGestureHandler,
|
|
7
|
-
PanGestureHandler,
|
|
8
|
-
State,
|
|
9
|
-
TapGestureHandler,
|
|
10
|
-
} from "react-native-gesture-handler";
|
|
11
|
-
|
|
12
|
-
import { PlayerContainerContext } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainerContext";
|
|
13
|
-
import {
|
|
14
|
-
PlayerAnimationStateEnum,
|
|
15
|
-
useModalAnimationContext,
|
|
16
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
17
|
-
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
18
|
-
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
19
|
-
|
|
20
|
-
import {
|
|
21
|
-
resetScrollAnimatedValues,
|
|
22
|
-
setScrollModalAnimatedValue,
|
|
23
|
-
} from "./utils";
|
|
24
|
-
|
|
25
|
-
import { DURATION_TO_MINIMIZE } from "./const";
|
|
26
|
-
|
|
27
|
-
const getAnimatedConfig = (toValue) => {
|
|
28
|
-
return {
|
|
29
|
-
toValue,
|
|
30
|
-
duration: DURATION_TO_MINIMIZE,
|
|
31
|
-
useNativeDriver: true,
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const generalStyles = StyleSheet.create({
|
|
36
|
-
container: {
|
|
37
|
-
flex: 1,
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
type Props = {
|
|
42
|
-
children: React.ReactNode;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const activeOffsetY = [-5, 5] as [number, number];
|
|
46
|
-
|
|
47
|
-
export const AnimatedScrollModalComponent = ({ children }: Props) => {
|
|
48
|
-
const {
|
|
49
|
-
isActiveGesture,
|
|
50
|
-
playerAnimationState,
|
|
51
|
-
setPlayerAnimationState,
|
|
52
|
-
resetPlayerAnimationState,
|
|
53
|
-
animatedValues: {
|
|
54
|
-
lastScrollY,
|
|
55
|
-
dragScrollY,
|
|
56
|
-
dragVideoPlayerY,
|
|
57
|
-
translateYOffset,
|
|
58
|
-
},
|
|
59
|
-
lastScrollYValue,
|
|
60
|
-
scrollPosition,
|
|
61
|
-
modalSnapPoints,
|
|
62
|
-
lastSnap,
|
|
63
|
-
setLastSnap,
|
|
64
|
-
setStartComponentsAnimation,
|
|
65
|
-
} = useModalAnimationContext();
|
|
66
|
-
|
|
67
|
-
const [enableGesture, setIEnableGesture] = React.useState<boolean>(true);
|
|
68
|
-
|
|
69
|
-
const { isLanguageOverlayVisible, isSeekBarTouch } = React.useContext(
|
|
70
|
-
PlayerContainerContext
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const { maximiseVideoModal, minimiseVideoModal, videoModalState } =
|
|
74
|
-
useNavigation();
|
|
75
|
-
|
|
76
|
-
const {
|
|
77
|
-
mode: videoModalMode,
|
|
78
|
-
previousMode: previousVideoModalMode,
|
|
79
|
-
item: videoModalItem,
|
|
80
|
-
} = videoModalState;
|
|
81
|
-
|
|
82
|
-
const isMaximizedModal: boolean = videoModalMode === "MAXIMIZED";
|
|
83
|
-
const isMinimizedModal: boolean = videoModalMode === "MINIMIZED";
|
|
84
|
-
const previousItemId = usePrevious(videoModalItem?.id);
|
|
85
|
-
|
|
86
|
-
const isNotMinimizeMaximazeAnimation =
|
|
87
|
-
playerAnimationState !== PlayerAnimationStateEnum.minimize &&
|
|
88
|
-
playerAnimationState !== PlayerAnimationStateEnum.maximize;
|
|
89
|
-
|
|
90
|
-
const isEnablePanGesture =
|
|
91
|
-
enableGesture &&
|
|
92
|
-
!isLanguageOverlayVisible &&
|
|
93
|
-
isNotMinimizeMaximazeAnimation &&
|
|
94
|
-
!isSeekBarTouch &&
|
|
95
|
-
(isMaximizedModal || isMinimizedModal);
|
|
96
|
-
|
|
97
|
-
const isAudioItem = React.useMemo(
|
|
98
|
-
() =>
|
|
99
|
-
videoModalItem?.content?.type?.includes?.("audio") ||
|
|
100
|
-
videoModalItem?.type?.value === "audio",
|
|
101
|
-
[videoModalItem]
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// Refs for components
|
|
105
|
-
const scrollRef = React.useRef(null);
|
|
106
|
-
const tapHandlerRef = React.useRef(null);
|
|
107
|
-
const panHandlerRef = React.useRef(null);
|
|
108
|
-
|
|
109
|
-
const onRegisterLastScroll = Animated.event(
|
|
110
|
-
[{ nativeEvent: { contentOffset: { y: lastScrollY } } }],
|
|
111
|
-
{ useNativeDriver: true }
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const onGestureEvent = Animated.event(
|
|
115
|
-
[{ nativeEvent: { translationY: dragScrollY } }],
|
|
116
|
-
{ useNativeDriver: true }
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const onHandlerStateChange = React.useCallback(
|
|
120
|
-
({ nativeEvent }) => {
|
|
121
|
-
if (
|
|
122
|
-
nativeEvent.oldState === State.ACTIVE &&
|
|
123
|
-
scrollPosition.current === 0
|
|
124
|
-
) {
|
|
125
|
-
// eslint-disable-next-line prefer-const
|
|
126
|
-
const { velocityY, translationY } = nativeEvent;
|
|
127
|
-
const dragToss = 0.05;
|
|
128
|
-
|
|
129
|
-
const preparedTranslationY =
|
|
130
|
-
Math.abs(translationY) - lastScrollYValue.current;
|
|
131
|
-
|
|
132
|
-
if (isMaximizedModal) {
|
|
133
|
-
const endOffsetY =
|
|
134
|
-
lastSnap + preparedTranslationY + dragToss * velocityY + 150;
|
|
135
|
-
|
|
136
|
-
let destSnapPoint = modalSnapPoints[0];
|
|
137
|
-
|
|
138
|
-
for (const snapPoint of modalSnapPoints) {
|
|
139
|
-
const distFromSnap = Math.abs(snapPoint - endOffsetY);
|
|
140
|
-
|
|
141
|
-
if (distFromSnap < Math.abs(destSnapPoint - endOffsetY)) {
|
|
142
|
-
destSnapPoint = snapPoint;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
setLastSnap(destSnapPoint);
|
|
147
|
-
|
|
148
|
-
if (destSnapPoint === modalSnapPoints[0]) {
|
|
149
|
-
translateYOffset.extractOffset();
|
|
150
|
-
translateYOffset.setValue(preparedTranslationY);
|
|
151
|
-
translateYOffset.flattenOffset();
|
|
152
|
-
dragScrollY.setValue(0);
|
|
153
|
-
|
|
154
|
-
setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
|
|
155
|
-
} else if (destSnapPoint !== modalSnapPoints[0] && isMaximizedModal) {
|
|
156
|
-
setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
|
|
157
|
-
}
|
|
158
|
-
} else {
|
|
159
|
-
if (translationY < 0) {
|
|
160
|
-
// from mini to full
|
|
161
|
-
setLastSnap(modalSnapPoints[0]);
|
|
162
|
-
|
|
163
|
-
translateYOffset.setValue(
|
|
164
|
-
modalSnapPoints[1] - preparedTranslationY
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
dragScrollY.setValue(0);
|
|
168
|
-
|
|
169
|
-
setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
|
|
170
|
-
} else {
|
|
171
|
-
resetPlayerAnimationState();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
playerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
|
|
176
|
-
resetPlayerAnimationState();
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
[
|
|
180
|
-
lastSnap,
|
|
181
|
-
modalSnapPoints,
|
|
182
|
-
playerAnimationState,
|
|
183
|
-
isMinimizedModal,
|
|
184
|
-
isMaximizedModal,
|
|
185
|
-
]
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
const onScroll = React.useCallback(({ nativeEvent }) => {
|
|
189
|
-
scrollPosition.current = nativeEvent.contentOffset.y;
|
|
190
|
-
}, []);
|
|
191
|
-
|
|
192
|
-
// Workaround for onMomentumScrollEnd issue
|
|
193
|
-
// https://github.com/facebook/react-native/issues/32696#issuecomment-1104217223
|
|
194
|
-
const canMomentum = React.useRef(false);
|
|
195
|
-
|
|
196
|
-
const onMomentumScrollBegin = React.useCallback(() => {
|
|
197
|
-
canMomentum.current = true;
|
|
198
|
-
}, []);
|
|
199
|
-
|
|
200
|
-
const onMomentumScrollEnd = React.useCallback(
|
|
201
|
-
({ nativeEvent }) => {
|
|
202
|
-
if (canMomentum.current && !isActiveGesture) {
|
|
203
|
-
if (nativeEvent.contentOffset.y === 0) {
|
|
204
|
-
resetScrollAnimatedValues(
|
|
205
|
-
lastScrollY,
|
|
206
|
-
lastScrollYValue,
|
|
207
|
-
dragScrollY,
|
|
208
|
-
dragVideoPlayerY
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
setIEnableGesture(true);
|
|
212
|
-
} else {
|
|
213
|
-
setIEnableGesture(false);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
canMomentum.current = false;
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
[isActiveGesture]
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
React.useEffect(() => {
|
|
223
|
-
return () => {
|
|
224
|
-
scrollPosition.current = 0;
|
|
225
|
-
|
|
226
|
-
resetScrollAnimatedValues(
|
|
227
|
-
lastScrollY,
|
|
228
|
-
lastScrollYValue,
|
|
229
|
-
dragScrollY,
|
|
230
|
-
dragVideoPlayerY
|
|
231
|
-
);
|
|
232
|
-
};
|
|
233
|
-
}, []);
|
|
234
|
-
|
|
235
|
-
React.useEffect(() => {
|
|
236
|
-
if (
|
|
237
|
-
videoModalMode === "MAXIMIZED" &&
|
|
238
|
-
!enableGesture &&
|
|
239
|
-
scrollPosition.current === 0
|
|
240
|
-
) {
|
|
241
|
-
setIEnableGesture(true);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (
|
|
245
|
-
videoModalMode === "MINIMIZED" &&
|
|
246
|
-
previousVideoModalMode === "MAXIMIZED"
|
|
247
|
-
) {
|
|
248
|
-
// set animation to the minimize values if moving from the player to another screen
|
|
249
|
-
if (playerAnimationState === null) {
|
|
250
|
-
setScrollModalAnimatedValue(
|
|
251
|
-
translateYOffset,
|
|
252
|
-
modalSnapPoints[1],
|
|
253
|
-
setLastSnap
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
resetScrollAnimatedValues(
|
|
257
|
-
lastScrollY,
|
|
258
|
-
lastScrollYValue,
|
|
259
|
-
dragScrollY,
|
|
260
|
-
dragVideoPlayerY
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
} else if (
|
|
264
|
-
playerAnimationState === null &&
|
|
265
|
-
((previousItemId === videoModalItem?.id &&
|
|
266
|
-
videoModalMode === "MAXIMIZED" &&
|
|
267
|
-
(previousVideoModalMode === "MINIMIZED" ||
|
|
268
|
-
previousVideoModalMode === "MAXIMIZED")) ||
|
|
269
|
-
(previousItemId !== videoModalItem?.id &&
|
|
270
|
-
videoModalMode !== "FULLSCREEN"))
|
|
271
|
-
) {
|
|
272
|
-
setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
|
|
273
|
-
}
|
|
274
|
-
}, [videoModalMode, previousVideoModalMode, videoModalItem]);
|
|
275
|
-
|
|
276
|
-
React.useEffect(() => {
|
|
277
|
-
if (playerAnimationState === PlayerAnimationStateEnum.minimize) {
|
|
278
|
-
if (
|
|
279
|
-
(scrollPosition.current === 0 &&
|
|
280
|
-
(lastScrollY as any)._value !== 0 &&
|
|
281
|
-
(dragScrollY as any)._value === 0 &&
|
|
282
|
-
(dragVideoPlayerY as any)._value === 0) ||
|
|
283
|
-
(scrollPosition.current !== 0 &&
|
|
284
|
-
((dragScrollY as any)._value !== 0 ||
|
|
285
|
-
(dragVideoPlayerY as any)._value !== 0))
|
|
286
|
-
) {
|
|
287
|
-
resetScrollAnimatedValues(
|
|
288
|
-
lastScrollY,
|
|
289
|
-
lastScrollYValue,
|
|
290
|
-
dragScrollY,
|
|
291
|
-
dragVideoPlayerY
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
Animated.timing(
|
|
296
|
-
translateYOffset,
|
|
297
|
-
getAnimatedConfig(modalSnapPoints[1])
|
|
298
|
-
).start(() => {
|
|
299
|
-
minimiseVideoModal();
|
|
300
|
-
|
|
301
|
-
setScrollModalAnimatedValue(
|
|
302
|
-
translateYOffset,
|
|
303
|
-
modalSnapPoints[1],
|
|
304
|
-
setLastSnap
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
resetScrollAnimatedValues(
|
|
308
|
-
lastScrollY,
|
|
309
|
-
lastScrollYValue,
|
|
310
|
-
dragScrollY,
|
|
311
|
-
dragVideoPlayerY
|
|
312
|
-
);
|
|
313
|
-
|
|
314
|
-
resetPlayerAnimationState();
|
|
315
|
-
});
|
|
316
|
-
} else if (playerAnimationState === PlayerAnimationStateEnum.maximize) {
|
|
317
|
-
Animated.timing(translateYOffset, getAnimatedConfig(0)).start(() => {
|
|
318
|
-
maximiseVideoModal();
|
|
319
|
-
setScrollModalAnimatedValue(translateYOffset, 0, setLastSnap);
|
|
320
|
-
|
|
321
|
-
resetScrollAnimatedValues(
|
|
322
|
-
lastScrollY,
|
|
323
|
-
lastScrollYValue,
|
|
324
|
-
dragScrollY,
|
|
325
|
-
dragVideoPlayerY
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
resetPlayerAnimationState();
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
}, [playerAnimationState]);
|
|
332
|
-
|
|
333
|
-
React.useEffect(() => {
|
|
334
|
-
const lastScrollYListenerId = lastScrollY.addListener(({ value }) => {
|
|
335
|
-
lastScrollYValue.current = value;
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
const dragListenerId = dragScrollY.addListener(({ value }) => {
|
|
339
|
-
const preparedValue =
|
|
340
|
-
isMinimizedModal && value >= 0
|
|
341
|
-
? 0
|
|
342
|
-
: Math.round(isAudioItem ? Math.abs(value) : value);
|
|
343
|
-
|
|
344
|
-
if (
|
|
345
|
-
preparedValue > 0 &&
|
|
346
|
-
scrollPosition.current === 0 &&
|
|
347
|
-
playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
|
|
348
|
-
playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
|
|
349
|
-
) {
|
|
350
|
-
isMinimizedModal && setStartComponentsAnimation(true);
|
|
351
|
-
setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
return () => {
|
|
356
|
-
lastScrollY.removeListener(lastScrollYListenerId);
|
|
357
|
-
dragScrollY.removeListener(dragListenerId);
|
|
358
|
-
};
|
|
359
|
-
}, [playerAnimationState, isAudioItem, isMinimizedModal]);
|
|
360
|
-
|
|
361
|
-
const scrollEnabled = isMaximizedModal && isNotMinimizeMaximazeAnimation;
|
|
362
|
-
|
|
363
|
-
return (
|
|
364
|
-
<View style={generalStyles.container}>
|
|
365
|
-
<TapGestureHandler
|
|
366
|
-
maxDurationMs={100000}
|
|
367
|
-
ref={tapHandlerRef}
|
|
368
|
-
maxDeltaY={lastSnap - modalSnapPoints[0]}
|
|
369
|
-
numberOfTaps={1}
|
|
370
|
-
>
|
|
371
|
-
<View pointerEvents="box-none">
|
|
372
|
-
<PanGestureHandler
|
|
373
|
-
enabled={isEnablePanGesture}
|
|
374
|
-
ref={panHandlerRef}
|
|
375
|
-
simultaneousHandlers={[scrollRef, tapHandlerRef]}
|
|
376
|
-
shouldCancelWhenOutside={isMaximizedModal}
|
|
377
|
-
activeOffsetY={activeOffsetY}
|
|
378
|
-
onGestureEvent={onGestureEvent}
|
|
379
|
-
onHandlerStateChange={onHandlerStateChange}
|
|
380
|
-
>
|
|
381
|
-
<Animated.View>
|
|
382
|
-
<NativeViewGestureHandler
|
|
383
|
-
ref={scrollRef}
|
|
384
|
-
waitFor={tapHandlerRef}
|
|
385
|
-
simultaneousHandlers={panHandlerRef}
|
|
386
|
-
>
|
|
387
|
-
<Animated.ScrollView
|
|
388
|
-
scrollEnabled={scrollEnabled}
|
|
389
|
-
bounces={false}
|
|
390
|
-
onScrollBeginDrag={onRegisterLastScroll}
|
|
391
|
-
onScroll={onScroll}
|
|
392
|
-
onMomentumScrollBegin={onMomentumScrollBegin}
|
|
393
|
-
onMomentumScrollEnd={onMomentumScrollEnd}
|
|
394
|
-
scrollEventThrottle={1}
|
|
395
|
-
showsVerticalScrollIndicator={false}
|
|
396
|
-
>
|
|
397
|
-
{children}
|
|
398
|
-
</Animated.ScrollView>
|
|
399
|
-
</NativeViewGestureHandler>
|
|
400
|
-
</Animated.View>
|
|
401
|
-
</PanGestureHandler>
|
|
402
|
-
</View>
|
|
403
|
-
</TapGestureHandler>
|
|
404
|
-
</View>
|
|
405
|
-
);
|
|
406
|
-
};
|
|
407
|
-
|
|
408
|
-
export const AnimatedScrollModal = ({ children }: Props) => {
|
|
409
|
-
const {
|
|
410
|
-
videoModalState: { visible },
|
|
411
|
-
} = useNavigation();
|
|
412
|
-
|
|
413
|
-
const Component =
|
|
414
|
-
!isTV() && visible ? AnimatedScrollModalComponent : React.Fragment;
|
|
415
|
-
|
|
416
|
-
return <Component>{children}</Component>;
|
|
417
|
-
};
|