@applicaster/zapp-react-native-ui-components 12.0.0-alpha.7725319213 → 12.0.0-alpha.8058554488

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 (95) 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/Cell/Cell.tsx +2 -2
  5. package/Components/Cell/CellWithFocusable.tsx +21 -14
  6. package/Components/Cell/TvOSCellComponent.tsx +2 -2
  7. package/Components/ErrorScreen/index.tsx +1 -1
  8. package/Components/FocusableCell/index.tsx +7 -7
  9. package/Components/FocusableList/FocusableChild.ts +24 -14
  10. package/Components/FocusableList/FocusableItem.tsx +1 -1
  11. package/Components/FocusableList/FocusableListItemWrapper.tsx +76 -0
  12. package/Components/FocusableList/hooks/useCellState.android.ts +3 -1
  13. package/Components/FocusableList/index.tsx +26 -25
  14. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +6 -3
  15. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  16. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  17. package/Components/HookRenderer/index.tsx +1 -6
  18. package/Components/Image/Image.android.tsx +3 -25
  19. package/Components/Image/Image.tsx +18 -2
  20. package/Components/Image/utils/index.ts +39 -0
  21. package/Components/Layout/TV/__tests__/index.test.tsx +1 -34
  22. package/Components/Layout/TV/index.tsx +20 -36
  23. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
  24. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  25. package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
  26. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +17 -2
  27. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
  28. package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
  29. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  30. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +8 -14
  31. package/Components/MasterCell/utils/index.ts +16 -5
  32. package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
  33. package/Components/ModalComponent/Button/Item.tsx +82 -0
  34. package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
  35. package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
  36. package/Components/ModalComponent/Button/assets.ts +4 -0
  37. package/Components/ModalComponent/Button/index.tsx +111 -0
  38. package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
  39. package/Components/ModalComponent/Header/Title.tsx +70 -0
  40. package/Components/ModalComponent/Header/assets.ts +4 -0
  41. package/Components/ModalComponent/Header/index.tsx +71 -0
  42. package/Components/ModalComponent/Header/utils.ts +79 -0
  43. package/Components/ModalComponent/index.tsx +38 -0
  44. package/Components/ModalComponent/utils.ts +126 -0
  45. package/Components/PlayerContainer/PlayerContainer.tsx +59 -31
  46. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
  47. package/Components/PlayerImageBackground/index.tsx +34 -8
  48. package/Components/River/ComponentsMap/ComponentsMap.tsx +91 -2
  49. package/Components/River/TV/River.tsx +2 -2
  50. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
  51. package/Components/River/__tests__/componentsMap.test.js +7 -0
  52. package/Components/River/useScreenConfiguration.ts +2 -2
  53. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
  54. package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
  55. package/Components/RouteManager/index.tsx +5 -3
  56. package/Components/Screen/__tests__/Screen.test.tsx +88 -74
  57. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
  58. package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
  59. package/Components/Screen/index.tsx +103 -43
  60. package/Components/Screen/navigationHandler.ts +0 -82
  61. package/Components/ScreenResolver/index.tsx +1 -1
  62. package/Components/Tabs/TV/styles.ts +1 -1
  63. package/Components/VideoLive/LiveImageManager.ts +2 -2
  64. package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -28
  65. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
  66. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
  67. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
  68. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
  69. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
  70. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
  71. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +143 -0
  72. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  73. package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
  74. package/Components/VideoModal/PlayerDetails.tsx +3 -0
  75. package/Components/VideoModal/PlayerWrapper.tsx +64 -41
  76. package/Components/VideoModal/VideoModal.tsx +8 -25
  77. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
  78. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +5 -1
  79. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
  80. package/Components/VideoModal/utils.ts +3 -3
  81. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
  82. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  83. package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
  84. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  85. package/Components/Viewport/utils.js +1 -1
  86. package/Components/ZappUIComponent/index.tsx +22 -12
  87. package/Components/index.js +2 -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 +95 -29
  92. package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
  93. package/package.json +5 -5
  94. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  95. /package/Contexts/{index.js → index.ts} +0 -0
@@ -1,85 +1,3 @@
1
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
2
-
3
- /**
4
- * This function helps to decide wether the navbar should be presented on the screen
5
- * based on route and / or screen Data
6
- *
7
- * Currently the scenarios include
8
- * - players => false
9
- * - search screen plugin => false
10
- * - hooks with `showNavBar: true` or `presentFullScreen` not set to true, defaults to no navbar for hook screens
11
- * - screens with `allow_screen_plugin_presentation` in general property => false
12
- *
13
- * @param {String} route current route of the screen
14
- * @param {Object} screenData payload associated with the currently presented screen
15
- * @returns {Boolean}
16
- */
17
- export function isNavBarVisible(
18
- route,
19
- screenData,
20
- showNavBar,
21
- canGoBack,
22
- videoModalState: QuickBrickVideoModalState | null = null
23
- ) {
24
- /* screenData is not actual navigator.data
25
- * or navigator.screenData,
26
- * but navigator.data.screen */
27
- if (route.includes("playable")) {
28
- return false;
29
- }
30
-
31
- if (
32
- videoModalState?.mode === "FULLSCREEN" &&
33
- videoModalState?.visible === true
34
- ) {
35
- return false;
36
- }
37
-
38
- if (screenData?.type === "qb_search_screen" && !isTV()) {
39
- return false;
40
- }
41
-
42
- /* Match if screen is Hook */
43
- if (route.startsWith("/hooks/")) {
44
- const module = screenData?.module;
45
-
46
- if (module?.presentFullScreen) {
47
- return false;
48
- }
49
-
50
- return module?.showNavBar ?? false;
51
- }
52
-
53
- if (screenData?.hookPlugin) {
54
- const hookPlugin = screenData?.hookPlugin?.module;
55
-
56
- return (
57
- hookPlugin?.showNavBar || hookPlugin?.presentFullScreen !== true || false
58
- );
59
- }
60
-
61
- if (
62
- screenData?.general?.allow_screen_plugin_presentation ||
63
- screenData?.general?.hide_app_nav_bar
64
- ) {
65
- return false;
66
- }
67
-
68
- const hideSecondaryLevel = screenData?.navigations?.some(
69
- (navigation) => navigation.styles?.hide_secondary_level_menu
70
- );
71
-
72
- if (canGoBack && hideSecondaryLevel) {
73
- return false;
74
- }
75
-
76
- if (typeof showNavBar === "boolean" && !showNavBar) {
77
- return false;
78
- }
79
-
80
- return true;
81
- }
82
-
83
1
  /**
84
2
  * This function helps to decide wether the menu should be presented on the screen
85
3
  * based on route and / or screen Data
@@ -91,7 +91,7 @@ export function ScreenResolverComponent(props: Props) {
91
91
  <HookRenderer
92
92
  screenData={screenData}
93
93
  focused={props.focused}
94
- parentFocus={props.parentFocus}
94
+ parentFocus={props.parentFocus as ParentFocus}
95
95
  />
96
96
  )
97
97
  );
@@ -78,7 +78,7 @@ export const getStyles = (config): Partial<TVTabsStyles> => {
78
78
  },
79
79
  tvos: {
80
80
  marginTop: -1,
81
- }
81
+ },
82
82
  }),
83
83
  },
84
84
  tabsBackground: {
@@ -369,8 +369,8 @@ export class LiveImageManager implements PlayerLifecycleListener {
369
369
  // TODO: This branch was used when we had play button to toggle replay.
370
370
  // Now we mute button instead but we keep it just in case.
371
371
  if (IS_ALLOWED_REPLAY && !isTV() && isCurrentItemEnded) {
372
- this.currentlyPlaying.player.seekTo(0);
373
- this.currentlyPlaying.player.pause();
372
+ this.currentlyPlaying?.player.seekTo(0);
373
+ this.currentlyPlaying?.player.pause();
374
374
 
375
375
  // TODO: ...Maybe player some other item
376
376
  } else {
@@ -14,7 +14,7 @@ import {
14
14
  } from "@applicaster/zapp-react-native-utils/reactUtils";
15
15
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
16
16
  import { getUserCellPlayerMutedPreference } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/userCellPlayerMutedPreference";
17
- import { PlayerImageBackground } from "../PlayerImageBackground";
17
+ import Image from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/Image";
18
18
  import { LiveImage, LiveImageManager, LiveImageType } from "./LiveImageManager";
19
19
 
20
20
  import { AnimatedInOut } from "@applicaster/zapp-react-native-ui-components/Components/AnimatedInOut";
@@ -39,12 +39,13 @@ type Props = {
39
39
  imageKey?: string;
40
40
  screenConfig: Record<string, any>;
41
41
  audioMutedByDefault?: boolean;
42
+ uri: string; // cover image url
42
43
  };
43
44
 
44
45
  const PlayerLiveImageComponent = (props: Props) => {
45
46
  const dimensions = useDimensions("screen", { fullDimensions: true });
46
47
 
47
- const { item, style, playerId, imageKey } = props;
48
+ const { item, style, playerId } = props;
48
49
 
49
50
  const timeoutRef = React.useRef<NodeJS.Timeout | null>(null);
50
51
  const [mode, setMode] = React.useState(LiveImageType.Image);
@@ -63,24 +64,27 @@ const PlayerLiveImageComponent = (props: Props) => {
63
64
  *
64
65
  * @param type video or image
65
66
  */
66
- const setModeDebounced = React.useCallback((type: LiveImageType) => {
67
- if (type === LiveImageType.Video) {
68
- if (type === mode) {
69
- return;
70
- }
67
+ const setModeDebounced = React.useCallback(
68
+ (type: LiveImageType) => {
69
+ if (type === LiveImageType.Video) {
70
+ if (type === mode) {
71
+ return;
72
+ }
73
+
74
+ timeoutRef.current = setTimeout(() => {
75
+ setMode(type);
76
+ }, 1000) as unknown as NodeJS.Timeout;
77
+ } else {
78
+ if (timeoutRef.current) {
79
+ clearTimeout(timeoutRef.current);
80
+ timeoutRef.current = null;
81
+ }
71
82
 
72
- timeoutRef.current = setTimeout(() => {
73
83
  setMode(type);
74
- }, 1000) as unknown as NodeJS.Timeout;
75
- } else {
76
- if (timeoutRef.current) {
77
- clearTimeout(timeoutRef.current);
78
- timeoutRef.current = null;
79
84
  }
80
-
81
- setMode(type);
82
- }
83
- }, [mode]);
85
+ },
86
+ [mode]
87
+ );
84
88
 
85
89
  const { screenConfig, playerPluginId } = props;
86
90
 
@@ -100,7 +104,7 @@ const PlayerLiveImageComponent = (props: Props) => {
100
104
  return new LiveImage({
101
105
  playerId,
102
106
  player: playerFactoryItem.controller,
103
- component: playerFactoryItem?.Component
107
+ component: playerFactoryItem?.Component,
104
108
  });
105
109
  } else {
106
110
  throw new Error("Player factory item is null");
@@ -111,10 +115,7 @@ const PlayerLiveImageComponent = (props: Props) => {
111
115
  liveImageItem.setMode = setModeDebounced;
112
116
  }, [setModeDebounced, liveImageItem]);
113
117
 
114
- const { start, end } = React.useMemo(
115
- () => getAutoplaySettings(item),
116
- [item]
117
- );
118
+ const { start, end } = React.useMemo(() => getAutoplaySettings(item), [item]);
118
119
 
119
120
  const controller = liveImageItem.getPlayer();
120
121
  const player = usePlayer(playerId);
@@ -239,7 +240,12 @@ const PlayerLiveImageComponent = (props: Props) => {
239
240
 
240
241
  const onPositionUpdated = React.useCallback(
241
242
  (data) => {
242
- const normalizedRect = (rect: {left: number, right: number, top: number, bottom: number }) => {
243
+ const normalizedRect = (rect: {
244
+ left: number;
245
+ right: number;
246
+ top: number;
247
+ bottom: number;
248
+ }) => {
243
249
  if (!rect) {
244
250
  return null;
245
251
  }
@@ -283,6 +289,7 @@ const PlayerLiveImageComponent = (props: Props) => {
283
289
  const videoStyles = { ...style, position: "absolute", zIndex: -100 };
284
290
  const Player: any = liveImageItem.component || BufferAnimation;
285
291
 
292
+ // TODO: nice to have - resolve imageKey when imageUrl is not provided
286
293
  return (
287
294
  <TrackedView
288
295
  testId={`tracked-view-${playerId}-${item.title}`}
@@ -307,11 +314,7 @@ const PlayerLiveImageComponent = (props: Props) => {
307
314
  animationConfig={overlayFadeIn}
308
315
  staticStyles={style}
309
316
  >
310
- <PlayerImageBackground
311
- entry={item}
312
- style={style}
313
- imageKey={imageKey}
314
- />
317
+ <Image {...props} resizeMode="cover" style={style} applyMaxSize />
315
318
  </AnimatedInOut>
316
319
  }
317
320
  </TrackedView>
@@ -3,7 +3,14 @@ import * as React from "react";
3
3
  import { render } from "@testing-library/react-native";
4
4
  import * as PlayerFactory from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
5
5
  import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
6
+ import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
7
+ import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
8
+
6
9
  import { PlayerLiveImage } from "../PlayerLiveImageComponent";
10
+ import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
11
+
12
+ import { Provider } from "react-redux";
13
+ import configureStore from "redux-mock-store";
7
14
 
8
15
  const seekTo = jest.fn();
9
16
 
@@ -16,6 +23,27 @@ jest.mock(
16
23
  })
17
24
  );
18
25
 
26
+ jest
27
+ .spyOn(useNavigationHooks, "useNavigation")
28
+ .mockImplementation(() => ({ videoModalState: { visible: false } }));
29
+
30
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
31
+
32
+ const mockStore = configureStore();
33
+
34
+ const store = mockStore({ appData: {} });
35
+
36
+ const Wrapper = ({ children }: { children: React.ReactChildren }) => (
37
+ /* @ts-ignore */
38
+ <Provider store={store}>
39
+ <ThemeContext.Provider
40
+ value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
41
+ >
42
+ {children}
43
+ </ThemeContext.Provider>
44
+ </Provider>
45
+ );
46
+
19
47
  describe("PlayerLiveImageComponent", () => {
20
48
  const defaultProps = {
21
49
  item: { id: "1", title: "Test", type: { value: "" } },
@@ -36,10 +64,16 @@ describe("PlayerLiveImageComponent", () => {
36
64
  controller: new Player({}),
37
65
  Component: () => null,
38
66
  }));
67
+
68
+ jest.spyOn(navigationHooks, "useIsScreenActive").mockReturnValue(true);
39
69
  });
40
70
 
41
71
  it("should render correctly with default props", () => {
42
- const component = render(<PlayerLiveImage {...defaultProps} />);
72
+ const component = render(
73
+ <Wrapper>
74
+ <PlayerLiveImage {...defaultProps} />
75
+ </Wrapper>
76
+ );
43
77
 
44
78
  expect(component.toJSON()).toMatchSnapshot();
45
79
  });
@@ -53,7 +87,11 @@ describe("PlayerLiveImageComponent", () => {
53
87
  },
54
88
  };
55
89
 
56
- render(<PlayerLiveImage {...props} />);
90
+ render(
91
+ <Wrapper>
92
+ <PlayerLiveImage {...props} />
93
+ </Wrapper>
94
+ );
57
95
 
58
96
  // TODO: implement this test
59
97
  });
@@ -67,7 +105,11 @@ describe("PlayerLiveImageComponent", () => {
67
105
  },
68
106
  };
69
107
 
70
- render(<PlayerLiveImage {...props} />);
108
+ render(
109
+ <Wrapper>
110
+ <PlayerLiveImage {...props} />
111
+ </Wrapper>
112
+ );
71
113
 
72
114
  // TODO: implement this test
73
115
  });
@@ -13,35 +13,25 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
13
13
  }
14
14
  }
15
15
  >
16
- <View
17
- accessibilityIgnoresInvertColors={true}
18
- style={Object {}}
19
- >
20
- <Image
21
- resizeMode="cover"
22
- source={
23
- Object {
24
- "uri": undefined,
25
- }
26
- }
27
- style={
28
- Array [
29
- Object {
30
- "bottom": 0,
31
- "left": 0,
32
- "position": "absolute",
33
- "right": 0,
34
- "top": 0,
35
- },
36
- Object {
37
- "height": undefined,
38
- "width": undefined,
39
- },
40
- undefined,
41
- ]
16
+ <Image
17
+ applyMaxSize={true}
18
+ audioMutedByDefault={false}
19
+ imageKey="image1"
20
+ item={
21
+ Object {
22
+ "id": "1",
23
+ "title": "Test",
24
+ "type": Object {
25
+ "value": "",
26
+ },
42
27
  }
43
- />
44
- </View>
28
+ }
29
+ onError={[Function]}
30
+ playerId="player1"
31
+ resizeMode="cover"
32
+ screenConfig={Object {}}
33
+ style={Object {}}
34
+ />
45
35
  </View>
46
36
  </TrackedView>
47
37
  `;
@@ -0,0 +1,78 @@
1
+ import React from "react";
2
+ import { Animated, ViewStyle } from "react-native";
3
+
4
+ import {
5
+ useModalAnimationContext,
6
+ PlayerAnimationStateEnum,
7
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
+ import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks";
9
+
10
+ type Props = {
11
+ style: ViewStyle[];
12
+ children: React.ReactNode;
13
+ };
14
+
15
+ export const AnimatedPlayerModalWrapper = (props: Props) => {
16
+ const {
17
+ playerAnimationState,
18
+ animatedValues: { lastScrollY, dragScrollY, translateYOffset },
19
+ modalSnapPoints,
20
+ setStartComponentsAnimation,
21
+ lastScrollYValue,
22
+ } = useModalAnimationContext();
23
+
24
+ const { height: screenHeight } = useDimensions("screen", {
25
+ deviceInfo: true,
26
+ });
27
+
28
+ const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
29
+ () => ({
30
+ inputRange: modalSnapPoints,
31
+ outputRange: modalSnapPoints,
32
+ extrapolate: "clamp",
33
+ }),
34
+ [modalSnapPoints]
35
+ );
36
+
37
+ let translateY;
38
+
39
+ if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
40
+ translateY = translateYOffset.interpolate(interpolateConfig);
41
+ } else {
42
+ const reverseLastScrollY = Animated.multiply(
43
+ new Animated.Value(-1),
44
+ lastScrollY
45
+ );
46
+
47
+ translateY = Animated.add(
48
+ translateYOffset,
49
+ Animated.add(dragScrollY, reverseLastScrollY)
50
+ ).interpolate(interpolateConfig);
51
+ }
52
+
53
+ React.useEffect(() => {
54
+ const translateYListener = translateY.addListener(({ value }) => {
55
+ const preparedValue = Math.round(
56
+ Math.abs(value) - lastScrollYValue.current
57
+ );
58
+
59
+ (playerAnimationState === PlayerAnimationStateEnum.minimize ||
60
+ playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
61
+ setStartComponentsAnimation(
62
+ preparedValue >= Math.round((screenHeight * 10) / 100)
63
+ );
64
+ });
65
+
66
+ return () => {
67
+ translateYListener && translateY.removeListener(translateYListener);
68
+ };
69
+ }, [playerAnimationState]);
70
+
71
+ return (
72
+ <Animated.View
73
+ style={[props.style, { transform: [{ translateY: translateY }] }]}
74
+ >
75
+ {props.children}
76
+ </Animated.View>
77
+ );
78
+ };