@applicaster/zapp-react-native-ui-components 13.0.0-alpha.3592913150 → 13.0.0-alpha.3637360334

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 (153) hide show
  1. package/Components/AppContainer/__tests__/AppContainer.test.js +4 -6
  2. package/Components/AudioPlayer/AudioPlayer.tsx +7 -0
  3. package/Components/AudioPlayer/__tests__/Runtime.test.js +5 -8
  4. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +54 -111
  5. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +36 -20
  6. package/Components/AudioPlayer/__tests__/artWork.test.js +3 -5
  7. package/Components/AudioPlayer/__tests__/audioPlayer.test.js +3 -5
  8. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +7 -8
  9. package/Components/AudioPlayer/__tests__/channel.test.js +3 -5
  10. package/Components/AudioPlayer/__tests__/summary.test.js +3 -5
  11. package/Components/AudioPlayer/__tests__/title.test.js +3 -5
  12. package/Components/AudioPlayer/helpers.tsx +1 -0
  13. package/Components/BaseFocusable/index.ios.ts +1 -1
  14. package/Components/BaseFocusable/index.tsx +2 -3
  15. package/Components/Cell/Cell.tsx +10 -16
  16. package/Components/Cell/CellWithFocusable.tsx +48 -59
  17. package/Components/Cell/CellWrapper.ts +5 -0
  18. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  19. package/Components/Cell/styles.ts +17 -0
  20. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +46 -48
  21. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  22. package/Components/ComponentResolver/__tests__/componentResolver.test.js +16 -22
  23. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  24. package/Components/ErrorScreen/index.tsx +14 -6
  25. package/Components/Focusable/Focusable.tsx +1 -0
  26. package/Components/Focusable/Touchable.tsx +19 -20
  27. package/Components/Focusable/index.android.tsx +10 -3
  28. package/Components/FocusableCell/index.tsx +1 -1
  29. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  30. package/Components/FocusableGroup/index.tsx +0 -3
  31. package/Components/FocusableList/index.tsx +1 -0
  32. package/Components/FocusableScrollView/index.tsx +6 -3
  33. package/Components/HandlePlayable/HandlePlayable.tsx +14 -27
  34. package/Components/Layout/TV/NavBarContainer.tsx +14 -19
  35. package/Components/Layout/TV/ScreenContainer.tsx +8 -1
  36. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  37. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +2 -1
  38. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -2
  39. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +3 -2
  40. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  41. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  42. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  43. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +9 -14
  44. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  45. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  46. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  47. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  48. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  49. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  50. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +4 -12
  51. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +0 -229
  52. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  53. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  54. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  55. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  56. package/Components/MasterCell/utils/index.ts +9 -135
  57. package/Components/ModalComponent/Button/assets.ts +1 -1
  58. package/Components/ModalComponent/Button/index.tsx +6 -6
  59. package/Components/ModalComponent/Header/index.tsx +3 -3
  60. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  61. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  62. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  63. package/Components/OfflineHandler/utils/index.ts +1 -1
  64. package/Components/PlayerContainer/PlayerContainer.tsx +17 -13
  65. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  66. package/Components/PlayerImageBackground/index.tsx +1 -1
  67. package/Components/River/ComponentsMap/ComponentsMap.tsx +42 -65
  68. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  69. package/Components/River/RiverFooter.tsx +39 -9
  70. package/Components/River/RiverItem.tsx +37 -2
  71. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +100 -31
  72. package/Components/River/__tests__/__snapshots__/river.test.js.snap +20 -82
  73. package/Components/River/__tests__/componentsMap.test.js +17 -5
  74. package/Components/River/__tests__/river.test.js +75 -40
  75. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +11 -4
  76. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  77. package/Components/RouteManager/__tests__/testId.test.js +8 -6
  78. package/Components/Screen/TV/index.web.tsx +5 -6
  79. package/Components/Screen/hooks.ts +53 -0
  80. package/Components/Screen/index.tsx +16 -42
  81. package/Components/ScreenResolver/__tests__/screenResolver.test.js +91 -70
  82. package/Components/Tabs/Tab.tsx +11 -9
  83. package/Components/TextInputTv/index.tsx +4 -3
  84. package/Components/TrackedView/index.tsx +1 -0
  85. package/Components/Transitioner/AnimationManager.js +15 -15
  86. package/Components/Transitioner/Scene.tsx +53 -24
  87. package/Components/Transitioner/Transitioner.tsx +3 -3
  88. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  89. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +9 -49
  90. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
  91. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  92. package/Components/Transitioner/index.js +8 -4
  93. package/Components/VideoLive/LiveImageManager.ts +27 -1
  94. package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
  95. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +51 -1
  96. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -5
  97. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  98. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +47 -31
  99. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +3 -3
  100. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +43 -21
  101. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +4 -5
  102. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  103. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  104. package/Components/VideoModal/ModalAnimation/index.ts +2 -0
  105. package/Components/VideoModal/ModalAnimation/utils.ts +38 -2
  106. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  107. package/Components/VideoModal/PlayerDetails.tsx +9 -6
  108. package/Components/VideoModal/PlayerWrapper.tsx +17 -36
  109. package/Components/VideoModal/VideoModal.tsx +16 -25
  110. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -1
  111. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +0 -90
  112. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  113. package/Components/VideoModal/hooks/index.ts +7 -0
  114. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  115. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  116. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  117. package/Components/VideoModal/utils.ts +1 -1
  118. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  119. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  120. package/Components/Viewport/__tests__/utils.test.js +5 -4
  121. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  122. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  123. package/Components/ZappUIComponent/index.tsx +3 -16
  124. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  125. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  126. package/Contexts/ComponentsMapOffsetContext/index.tsx +8 -5
  127. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
  128. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  129. package/Contexts/ScreenContext/index.tsx +6 -12
  130. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  131. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  132. package/Decorators/Navigator/index.tsx +1 -1
  133. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +18 -24
  134. package/Decorators/RiverResolver/index.tsx +6 -8
  135. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  136. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  137. package/Decorators/ZappPipesDataConnector/index.tsx +6 -2
  138. package/package.json +7 -11
  139. package/tsconfig.json +2 -3
  140. package/.babelrc +0 -8
  141. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  142. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  143. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  144. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  145. package/Components/Cell/CellStyles/colors.js +0 -40
  146. package/Components/Cell/CellStyles/index.js +0 -15
  147. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  148. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  149. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  150. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  151. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  152. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  153. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
@@ -1,63 +1,23 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`<Scene /> renders correctly 1`] = `
4
- <ForwardRef(AnimatedComponentWrapper)
5
- pointerEvents="auto"
6
- style={
7
- [
4
+ <View>
5
+ <View
6
+ collapsable={false}
7
+ pointerEvents="auto"
8
+ style={
8
9
  {
9
10
  "flex": 1,
10
- },
11
- {
12
- "paddingBottom": 49,
13
- },
14
- {
15
11
  "fontScale": 2,
16
12
  "height": 1334,
13
+ "paddingBottom": 49,
17
14
  "scale": 2,
18
15
  "statusBarHeight": null,
19
16
  "width": 750,
20
- },
21
- ]
22
- }
23
- >
24
- <ContextProvider>
25
- <ContextProvider>
26
- <ScreenContextProvider />
27
- </ContextProvider>
28
- </ContextProvider>
29
- </ForwardRef(AnimatedComponentWrapper)>
30
- `;
31
-
32
- exports[`<Scene /> renders the overlay while animating 1`] = `
33
- <ForwardRef(AnimatedComponentWrapper)
34
- pointerEvents="auto"
35
- style={
36
- [
37
- {
38
- "flex": 1,
39
- },
40
- {
41
- "paddingBottom": 49,
42
- },
43
- {
44
- "height": "100%",
45
- "width": "100%",
46
- },
47
- ]
48
- }
49
- >
50
- <ContextProvider>
51
- <ContextProvider>
52
- <ScreenContextProvider />
53
- </ContextProvider>
54
- </ContextProvider>
55
- <ForwardRef(AnimatedComponentWrapper)
56
- style={
57
- {
58
- "opacity": 1,
59
17
  }
60
18
  }
61
19
  />
62
- </ForwardRef(AnimatedComponentWrapper)>
20
+ </View>
63
21
  `;
22
+
23
+ exports[`<Scene /> renders the overlay while animating 1`] = `[Function]`;
@@ -9,7 +9,7 @@ exports[`<TransitionerComponent /> renders correctly 1`] = `
9
9
  }
10
10
  }
11
11
  >
12
- <Scene
12
+ <View
13
13
  isActive={true}
14
14
  screenUniqueId="mocked-uuid"
15
15
  style={{}}
@@ -23,6 +23,6 @@ exports[`<TransitionerComponent /> renders correctly 1`] = `
23
23
  children
24
24
  </Text>
25
25
  </View>
26
- </Scene>
26
+ </View>
27
27
  </View>
28
28
  `;
@@ -1,9 +1,18 @@
1
1
  import React from "react";
2
2
  import { Text, View } from "react-native";
3
- import { shallow } from "enzyme";
4
- import { shallowToJson } from "enzyme-to-json";
5
3
 
6
4
  import { TransitionerComponent } from "../Transitioner";
5
+ import { render } from "@testing-library/react-native";
6
+
7
+ jest.mock("../Scene", () => {
8
+ const View = jest.requireActual("react-native").View;
9
+
10
+ return {
11
+ Scene(props) {
12
+ return <View {...props} />;
13
+ },
14
+ };
15
+ });
7
16
 
8
17
  const children = (
9
18
  <View foo="bar">
@@ -33,12 +42,12 @@ jest.mock("uuid");
33
42
 
34
43
  describe("<TransitionerComponent />", () => {
35
44
  it("renders correctly", () => {
36
- const wrapper = shallow(
45
+ const wrapper = render(
37
46
  <TransitionerComponent {...transitionerComponentProps}>
38
47
  {children}
39
48
  </TransitionerComponent>
40
49
  );
41
50
 
42
- expect(shallowToJson(wrapper)).toMatchSnapshot();
51
+ expect(wrapper.toJSON()).toMatchSnapshot();
43
52
  });
44
53
  });
@@ -1,5 +1,4 @@
1
1
  import * as React from "react";
2
- import { useWindowDimensions } from "react-native";
3
2
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
3
  import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
5
4
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
@@ -7,10 +6,15 @@ import { TransitionerComponent } from "./Transitioner";
7
6
 
8
7
  export const Transitioner = (props) => {
9
8
  const navigator = useNavigation();
10
- const { height, width } = useWindowDimensions();
11
9
 
12
- const dimensions = useDimensions("window", { deviceInfo: true });
13
- const isTablet = dimensions?.deviceInfo?.isTablet;
10
+ const {
11
+ width,
12
+ height,
13
+ deviceInfo: { isTablet },
14
+ } = useDimensions("window", {
15
+ updateForInactiveScreens: false,
16
+ deviceInfo: true,
17
+ });
14
18
 
15
19
  const { appData } = usePickFromState(["appData"]);
16
20
  const isTabletPortrait = appData?.isTabletPortrait;
@@ -8,6 +8,8 @@ import { loggerLiveImageManager } from "./loggerHelper";
8
8
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
9
9
  import { Component } from "react";
10
10
 
11
+ const TIMEOUT_FOR_DELAY_CHECK_PLAYER_POSITION = 500; // ms
12
+
11
13
  const { log_debug, log_info, log_error } = loggerLiveImageManager;
12
14
 
13
15
  export type LiveImageManagerEvent =
@@ -62,6 +64,9 @@ export class LiveImageManager implements PlayerLifecycleListener {
62
64
  protected currentlyPlaying: LiveImage | null = null;
63
65
  protected primaryPlayer: Player | null = null;
64
66
 
67
+ private checkPlayerPositionTimeout: ReturnType<typeof setTimeout> | null =
68
+ null;
69
+
65
70
  protected listeners: Record<
66
71
  string,
67
72
  Record<LiveImageManagerEvent, (event?: Record<string, any>) => void>
@@ -118,6 +123,11 @@ export class LiveImageManager implements PlayerLifecycleListener {
118
123
  });
119
124
  };
120
125
 
126
+ private cancelCheckPlayerPositionTimeout = () => {
127
+ clearTimeout(this.checkPlayerPositionTimeout);
128
+ this.checkPlayerPositionTimeout = null;
129
+ };
130
+
121
131
  public onViewportEnter = (item: LiveImage) => {
122
132
  log_debug(
123
133
  `onViewportEnter: live-image ${playerInfo(
@@ -125,7 +135,21 @@ export class LiveImageManager implements PlayerLifecycleListener {
125
135
  )}, primary ${playerInfo(this.primaryPlayer)}`
126
136
  );
127
137
 
128
- this.checkPlayerPosition(item);
138
+ if (!isTV()) {
139
+ // mobile only
140
+ // we have to delay running checkPlayerPosition, because sometimes on fast scrolling we get wrong order onEnter, then onLeave.
141
+ // which could cause select wrong item to play
142
+
143
+ this.cancelCheckPlayerPositionTimeout();
144
+
145
+ this.checkPlayerPositionTimeout = setTimeout(() => {
146
+ this.cancelCheckPlayerPositionTimeout();
147
+
148
+ this.checkPlayerPosition(item);
149
+ }, TIMEOUT_FOR_DELAY_CHECK_PLAYER_POSITION);
150
+ } else {
151
+ this.checkPlayerPosition(item);
152
+ }
129
153
  };
130
154
 
131
155
  public onViewportLeave = (item: LiveImage) => {
@@ -246,6 +270,8 @@ export class LiveImageManager implements PlayerLifecycleListener {
246
270
  };
247
271
 
248
272
  public checkPlayerPosition = (item: LiveImage) => {
273
+ this.cancelCheckPlayerPositionTimeout();
274
+
249
275
  log_debug(
250
276
  `checkPlayerPosition: live-image playerId: ${playerInfo(
251
277
  item.player
@@ -1,6 +1,7 @@
1
1
  // /// <reference types="@applicaster/applicaster-types" />
2
2
  //
3
3
  import * as React from "react";
4
+ import { useEffect } from "react";
4
5
 
5
6
  import { AppState, AppStateStatus, View } from "react-native";
6
7
  import { TrackedView } from "../TrackedView";
@@ -25,13 +26,15 @@ import { PlayerRole } from "@applicaster/zapp-react-native-utils/appUtils/player
25
26
  import { getAutoplaySettings } from "./utils";
26
27
  import { isString } from "@applicaster/zapp-react-native-utils/stringUtils";
27
28
  import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
28
- import { useEffect } from "react";
29
29
 
30
30
  const { log_error, log_debug } = loggerLiveImageComponent;
31
31
 
32
32
  const isMeasurement = (item: ZappEntry) =>
33
33
  isString(item.id) && item.id.startsWith("pre-measurement-");
34
34
 
35
+ // Pixels by which the view can slightly extend outside the viewport and still be considered fully visible.
36
+ const CLIP_THRESHOLD = 10;
37
+
35
38
  type Props = {
36
39
  item: ZappEntry;
37
40
  style: Record<string, any>;
@@ -44,7 +47,10 @@ type Props = {
44
47
  };
45
48
 
46
49
  const PlayerLiveImageComponent = (props: Props) => {
47
- const dimensions = useDimensions("screen", { fullDimensions: true });
50
+ const dimensions = useDimensions("screen", {
51
+ fullDimensions: true,
52
+ updateForInactiveScreens: false,
53
+ });
48
54
 
49
55
  const { item, style, playerId } = props;
50
56
 
@@ -135,13 +141,16 @@ const PlayerLiveImageComponent = (props: Props) => {
135
141
  } else {
136
142
  throw new Error("Player factory item is null");
137
143
  }
138
- }, [playerId, item, playerPluginId, screenConfig]);
144
+ }, [playerId, item.id, playerPluginId, screenConfig]);
139
145
 
140
146
  React.useEffect(() => {
141
147
  liveImageItem.setMode = setModeDebounced;
142
148
  }, [setModeDebounced, liveImageItem]);
143
149
 
144
- const { start, end } = React.useMemo(() => getAutoplaySettings(item), [item]);
150
+ const { start, end } = React.useMemo(
151
+ () => getAutoplaySettings(item),
152
+ [item.id]
153
+ );
145
154
 
146
155
  const controller = liveImageItem.getPlayer();
147
156
  const player = usePlayer(playerId);
@@ -174,7 +183,7 @@ const PlayerLiveImageComponent = (props: Props) => {
174
183
 
175
184
  unregister();
176
185
  };
177
- }, [item, liveImageItem]);
186
+ }, [item.id, liveImageItem]);
178
187
 
179
188
  React.useEffect(() => {
180
189
  if (!player) {
@@ -244,25 +253,27 @@ const PlayerLiveImageComponent = (props: Props) => {
244
253
  }, [item.id]);
245
254
 
246
255
  React.useEffect(() => {
247
- if (playerManager) {
248
- const isPlayerRegistered = playerManager.isPlayerRegistered(playerId);
256
+ if (isMeasurement(item) || !playerManager) {
257
+ return;
258
+ }
249
259
 
250
- if (isPlayerRegistered) {
251
- log_error(
252
- `PlayerLiveImageComponent: player ${playerId} already registered`
253
- );
254
- } else {
255
- playerManager.registerPlayer({
256
- id: playerId,
257
- playerController: controller,
258
- });
260
+ const isPlayerRegistered = playerManager.isPlayerRegistered(playerId);
259
261
 
260
- return () => {
261
- playerManager.unregisterPlayer(playerId);
262
- };
263
- }
262
+ if (isPlayerRegistered) {
263
+ log_error(
264
+ `PlayerLiveImageComponent: player ${playerId} already registered`
265
+ );
266
+ } else {
267
+ playerManager.registerPlayer({
268
+ id: playerId,
269
+ playerController: controller,
270
+ });
271
+
272
+ return () => {
273
+ playerManager.unregisterPlayer(playerId);
274
+ };
264
275
  }
265
- }, [liveImageItem, playerId, controller]);
276
+ }, [liveImageItem, playerId, controller, item.id]);
266
277
 
267
278
  const onPositionUpdated = React.useCallback(
268
279
  (data) => {
@@ -302,7 +313,7 @@ const PlayerLiveImageComponent = (props: Props) => {
302
313
  LiveImageManager.instance.checkPlayerPosition(liveImageItem);
303
314
  }
304
315
  },
305
- [liveImageItem, dimensions]
316
+ [liveImageItem, dimensions.height, dimensions.width]
306
317
  );
307
318
 
308
319
  const platformSpecificProps = isApplePlatform()
@@ -320,9 +331,10 @@ const PlayerLiveImageComponent = (props: Props) => {
320
331
  <TrackedView
321
332
  testId={`tracked-view-${playerId}-${item.title}`}
322
333
  onPositionUpdated={onPositionUpdated}
334
+ clipThreshold={CLIP_THRESHOLD}
323
335
  >
324
336
  <View ref={trackViewRef}>
325
- {isVideoMode && (
337
+ {isVideoMode ? (
326
338
  <Player
327
339
  autoplay={false}
328
340
  ref={_assignRoot}
@@ -334,7 +346,7 @@ const PlayerLiveImageComponent = (props: Props) => {
334
346
  resizeMode={"cover"}
335
347
  {...platformSpecificProps}
336
348
  />
337
- )}
349
+ ) : null}
338
350
  {
339
351
  <AnimatedInOut
340
352
  visible={isBackgroundImageVisible}
@@ -4,6 +4,7 @@ import { render } from "@testing-library/react-native";
4
4
  import * as PlayerFactory from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
5
5
  import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
6
6
  import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
7
+ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
7
8
 
8
9
  import { PlayerLiveImage } from "../PlayerLiveImageComponent";
9
10
  import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
@@ -32,7 +33,7 @@ const mockStore = configureStore();
32
33
 
33
34
  const store = mockStore({ appData: {} });
34
35
 
35
- const Wrapper = ({ children }: { children: React.ReactChildren }) => (
36
+ const Wrapper = ({ children }: { children: React.ReactNode }) => (
36
37
  /* @ts-ignore */
37
38
  <Provider store={store}>
38
39
  <ThemeContext.Provider
@@ -118,4 +119,53 @@ describe("PlayerLiveImageComponent", () => {
118
119
 
119
120
  // TODO: implement this test
120
121
  });
122
+
123
+ it("should register the player for normal item", () => {
124
+ render(
125
+ <Wrapper>
126
+ <PlayerLiveImage {...defaultProps} />
127
+ </Wrapper>
128
+ );
129
+
130
+ const isPlayerRegistered = playerManager.isPlayerRegistered(
131
+ defaultProps.playerId
132
+ );
133
+
134
+ expect(isPlayerRegistered).toBe(true);
135
+ });
136
+
137
+ it("should unregister the player for normal item", () => {
138
+ const component = render(
139
+ <Wrapper>
140
+ <PlayerLiveImage {...defaultProps} />
141
+ </Wrapper>
142
+ );
143
+
144
+ component.unmount();
145
+
146
+ const isPlayerRegistered = playerManager.isPlayerRegistered(
147
+ defaultProps.playerId
148
+ );
149
+
150
+ expect(isPlayerRegistered).toBe(false);
151
+ });
152
+
153
+ it("should not register the player for 'pre-measurement' item", () => {
154
+ const props = {
155
+ ...defaultProps,
156
+ item: {
157
+ ...defaultProps.item,
158
+ id: "pre-measurement-1",
159
+ },
160
+ };
161
+
162
+ render(
163
+ <Wrapper>
164
+ <PlayerLiveImage {...props} />
165
+ </Wrapper>
166
+ );
167
+
168
+ const isPlayerRegistered = playerManager.isPlayerRegistered(props.playerId);
169
+ expect(isPlayerRegistered).toBe(false);
170
+ });
121
171
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  exports[`PlayerLiveImageComponent should render correctly with default props 1`] = `
4
4
  <TrackedView
5
+ clipThreshold={10}
5
6
  onPositionUpdated={[Function]}
6
7
  testId="tracked-view-player1-Test"
7
8
  >
@@ -31,11 +32,6 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
31
32
  playerId="player1"
32
33
  resizeMode="cover"
33
34
  screenConfig={{}}
34
- source={
35
- {
36
- "uri": "",
37
- }
38
- }
39
35
  style={{}}
40
36
  />
41
37
  </View>
@@ -46,7 +46,7 @@ export const AnimatedPlayerModalWrapper = (props: Props) => {
46
46
 
47
47
  React.useEffect(() => {
48
48
  (playerAnimationState === PlayerAnimationStateEnum.minimize ||
49
- playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
49
+ playerAnimationState === PlayerAnimationStateEnum.maximize) &&
50
50
  setStartComponentsAnimation(true);
51
51
  }, [playerAnimationState]);
52
52
 
@@ -1,32 +1,34 @@
1
1
  import React from "react";
2
- import { Animated, StyleSheet, View, Platform } from "react-native";
2
+ import { Animated, Platform, StyleSheet, View } from "react-native";
3
3
 
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
5
  import {
6
+ GestureHandlerRootView,
6
7
  NativeViewGestureHandler,
7
8
  PanGestureHandler,
8
9
  State,
9
10
  TapGestureHandler,
10
- GestureHandlerRootView,
11
11
  } from "react-native-gesture-handler";
12
12
 
13
13
  import { PlayerContainerContext } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainerContext";
14
14
  import {
15
- useModalAnimationContext,
16
15
  PlayerAnimationStateEnum,
16
+ useModalAnimationContext,
17
17
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
18
18
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
19
19
  import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
20
20
 
21
21
  import {
22
- setScrollModalAnimatedValue,
23
22
  resetScrollAnimatedValues,
23
+ setScrollModalAnimatedValue,
24
24
  } from "./utils";
25
25
 
26
+ import { DURATION_TO_MINIMIZE } from "./const";
27
+
26
28
  const getAnimatedConfig = (toValue) => {
27
29
  return {
28
30
  toValue,
29
- duration: 200,
31
+ duration: DURATION_TO_MINIMIZE,
30
32
  useNativeDriver: true,
31
33
  };
32
34
  };
@@ -70,21 +72,26 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
70
72
  const { maximiseVideoModal, minimiseVideoModal, videoModalState } =
71
73
  useNavigation();
72
74
 
73
- const { mode: videoModalMode, item: videoModalItem } = videoModalState;
74
- const isMaximazedModal = videoModalMode === "MAXIMIZED";
75
- const isMinimizedModal = videoModalMode === "MINIMIZED";
75
+ const {
76
+ mode: videoModalMode,
77
+ previousMode: previousVideoModalMode,
78
+ item: videoModalItem,
79
+ } = videoModalState;
80
+
81
+ const isMaximizedModal: boolean = videoModalMode === "MAXIMIZED";
82
+ const isMinimizedModal: boolean = videoModalMode === "MINIMIZED";
76
83
  const previousItemId = usePrevious(videoModalItem?.id);
77
84
 
78
85
  const isNotMinimizeMaximazeAnimation =
79
86
  playerAnimationState !== PlayerAnimationStateEnum.minimize &&
80
- playerAnimationState !== PlayerAnimationStateEnum.maximaze;
87
+ playerAnimationState !== PlayerAnimationStateEnum.maximize;
81
88
 
82
89
  const isEnablePanGesture =
83
90
  enableGesture &&
84
91
  !isLanguageOverlayVisible &&
85
92
  isNotMinimizeMaximazeAnimation &&
86
93
  !isSeekBarTouch &&
87
- (isMaximazedModal || isMinimizedModal);
94
+ (isMaximizedModal || isMinimizedModal);
88
95
 
89
96
  const isAudioItem = React.useMemo(
90
97
  () =>
@@ -121,7 +128,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
121
128
  const preparedTranslationY =
122
129
  Math.abs(translationY) - lastScrollYValue.current;
123
130
 
124
- if (videoModalMode === "MAXIMIZED") {
131
+ if (isMaximizedModal) {
125
132
  const endOffsetY =
126
133
  lastSnap + preparedTranslationY + dragToss * velocityY + 150;
127
134
 
@@ -137,14 +144,14 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
137
144
 
138
145
  setLastSnap(destSnapPoint);
139
146
 
140
- if (destSnapPoint === modalSnapPoints[0]) {
147
+ if (destSnapPoint === modalSnapPoints[0] && isMinimizedModal) {
141
148
  translateYOffset.extractOffset();
142
149
  translateYOffset.setValue(preparedTranslationY);
143
150
  translateYOffset.flattenOffset();
144
151
  dragScrollY.setValue(0);
145
152
 
146
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
147
- } else {
153
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
154
+ } else if (destSnapPoint !== modalSnapPoints[0] && isMaximizedModal) {
148
155
  setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
149
156
  }
150
157
  } else {
@@ -158,7 +165,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
158
165
 
159
166
  dragScrollY.setValue(0);
160
167
 
161
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
168
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
162
169
  } else {
163
170
  resetPlayerAnimationState();
164
171
  }
@@ -168,7 +175,13 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
168
175
  resetPlayerAnimationState();
169
176
  }
170
177
  },
171
- [lastSnap, modalSnapPoints, playerAnimationState, videoModalMode]
178
+ [
179
+ lastSnap,
180
+ modalSnapPoints,
181
+ playerAnimationState,
182
+ isMinimizedModal,
183
+ isMaximizedModal,
184
+ ]
172
185
  );
173
186
 
174
187
  const onScroll = React.useCallback(({ nativeEvent }) => {
@@ -219,17 +232,18 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
219
232
  }, []);
220
233
 
221
234
  React.useEffect(() => {
222
- const { mode, previousMode, item } = videoModalState;
223
-
224
235
  if (
225
- mode === "MAXIMIZED" &&
236
+ videoModalMode === "MAXIMIZED" &&
226
237
  !enableGesture &&
227
238
  scrollPosition.current === 0
228
239
  ) {
229
240
  setIEnableGesture(true);
230
241
  }
231
242
 
232
- if (mode === "MINIMIZED" && previousMode === "MAXIMIZED") {
243
+ if (
244
+ videoModalMode === "MINIMIZED" &&
245
+ previousVideoModalMode === "MAXIMIZED"
246
+ ) {
233
247
  // set animation to the minimize values if moving from the player to another screen
234
248
  if (playerAnimationState === null) {
235
249
  setScrollModalAnimatedValue(
@@ -247,14 +261,16 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
247
261
  }
248
262
  } else if (
249
263
  playerAnimationState === null &&
250
- ((previousItemId === item?.id &&
251
- mode === "MAXIMIZED" &&
252
- (previousMode === "MINIMIZED" || previousMode === "MAXIMIZED")) ||
253
- (previousItemId !== item?.id && mode !== "FULLSCREEN"))
264
+ ((previousItemId === videoModalItem?.id &&
265
+ videoModalMode === "MAXIMIZED" &&
266
+ (previousVideoModalMode === "MINIMIZED" ||
267
+ previousVideoModalMode === "MAXIMIZED")) ||
268
+ (previousItemId !== videoModalItem?.id &&
269
+ videoModalMode !== "FULLSCREEN"))
254
270
  ) {
255
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
271
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
256
272
  }
257
- }, [videoModalState]);
273
+ }, [videoModalMode, previousVideoModalMode, videoModalItem]);
258
274
 
259
275
  React.useEffect(() => {
260
276
  if (playerAnimationState === PlayerAnimationStateEnum.minimize) {
@@ -296,7 +312,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
296
312
 
297
313
  resetPlayerAnimationState();
298
314
  });
299
- } else if (playerAnimationState === PlayerAnimationStateEnum.maximaze) {
315
+ } else if (playerAnimationState === PlayerAnimationStateEnum.maximize) {
300
316
  Animated.timing(translateYOffset, getAnimatedConfig(0)).start(() => {
301
317
  maximiseVideoModal();
302
318
  setScrollModalAnimatedValue(translateYOffset, 0, setLastSnap);
@@ -346,6 +362,8 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
346
362
  []
347
363
  );
348
364
 
365
+ const scrollEnabled = isMaximizedModal && isNotMinimizeMaximazeAnimation;
366
+
349
367
  return (
350
368
  <Wrapper style={generalStyles.container}>
351
369
  <TapGestureHandler
@@ -359,7 +377,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
359
377
  enabled={isEnablePanGesture}
360
378
  ref={panHandlerRef}
361
379
  simultaneousHandlers={[scrollRef, tapHandlerRef]}
362
- shouldCancelWhenOutside={isMaximazedModal}
380
+ shouldCancelWhenOutside={isMaximizedModal}
363
381
  onGestureEvent={onGestureEvent}
364
382
  onHandlerStateChange={onHandlerStateChange}
365
383
  activeOffsetY={[-5, 5]}
@@ -371,9 +389,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
371
389
  simultaneousHandlers={panHandlerRef}
372
390
  >
373
391
  <Animated.ScrollView
374
- scrollEnabled={
375
- isMaximazedModal && isNotMinimizeMaximazeAnimation
376
- }
392
+ scrollEnabled={scrollEnabled}
377
393
  bounces={false}
378
394
  onScrollBeginDrag={onRegisterLastScroll}
379
395
  onScroll={onScroll}
@@ -50,7 +50,7 @@ export const AnimatedVideoPlayer = ({ children }: Props) => {
50
50
 
51
51
  const isNotMinimizeMaximazeAnimation =
52
52
  playerAnimationState !== PlayerAnimationStateEnum.minimize &&
53
- playerAnimationState !== PlayerAnimationStateEnum.maximaze;
53
+ playerAnimationState !== PlayerAnimationStateEnum.maximize;
54
54
 
55
55
  const isEnablePanGesture =
56
56
  !isLanguageOverlayVisible &&
@@ -89,7 +89,7 @@ export const AnimatedVideoPlayer = ({ children }: Props) => {
89
89
  setLastSnap(destSnapPoint);
90
90
 
91
91
  if (destSnapPoint === modalSnapPoints[0]) {
92
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
92
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
93
93
  } else {
94
94
  lastScrollY.setValue(0);
95
95
  lastScrollYValue.current = 0;
@@ -105,7 +105,7 @@ export const AnimatedVideoPlayer = ({ children }: Props) => {
105
105
  modalSnapPoints[1] - preparedTranslationY
106
106
  );
107
107
 
108
- setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
108
+ setPlayerAnimationState(PlayerAnimationStateEnum.maximize);
109
109
  } else {
110
110
  resetPlayerAnimationState();
111
111
  }