@applicaster/zapp-react-native-ui-components 12.0.0-rc.9 → 12.0.0-rc.90

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 (147) 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 +12 -7
  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 +84 -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 +2 -0
  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 +17 -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/hooks/useAsyncRendering/index.ts +1 -1
  53. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  54. package/Components/MasterCell/utils/index.ts +33 -35
  55. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  56. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  57. package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
  58. package/Components/ModalComponent/Button/Item.tsx +82 -0
  59. package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
  60. package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
  61. package/Components/ModalComponent/Button/assets.ts +4 -0
  62. package/Components/ModalComponent/Button/index.tsx +111 -0
  63. package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
  64. package/Components/ModalComponent/Header/Title.tsx +70 -0
  65. package/Components/ModalComponent/Header/assets.ts +4 -0
  66. package/Components/ModalComponent/Header/index.tsx +71 -0
  67. package/Components/ModalComponent/Header/utils.ts +79 -0
  68. package/Components/ModalComponent/index.tsx +38 -0
  69. package/Components/ModalComponent/utils.ts +126 -0
  70. package/Components/Navigator/StackNavigator.tsx +57 -0
  71. package/Components/Navigator/index.ts +1 -0
  72. package/Components/PlayerContainer/PlayerContainer.tsx +69 -31
  73. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
  74. package/Components/PlayerImageBackground/index.tsx +34 -8
  75. package/Components/River/ComponentsMap/ComponentsMap.tsx +97 -2
  76. package/Components/River/RefreshControl.tsx +55 -1
  77. package/Components/River/River.tsx +8 -5
  78. package/Components/River/TV/River.tsx +2 -25
  79. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
  80. package/Components/River/__tests__/componentsMap.test.js +7 -0
  81. package/Components/River/useScreenConfiguration.ts +2 -2
  82. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
  83. package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
  84. package/Components/RouteManager/index.tsx +4 -2
  85. package/Components/Screen/TV/hooks/index.ts +3 -0
  86. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  87. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  88. package/Components/Screen/TV/index.web.tsx +169 -0
  89. package/Components/Screen/__tests__/Screen.test.tsx +91 -74
  90. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
  91. package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
  92. package/Components/Screen/index.tsx +131 -44
  93. package/Components/Screen/navigationHandler.ts +0 -82
  94. package/Components/ScreenResolver/index.tsx +4 -2
  95. package/Components/Tabs/TV/styles.ts +1 -1
  96. package/Components/TrackedView/index.tsx +6 -3
  97. package/Components/Transitioner/Scene.tsx +24 -19
  98. package/Components/Transitioner/Transitioner.tsx +21 -28
  99. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
  100. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  101. package/Components/VideoLive/LiveImageManager.ts +70 -14
  102. package/Components/VideoLive/PlayerLiveImageComponent.tsx +81 -72
  103. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
  104. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
  105. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
  106. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +352 -0
  107. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +158 -0
  108. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +455 -0
  109. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +162 -0
  110. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  111. package/Components/VideoModal/ModalAnimation/utils.ts +301 -0
  112. package/Components/VideoModal/PlayerDetails.tsx +6 -3
  113. package/Components/VideoModal/PlayerWrapper.tsx +81 -49
  114. package/Components/VideoModal/VideoModal.tsx +23 -40
  115. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
  116. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +12 -1
  117. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +266 -166
  118. package/Components/VideoModal/utils.ts +8 -5
  119. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
  120. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  121. package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
  122. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  123. package/Components/Viewport/utils.js +1 -1
  124. package/Components/ZappUIComponent/index.tsx +22 -12
  125. package/Components/index.js +2 -0
  126. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  127. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  128. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  129. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  130. package/Contexts/FocusableGroupContext/index.ts +7 -0
  131. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  132. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  133. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  134. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  135. package/Contexts/ScreenContext/index.tsx +95 -29
  136. package/Contexts/ScreenDataContext/index.tsx +20 -0
  137. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  138. package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
  139. package/Decorators/RiverResolver/index.tsx +0 -4
  140. package/Decorators/index.tsx +0 -4
  141. package/events/index.ts +1 -0
  142. package/package.json +5 -6
  143. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  144. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  145. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  146. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
  147. /package/Contexts/{index.js → index.ts} +0 -0
@@ -0,0 +1,455 @@
1
+ import React, { useRef, useState } from "react";
2
+ import { Animated, View } from "react-native";
3
+
4
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
5
+
6
+ import {
7
+ useModalAnimationContext,
8
+ PlayerAnimationStateEnum,
9
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
10
+
11
+ import {
12
+ useGetBottomTabBarHeight,
13
+ useNavigation,
14
+ useDimensions,
15
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
16
+ import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
17
+ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
18
+ import { useAppState } from "@applicaster/zapp-react-native-utils/reactHooks/app";
19
+
20
+ import {
21
+ gestureListenerHelper,
22
+ getAnimationStyle,
23
+ defaultAspectRatioWidth,
24
+ getAnimationDefaultValue,
25
+ ComponentAnimationType,
26
+ AUDIO_PLAYER_HORIZONTAL_PADDING,
27
+ } from "./utils";
28
+
29
+ type Props = {
30
+ animationType: string;
31
+ children: React.ReactNode;
32
+ style?: Record<string, any>;
33
+ additionalData?: { [key: string]: any };
34
+ };
35
+
36
+ export const AnimationView = ({
37
+ animationType,
38
+ style,
39
+ children,
40
+ additionalData = {},
41
+ }: Props) => {
42
+ const {
43
+ startComponentsAnimation,
44
+ setStartComponentsAnimation,
45
+ playerAnimationState,
46
+ minimisedHeight,
47
+ animatedValues: { dragScrollY, dragVideoPlayerY },
48
+ lastScrollYValue,
49
+ scrollPosition,
50
+ tabletLandscapePlayerTopPosition,
51
+ setTabletLandscapePlayerTopPosition,
52
+ modalSnapPoints,
53
+ startComponentsAnimationDistance,
54
+ } = useModalAnimationContext();
55
+
56
+ const isRTL = useIsRTL();
57
+ const isAppActive = useAppState(true);
58
+
59
+ const {
60
+ width: screenWidth,
61
+ deviceInfo: { isTablet, isTabletLandscape },
62
+ } = useDimensions("window", { deviceInfo: true });
63
+
64
+ const { videoModalState } = useNavigation();
65
+ const bottomTabBarHeight = useGetBottomTabBarHeight();
66
+ const minimisedWidth = defaultAspectRatioWidth(minimisedHeight);
67
+ const insets = useSafeAreaInsets();
68
+ const animationComponentRef = useRef(null);
69
+
70
+ // retrieving top position of the player for tablet landscape mode
71
+ const measureView = React.useCallback(() => {
72
+ if (isTabletLandscape && tabletLandscapePlayerTopPosition === 0) {
73
+ animationComponentRef.current.measure(
74
+ (x, y, width, height, pageX, pageY) => {
75
+ setTabletLandscapePlayerTopPosition(pageY - 20);
76
+ }
77
+ );
78
+ }
79
+ }, [tabletLandscapePlayerTopPosition]);
80
+
81
+ const [defaultValue, setDefaultValue] = useState<any>(
82
+ getAnimationDefaultValue(animationType, bottomTabBarHeight)
83
+ );
84
+
85
+ const isAudioItem = React.useMemo(
86
+ () =>
87
+ videoModalState.item?.content?.type?.includes?.("audio") ||
88
+ videoModalState.item?.type?.value === "audio",
89
+ [videoModalState.item]
90
+ );
91
+
92
+ const inlineAudioPlayer = additionalData.inlineAudioPlayer;
93
+
94
+ const moveUpValue = additionalData.saveArea
95
+ ? -insets.top
96
+ : isTablet
97
+ ? isTabletLandscape && (!isAudioItem || (isAudioItem && inlineAudioPlayer))
98
+ ? -tabletLandscapePlayerTopPosition
99
+ : -130
100
+ : -50;
101
+
102
+ const moveComponentHorizontalValue = additionalData.moveValue
103
+ ? isRTL
104
+ ? additionalData.moveValue
105
+ : -additionalData.moveValue
106
+ : 0;
107
+
108
+ const animationValueType: string =
109
+ animationType === ComponentAnimationType.player ? "ValueXY" : "Value";
110
+
111
+ const getAnimationValue = React.useCallback(
112
+ (animationType, state) => {
113
+ const defaultConfig = {
114
+ toValue: 0,
115
+ duration: state === PlayerAnimationStateEnum.minimize ? 150 : 100,
116
+ useNativeDriver: true,
117
+ };
118
+
119
+ switch (animationType) {
120
+ case ComponentAnimationType.bottomBar: {
121
+ if (state === PlayerAnimationStateEnum.minimize) {
122
+ return defaultConfig;
123
+ }
124
+
125
+ defaultConfig.toValue = defaultValue;
126
+
127
+ return defaultConfig;
128
+ }
129
+
130
+ case ComponentAnimationType.player: {
131
+ if (state === PlayerAnimationStateEnum.minimize) {
132
+ const minWidth =
133
+ isAudioItem && !inlineAudioPlayer
134
+ ? minimisedHeight
135
+ : minimisedWidth;
136
+
137
+ return {
138
+ ...defaultConfig,
139
+ toValue: { x: minWidth, y: minimisedHeight },
140
+ useNativeDriver: false,
141
+ };
142
+ }
143
+
144
+ return {
145
+ ...defaultConfig,
146
+ toValue: defaultValue,
147
+ useNativeDriver: false,
148
+ };
149
+ }
150
+
151
+ case ComponentAnimationType.componentFade: {
152
+ if (state === PlayerAnimationStateEnum.minimize) {
153
+ defaultConfig.toValue = 0;
154
+
155
+ return defaultConfig;
156
+ }
157
+
158
+ defaultConfig.toValue = defaultValue;
159
+
160
+ return defaultConfig;
161
+ }
162
+
163
+ case ComponentAnimationType.componentAppears: {
164
+ if (state === PlayerAnimationStateEnum.minimize) {
165
+ defaultConfig.toValue = 1;
166
+
167
+ return defaultConfig;
168
+ }
169
+
170
+ defaultConfig.toValue = defaultValue;
171
+
172
+ return defaultConfig;
173
+ }
174
+
175
+ case ComponentAnimationType.moveUpComponent: {
176
+ if (state === PlayerAnimationStateEnum.minimize) {
177
+ defaultConfig.toValue = moveUpValue;
178
+
179
+ return defaultConfig;
180
+ }
181
+
182
+ defaultConfig.toValue = defaultValue;
183
+
184
+ return defaultConfig;
185
+ }
186
+
187
+ case ComponentAnimationType.moveComponentHorizontal: {
188
+ if (state === PlayerAnimationStateEnum.minimize) {
189
+ defaultConfig.toValue = moveComponentHorizontalValue;
190
+
191
+ return defaultConfig;
192
+ }
193
+
194
+ defaultConfig.toValue = defaultValue;
195
+
196
+ return defaultConfig;
197
+ }
198
+
199
+ case ComponentAnimationType.audioPlayerPaddingHorizontal: {
200
+ if (state === PlayerAnimationStateEnum.minimize) {
201
+ defaultConfig.toValue = isRTL
202
+ ? AUDIO_PLAYER_HORIZONTAL_PADDING
203
+ : -AUDIO_PLAYER_HORIZONTAL_PADDING;
204
+
205
+ return defaultConfig;
206
+ }
207
+
208
+ defaultConfig.toValue = 0;
209
+
210
+ return defaultConfig;
211
+ }
212
+
213
+ default:
214
+ return defaultConfig;
215
+ }
216
+ },
217
+ [
218
+ defaultValue,
219
+ minimisedWidth,
220
+ minimisedHeight,
221
+ isAudioItem,
222
+ moveUpValue,
223
+ moveComponentHorizontalValue,
224
+ ]
225
+ );
226
+
227
+ const getInitialValue = React.useCallback(() => {
228
+ const mode =
229
+ videoModalState.mode === "PIP"
230
+ ? videoModalState.previousMode
231
+ : videoModalState.mode;
232
+
233
+ switch (mode) {
234
+ case "MINIMIZED":
235
+ return getAnimationValue(
236
+ animationType,
237
+ PlayerAnimationStateEnum.minimize
238
+ ).toValue;
239
+
240
+ case "MAXIMIZED":
241
+ default:
242
+ return getAnimationValue(
243
+ animationType,
244
+ PlayerAnimationStateEnum.maximaze
245
+ ).toValue;
246
+ }
247
+ }, [defaultValue, videoModalState]);
248
+
249
+ const animatedValue = useRef(
250
+ new Animated[animationValueType](getInitialValue())
251
+ ).current;
252
+
253
+ const calculationData = React.useMemo(
254
+ () => ({
255
+ isAudioItem,
256
+ bottomTabBarHeight,
257
+ minimisedHeight,
258
+ minimisedWidth,
259
+ defaultValue,
260
+ moveUpValue,
261
+ moveComponentHorizontalValue,
262
+ isTablet,
263
+ isTabletLandscape,
264
+ isRTL,
265
+ fromMiniPlayer: videoModalState.mode === "MINIMIZED",
266
+ inlineAudioPlayer,
267
+ }),
268
+ [
269
+ bottomTabBarHeight,
270
+ minimisedHeight,
271
+ minimisedWidth,
272
+ defaultValue,
273
+ moveUpValue,
274
+ moveComponentHorizontalValue,
275
+ videoModalState.mode,
276
+ ]
277
+ );
278
+
279
+ React.useEffect(() => {
280
+ if (additionalData.resetAnimationValue) {
281
+ animatedValue.setValue(defaultValue);
282
+ }
283
+ }, [additionalData.resetAnimationValue, defaultValue]);
284
+
285
+ React.useEffect(() => {
286
+ if (animationType === ComponentAnimationType.player) {
287
+ let width, height;
288
+
289
+ if (additionalData.aspectRatio) {
290
+ width = isTabletLandscape ? additionalData.width : screenWidth;
291
+
292
+ height =
293
+ (isTabletLandscape ? additionalData.width : screenWidth) /
294
+ additionalData.aspectRatio;
295
+ } else {
296
+ width =
297
+ typeof additionalData.width === "number" && additionalData.width;
298
+
299
+ height =
300
+ typeof additionalData.height === "number" && additionalData.height;
301
+ }
302
+
303
+ if (defaultValue.x === 0 && width && height) {
304
+ const value = { x: width, y: height };
305
+ setDefaultValue(value);
306
+ animatedValue.setValue(value);
307
+ }
308
+ }
309
+ }, [additionalData, screenWidth]);
310
+
311
+ React.useEffect(() => {
312
+ if (
313
+ playerAnimationState === PlayerAnimationStateEnum.minimize &&
314
+ startComponentsAnimation &&
315
+ videoModalState.mode === "MAXIMIZED"
316
+ ) {
317
+ Animated.timing(
318
+ animatedValue,
319
+ getAnimationValue(animationType, playerAnimationState)
320
+ ).start();
321
+ } else if (playerAnimationState === PlayerAnimationStateEnum.maximaze) {
322
+ animatedValue.setValue(defaultValue);
323
+ }
324
+ }, [
325
+ playerAnimationState,
326
+ startComponentsAnimation,
327
+ videoModalState.mode,
328
+ defaultValue,
329
+ ]);
330
+
331
+ React.useEffect(() => {
332
+ const dragVideoPlayerYListenerId = dragVideoPlayerY.addListener(
333
+ ({ value }) => {
334
+ if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
335
+ const preparedValue = Math.round(Math.abs(value));
336
+
337
+ gestureListenerHelper({
338
+ listenerValue: value,
339
+ preparedValue,
340
+ animationType,
341
+ animatedValue,
342
+ calculationData,
343
+ modalSnapPoint: modalSnapPoints[1],
344
+ startComponentsAnimationDistance,
345
+ startComponentsAnimation,
346
+ setStartComponentsAnimation,
347
+ getAnimationValue,
348
+ });
349
+ }
350
+ }
351
+ );
352
+
353
+ const dragListenerId = dragScrollY.addListener(({ value }) => {
354
+ if (
355
+ scrollPosition.current === 0 &&
356
+ playerAnimationState === PlayerAnimationStateEnum.drag_scroll
357
+ ) {
358
+ const preparedValue = Math.round(
359
+ Math.abs(value) - lastScrollYValue.current
360
+ );
361
+
362
+ gestureListenerHelper({
363
+ listenerValue: value,
364
+ preparedValue,
365
+ animationType,
366
+ animatedValue,
367
+ calculationData,
368
+ modalSnapPoint: modalSnapPoints[1],
369
+ startComponentsAnimationDistance,
370
+ startComponentsAnimation,
371
+ setStartComponentsAnimation,
372
+ getAnimationValue,
373
+ });
374
+ }
375
+ });
376
+
377
+ return () => {
378
+ dragScrollY.removeListener(dragListenerId);
379
+ dragVideoPlayerY.removeListener(dragVideoPlayerYListenerId);
380
+ };
381
+ }, [playerAnimationState, calculationData, startComponentsAnimation]);
382
+
383
+ const preparedStyles = Array.isArray(style) ? style : [style];
384
+
385
+ return (
386
+ <Animated.View
387
+ onLayout={additionalData.useLayoutMeasure && measureView}
388
+ ref={animationComponentRef}
389
+ style={[
390
+ ...preparedStyles,
391
+ (videoModalState.mode === "MAXIMIZED" ||
392
+ videoModalState.mode === "MINIMIZED" ||
393
+ (videoModalState.mode === "PIP" && isAppActive)) &&
394
+ getAnimationStyle(animationType, animatedValue),
395
+ ]}
396
+ >
397
+ {children}
398
+ </Animated.View>
399
+ );
400
+ };
401
+
402
+ export const AnimationComponent = (props: Props) => {
403
+ const { additionalData = {}, style } = props;
404
+
405
+ const {
406
+ videoModalState: { visible },
407
+ } = useNavigation();
408
+
409
+ const useAnimation =
410
+ visible && !additionalData.disableAnimatedComponent && !isTV();
411
+
412
+ const isReactFragment = !useAnimation && !style;
413
+
414
+ const Component = useAnimation
415
+ ? AnimationView
416
+ : style
417
+ ? View
418
+ : React.Fragment;
419
+
420
+ if (
421
+ additionalData.extraAnimation &&
422
+ typeof additionalData.extraAnimation === "object" &&
423
+ !Array.isArray(additionalData.extraAnimation) &&
424
+ !!Object.keys(additionalData.extraAnimation).length
425
+ ) {
426
+ const animationType = Object.keys(additionalData.extraAnimation)[0];
427
+ const animationProps = additionalData.extraAnimation[animationType] || {};
428
+ delete additionalData.extraAnimation[animationType];
429
+
430
+ return (
431
+ // @ts-ignore
432
+ <Component {...(isReactFragment ? null : props)}>
433
+ <AnimationComponent
434
+ {...animationProps}
435
+ animationType={animationType}
436
+ additionalData={{
437
+ ...animationProps.additionalData,
438
+ extraAnimation:
439
+ !!Object.keys(additionalData.extraAnimation).length &&
440
+ additionalData.extraAnimation,
441
+ }}
442
+ >
443
+ {props.children}
444
+ </AnimationComponent>
445
+ </Component>
446
+ );
447
+ }
448
+
449
+ if (isReactFragment) {
450
+ // @ts-ignore
451
+ return <Component>{props.children}</Component>;
452
+ }
453
+
454
+ return <Component {...props}>{props.children}</Component>;
455
+ };
@@ -0,0 +1,162 @@
1
+ import React, { useContext } from "react";
2
+ import { Animated } from "react-native";
3
+
4
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
5
+ import {
6
+ useGetBottomTabBarHeight,
7
+ useDimensions,
8
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
9
+
10
+ import { useConfiguration } from "../utils";
11
+
12
+ export enum PlayerAnimationStateEnum {
13
+ minimize = "minimize",
14
+ maximaze = "maximaze",
15
+ drag_player = "drag_player",
16
+ drag_scroll = "drag_scroll",
17
+ }
18
+
19
+ type PlayerAnimationStateT = number | PlayerAnimationStateEnum | null;
20
+
21
+ export type ModalAnimationContextT = {
22
+ isActiveGesture: boolean;
23
+ playerAnimationState: PlayerAnimationStateT;
24
+ setPlayerAnimationState: (value: PlayerAnimationStateT) => void;
25
+ startComponentsAnimation: boolean;
26
+ setStartComponentsAnimation: (value: boolean) => void;
27
+ resetPlayerAnimationState: () => void;
28
+ minimisedHeight: number;
29
+ animatedValues: {
30
+ lastScrollY: Animated.Value;
31
+ dragScrollY: Animated.Value;
32
+ dragVideoPlayerY: Animated.Value;
33
+ translateYOffset: Animated.Value;
34
+ };
35
+ lastScrollYValue: React.MutableRefObject<number>;
36
+ scrollPosition: React.MutableRefObject<number>;
37
+ modalSnapPoints: number[];
38
+ lastSnap: number;
39
+ setLastSnap: (value: number) => void;
40
+ tabletLandscapePlayerTopPosition: number;
41
+ setTabletLandscapePlayerTopPosition: (value: number) => void;
42
+ startComponentsAnimationDistance: number;
43
+ };
44
+
45
+ const ReactContext = React.createContext<ModalAnimationContextT>({
46
+ isActiveGesture: false,
47
+ playerAnimationState: null,
48
+ setPlayerAnimationState: () => null,
49
+ startComponentsAnimation: false,
50
+ setStartComponentsAnimation: () => null,
51
+ resetPlayerAnimationState: () => null,
52
+ minimisedHeight: 60,
53
+ animatedValues: {
54
+ lastScrollY: new Animated.Value(0),
55
+ dragScrollY: new Animated.Value(0),
56
+ dragVideoPlayerY: new Animated.Value(0),
57
+ translateYOffset: new Animated.Value(0),
58
+ },
59
+ lastScrollYValue: null,
60
+ scrollPosition: null,
61
+ modalSnapPoints: [0, 0],
62
+ lastSnap: 0,
63
+ setLastSnap: () => null,
64
+ tabletLandscapePlayerTopPosition: 0,
65
+ setTabletLandscapePlayerTopPosition: () => null,
66
+ startComponentsAnimationDistance: 0,
67
+ });
68
+
69
+ export function useModalAnimationContext() {
70
+ return useContext<ModalAnimationContextT>(ReactContext);
71
+ }
72
+
73
+ const Provider = ({ children }: { children: React.ReactNode }) => {
74
+ const [playerAnimationState, setPlayerAnimationState] =
75
+ React.useState<PlayerAnimationStateT>(null);
76
+
77
+ const [
78
+ tabletLandscapePlayerTopPosition,
79
+ setTabletLandscapePlayerTopPosition,
80
+ ] = React.useState<number>(0);
81
+
82
+ const [startComponentsAnimation, setStartComponentsAnimation] =
83
+ React.useState<boolean>(false);
84
+
85
+ const { minimised_height: minimisedHeight } = useConfiguration();
86
+
87
+ const resetPlayerAnimationState = React.useCallback(() => {
88
+ setPlayerAnimationState(null);
89
+ setStartComponentsAnimation(false);
90
+ }, []);
91
+
92
+ // Animated values
93
+ const lastScrollY = React.useRef(new Animated.Value(0)).current;
94
+ const dragScrollY = React.useRef(new Animated.Value(0)).current;
95
+ const translateYOffset = React.useRef(new Animated.Value(0)).current;
96
+ const dragVideoPlayerY = React.useRef(new Animated.Value(0)).current;
97
+
98
+ const { height } = useDimensions("window", { fullDimensions: true });
99
+ const { bottom: bottomSafeArea } = useSafeAreaInsets();
100
+ const bottomTabBarHeight = useGetBottomTabBarHeight();
101
+
102
+ const startComponentsAnimationDistance = React.useMemo(
103
+ () => Math.round((height * 60) / 100),
104
+ [height]
105
+ );
106
+
107
+ /*
108
+ If bottomTabBarHeight is equal 0 it means an app does not use bottomTabBar.
109
+ Because of this we need to minus bottom SafeArea offset.
110
+ */
111
+ const minValue =
112
+ height - minimisedHeight - (bottomTabBarHeight || bottomSafeArea);
113
+
114
+ const modalSnapPoints = React.useMemo(() => [0, minValue], [minValue]);
115
+ // Last snap state which will helps us to make smooth responder to scrollview animation
116
+ const [lastSnap, setLastSnap] = React.useState<number>(modalSnapPoints[0]);
117
+ // Extracted animated values which we will use for calculations
118
+ const lastScrollYValue = React.useRef<number>(0);
119
+ const scrollPosition = React.useRef<number>(0);
120
+
121
+ return (
122
+ <ReactContext.Provider
123
+ value={{
124
+ startComponentsAnimation,
125
+ setStartComponentsAnimation,
126
+ isActiveGesture: playerAnimationState !== null,
127
+ playerAnimationState,
128
+ setPlayerAnimationState,
129
+ resetPlayerAnimationState,
130
+ minimisedHeight,
131
+ animatedValues: {
132
+ lastScrollY,
133
+ dragScrollY,
134
+ dragVideoPlayerY,
135
+ translateYOffset,
136
+ },
137
+ lastScrollYValue,
138
+ scrollPosition,
139
+ modalSnapPoints,
140
+ lastSnap,
141
+ setLastSnap,
142
+ tabletLandscapePlayerTopPosition,
143
+ setTabletLandscapePlayerTopPosition,
144
+ startComponentsAnimationDistance,
145
+ }}
146
+ >
147
+ {children}
148
+ </ReactContext.Provider>
149
+ );
150
+ };
151
+
152
+ export const withModalAnimationProvider = (Component) => {
153
+ const WithProvider = (props) => {
154
+ return (
155
+ <Provider>
156
+ <Component {...props} />
157
+ </Provider>
158
+ );
159
+ };
160
+
161
+ return WithProvider;
162
+ };
@@ -0,0 +1,15 @@
1
+ export { AnimatedPlayerModalWrapper } from "./AnimatedPlayerModalWrapper";
2
+
3
+ export { AnimatedScrollModal } from "./AnimatedScrollModal";
4
+
5
+ export { AnimatedVideoPlayerComponent } from "./AnimatedVideoPlayerComponent";
6
+
7
+ export {
8
+ withModalAnimationProvider,
9
+ useModalAnimationContext,
10
+ PlayerAnimationStateEnum,
11
+ } from "./ModalAnimationContext";
12
+
13
+ export { AnimationComponent } from "./AnimationComponent";
14
+
15
+ export { ComponentAnimationType, defaultAspectRatioWidth } from "./utils";