@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4802689107 → 12.0.0-alpha.4960304100

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.
@@ -177,10 +177,23 @@ const getPlayerConfig = (player_screen_id, actionIdentifier) => {
177
177
  const positionAbsolute: ViewStyle = { position: "absolute" };
178
178
 
179
179
  const LiveImageComponent = (props: LiveImageProps) => {
180
- const { item, style, cellUUID, imageKey, actionIdentifier, state } = props;
180
+ const {
181
+ item,
182
+ style: componentStyle,
183
+ cellUUID,
184
+ imageKey,
185
+ actionIdentifier,
186
+ state,
187
+ } = props;
181
188
 
182
189
  const component = useUIComponentContext();
183
190
 
191
+ // Fix for blinking on state change
192
+ const style = React.useMemo(
193
+ () => ({ ...componentStyle, backgroundColor: "transparent" }),
194
+ [componentStyle]
195
+ );
196
+
184
197
  const componentType = React.useMemo(
185
198
  () => getPropComponentType(component),
186
199
  [component?.id]
@@ -125,13 +125,24 @@ export const useFilterChildren = <
125
125
 
126
126
  const filteredChildren = children.filter((child) => {
127
127
  const item = child.props.item;
128
- const action = actions.actions[child.props.pluginIdentifier];
128
+ const actionIdentifier = child.props.pluginIdentifier;
129
+ const action = actions.actions[actionIdentifier];
130
+
129
131
  // context value of specific plugin
130
- const currentValue = action.module.context._currentValue;
132
+ if (action?.module && action.module.context) {
133
+ const currentValue = action.module.context._currentValue;
134
+
135
+ return currentValue?.isActionAvailable
136
+ ? currentValue.isActionAvailable(item)
137
+ : true;
138
+ }
131
139
 
132
- return currentValue?.isActionAvailable
133
- ? currentValue.isActionAvailable(item)
134
- : true;
140
+ masterCellLogger.error({
141
+ message: `Action plugin for ${actionIdentifier} could not be found, check the configuration of your action button`,
142
+ data: { item, action: child.props.pluginIdentifier },
143
+ });
144
+
145
+ return false;
135
146
  });
136
147
 
137
148
  return filteredChildren;
@@ -54,6 +54,11 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
54
54
  import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
55
55
  import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
56
56
 
57
+ import {
58
+ useModalAnimationContext,
59
+ PlayerAnimationStateEnum,
60
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
61
+
57
62
  type Props = {
58
63
  Player: React.ComponentType<any>;
59
64
  PlayerLoadingView?: React.ComponentType<any>; // 👀 we are not receiving this prop
@@ -229,6 +234,9 @@ const PlayerContainerComponent = (props: Props) => {
229
234
  const screenData = useTargetScreenData(item);
230
235
  const { setVisible: showNavBar } = useSetNavbarState();
231
236
 
237
+ const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
238
+ useModalAnimationContext();
239
+
232
240
  const playerEvent = (event, ...args) => {
233
241
  playerManager.invokeHandler(event, ...args);
234
242
  };
@@ -446,7 +454,7 @@ const PlayerContainerComponent = (props: Props) => {
446
454
  if (disableMiniPlayer) {
447
455
  navigator.closeVideoModal();
448
456
  } else {
449
- navigator.minimiseVideoModal();
457
+ setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
450
458
  }
451
459
  }
452
460
 
@@ -641,7 +649,11 @@ const PlayerContainerComponent = (props: Props) => {
641
649
  autoplay={true}
642
650
  controls={false}
643
651
  disableCastAction={disableCastAction}
644
- docked={navigator.isVideoModalDocked()}
652
+ docked={
653
+ navigator.isVideoModalDocked() &&
654
+ !startComponentsAnimation &&
655
+ !isActiveGesture
656
+ }
645
657
  entry={item}
646
658
  fullscreen={mode === VideoModalMode.FULLSCREEN}
647
659
  inline={inline}
@@ -1,38 +1,64 @@
1
1
  import React, { PropsWithChildren } from "react";
2
- import { ImageBackground } from "react-native";
2
+ import { ImageBackground, View } from "react-native";
3
3
 
4
4
  import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
5
+ import {
6
+ AnimationComponent,
7
+ ComponentAnimationType,
8
+ useModalAnimationContext,
9
+ PlayerAnimationStateEnum,
10
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
5
11
 
6
12
  type Props = PropsWithChildren<{
7
13
  entry: ZappEntry;
8
14
  style?: { [K: string]: any };
9
15
  imageStyle?: { [K: string]: any };
10
16
  imageKey?: string;
17
+ defaultImageDimensions?: { [K: string]: any };
11
18
  }>;
12
19
 
20
+ const imageSize = { width: "100%", height: "100%" };
21
+
13
22
  const PlayerImageBackgroundComponent = ({
14
23
  entry,
15
24
  children,
16
25
  style,
17
26
  imageStyle,
18
27
  imageKey,
28
+ defaultImageDimensions,
19
29
  }: Props) => {
20
30
  const source = React.useMemo(
21
31
  () => ({ uri: imageSrcFromMediaItem(entry, imageKey) }),
22
32
  [imageKey, entry]
23
33
  );
24
34
 
35
+ const { playerAnimationState } = useModalAnimationContext();
36
+
25
37
  if (!source) return <>{children}</>;
26
38
 
27
39
  return (
28
- <ImageBackground
29
- resizeMode="cover"
30
- style={style}
31
- imageStyle={imageStyle}
32
- source={source}
40
+ <View
41
+ style={
42
+ playerAnimationState === PlayerAnimationStateEnum.maximaze
43
+ ? defaultImageDimensions
44
+ : style
45
+ }
33
46
  >
34
- {children}
35
- </ImageBackground>
47
+ <AnimationComponent
48
+ style={style}
49
+ animationType={ComponentAnimationType.player}
50
+ additionalData={defaultImageDimensions}
51
+ >
52
+ <ImageBackground
53
+ resizeMode="cover"
54
+ style={imageSize}
55
+ imageStyle={imageStyle}
56
+ source={source}
57
+ >
58
+ {children}
59
+ </ImageBackground>
60
+ </AnimationComponent>
61
+ </View>
36
62
  );
37
63
  };
38
64
 
@@ -6,6 +6,12 @@ import configureStore from "redux-mock-store";
6
6
 
7
7
  import * as themeUtils from "@applicaster/zapp-react-native-utils/theme";
8
8
 
9
+ // silences the errors related to React-native-gesture-handler in tests
10
+ jest.mock(
11
+ "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation",
12
+ () => () => null
13
+ );
14
+
9
15
  jest.mock("react-native-safe-area-context", () => ({
10
16
  useSafeAreaInsets: () => ({ top: 50 }),
11
17
  }));
@@ -137,7 +137,7 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
137
137
  {...{ ...(navBarProps as MobileNavBarPluginProps), id: pathname }}
138
138
  />
139
139
 
140
- <OfflineFallbackScreen screenData={screenData}>
140
+ <OfflineFallbackScreen screenData={targetScreenData}>
141
141
  {/* @TODO RouteManager doesn't use props, can they be removed ? */}
142
142
  <RouteManager pathname={pathname} screenData={screenData} />
143
143
  </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", () => {
@@ -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
+ };