@applicaster/zapp-react-native-ui-components 12.0.0-rc.10 → 12.0.0-rc.101

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.
Files changed (150) hide show
  1. package/Components/AudioPlayer/AudioPlayer.tsx +9 -1
  2. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +5 -0
  3. package/Components/AudioPlayer/helpers.tsx +1 -0
  4. package/Components/BaseFocusable/index.tsx +3 -3
  5. package/Components/Cell/Cell.tsx +32 -11
  6. package/Components/Cell/CellWithFocusable.tsx +40 -19
  7. package/Components/Cell/TvOSCellComponent.tsx +5 -9
  8. package/Components/ErrorScreen/index.tsx +1 -1
  9. package/Components/Focusable/Focusable.tsx +6 -1
  10. package/Components/FocusableCell/index.tsx +7 -7
  11. package/Components/FocusableGroup/index.tsx +11 -2
  12. package/Components/FocusableList/FocusableChild.ts +24 -14
  13. package/Components/FocusableList/FocusableItem.tsx +1 -1
  14. package/Components/FocusableList/FocusableListItemWrapper.tsx +76 -0
  15. package/Components/FocusableList/hooks/useCellState.android.ts +3 -1
  16. package/Components/FocusableList/index.tsx +26 -25
  17. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +11 -8
  18. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  19. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  20. package/Components/HandlePlayable/HandlePlayable.tsx +4 -1
  21. package/Components/HookRenderer/index.tsx +1 -6
  22. package/Components/Image/Image.android.tsx +3 -26
  23. package/Components/Image/Image.tsx +18 -2
  24. package/Components/Image/utils/index.ts +39 -0
  25. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  26. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  27. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  28. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  29. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  30. package/Components/Layout/TV/__tests__/index.test.tsx +20 -108
  31. package/Components/Layout/TV/index.tsx +15 -84
  32. package/Components/Layout/TV/index.web.tsx +33 -0
  33. package/Components/Layout/index.tsx +15 -11
  34. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
  35. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +88 -113
  36. package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
  37. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  38. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  39. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
  40. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  41. package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
  42. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  43. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +37 -2
  44. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
  45. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  46. package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
  47. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  48. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  49. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  50. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
  51. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +6 -10
  52. package/Components/MasterCell/dataAdapter.ts +21 -7
  53. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  54. package/Components/MasterCell/index.tsx +3 -1
  55. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  56. package/Components/MasterCell/utils/index.ts +33 -35
  57. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  58. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  59. package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
  60. package/Components/ModalComponent/Button/Item.tsx +82 -0
  61. package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
  62. package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
  63. package/Components/ModalComponent/Button/assets.ts +4 -0
  64. package/Components/ModalComponent/Button/index.tsx +111 -0
  65. package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
  66. package/Components/ModalComponent/Header/Title.tsx +70 -0
  67. package/Components/ModalComponent/Header/assets.ts +4 -0
  68. package/Components/ModalComponent/Header/index.tsx +71 -0
  69. package/Components/ModalComponent/Header/utils.ts +79 -0
  70. package/Components/ModalComponent/index.tsx +38 -0
  71. package/Components/ModalComponent/utils.ts +126 -0
  72. package/Components/Navigator/StackNavigator.tsx +57 -0
  73. package/Components/Navigator/index.ts +1 -0
  74. package/Components/PlayerContainer/PlayerContainer.tsx +66 -31
  75. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
  76. package/Components/PlayerImageBackground/index.tsx +34 -8
  77. package/Components/River/ComponentsMap/ComponentsMap.tsx +97 -2
  78. package/Components/River/RefreshControl.tsx +55 -1
  79. package/Components/River/River.tsx +8 -5
  80. package/Components/River/TV/River.tsx +2 -25
  81. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
  82. package/Components/River/__tests__/componentsMap.test.js +7 -0
  83. package/Components/River/useScreenConfiguration.ts +2 -2
  84. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
  85. package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
  86. package/Components/RouteManager/index.tsx +4 -2
  87. package/Components/Screen/TV/hooks/index.ts +3 -0
  88. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  89. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  90. package/Components/Screen/TV/index.web.tsx +165 -0
  91. package/Components/Screen/__tests__/Screen.test.tsx +91 -74
  92. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
  93. package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
  94. package/Components/Screen/index.tsx +110 -54
  95. package/Components/Screen/navigationHandler.ts +5 -82
  96. package/Components/ScreenResolver/index.tsx +10 -13
  97. package/Components/Tabs/TV/styles.ts +1 -1
  98. package/Components/TrackedView/index.tsx +6 -3
  99. package/Components/Transitioner/Scene.tsx +32 -26
  100. package/Components/Transitioner/Transitioner.tsx +21 -28
  101. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
  102. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  103. package/Components/VideoLive/LiveImageManager.ts +70 -14
  104. package/Components/VideoLive/PlayerLiveImageComponent.tsx +132 -95
  105. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
  106. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +21 -29
  107. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +66 -0
  108. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +355 -0
  109. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +161 -0
  110. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +456 -0
  111. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +182 -0
  112. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  113. package/Components/VideoModal/ModalAnimation/utils.ts +302 -0
  114. package/Components/VideoModal/PlayerDetails.tsx +6 -3
  115. package/Components/VideoModal/PlayerWrapper.tsx +81 -49
  116. package/Components/VideoModal/VideoModal.tsx +23 -40
  117. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
  118. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +12 -1
  119. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +266 -166
  120. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  121. package/Components/VideoModal/utils.ts +8 -5
  122. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
  123. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  124. package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
  125. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  126. package/Components/Viewport/utils.js +1 -1
  127. package/Components/ZappUIComponent/index.tsx +22 -12
  128. package/Components/index.js +2 -0
  129. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  130. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  131. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  132. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  133. package/Contexts/FocusableGroupContext/index.ts +7 -0
  134. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  135. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  136. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  137. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  138. package/Contexts/ScreenContext/index.tsx +95 -29
  139. package/Contexts/ScreenDataContext/index.tsx +20 -0
  140. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  141. package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
  142. package/Decorators/RiverResolver/index.tsx +0 -4
  143. package/Decorators/index.tsx +0 -4
  144. package/events/index.ts +1 -0
  145. package/package.json +5 -6
  146. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  147. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  148. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  149. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
  150. /package/Contexts/{index.js → index.ts} +0 -0
@@ -3,7 +3,14 @@ import * as React from "react";
3
3
  import { render } from "@testing-library/react-native";
4
4
  import * as PlayerFactory from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
5
5
  import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
6
+ import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
7
+ import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
8
+
6
9
  import { PlayerLiveImage } from "../PlayerLiveImageComponent";
10
+ import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
11
+
12
+ import { Provider } from "react-redux";
13
+ import configureStore from "redux-mock-store";
7
14
 
8
15
  const seekTo = jest.fn();
9
16
 
@@ -16,6 +23,27 @@ jest.mock(
16
23
  })
17
24
  );
18
25
 
26
+ jest
27
+ .spyOn(useNavigationHooks, "useNavigation")
28
+ .mockImplementation(() => ({ videoModalState: { visible: false } }));
29
+
30
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
31
+
32
+ const mockStore = configureStore();
33
+
34
+ const store = mockStore({ appData: {} });
35
+
36
+ const Wrapper = ({ children }: { children: React.ReactChildren }) => (
37
+ /* @ts-ignore */
38
+ <Provider store={store}>
39
+ <ThemeContext.Provider
40
+ value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
41
+ >
42
+ {children}
43
+ </ThemeContext.Provider>
44
+ </Provider>
45
+ );
46
+
19
47
  describe("PlayerLiveImageComponent", () => {
20
48
  const defaultProps = {
21
49
  item: { id: "1", title: "Test", type: { value: "" } },
@@ -36,10 +64,16 @@ describe("PlayerLiveImageComponent", () => {
36
64
  controller: new Player({}),
37
65
  Component: () => null,
38
66
  }));
67
+
68
+ jest.spyOn(navigationHooks, "useIsScreenActive").mockReturnValue(true);
39
69
  });
40
70
 
41
71
  it("should render correctly with default props", () => {
42
- const component = render(<PlayerLiveImage {...defaultProps} />);
72
+ const component = render(
73
+ <Wrapper>
74
+ <PlayerLiveImage {...defaultProps} />
75
+ </Wrapper>
76
+ );
43
77
 
44
78
  expect(component.toJSON()).toMatchSnapshot();
45
79
  });
@@ -53,7 +87,11 @@ describe("PlayerLiveImageComponent", () => {
53
87
  },
54
88
  };
55
89
 
56
- render(<PlayerLiveImage {...props} />);
90
+ render(
91
+ <Wrapper>
92
+ <PlayerLiveImage {...props} />
93
+ </Wrapper>
94
+ );
57
95
 
58
96
  // TODO: implement this test
59
97
  });
@@ -67,7 +105,11 @@ describe("PlayerLiveImageComponent", () => {
67
105
  },
68
106
  };
69
107
 
70
- render(<PlayerLiveImage {...props} />);
108
+ render(
109
+ <Wrapper>
110
+ <PlayerLiveImage {...props} />
111
+ </Wrapper>
112
+ );
71
113
 
72
114
  // TODO: implement this test
73
115
  });
@@ -5,41 +5,33 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
5
5
  onPositionUpdated={[Function]}
6
6
  testId="tracked-view-player1-Test"
7
7
  >
8
- <View
9
- collapsable={false}
10
- style={
11
- Object {
12
- "opacity": 1,
13
- }
14
- }
15
- >
8
+ <View>
16
9
  <View
17
- accessibilityIgnoresInvertColors={true}
18
- style={Object {}}
10
+ collapsable={false}
11
+ style={
12
+ Object {
13
+ "opacity": 1,
14
+ }
15
+ }
19
16
  >
20
17
  <Image
21
- resizeMode="cover"
22
- source={
18
+ applyMaxSize={true}
19
+ audioMutedByDefault={false}
20
+ imageKey="image1"
21
+ item={
23
22
  Object {
24
- "uri": undefined,
25
- }
26
- }
27
- style={
28
- Array [
29
- Object {
30
- "bottom": 0,
31
- "left": 0,
32
- "position": "absolute",
33
- "right": 0,
34
- "top": 0,
35
- },
36
- Object {
37
- "height": undefined,
38
- "width": undefined,
23
+ "id": "1",
24
+ "title": "Test",
25
+ "type": Object {
26
+ "value": "",
39
27
  },
40
- undefined,
41
- ]
28
+ }
42
29
  }
30
+ onError={[Function]}
31
+ playerId="player1"
32
+ resizeMode="cover"
33
+ screenConfig={Object {}}
34
+ style={Object {}}
43
35
  />
44
36
  </View>
45
37
  </View>
@@ -0,0 +1,66 @@
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
+ const translateYListener = translateY.addListener(() => {
49
+ (playerAnimationState === PlayerAnimationStateEnum.minimize ||
50
+ playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
51
+ setStartComponentsAnimation(true);
52
+ });
53
+
54
+ return () => {
55
+ translateYListener && translateY.removeListener(translateYListener);
56
+ };
57
+ }, [playerAnimationState]);
58
+
59
+ return (
60
+ <Animated.View
61
+ style={[props.style, { transform: [{ translateY: translateY }] }]}
62
+ >
63
+ {props.children}
64
+ </Animated.View>
65
+ );
66
+ };
@@ -0,0 +1,355 @@
1
+ import React from "react";
2
+ import { Animated, StyleSheet, View, Platform } 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
+ GestureHandlerRootView,
11
+ } from "react-native-gesture-handler";
12
+
13
+ import { PlayerContainerContext } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainerContext";
14
+ import {
15
+ useModalAnimationContext,
16
+ PlayerAnimationStateEnum,
17
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
18
+ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
19
+ import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
20
+
21
+ import {
22
+ setScrollModalAnimatedValue,
23
+ resetScrollAnimatedValues,
24
+ } from "./utils";
25
+
26
+ const getAnimatedConfig = (toValue) => {
27
+ return {
28
+ toValue,
29
+ duration: 200,
30
+ useNativeDriver: true,
31
+ };
32
+ };
33
+
34
+ const generalStyles = StyleSheet.create({
35
+ container: {
36
+ flex: 1,
37
+ },
38
+ });
39
+
40
+ type Props = {
41
+ children: React.ReactNode;
42
+ };
43
+
44
+ export const AnimatedScrollModalComponent = ({ children }: Props) => {
45
+ const {
46
+ isActiveGesture,
47
+ playerAnimationState,
48
+ setPlayerAnimationState,
49
+ resetPlayerAnimationState,
50
+ animatedValues: {
51
+ lastScrollY,
52
+ dragScrollY,
53
+ dragVideoPlayerY,
54
+ translateYOffset,
55
+ },
56
+ lastScrollYValue,
57
+ scrollPosition,
58
+ modalSnapPoints,
59
+ lastSnap,
60
+ setLastSnap,
61
+ setStartComponentsAnimation,
62
+ } = useModalAnimationContext();
63
+
64
+ const { isLanguageOverlayVisible } = React.useContext(PlayerContainerContext);
65
+
66
+ const { maximiseVideoModal, minimiseVideoModal, videoModalState } =
67
+ useNavigation();
68
+
69
+ const isMaximazedModal = videoModalState.mode === "MAXIMIZED";
70
+ const isMinimizedModal = videoModalState.mode === "MINIMIZED";
71
+ const previousItemId = usePrevious(videoModalState.item?.id);
72
+
73
+ const isNotMinimizeMaximazeAnimation =
74
+ playerAnimationState !== PlayerAnimationStateEnum.minimize &&
75
+ playerAnimationState !== PlayerAnimationStateEnum.maximaze;
76
+
77
+ const isEnablePanGesture =
78
+ !isLanguageOverlayVisible &&
79
+ isNotMinimizeMaximazeAnimation &&
80
+ (isMaximazedModal || isMinimizedModal);
81
+
82
+ const isAudioItem = React.useMemo(
83
+ () =>
84
+ videoModalState.item?.content?.type?.includes?.("audio") ||
85
+ videoModalState.item?.type?.value === "audio",
86
+ [videoModalState.item]
87
+ );
88
+
89
+ // Refs for components
90
+ const scrollRef = React.useRef(null);
91
+ const tapHandlerRef = React.useRef(null);
92
+ const panHandlerRef = React.useRef(null);
93
+
94
+ const onRegisterLastScroll = Animated.event(
95
+ [{ nativeEvent: { contentOffset: { y: lastScrollY } } }],
96
+ { useNativeDriver: true }
97
+ );
98
+
99
+ const onGestureEvent = Animated.event(
100
+ [{ nativeEvent: { translationY: dragScrollY } }],
101
+ { useNativeDriver: true }
102
+ );
103
+
104
+ const onHandlerStateChange = React.useCallback(
105
+ ({ nativeEvent }) => {
106
+ if (
107
+ nativeEvent.oldState === State.ACTIVE &&
108
+ scrollPosition.current === 0
109
+ ) {
110
+ // eslint-disable-next-line prefer-const
111
+ const { velocityY, translationY } = nativeEvent;
112
+ const dragToss = 0.05;
113
+
114
+ const preparedTranslationY =
115
+ Math.abs(translationY) - lastScrollYValue.current;
116
+
117
+ if (videoModalState.mode === "MAXIMIZED") {
118
+ const endOffsetY =
119
+ lastSnap + preparedTranslationY + dragToss * velocityY + 150;
120
+
121
+ let destSnapPoint = modalSnapPoints[0];
122
+
123
+ for (const snapPoint of modalSnapPoints) {
124
+ const distFromSnap = Math.abs(snapPoint - endOffsetY);
125
+
126
+ if (distFromSnap < Math.abs(destSnapPoint - endOffsetY)) {
127
+ destSnapPoint = snapPoint;
128
+ }
129
+ }
130
+
131
+ setLastSnap(destSnapPoint);
132
+
133
+ if (destSnapPoint === modalSnapPoints[0]) {
134
+ translateYOffset.extractOffset();
135
+ translateYOffset.setValue(preparedTranslationY);
136
+ translateYOffset.flattenOffset();
137
+ dragScrollY.setValue(0);
138
+
139
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
140
+ } else {
141
+ setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
142
+ }
143
+ } else {
144
+ if (translationY < 0) {
145
+ // from mini to full
146
+ setLastSnap(modalSnapPoints[0]);
147
+
148
+ translateYOffset.setValue(
149
+ modalSnapPoints[1] - preparedTranslationY
150
+ );
151
+
152
+ dragScrollY.setValue(0);
153
+
154
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
155
+ } else {
156
+ resetPlayerAnimationState();
157
+ }
158
+ }
159
+ } else {
160
+ playerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
161
+ resetPlayerAnimationState();
162
+ }
163
+ },
164
+ [lastSnap, modalSnapPoints, playerAnimationState, videoModalState.mode]
165
+ );
166
+
167
+ const onScroll = React.useCallback(({ nativeEvent }) => {
168
+ scrollPosition.current = nativeEvent.contentOffset.y;
169
+ }, []);
170
+
171
+ const onMomentumScrollEnd = React.useCallback(
172
+ ({ nativeEvent }) => {
173
+ if (nativeEvent.contentOffset.y === 0 && !isActiveGesture) {
174
+ resetScrollAnimatedValues(
175
+ lastScrollY,
176
+ lastScrollYValue,
177
+ dragScrollY,
178
+ dragVideoPlayerY
179
+ );
180
+ }
181
+ },
182
+ [isActiveGesture]
183
+ );
184
+
185
+ React.useEffect(() => {
186
+ return () => {
187
+ scrollPosition.current = 0;
188
+
189
+ resetScrollAnimatedValues(
190
+ lastScrollY,
191
+ lastScrollYValue,
192
+ dragScrollY,
193
+ dragVideoPlayerY
194
+ );
195
+ };
196
+ }, []);
197
+
198
+ React.useEffect(() => {
199
+ if (
200
+ videoModalState.mode === "MINIMIZED" &&
201
+ videoModalState.previousMode === "MAXIMIZED"
202
+ ) {
203
+ resetPlayerAnimationState();
204
+ }
205
+
206
+ if (
207
+ (videoModalState.mode === "MAXIMIZED" &&
208
+ videoModalState.previousMode === "MINIMIZED" &&
209
+ previousItemId === videoModalState.item?.id) ||
210
+ previousItemId !== videoModalState.item?.id
211
+ ) {
212
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
213
+ setTimeout(() => resetPlayerAnimationState());
214
+ }
215
+ }, [videoModalState, previousItemId]);
216
+
217
+ React.useEffect(() => {
218
+ if (playerAnimationState === PlayerAnimationStateEnum.minimize) {
219
+ if (
220
+ (scrollPosition.current === 0 &&
221
+ (lastScrollY as any)._value !== 0 &&
222
+ (dragScrollY as any)._value === 0 &&
223
+ (dragVideoPlayerY as any)._value === 0) ||
224
+ (scrollPosition.current !== 0 &&
225
+ ((dragScrollY as any)._value !== 0 ||
226
+ (dragVideoPlayerY as any)._value !== 0))
227
+ ) {
228
+ resetScrollAnimatedValues(
229
+ lastScrollY,
230
+ lastScrollYValue,
231
+ dragScrollY,
232
+ dragVideoPlayerY
233
+ );
234
+ }
235
+
236
+ Animated.timing(
237
+ translateYOffset,
238
+ getAnimatedConfig(modalSnapPoints[1])
239
+ ).start(() => {
240
+ setTimeout(() => {
241
+ minimiseVideoModal();
242
+
243
+ setScrollModalAnimatedValue(
244
+ translateYOffset,
245
+ modalSnapPoints[1],
246
+ setLastSnap
247
+ );
248
+
249
+ resetScrollAnimatedValues(
250
+ lastScrollY,
251
+ lastScrollYValue,
252
+ dragScrollY,
253
+ dragVideoPlayerY
254
+ );
255
+ }, 150);
256
+ });
257
+ } else if (playerAnimationState === PlayerAnimationStateEnum.maximaze) {
258
+ Animated.timing(translateYOffset, getAnimatedConfig(0)).start(() => {
259
+ maximiseVideoModal();
260
+ setScrollModalAnimatedValue(translateYOffset, 0, setLastSnap);
261
+
262
+ resetScrollAnimatedValues(
263
+ lastScrollY,
264
+ lastScrollYValue,
265
+ dragScrollY,
266
+ dragVideoPlayerY
267
+ );
268
+
269
+ resetPlayerAnimationState();
270
+ });
271
+ }
272
+
273
+ const lastScrollYListenerId = lastScrollY.addListener(({ value }) => {
274
+ lastScrollYValue.current = value;
275
+ });
276
+
277
+ const dragListenerId = dragScrollY.addListener(({ value }) => {
278
+ const preparedValue =
279
+ isMinimizedModal && value >= 0
280
+ ? 0
281
+ : Math.round(isAudioItem ? Math.abs(value) : value);
282
+
283
+ if (
284
+ preparedValue > 0 &&
285
+ scrollPosition.current === 0 &&
286
+ playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
287
+ playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
288
+ ) {
289
+ isMinimizedModal && setStartComponentsAnimation(true);
290
+ setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
291
+ }
292
+ });
293
+
294
+ return () => {
295
+ lastScrollY.removeListener(lastScrollYListenerId);
296
+ dragScrollY.removeListener(dragListenerId);
297
+ };
298
+ }, [playerAnimationState, isAudioItem, modalSnapPoints, isMinimizedModal]);
299
+
300
+ const Wrapper = React.useMemo(
301
+ () => (Platform.OS === "android" ? GestureHandlerRootView : View),
302
+ []
303
+ );
304
+
305
+ return (
306
+ <Wrapper style={generalStyles.container}>
307
+ <TapGestureHandler
308
+ maxDurationMs={100000}
309
+ ref={tapHandlerRef}
310
+ maxDeltaY={lastSnap - modalSnapPoints[0]}
311
+ numberOfTaps={1}
312
+ >
313
+ <View pointerEvents="box-none">
314
+ <PanGestureHandler
315
+ enabled={isEnablePanGesture}
316
+ ref={panHandlerRef}
317
+ simultaneousHandlers={[scrollRef, tapHandlerRef]}
318
+ shouldCancelWhenOutside={isMaximazedModal}
319
+ onGestureEvent={onGestureEvent}
320
+ onHandlerStateChange={onHandlerStateChange}
321
+ activeOffsetY={[-5, 5]}
322
+ >
323
+ <Animated.View>
324
+ <NativeViewGestureHandler
325
+ ref={scrollRef}
326
+ waitFor={tapHandlerRef}
327
+ simultaneousHandlers={panHandlerRef}
328
+ >
329
+ <Animated.ScrollView
330
+ scrollEnabled={
331
+ isMaximazedModal && isNotMinimizeMaximazeAnimation
332
+ }
333
+ bounces={false}
334
+ onScrollBeginDrag={onRegisterLastScroll}
335
+ onScroll={onScroll}
336
+ onMomentumScrollEnd={onMomentumScrollEnd}
337
+ scrollEventThrottle={1}
338
+ showsVerticalScrollIndicator={false}
339
+ >
340
+ {children}
341
+ </Animated.ScrollView>
342
+ </NativeViewGestureHandler>
343
+ </Animated.View>
344
+ </PanGestureHandler>
345
+ </View>
346
+ </TapGestureHandler>
347
+ </Wrapper>
348
+ );
349
+ };
350
+
351
+ export const AnimatedScrollModal = ({ children }: Props) => {
352
+ const Component = !isTV() ? AnimatedScrollModalComponent : React.Fragment;
353
+
354
+ return <Component>{children}</Component>;
355
+ };