@applicaster/zapp-react-native-ui-components 12.0.0-alpha.7725319213 → 12.0.0-alpha.8121552272

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