@applicaster/zapp-react-native-ui-components 12.0.0-alpha.8433353116 → 12.0.0-alpha.8961274073

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 (40) hide show
  1. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  2. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  3. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  4. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +14 -1
  5. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  6. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  7. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  8. package/Components/MasterCell/utils/index.ts +16 -5
  9. package/Components/PlayerContainer/PlayerContainer.tsx +16 -9
  10. package/Components/PlayerImageBackground/index.tsx +34 -8
  11. package/Components/River/ComponentsMap/ComponentsMap.tsx +86 -22
  12. package/Components/River/RefreshControl.tsx +55 -1
  13. package/Components/River/__tests__/componentsMap.test.js +6 -0
  14. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  15. package/Components/Screen/index.tsx +36 -25
  16. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +20 -5
  17. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  18. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
  19. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
  20. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
  21. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
  22. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
  23. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  24. package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
  25. package/Components/VideoModal/PlayerWrapper.tsx +64 -41
  26. package/Components/VideoModal/VideoModal.tsx +25 -42
  27. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +6 -1
  28. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +151 -119
  29. package/Components/VideoModal/utils.ts +3 -3
  30. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +1 -1
  31. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  32. package/Components/Viewport/utils.js +1 -1
  33. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  34. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  35. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  36. package/Contexts/ScreenContext/index.tsx +94 -25
  37. package/events/index.ts +1 -0
  38. package/package.json +5 -5
  39. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  40. /package/Contexts/{index.js → index.ts} +0 -0
@@ -6,7 +6,10 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
6
 
7
7
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
8
8
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
9
- import { getNavigationPropsV2 } from "@applicaster/zapp-react-native-utils/navigationUtils";
9
+ import {
10
+ getNavigationPropsV2,
11
+ resolveNavigationPlugin,
12
+ } from "@applicaster/zapp-react-native-utils/navigationUtils";
10
13
  import { useSafeAreaInsets } from "react-native-safe-area-context";
11
14
  import {
12
15
  useDimensions,
@@ -52,11 +55,11 @@ function isValidColor(string) {
52
55
  }
53
56
 
54
57
  type Props = {
55
- setToggleMenu: () => void;
56
- setCloseMenu: () => void;
58
+ pathname: unknown;
59
+ screenData: unknown;
57
60
  };
58
61
 
59
- export function Screen({ setToggleMenu, setCloseMenu }: Props) {
62
+ export function Screen(_props: Props) {
60
63
  const theme = useTheme<BaseThemePropertiesMobile>();
61
64
  const navigation = useNavigation();
62
65
  const { plugins } = usePickFromState(["plugins"]);
@@ -70,26 +73,38 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
70
73
  fullDimensions: true,
71
74
  });
72
75
 
73
- const routeData = useRoute();
76
+ const { screenData, pathname } = useRoute();
74
77
 
75
78
  const currentRiver = useScreenData(
76
- getScreenId(routeData.screenData, navigation.activeRiver)
79
+ getScreenId(screenData, navigation.activeRiver)
77
80
  );
78
81
 
79
82
  const { title } = useNavbarState();
80
83
 
81
- const navBarProps = React.useMemo(
82
- () => ({
83
- ...getNavigationPropsV2({
84
- currentRiver,
85
- title,
86
- category: "nav_bar",
87
- }),
88
- setToggleMenu,
89
- setCloseMenu,
90
- }),
91
- [currentRiver, setCloseMenu, setToggleMenu]
92
- );
84
+ const hasMenu =
85
+ resolveNavigationPlugin({
86
+ category: "menu",
87
+ navigations: currentRiver.navigations,
88
+ plugins,
89
+ })?.identifier === "quick_brick_side_menu";
90
+
91
+ const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
92
+ const props = getNavigationPropsV2({
93
+ currentRiver,
94
+ title,
95
+ category: "nav_bar",
96
+ });
97
+
98
+ if (props) {
99
+ return {
100
+ ...props,
101
+ id: pathname,
102
+ pathname: pathname,
103
+ };
104
+ }
105
+
106
+ return null;
107
+ }, [currentRiver, pathname]);
93
108
 
94
109
  const NavBar = React.useMemo(
95
110
  () =>
@@ -97,12 +112,10 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
97
112
  "nav_bar",
98
113
  currentRiver,
99
114
  plugins
100
- ) as React.ComponentType<MobileNavBarPluginProps>,
115
+ ) as React.ComponentType<MobileNavBarPluginProps & { hasMenu: boolean }>,
101
116
  []
102
117
  );
103
118
 
104
- const { screenData, pathname } = routeData;
105
-
106
119
  const offlinePlugin = getComponentModule({
107
120
  plugins,
108
121
  components: {},
@@ -133,11 +146,9 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
133
146
  return (
134
147
  <ScreenContextProvider pathname={pathname}>
135
148
  <View style={style}>
136
- <NavBar
137
- {...{ ...(navBarProps as MobileNavBarPluginProps), id: pathname }}
138
- />
149
+ {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
139
150
 
140
- <OfflineFallbackScreen screenData={screenData}>
151
+ <OfflineFallbackScreen screenData={targetScreenData}>
141
152
  {/* @TODO RouteManager doesn't use props, can they be removed ? */}
142
153
  <RouteManager pathname={pathname} screenData={screenData} />
143
154
  </OfflineFallbackScreen>
@@ -7,6 +7,10 @@ import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
7
7
  import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
8
8
 
9
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";
10
14
 
11
15
  const seekTo = jest.fn();
12
16
 
@@ -19,14 +23,25 @@ jest.mock(
19
23
  })
20
24
  );
21
25
 
26
+ jest
27
+ .spyOn(useNavigationHooks, "useNavigation")
28
+ .mockImplementation(() => ({ videoModalState: { visible: false } }));
29
+
22
30
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
23
31
 
32
+ const mockStore = configureStore();
33
+
34
+ const store = mockStore({ appData: {} });
35
+
24
36
  const Wrapper = ({ children }: { children: React.ReactChildren }) => (
25
- <ThemeContext.Provider
26
- value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
27
- >
28
- {children}
29
- </ThemeContext.Provider>
37
+ /* @ts-ignore */
38
+ <Provider store={store}>
39
+ <ThemeContext.Provider
40
+ value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
41
+ >
42
+ {children}
43
+ </ThemeContext.Provider>
44
+ </Provider>
30
45
  );
31
46
 
32
47
  describe("PlayerLiveImageComponent", () => {
@@ -30,11 +30,6 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
30
30
  playerId="player1"
31
31
  resizeMode="cover"
32
32
  screenConfig={Object {}}
33
- source={
34
- Object {
35
- "uri": "",
36
- }
37
- }
38
33
  style={Object {}}
39
34
  />
40
35
  </View>
@@ -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
+ };