@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3788876021 → 12.0.0-alpha.3823240084

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 (99) 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/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  8. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  9. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  10. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  11. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  12. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  13. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  14. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  15. package/Components/Layout/TV/__tests__/index.test.tsx +20 -75
  16. package/Components/Layout/TV/index.tsx +14 -67
  17. package/Components/Layout/TV/index.web.tsx +33 -0
  18. package/Components/Layout/index.tsx +15 -11
  19. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
  20. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +86 -116
  21. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  22. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  23. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  24. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +57 -0
  25. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  26. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +34 -1
  27. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  28. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  29. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  30. package/Components/MasterCell/DefaultComponents/index.ts +2 -0
  31. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  32. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
  33. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  34. package/Components/MasterCell/dataAdapter.ts +21 -7
  35. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  36. package/Components/MasterCell/index.tsx +5 -3
  37. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  38. package/Components/MasterCell/utils/index.ts +17 -30
  39. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  40. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  41. package/Components/Navigator/StackNavigator.tsx +57 -0
  42. package/Components/Navigator/index.ts +1 -0
  43. package/Components/PlayerContainer/PlayerContainer.tsx +14 -6
  44. package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
  45. package/Components/River/RefreshControl.tsx +55 -1
  46. package/Components/River/TV/River.tsx +0 -23
  47. package/Components/RouteManager/index.tsx +2 -2
  48. package/Components/Screen/TV/hooks/index.ts +3 -0
  49. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  50. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  51. package/Components/Screen/TV/index.web.tsx +165 -0
  52. package/Components/Screen/__tests__/Screen.test.tsx +3 -0
  53. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  54. package/Components/Screen/index.tsx +62 -54
  55. package/Components/Screen/navigationHandler.ts +6 -3
  56. package/Components/ScreenResolver/index.tsx +9 -12
  57. package/Components/Transitioner/Scene.tsx +24 -25
  58. package/Components/Transitioner/Transitioner.tsx +38 -43
  59. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
  60. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  61. package/Components/VideoLive/LiveImageManager.ts +28 -1
  62. package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
  63. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +25 -28
  64. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +2 -14
  65. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +73 -48
  66. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +55 -34
  67. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +104 -86
  68. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +44 -5
  69. package/Components/VideoModal/ModalAnimation/utils.ts +7 -4
  70. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  71. package/Components/VideoModal/PlayerWrapper.tsx +67 -60
  72. package/Components/VideoModal/VideoModal.tsx +17 -17
  73. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
  74. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +80 -14
  75. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  76. package/Components/VideoModal/utils.ts +5 -2
  77. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  78. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  79. package/Components/Viewport/utils.js +1 -1
  80. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -3
  81. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
  82. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  83. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  84. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  85. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  86. package/Contexts/FocusableGroupContext/index.ts +7 -0
  87. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  88. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  89. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  90. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  91. package/Contexts/ScreenContext/index.tsx +94 -25
  92. package/Contexts/ScreenDataContext/index.tsx +20 -0
  93. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  94. package/events/index.ts +1 -0
  95. package/package.json +5 -5
  96. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  97. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  98. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
  99. /package/Contexts/{index.js → index.ts} +0 -0
@@ -4,10 +4,7 @@ import * as R from "ramda";
4
4
 
5
5
  import { AnimationManager } from "./AnimationManager";
6
6
  import { Scene } from "./Scene";
7
- import {
8
- getScreenOrientation,
9
- isOrientationCompatible,
10
- } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
7
+
11
8
  import {
12
9
  getSceneByRoute,
13
10
  shouldSkipAnimationForPreviousWebViewScene,
@@ -169,21 +166,23 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
169
166
 
170
167
  transitionWithoutAnimation(resetState) {
171
168
  const { scenes } = this.state;
172
-
173
- const newState = resetState
174
- ? {
175
- scenes: [prepareScene(this.props.children)],
176
- to: {
177
- index: 0,
178
- },
179
- }
180
- : {
181
- scenes: R.update(
182
- scenes.length - 1,
183
- prepareScene(this.props.children),
184
- scenes
185
- ),
186
- };
169
+ const newScene = prepareScene(this.props.children);
170
+ const isLastSceneHook = scenes[scenes.length - 1].key.startsWith("/hook");
171
+
172
+ let newState;
173
+
174
+ if (resetState) {
175
+ newState = {
176
+ scenes: [newScene],
177
+ to: { index: 0 },
178
+ };
179
+ } else if (isLastSceneHook || scenes.length === 1) {
180
+ newState = { scenes: R.update(scenes.length - 1, newScene, scenes) };
181
+ } else {
182
+ newState = {
183
+ scenes: R.compose(R.tail, R.append(newScene))(scenes),
184
+ };
185
+ }
187
186
 
188
187
  this.setState(newState);
189
188
  }
@@ -277,33 +276,25 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
277
276
  // so only a single scene should be rendered,
278
277
  // instead of dangerous nulls or duplicates.
279
278
  renderSingleScene({ scenes, to }) {
280
- const { contentStyle, layoutData } = this.props;
281
- const screenData = scenes[to.index]?.children?.props?.screenData;
282
-
283
- const orientation = getScreenOrientation({
284
- screenData,
285
- layoutData,
286
- });
279
+ const { contentStyle } = this.props;
280
+ const screenData = this.props.children.props.screenData;
281
+ const pathname = scenes[to.index].key;
287
282
 
288
- // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
289
- // This saves unnecessary re-renders and user will not see distorted aspect screen.
290
283
  return (
291
284
  <View style={styles.container}>
292
- {scenes[to.index] &&
293
- isOrientationCompatible({
294
- orientation,
295
- layoutData,
296
- }) && (
297
- <Scene
298
- {...{ style: to.style }}
299
- pathname={scenes[to.index].key}
300
- contentStyle={contentStyle}
301
- key={scenes[to.index].key}
302
- screenUniqueId={scenes[to.index].screenUniqueId}
303
- >
304
- {scenes[to.index].children}
305
- </Scene>
306
- )}
285
+ {scenes[to.index] && (
286
+ <Scene
287
+ {...{ style: to.style }}
288
+ pathname={pathname}
289
+ isActive={pathname === this.props.navigator.currentRoute}
290
+ contentStyle={contentStyle}
291
+ key={scenes[to.index].key}
292
+ screenUniqueId={scenes[to.index].screenUniqueId}
293
+ screenData={screenData}
294
+ >
295
+ {scenes[to.index].children}
296
+ </Scene>
297
+ )}
307
298
  </View>
308
299
  );
309
300
  }
@@ -319,12 +310,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
319
310
  <Scene
320
311
  key={scenes[from.index].key}
321
312
  pathname={scenes[from.index].key}
313
+ isActive={scenes[from.index].key === this.props.navigator.currentRoute}
322
314
  style={from.style}
323
315
  pointerEvents="none"
324
316
  overlayStyle={from.overlayStyle}
325
317
  animating={this.state.animating}
326
318
  contentStyle={contentStyle}
327
319
  screenUniqueId={scenes[from.index].screenUniqueId}
320
+ screenData={scenes[from.index].children.props.screenData}
328
321
  >
329
322
  {scenes[from.index].children}
330
323
  </Scene>
@@ -333,12 +326,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
333
326
  const toScene = scenes[to.index] && (
334
327
  <Scene
335
328
  pathname={scenes[to.index].key}
329
+ isActive={scenes[to.index].key === this.props.navigator.currentRoute}
336
330
  key={scenes[to.index].key}
337
331
  style={to.style}
338
332
  overlayStyle={to.overlayStyle}
339
333
  animating={this.state.animating}
340
334
  contentStyle={contentStyle}
341
335
  screenUniqueId={scenes[to.index].screenUniqueId}
336
+ screenData={this.props.children.props.screenData}
342
337
  >
343
338
  {scenes[to.index].children}
344
339
  </Scene>
@@ -21,7 +21,11 @@ exports[`<Scene /> renders correctly 1`] = `
21
21
  ]
22
22
  }
23
23
  >
24
- <ContextProvider />
24
+ <ContextProvider>
25
+ <ContextProvider>
26
+ <ScreenContextProvider />
27
+ </ContextProvider>
28
+ </ContextProvider>
25
29
  </ForwardRef(AnimatedComponentWrapper)>
26
30
  `;
27
31
 
@@ -37,13 +41,17 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
37
41
  "paddingBottom": 49,
38
42
  },
39
43
  Object {
40
- "height": 1334,
41
- "width": 750,
44
+ "height": "100%",
45
+ "width": "100%",
42
46
  },
43
47
  ]
44
48
  }
45
49
  >
46
- <ContextProvider />
50
+ <ContextProvider>
51
+ <ContextProvider>
52
+ <ScreenContextProvider />
53
+ </ContextProvider>
54
+ </ContextProvider>
47
55
  <ForwardRef(AnimatedComponentWrapper)
48
56
  style={
49
57
  Object {
@@ -10,6 +10,7 @@ exports[`<TransitionerComponent /> renders correctly 1`] = `
10
10
  }
11
11
  >
12
12
  <Scene
13
+ isActive={true}
13
14
  screenUniqueId="mocked-uuid"
14
15
  >
15
16
  <View
@@ -10,7 +10,11 @@ import { Component } from "react";
10
10
 
11
11
  const { log_debug, log_info, log_error } = loggerLiveImageManager;
12
12
 
13
- export type LiveImageManagerEvent = "onEnd" | "onStart" | "onError";
13
+ export type LiveImageManagerEvent =
14
+ | "onEnd"
15
+ | "onStart"
16
+ | "onError"
17
+ | "onDestroy";
14
18
 
15
19
  export type LiveImageManagerListenerData = {
16
20
  id: string;
@@ -102,6 +106,16 @@ export class LiveImageManager implements PlayerLifecycleListener {
102
106
  }
103
107
 
104
108
  this.items = this.items.filter((i) => i !== item);
109
+
110
+ this.invokeListenersUpdate({
111
+ callbackName: "onDestroy",
112
+ event: {
113
+ item,
114
+ playerId: this.currentlyPlaying?.playerId,
115
+ primaryPlayerId: this.primaryPlayer?.playerId,
116
+ entry: item.getPlayer().getEntry(),
117
+ },
118
+ });
105
119
  };
106
120
 
107
121
  public onViewportEnter = (item: LiveImage) => {
@@ -351,6 +365,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
351
365
  item,
352
366
  playerId: this.currentlyPlaying?.playerId,
353
367
  primaryPlayerId: this.primaryPlayer?.playerId,
368
+ entry: item.getPlayer().getEntry(),
354
369
  },
355
370
  });
356
371
  };
@@ -385,6 +400,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
385
400
  item,
386
401
  playerId: this.currentlyPlaying?.playerId,
387
402
  primaryPlayerId: this.primaryPlayer?.playerId,
403
+ entry: item.getPlayer().getEntry(),
388
404
  },
389
405
  });
390
406
  };
@@ -419,6 +435,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
419
435
  error,
420
436
  playerId: currentItem?.playerId,
421
437
  primaryPlayerId: currentItem?.playerId,
438
+ entry: item.getPlayer().getEntry(),
422
439
  },
423
440
  });
424
441
  };
@@ -508,6 +525,16 @@ export class LiveImage implements QuickBrickPlayer.SharedPlayerCallBacks {
508
525
  LiveImageManager.instance.onLiveImageError(this, error);
509
526
  };
510
527
 
528
+ onVideoError = (error: Error) => {
529
+ log_error(
530
+ `onVideoError: live-image, fail to play, switching back to image. error: ${
531
+ error?.message
532
+ }, ${playerInfo(this.player)}`
533
+ );
534
+
535
+ LiveImageManager.instance.onLiveImageError(this, error);
536
+ };
537
+
511
538
  onVideoEnd = (_event) => {
512
539
  log_info(
513
540
  `onVideoEnd: live-image, video completed, switching back to image, ${playerInfo(
@@ -2,7 +2,7 @@
2
2
  //
3
3
  import * as React from "react";
4
4
 
5
- import { AppState, AppStateStatus } from "react-native";
5
+ import { AppState, AppStateStatus, View } from "react-native";
6
6
  import { TrackedView } from "../TrackedView";
7
7
  import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
8
8
 
@@ -25,8 +25,9 @@ import { PlayerRole } from "@applicaster/zapp-react-native-utils/appUtils/player
25
25
  import { getAutoplaySettings } from "./utils";
26
26
  import { isString } from "@applicaster/zapp-react-native-utils/stringUtils";
27
27
  import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
28
+ import { useEffect } from "react";
28
29
 
29
- const { log_error } = loggerLiveImageComponent;
30
+ const { log_error, log_debug } = loggerLiveImageComponent;
30
31
 
31
32
  const isMeasurement = (item: ZappEntry) =>
32
33
  isString(item.id) && item.id.startsWith("pre-measurement-");
@@ -56,6 +57,7 @@ const PlayerLiveImageComponent = (props: Props) => {
56
57
  );
57
58
 
58
59
  const ref = React.useRef(null);
60
+ const trackViewRef = React.useRef(null);
59
61
 
60
62
  /**
61
63
  * Debounced setMode function.
@@ -86,6 +88,30 @@ const PlayerLiveImageComponent = (props: Props) => {
86
88
  [mode]
87
89
  );
88
90
 
91
+ const entryToViewIdMapping = React.useRef({});
92
+
93
+ useEffect(() => {
94
+ const nativeTag = trackViewRef.current?._nativeTag?.toString();
95
+
96
+ if (!nativeTag) {
97
+ return;
98
+ }
99
+
100
+ const prevValue = entryToViewIdMapping.current[nativeTag];
101
+
102
+ if (prevValue && prevValue.itemId !== item.id) {
103
+ if (mode === LiveImageType.Video) {
104
+ log_debug(
105
+ "Entry to view association changed, stopping current live image"
106
+ );
107
+
108
+ setMode(LiveImageType.Image);
109
+ }
110
+ }
111
+
112
+ entryToViewIdMapping.current[nativeTag] = { itemId: item.id };
113
+ }, [trackViewRef.current, item.id, mode]);
114
+
89
115
  const { screenConfig, playerPluginId } = props;
90
116
 
91
117
  const liveImageItem: LiveImage = React.useMemo(() => {
@@ -295,28 +321,30 @@ const PlayerLiveImageComponent = (props: Props) => {
295
321
  testId={`tracked-view-${playerId}-${item.title}`}
296
322
  onPositionUpdated={onPositionUpdated}
297
323
  >
298
- {isVideoMode && (
299
- <Player
300
- autoplay={false}
301
- ref={_assignRoot}
302
- entry={item} // Must be passed first in list
303
- style={videoStyles}
304
- playerId={playerId}
305
- muted={muted}
306
- listener={controller?.getListener()}
307
- resizeMode={"cover"}
308
- {...platformSpecificProps}
309
- />
310
- )}
311
- {
312
- <AnimatedInOut
313
- visible={isBackgroundImageVisible}
314
- animationConfig={overlayFadeIn}
315
- staticStyles={style}
316
- >
317
- <Image {...props} resizeMode="cover" style={style} applyMaxSize />
318
- </AnimatedInOut>
319
- }
324
+ <View ref={trackViewRef}>
325
+ {isVideoMode && (
326
+ <Player
327
+ autoplay={false}
328
+ ref={_assignRoot}
329
+ entry={item} // Must be passed first in list
330
+ style={videoStyles}
331
+ playerId={playerId}
332
+ muted={muted}
333
+ listener={controller?.getListener()}
334
+ resizeMode={"cover"}
335
+ {...platformSpecificProps}
336
+ />
337
+ )}
338
+ {
339
+ <AnimatedInOut
340
+ visible={isBackgroundImageVisible}
341
+ animationConfig={overlayFadeIn}
342
+ staticStyles={style}
343
+ >
344
+ <Image {...props} resizeMode="cover" style={style} applyMaxSize />
345
+ </AnimatedInOut>
346
+ }
347
+ </View>
320
348
  </TrackedView>
321
349
  );
322
350
  };
@@ -5,38 +5,35 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
5
5
  onPositionUpdated={[Function]}
6
6
  testId="tracked-view-player1-Test"
7
7
  >
8
- <View
9
- collapsable={false}
10
- style={
11
- Object {
12
- "opacity": 1,
13
- }
14
- }
15
- >
16
- <Image
17
- applyMaxSize={true}
18
- audioMutedByDefault={false}
19
- imageKey="image1"
20
- item={
8
+ <View>
9
+ <View
10
+ collapsable={false}
11
+ style={
21
12
  Object {
22
- "id": "1",
23
- "title": "Test",
24
- "type": Object {
25
- "value": "",
26
- },
13
+ "opacity": 1,
27
14
  }
28
15
  }
29
- onError={[Function]}
30
- playerId="player1"
31
- resizeMode="cover"
32
- screenConfig={Object {}}
33
- source={
34
- Object {
35
- "uri": "",
16
+ >
17
+ <Image
18
+ applyMaxSize={true}
19
+ audioMutedByDefault={false}
20
+ imageKey="image1"
21
+ item={
22
+ Object {
23
+ "id": "1",
24
+ "title": "Test",
25
+ "type": Object {
26
+ "value": "",
27
+ },
28
+ }
36
29
  }
37
- }
38
- style={Object {}}
39
- />
30
+ onError={[Function]}
31
+ playerId="player1"
32
+ resizeMode="cover"
33
+ screenConfig={Object {}}
34
+ style={Object {}}
35
+ />
36
+ </View>
40
37
  </View>
41
38
  </TrackedView>
42
39
  `;
@@ -5,7 +5,6 @@ import {
5
5
  useModalAnimationContext,
6
6
  PlayerAnimationStateEnum,
7
7
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
- import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks";
9
8
 
10
9
  type Props = {
11
10
  style: ViewStyle[];
@@ -18,13 +17,8 @@ export const AnimatedPlayerModalWrapper = (props: Props) => {
18
17
  animatedValues: { lastScrollY, dragScrollY, translateYOffset },
19
18
  modalSnapPoints,
20
19
  setStartComponentsAnimation,
21
- lastScrollYValue,
22
20
  } = useModalAnimationContext();
23
21
 
24
- const { height: screenHeight } = useDimensions("screen", {
25
- deviceInfo: true,
26
- });
27
-
28
22
  const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
29
23
  () => ({
30
24
  inputRange: modalSnapPoints,
@@ -51,16 +45,10 @@ export const AnimatedPlayerModalWrapper = (props: Props) => {
51
45
  }
52
46
 
53
47
  React.useEffect(() => {
54
- const translateYListener = translateY.addListener(({ value }) => {
55
- const preparedValue = Math.round(
56
- Math.abs(value) - lastScrollYValue.current
57
- );
58
-
48
+ const translateYListener = translateY.addListener(() => {
59
49
  (playerAnimationState === PlayerAnimationStateEnum.minimize ||
60
50
  playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
61
- setStartComponentsAnimation(
62
- preparedValue >= Math.round((screenHeight * 10) / 100)
63
- );
51
+ setStartComponentsAnimation(true);
64
52
  });
65
53
 
66
54
  return () => {
@@ -9,6 +9,8 @@ import {
9
9
  TapGestureHandler,
10
10
  GestureHandlerRootView,
11
11
  } from "react-native-gesture-handler";
12
+
13
+ import { PlayerContainerContext } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainerContext";
12
14
  import {
13
15
  useModalAnimationContext,
14
16
  PlayerAnimationStateEnum,
@@ -56,8 +58,11 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
56
58
  modalSnapPoints,
57
59
  lastSnap,
58
60
  setLastSnap,
61
+ setStartComponentsAnimation,
59
62
  } = useModalAnimationContext();
60
63
 
64
+ const { isLanguageOverlayVisible } = React.useContext(PlayerContainerContext);
65
+
61
66
  const { maximiseVideoModal, minimiseVideoModal, videoModalState } =
62
67
  useNavigation();
63
68
 
@@ -69,6 +74,11 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
69
74
  playerAnimationState !== PlayerAnimationStateEnum.minimize &&
70
75
  playerAnimationState !== PlayerAnimationStateEnum.maximaze;
71
76
 
77
+ const isEnablePanGesture =
78
+ !isLanguageOverlayVisible &&
79
+ isNotMinimizeMaximazeAnimation &&
80
+ (isMaximazedModal || isMinimizedModal);
81
+
72
82
  const isAudioItem = React.useMemo(
73
83
  () =>
74
84
  videoModalState.item?.content?.type?.includes?.("audio") ||
@@ -91,58 +101,68 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
91
101
  { useNativeDriver: true }
92
102
  );
93
103
 
94
- const onHandlerStateChange = ({ nativeEvent }) => {
95
- if (nativeEvent.oldState === State.ACTIVE && scrollPosition.current === 0) {
96
- // eslint-disable-next-line prefer-const
97
- const { velocityY, translationY } = nativeEvent;
98
- const dragToss = 0.05;
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;
99
113
 
100
- const preparedTranslationY =
101
- Math.abs(translationY) - lastScrollYValue.current;
114
+ const preparedTranslationY =
115
+ Math.abs(translationY) - lastScrollYValue.current;
102
116
 
103
- if (videoModalState.mode === "MAXIMIZED") {
104
- const endOffsetY =
105
- lastSnap + preparedTranslationY + dragToss * velocityY + 150;
117
+ if (videoModalState.mode === "MAXIMIZED") {
118
+ const endOffsetY =
119
+ lastSnap + preparedTranslationY + dragToss * velocityY + 150;
106
120
 
107
- let destSnapPoint = modalSnapPoints[0];
121
+ let destSnapPoint = modalSnapPoints[0];
108
122
 
109
- for (const snapPoint of modalSnapPoints) {
110
- const distFromSnap = Math.abs(snapPoint - endOffsetY);
123
+ for (const snapPoint of modalSnapPoints) {
124
+ const distFromSnap = Math.abs(snapPoint - endOffsetY);
111
125
 
112
- if (distFromSnap < Math.abs(destSnapPoint - endOffsetY)) {
113
- destSnapPoint = snapPoint;
126
+ if (distFromSnap < Math.abs(destSnapPoint - endOffsetY)) {
127
+ destSnapPoint = snapPoint;
128
+ }
114
129
  }
115
- }
116
130
 
117
- setLastSnap(destSnapPoint);
131
+ setLastSnap(destSnapPoint);
118
132
 
119
- if (destSnapPoint === modalSnapPoints[0]) {
120
- translateYOffset.extractOffset();
121
- translateYOffset.setValue(preparedTranslationY);
122
- translateYOffset.flattenOffset();
123
- dragScrollY.setValue(0);
133
+ if (destSnapPoint === modalSnapPoints[0]) {
134
+ translateYOffset.extractOffset();
135
+ translateYOffset.setValue(preparedTranslationY);
136
+ translateYOffset.flattenOffset();
137
+ dragScrollY.setValue(0);
124
138
 
125
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
139
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
140
+ } else {
141
+ setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
142
+ }
126
143
  } else {
127
- setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
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
+ }
128
158
  }
129
159
  } else {
130
- if (translationY < 0) {
131
- // from mini to full
132
- setLastSnap(modalSnapPoints[0]);
133
- translateYOffset.setValue(modalSnapPoints[1] - preparedTranslationY);
134
- dragScrollY.setValue(0);
135
-
136
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
137
- } else {
160
+ playerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
138
161
  resetPlayerAnimationState();
139
- }
140
162
  }
141
- } else {
142
- playerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
143
- resetPlayerAnimationState();
144
- }
145
- };
163
+ },
164
+ [lastSnap, modalSnapPoints, playerAnimationState, videoModalState.mode]
165
+ );
146
166
 
147
167
  const onScroll = React.useCallback(({ nativeEvent }) => {
148
168
  scrollPosition.current = nativeEvent.contentOffset.y;
@@ -185,7 +205,8 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
185
205
 
186
206
  if (
187
207
  (videoModalState.mode === "MAXIMIZED" &&
188
- videoModalState.previousMode === "MAXIMIZED") ||
208
+ videoModalState.previousMode === "MINIMIZED" &&
209
+ previousItemId === videoModalState.item?.id) ||
189
210
  previousItemId !== videoModalState.item?.id
190
211
  ) {
191
212
  setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
@@ -262,10 +283,11 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
262
283
  if (
263
284
  preparedValue > 0 &&
264
285
  scrollPosition.current === 0 &&
265
- playerAnimationState !== PlayerAnimationStateEnum.drag_player
286
+ playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
287
+ playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
266
288
  ) {
267
- playerAnimationState !== PlayerAnimationStateEnum.drag_scroll &&
268
- setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
289
+ isMinimizedModal && setStartComponentsAnimation(true);
290
+ setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
269
291
  }
270
292
  });
271
293
 
@@ -273,7 +295,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
273
295
  lastScrollY.removeListener(lastScrollYListenerId);
274
296
  dragScrollY.removeListener(dragListenerId);
275
297
  };
276
- }, [playerAnimationState, isAudioItem, modalSnapPoints]);
298
+ }, [playerAnimationState, isAudioItem, modalSnapPoints, isMinimizedModal]);
277
299
 
278
300
  const Wrapper = React.useMemo(
279
301
  () => (Platform.OS === "android" ? GestureHandlerRootView : View),
@@ -290,15 +312,13 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
290
312
  >
291
313
  <View pointerEvents="box-none">
292
314
  <PanGestureHandler
293
- enabled={
294
- (isMaximazedModal || isMinimizedModal) &&
295
- isNotMinimizeMaximazeAnimation
296
- }
315
+ enabled={isEnablePanGesture}
297
316
  ref={panHandlerRef}
298
317
  simultaneousHandlers={[scrollRef, tapHandlerRef]}
299
318
  shouldCancelWhenOutside={isMaximazedModal}
300
319
  onGestureEvent={onGestureEvent}
301
320
  onHandlerStateChange={onHandlerStateChange}
321
+ activeOffsetY={[-5, 5]}
302
322
  >
303
323
  <Animated.View>
304
324
  <NativeViewGestureHandler
@@ -329,7 +349,12 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
329
349
  };
330
350
 
331
351
  export const AnimatedScrollModal = ({ children }: Props) => {
332
- const Component = !isTV() ? AnimatedScrollModalComponent : React.Fragment;
352
+ const {
353
+ videoModalState: { visible },
354
+ } = useNavigation();
355
+
356
+ const Component =
357
+ !isTV() && visible ? AnimatedScrollModalComponent : React.Fragment;
333
358
 
334
359
  return <Component>{children}</Component>;
335
360
  };