@applicaster/zapp-react-native-ui-components 12.0.0-rc.13 → 12.0.0-rc.131

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