@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4757075613 → 12.0.0-alpha.4796013211

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 (114) hide show
  1. package/Components/BaseFocusable/index.tsx +3 -3
  2. package/Components/Cell/Cell.tsx +30 -9
  3. package/Components/Cell/CellWithFocusable.tsx +23 -9
  4. package/Components/Cell/TvOSCellComponent.tsx +3 -7
  5. package/Components/Focusable/Focusable.tsx +6 -1
  6. package/Components/FocusableGroup/index.tsx +11 -2
  7. package/Components/FreezeWithCallback/Freeze.tsx +31 -0
  8. package/Components/FreezeWithCallback/LICENSE +21 -0
  9. package/Components/FreezeWithCallback/Suspender.tsx +17 -0
  10. package/Components/FreezeWithCallback/__tests__/index.test.tsx +170 -0
  11. package/Components/FreezeWithCallback/index.tsx +3 -0
  12. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  13. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  14. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  15. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  16. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  17. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  18. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  19. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  20. package/Components/Layout/TV/__tests__/index.test.tsx +20 -75
  21. package/Components/Layout/TV/index.tsx +14 -67
  22. package/Components/Layout/TV/index.web.tsx +33 -0
  23. package/Components/Layout/index.tsx +15 -11
  24. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
  25. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +86 -116
  26. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  27. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +16 -1
  28. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  29. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +71 -0
  30. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  31. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +34 -1
  32. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  33. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  34. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  35. package/Components/MasterCell/DefaultComponents/index.ts +2 -0
  36. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  37. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
  38. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  39. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +7 -1
  40. package/Components/MasterCell/dataAdapter.ts +21 -7
  41. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  42. package/Components/MasterCell/index.tsx +5 -3
  43. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  44. package/Components/MasterCell/utils/index.ts +33 -35
  45. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  46. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  47. package/Components/Navigator/StackNavigator.tsx +57 -0
  48. package/Components/Navigator/index.ts +1 -0
  49. package/Components/PlayerContainer/PlayerContainer.tsx +20 -3
  50. package/Components/PlayerImageBackground/index.tsx +34 -8
  51. package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
  52. package/Components/River/RefreshControl.tsx +55 -1
  53. package/Components/River/TV/River.tsx +0 -23
  54. package/Components/River/__tests__/componentsMap.test.js +6 -0
  55. package/Components/RouteManager/index.tsx +2 -2
  56. package/Components/Screen/TV/hooks/index.ts +1 -0
  57. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  58. package/Components/Screen/TV/index.web.tsx +178 -0
  59. package/Components/Screen/__tests__/Screen.test.tsx +3 -49
  60. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  61. package/Components/Screen/index.tsx +62 -72
  62. package/Components/Screen/navigationHandler.ts +6 -3
  63. package/Components/Screen/orientationHandler.ts +18 -7
  64. package/Components/Screen/utils.ts +16 -0
  65. package/Components/ScreenResolver/index.tsx +9 -12
  66. package/Components/Transitioner/Scene.tsx +39 -26
  67. package/Components/Transitioner/Transitioner.tsx +46 -48
  68. package/Components/Transitioner/__tests__/Scene.test.js +7 -0
  69. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
  70. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -0
  71. package/Components/VideoLive/LiveImageManager.ts +28 -1
  72. package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
  73. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +20 -5
  74. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +25 -28
  75. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +66 -0
  76. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +376 -0
  77. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +165 -0
  78. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +473 -0
  79. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +182 -0
  80. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  81. package/Components/VideoModal/ModalAnimation/utils.ts +302 -0
  82. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  83. package/Components/VideoModal/PlayerWrapper.tsx +77 -47
  84. package/Components/VideoModal/VideoModal.tsx +23 -40
  85. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -1
  86. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +203 -105
  87. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  88. package/Components/VideoModal/utils.ts +8 -5
  89. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  90. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  91. package/Components/Viewport/utils.js +1 -1
  92. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -3
  93. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
  94. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  95. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  96. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  97. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  98. package/Contexts/FocusableGroupContext/index.ts +7 -0
  99. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  100. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  101. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  102. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  103. package/Contexts/ScreenContext/index.tsx +94 -25
  104. package/Contexts/ScreenDataContext/index.tsx +20 -0
  105. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  106. package/const.ts +6 -0
  107. package/events/index.ts +1 -0
  108. package/index.js +3 -0
  109. package/package.json +5 -5
  110. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  111. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  112. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  113. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
  114. /package/Contexts/{index.js → index.ts} +0 -0
@@ -0,0 +1,376 @@
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
+ // set animation to the minimize values if moving from the player to another screen
204
+ if (playerAnimationState === null) {
205
+ setScrollModalAnimatedValue(
206
+ translateYOffset,
207
+ modalSnapPoints[1],
208
+ setLastSnap
209
+ );
210
+
211
+ resetScrollAnimatedValues(
212
+ lastScrollY,
213
+ lastScrollYValue,
214
+ dragScrollY,
215
+ dragVideoPlayerY
216
+ );
217
+ } else {
218
+ resetPlayerAnimationState();
219
+ }
220
+ }
221
+
222
+ if (
223
+ (videoModalState.mode === "MAXIMIZED" &&
224
+ videoModalState.previousMode === "MINIMIZED" &&
225
+ previousItemId === videoModalState.item?.id) ||
226
+ previousItemId !== videoModalState.item?.id
227
+ ) {
228
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
229
+ setTimeout(() => resetPlayerAnimationState());
230
+ }
231
+ }, [videoModalState, previousItemId]);
232
+
233
+ React.useEffect(() => {
234
+ if (playerAnimationState === PlayerAnimationStateEnum.minimize) {
235
+ if (
236
+ (scrollPosition.current === 0 &&
237
+ (lastScrollY as any)._value !== 0 &&
238
+ (dragScrollY as any)._value === 0 &&
239
+ (dragVideoPlayerY as any)._value === 0) ||
240
+ (scrollPosition.current !== 0 &&
241
+ ((dragScrollY as any)._value !== 0 ||
242
+ (dragVideoPlayerY as any)._value !== 0))
243
+ ) {
244
+ resetScrollAnimatedValues(
245
+ lastScrollY,
246
+ lastScrollYValue,
247
+ dragScrollY,
248
+ dragVideoPlayerY
249
+ );
250
+ }
251
+
252
+ Animated.timing(
253
+ translateYOffset,
254
+ getAnimatedConfig(modalSnapPoints[1])
255
+ ).start(() => {
256
+ setTimeout(() => {
257
+ minimiseVideoModal();
258
+
259
+ setScrollModalAnimatedValue(
260
+ translateYOffset,
261
+ modalSnapPoints[1],
262
+ setLastSnap
263
+ );
264
+
265
+ resetScrollAnimatedValues(
266
+ lastScrollY,
267
+ lastScrollYValue,
268
+ dragScrollY,
269
+ dragVideoPlayerY
270
+ );
271
+ }, 150);
272
+ });
273
+ } else if (playerAnimationState === PlayerAnimationStateEnum.maximaze) {
274
+ Animated.timing(translateYOffset, getAnimatedConfig(0)).start(() => {
275
+ maximiseVideoModal();
276
+ setScrollModalAnimatedValue(translateYOffset, 0, setLastSnap);
277
+
278
+ resetScrollAnimatedValues(
279
+ lastScrollY,
280
+ lastScrollYValue,
281
+ dragScrollY,
282
+ dragVideoPlayerY
283
+ );
284
+
285
+ resetPlayerAnimationState();
286
+ });
287
+ }
288
+
289
+ const lastScrollYListenerId = lastScrollY.addListener(({ value }) => {
290
+ lastScrollYValue.current = value;
291
+ });
292
+
293
+ const dragListenerId = dragScrollY.addListener(({ value }) => {
294
+ const preparedValue =
295
+ isMinimizedModal && value >= 0
296
+ ? 0
297
+ : Math.round(isAudioItem ? Math.abs(value) : value);
298
+
299
+ if (
300
+ preparedValue > 0 &&
301
+ scrollPosition.current === 0 &&
302
+ playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
303
+ playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
304
+ ) {
305
+ isMinimizedModal && setStartComponentsAnimation(true);
306
+ setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
307
+ }
308
+ });
309
+
310
+ return () => {
311
+ lastScrollY.removeListener(lastScrollYListenerId);
312
+ dragScrollY.removeListener(dragListenerId);
313
+ };
314
+ }, [playerAnimationState, isAudioItem, modalSnapPoints, isMinimizedModal]);
315
+
316
+ const Wrapper = React.useMemo(
317
+ () => (Platform.OS === "android" ? GestureHandlerRootView : View),
318
+ []
319
+ );
320
+
321
+ return (
322
+ <Wrapper style={generalStyles.container}>
323
+ <TapGestureHandler
324
+ maxDurationMs={100000}
325
+ ref={tapHandlerRef}
326
+ maxDeltaY={lastSnap - modalSnapPoints[0]}
327
+ numberOfTaps={1}
328
+ >
329
+ <View pointerEvents="box-none">
330
+ <PanGestureHandler
331
+ enabled={isEnablePanGesture}
332
+ ref={panHandlerRef}
333
+ simultaneousHandlers={[scrollRef, tapHandlerRef]}
334
+ shouldCancelWhenOutside={isMaximazedModal}
335
+ onGestureEvent={onGestureEvent}
336
+ onHandlerStateChange={onHandlerStateChange}
337
+ activeOffsetY={[-5, 5]}
338
+ >
339
+ <Animated.View>
340
+ <NativeViewGestureHandler
341
+ ref={scrollRef}
342
+ waitFor={tapHandlerRef}
343
+ simultaneousHandlers={panHandlerRef}
344
+ >
345
+ <Animated.ScrollView
346
+ scrollEnabled={
347
+ isMaximazedModal && isNotMinimizeMaximazeAnimation
348
+ }
349
+ bounces={false}
350
+ onScrollBeginDrag={onRegisterLastScroll}
351
+ onScroll={onScroll}
352
+ onMomentumScrollEnd={onMomentumScrollEnd}
353
+ scrollEventThrottle={1}
354
+ showsVerticalScrollIndicator={false}
355
+ >
356
+ {children}
357
+ </Animated.ScrollView>
358
+ </NativeViewGestureHandler>
359
+ </Animated.View>
360
+ </PanGestureHandler>
361
+ </View>
362
+ </TapGestureHandler>
363
+ </Wrapper>
364
+ );
365
+ };
366
+
367
+ export const AnimatedScrollModal = ({ children }: Props) => {
368
+ const {
369
+ videoModalState: { visible },
370
+ } = useNavigation();
371
+
372
+ const Component =
373
+ !isTV() && visible ? AnimatedScrollModalComponent : React.Fragment;
374
+
375
+ return <Component>{children}</Component>;
376
+ };
@@ -0,0 +1,165 @@
1
+ import React from "react";
2
+ import { Animated, StyleSheet } from "react-native";
3
+
4
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
+ import { PanGestureHandler, State } from "react-native-gesture-handler";
6
+
7
+ import { PlayerContainerContext } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainerContext";
8
+ import {
9
+ useModalAnimationContext,
10
+ PlayerAnimationStateEnum,
11
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
12
+ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
13
+
14
+ const generalStyles = StyleSheet.create({
15
+ container: {
16
+ flex: 1,
17
+ width: "100%",
18
+ position: "absolute",
19
+ zIndex: 201,
20
+ },
21
+ });
22
+
23
+ type Props = {
24
+ children: React.ReactNode;
25
+ };
26
+
27
+ export const AnimatedVideoPlayer = ({ children }: Props) => {
28
+ const {
29
+ playerAnimationState,
30
+ setPlayerAnimationState,
31
+ animatedValues: { translateYOffset, dragVideoPlayerY, lastScrollY },
32
+ lastScrollYValue,
33
+ modalSnapPoints,
34
+ lastSnap,
35
+ setLastSnap,
36
+ resetPlayerAnimationState,
37
+ setStartComponentsAnimation,
38
+ } = useModalAnimationContext();
39
+
40
+ const { videoModalState } = useNavigation();
41
+ const { isLanguageOverlayVisible } = React.useContext(PlayerContainerContext);
42
+
43
+ const isMaximazedModal = videoModalState.mode === "MAXIMIZED";
44
+ const isMinimizedModal = videoModalState.mode === "MINIMIZED";
45
+
46
+ const isEnablePanGesture =
47
+ !isLanguageOverlayVisible && (isMaximazedModal || isMinimizedModal);
48
+
49
+ const onGestureEvent = Animated.event(
50
+ [{ nativeEvent: { translationY: dragVideoPlayerY } }],
51
+ { useNativeDriver: true }
52
+ );
53
+
54
+ const onHandlerStateChange = React.useCallback(
55
+ ({ nativeEvent }) => {
56
+ if (nativeEvent.oldState === State.ACTIVE) {
57
+ // eslint-disable-next-line prefer-const
58
+ const { velocityY, translationY } = nativeEvent;
59
+ const preparedTranslationY = Math.abs(translationY);
60
+ const dragToss = 0.05;
61
+
62
+ if (videoModalState.mode === "MAXIMIZED") {
63
+ if (translationY > 0) {
64
+ const endOffsetY =
65
+ lastSnap + preparedTranslationY + dragToss * velocityY + 200;
66
+
67
+ let destSnapPoint = modalSnapPoints[0];
68
+
69
+ for (const snapPoint of modalSnapPoints) {
70
+ const distFromSnap = Math.abs(snapPoint - endOffsetY);
71
+
72
+ if (distFromSnap < Math.abs(destSnapPoint - endOffsetY)) {
73
+ destSnapPoint = snapPoint;
74
+ }
75
+ }
76
+
77
+ setLastSnap(destSnapPoint);
78
+
79
+ if (destSnapPoint === modalSnapPoints[0]) {
80
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
81
+ } else {
82
+ lastScrollY.setValue(0);
83
+ lastScrollYValue.current = 0;
84
+ setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
85
+ }
86
+ }
87
+ } else if (videoModalState.mode === "MINIMIZED") {
88
+ if (translationY < 0) {
89
+ // from mini to full
90
+ setLastSnap(modalSnapPoints[0]);
91
+
92
+ translateYOffset.setValue(
93
+ modalSnapPoints[1] - preparedTranslationY
94
+ );
95
+
96
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
97
+ } else {
98
+ resetPlayerAnimationState();
99
+ }
100
+ }
101
+ }
102
+ },
103
+ [lastSnap, modalSnapPoints, videoModalState.mode]
104
+ );
105
+
106
+ React.useEffect(() => {
107
+ const dragVideoPlayerYListenerId = dragVideoPlayerY.addListener(
108
+ ({ value }) => {
109
+ if (
110
+ (isMinimizedModal && value >= 0) ||
111
+ (isMaximazedModal && value <= 0)
112
+ ) {
113
+ if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
114
+ translateYOffset.setValue(
115
+ modalSnapPoints[isMinimizedModal ? 1 : 0]
116
+ );
117
+ }
118
+ } else {
119
+ const preparedValue = Math.round(Math.abs(value));
120
+
121
+ if (
122
+ preparedValue > 0 &&
123
+ playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
124
+ ) {
125
+ if (playerAnimationState !== PlayerAnimationStateEnum.drag_player) {
126
+ isMinimizedModal && setStartComponentsAnimation(true);
127
+ setPlayerAnimationState(PlayerAnimationStateEnum.drag_player);
128
+ }
129
+
130
+ translateYOffset.setValue(
131
+ isMaximazedModal
132
+ ? preparedValue
133
+ : modalSnapPoints[1] - preparedValue
134
+ );
135
+ }
136
+ }
137
+ }
138
+ );
139
+
140
+ return () => {
141
+ dragVideoPlayerY.removeListener(dragVideoPlayerYListenerId);
142
+ };
143
+ }, [playerAnimationState, isMinimizedModal, isMaximazedModal]);
144
+
145
+ return (
146
+ <PanGestureHandler
147
+ enabled={isEnablePanGesture}
148
+ shouldCancelWhenOutside={isMaximazedModal}
149
+ onGestureEvent={onGestureEvent}
150
+ onHandlerStateChange={onHandlerStateChange}
151
+ >
152
+ <Animated.View style={generalStyles.container}>{children}</Animated.View>
153
+ </PanGestureHandler>
154
+ );
155
+ };
156
+
157
+ export const AnimatedVideoPlayerComponent = ({ children }: Props) => {
158
+ const {
159
+ videoModalState: { visible },
160
+ } = useNavigation();
161
+
162
+ const Component = !isTV() && visible ? AnimatedVideoPlayer : React.Fragment;
163
+
164
+ return <Component>{children}</Component>;
165
+ };