@applicaster/zapp-react-native-ui-components 15.1.0-rc.8 → 16.0.0-alpha.1011304583

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 (178) hide show
  1. package/Components/BackgroundImage/BackgroundImage.android.tv.tsx +28 -0
  2. package/Components/BackgroundImage/BackgroundImage.ios.tv.tsx +24 -0
  3. package/Components/BackgroundImage/BackgroundImage.tsx +42 -0
  4. package/Components/BackgroundImage/index.ts +1 -0
  5. package/Components/BaseFocusable/index.ios.ts +12 -2
  6. package/Components/Cell/FocusableWrapper.tsx +3 -0
  7. package/Components/Cell/TvOSCellComponent.tsx +6 -3
  8. package/Components/CellRendererResolver/index.ts +2 -2
  9. package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
  10. package/Components/Focusable/Focusable.tsx +4 -2
  11. package/Components/Focusable/FocusableTvOS.tsx +18 -1
  12. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
  13. package/Components/FocusableGroup/FocusableTvOS.tsx +41 -8
  14. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +39 -0
  15. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
  16. package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
  17. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  18. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  19. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
  20. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  21. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
  22. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
  23. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
  24. package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
  25. package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
  26. package/Components/GeneralContentScreen/index.ts +2 -0
  27. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  28. package/Components/HandlePlayable/HandlePlayable.tsx +13 -8
  29. package/Components/Layout/FullWidthRow.tsx +38 -0
  30. package/Components/Layout/TV/NavBarContainer.tsx +1 -10
  31. package/Components/Layout/TV/ScreenContainer.tsx +2 -6
  32. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
  33. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
  34. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +0 -1
  35. package/Components/Layout/TV/index.tsx +5 -7
  36. package/Components/Layout/TV/index.web.tsx +5 -7
  37. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  38. package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
  39. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +16 -5
  40. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
  41. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +187 -0
  42. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/selectors.test.ts +45 -0
  43. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/style.test.ts +49 -0
  44. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
  45. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
  46. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
  47. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
  48. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +170 -0
  49. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/selectors.ts +26 -0
  50. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/style.ts +29 -0
  51. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/types.ts +37 -0
  52. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -10
  53. package/Components/MasterCell/DefaultComponents/Button.tsx +0 -15
  54. package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
  55. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.android.tv.tsx +58 -0
  56. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
  57. package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
  58. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
  59. package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
  60. package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
  61. package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
  62. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
  63. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +8 -2
  64. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
  65. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
  66. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
  67. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +1 -2
  68. package/Components/MasterCell/DefaultComponents/PressableView.tsx +34 -0
  69. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
  70. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +11 -0
  71. package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
  72. package/Components/MasterCell/DefaultComponents/index.ts +9 -3
  73. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +135 -0
  74. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +33 -0
  75. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +22 -0
  76. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +125 -0
  77. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +16 -0
  78. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
  79. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +37 -0
  80. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +393 -0
  81. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +141 -0
  82. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +343 -0
  83. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
  84. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +122 -0
  85. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +118 -0
  86. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +238 -0
  87. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
  88. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
  89. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
  90. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
  91. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +89 -0
  92. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
  93. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +47 -48
  94. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
  95. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +101 -144
  96. package/Components/MasterCell/MappingFunctions/index.js +3 -2
  97. package/Components/MasterCell/README.md +4 -0
  98. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
  99. package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
  100. package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
  101. package/Components/MasterCell/dataAdapter.ts +19 -6
  102. package/Components/MasterCell/elementMapper.tsx +52 -7
  103. package/Components/MasterCell/index.tsx +30 -5
  104. package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
  105. package/Components/MasterCell/utils/__tests__/resolveColor.test.js +169 -132
  106. package/Components/MasterCell/utils/__tests__/resolveColorForProp.test.js +92 -0
  107. package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
  108. package/Components/MasterCell/utils/index.ts +170 -61
  109. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
  110. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
  111. package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
  112. package/Components/PlayerContainer/PlayerContainer.tsx +22 -17
  113. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +284 -0
  114. package/Components/River/ComponentsMap/ComponentsMap.tsx +8 -21
  115. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  116. package/Components/River/RefreshControl.tsx +19 -88
  117. package/Components/River/River.tsx +9 -82
  118. package/Components/River/TV/River.tsx +31 -14
  119. package/Components/River/TV/index.tsx +8 -4
  120. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
  121. package/Components/River/TV/utils/index.ts +4 -0
  122. package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
  123. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -15
  124. package/Components/River/__tests__/componentsMap.test.js +38 -0
  125. package/Components/River/hooks/__tests__/usePullToRefresh.test.ts +132 -0
  126. package/Components/River/hooks/index.ts +1 -0
  127. package/Components/River/hooks/usePullToRefresh.ts +51 -0
  128. package/Components/Screen/TV/index.web.tsx +4 -2
  129. package/Components/Screen/__tests__/Screen.test.tsx +65 -42
  130. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
  131. package/Components/Screen/hooks.ts +2 -3
  132. package/Components/Screen/index.tsx +10 -7
  133. package/Components/Screen/orientationHandler.ts +3 -3
  134. package/Components/ScreenResolver/index.tsx +9 -5
  135. package/Components/ScreenRevealManager/Overlay.tsx +34 -0
  136. package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
  137. package/Components/ScreenRevealManager/__tests__/Overlay.test.tsx +88 -0
  138. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
  139. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +9 -20
  140. package/Components/Tabs/TabContent.tsx +7 -4
  141. package/Components/TopCutoffOverlay/__tests__/TopCutoffOverlay.test.tsx +201 -0
  142. package/Components/TopCutoffOverlay/hooks/__tests__/useMarginTop.test.ts +130 -0
  143. package/Components/TopCutoffOverlay/hooks/index.ts +1 -0
  144. package/Components/TopCutoffOverlay/hooks/useMarginTop.ts +59 -0
  145. package/Components/TopCutoffOverlay/index.tsx +55 -0
  146. package/Components/Transitioner/index.js +3 -3
  147. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
  148. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
  149. package/Components/VideoModal/utils.ts +18 -10
  150. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
  151. package/Components/Viewport/ViewportAware/index.tsx +16 -7
  152. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  153. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +9 -4
  154. package/Components/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
  155. package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
  156. package/Contexts/CachedDimensionsContext/index.ts +17 -2
  157. package/Contexts/ScreenContext/index.tsx +25 -18
  158. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  159. package/Decorators/Analytics/index.tsx +6 -5
  160. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
  161. package/Decorators/ConfigurationWrapper/const.ts +1 -0
  162. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
  163. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  164. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  165. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  166. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
  167. package/Helpers/ComponentCellSelectionHelper/index.js +0 -6
  168. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
  169. package/Helpers/DataSourceHelper/index.ts +19 -0
  170. package/Helpers/index.js +7 -40
  171. package/package.json +5 -5
  172. package/Components/Layout/TV/LayoutBackground.tsx +0 -28
  173. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
  174. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
  175. package/Components/River/TV/withTVEventHandler.tsx +0 -36
  176. package/Components/Screen/utils.ts +0 -16
  177. package/Helpers/Analytics/index.js +0 -95
  178. package/Helpers/DataSourceHelper/index.js +0 -19
@@ -0,0 +1,55 @@
1
+ import React from "react";
2
+ import { View, StyleSheet } from "react-native";
3
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
4
+ import { useScreenConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/River/useScreenConfiguration";
5
+
6
+ import { useMarginTop } from "./hooks";
7
+
8
+ interface IProps {
9
+ targetScreenId?: string;
10
+ children?: React.ReactNode;
11
+ applyTopCutoff?: boolean;
12
+ }
13
+
14
+ const styles = StyleSheet.create({
15
+ container: {
16
+ flex: 1,
17
+ },
18
+ });
19
+
20
+ export const TopCutoffOverlay: React.FC<IProps> = ({
21
+ targetScreenId,
22
+ children,
23
+ applyTopCutoff = true,
24
+ }: IProps) => {
25
+ const cutoffHeight = useMarginTop(targetScreenId);
26
+
27
+ const { backgroundColor: screenBackgroundColor } =
28
+ useScreenConfiguration(targetScreenId);
29
+
30
+ const theme = useTheme();
31
+ const themeBackgroundColor = theme?.app_background_color;
32
+
33
+ if (!applyTopCutoff) {
34
+ return children;
35
+ }
36
+
37
+ return (
38
+ <View style={styles.container}>
39
+ {children}
40
+
41
+ <View
42
+ style={{
43
+ position: "absolute",
44
+ top: 0,
45
+ left: 0,
46
+ right: 0,
47
+ height: cutoffHeight,
48
+
49
+ backgroundColor:
50
+ screenBackgroundColor || themeBackgroundColor || "transparent",
51
+ }}
52
+ />
53
+ </View>
54
+ );
55
+ };
@@ -1,7 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
3
3
  import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
4
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
+ import { useAppData } from "@applicaster/zapp-react-native-redux";
5
+
5
6
  import { TransitionerComponent } from "./Transitioner";
6
7
 
7
8
  export const Transitioner = (props) => {
@@ -16,8 +17,7 @@ export const Transitioner = (props) => {
16
17
  deviceInfo: true,
17
18
  });
18
19
 
19
- const { appData } = usePickFromState(["appData"]);
20
- const isTabletPortrait = appData?.isTabletPortrait;
20
+ const { isTabletPortrait } = useAppData();
21
21
 
22
22
  return (
23
23
  <TransitionerComponent
@@ -4,7 +4,10 @@ import { Animated, Dimensions } from "react-native";
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
5
5
 
6
6
  import { useConfiguration } from "../utils";
7
- import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
7
+ import {
8
+ useAppData,
9
+ usePlugins,
10
+ } from "@applicaster/zapp-react-native-redux/hooks";
8
11
  import { isBottomTabVisible } from "../../Screen/navigationHandler";
9
12
 
10
13
  import {
@@ -18,7 +21,6 @@ import {
18
21
  import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
19
22
  import { PROGRESS_BAR_HEIGHT } from "./utils";
20
23
  import { useIsTablet as getIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
21
- import { useAppSelector } from "@applicaster/zapp-react-native-redux";
22
24
 
23
25
  export type ModalAnimationContextT = {
24
26
  yTranslate: React.MutableRefObject<Animated.AnimatedInterpolation<number>>;
@@ -64,9 +66,7 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
64
66
  screenData,
65
67
  } = useNavigation();
66
68
 
67
- const isTabletPortrait = useAppSelector(
68
- (state) => state.appData.isTabletPortrait
69
- );
69
+ const { isTabletPortrait } = useAppData();
70
70
 
71
71
  const plugins = usePlugins();
72
72
 
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-hooks";
1
+ import { act, renderHook, waitFor } from "@testing-library/react-native";
2
2
  import { useDelayedPlayerDetails } from "../useDelayedPlayerDetails";
3
3
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
4
4
 
@@ -13,16 +13,20 @@ describe("useDelayedPlayerDetails", () => {
13
13
  jest.clearAllMocks();
14
14
  });
15
15
 
16
- it("should return false initially, that changes after 1 second", () => {
16
+ it("should return false initially, that changes after 1 second", async () => {
17
17
  const { result } = renderHook(() =>
18
18
  useDelayedPlayerDetails({ isInline: true, isDocked: false, isPip: false })
19
19
  );
20
20
 
21
21
  expect(result.current).toBe(false);
22
22
 
23
- jest.advanceTimersByTime(1000);
23
+ act(() => {
24
+ jest.advanceTimersByTime(1000);
25
+ });
24
26
 
25
- expect(result.current).toBe(true);
27
+ await waitFor(() => {
28
+ expect(result.current).toBe(true);
29
+ });
26
30
  });
27
31
 
28
32
  it("should return false when isPip is true", () => {
@@ -41,7 +45,7 @@ describe("useDelayedPlayerDetails", () => {
41
45
  expect(result.current).toBe(false);
42
46
  });
43
47
 
44
- it("should return true for tablet regardless of other flags", () => {
48
+ it("should return true for tablet regardless of other flags", async () => {
45
49
  (useIsTablet as jest.Mock).mockReturnValue(true);
46
50
 
47
51
  const { result } = renderHook(() =>
@@ -52,8 +56,12 @@ describe("useDelayedPlayerDetails", () => {
52
56
  })
53
57
  );
54
58
 
55
- jest.advanceTimersByTime(1000);
59
+ act(() => {
60
+ jest.advanceTimersByTime(1000);
61
+ });
56
62
 
57
- expect(result.current).toBe(true);
63
+ await waitFor(() => {
64
+ expect(result.current).toBe(true);
65
+ });
58
66
  });
59
67
  });
@@ -1,32 +1,40 @@
1
1
  import { mergeRight } from "ramda";
2
2
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
3
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
+ import {
4
+ useAppSelector,
5
+ useContentTypes,
6
+ } from "@applicaster/zapp-react-native-redux/hooks";
4
7
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
5
8
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
6
9
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
7
10
  import { create } from "zustand";
11
+ import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks";
12
+ import { selectPluginConfigurationsByPluginId } from "@applicaster/zapp-react-native-redux";
13
+ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
8
14
 
9
15
  export const useConfiguration = () => {
10
16
  const {
11
17
  videoModalState: { item },
12
18
  } = useNavigation();
13
19
 
14
- const { rivers, contentTypes, pluginConfigurations } = usePickFromState([
15
- "rivers",
16
- "contentTypes",
17
- "pluginConfigurations",
18
- ]);
20
+ const rivers = useRivers();
21
+ const contentTypes = useContentTypes();
22
+ const player = usePlayer();
19
23
 
20
24
  const targetScreenId = contentTypes?.[item?.type?.value]?.screen_id;
21
25
  const targetScreenConfiguration = rivers?.[targetScreenId];
22
26
 
23
- const pluginConfiguration =
24
- pluginConfigurations[targetScreenConfiguration?.type]?.configuration_json;
27
+ const { configuration_json } = useAppSelector((state) =>
28
+ selectPluginConfigurationsByPluginId(state, targetScreenConfiguration?.type)
29
+ );
25
30
 
26
- const playerPluginConfig = playerManager.getPluginConfiguration();
31
+ const playerPluginConfig =
32
+ player?.getPluginConfiguration() ??
33
+ playerManager.getInstanceController()?.getPluginConfiguration() ??
34
+ {};
27
35
 
28
36
  const config = mergeRight(playerPluginConfig, {
29
- ...pluginConfiguration,
37
+ ...configuration_json,
30
38
  ...targetScreenConfiguration?.general,
31
39
  ...targetScreenConfiguration?.styles,
32
40
  });
@@ -22,8 +22,6 @@ ReactNative.UIManager.measureLayout = jest.fn(
22
22
  }
23
23
  );
24
24
 
25
- ReactNative.findNodeHandle = () => 1234;
26
-
27
25
  const viewportEventsManager = new ViewportEvents(true);
28
26
 
29
27
  const TestComponent = (props) => {
@@ -32,7 +32,7 @@ function getTestDimensions(testDimensions) {
32
32
  return (process.env.NODE_ENV === "test" && testDimensions) || null;
33
33
  }
34
34
 
35
- function ViewportAwareComponent(props: Props, ref) {
35
+ function ViewportAwareComponent(props: Props, forwardedRef) {
36
36
  const viewportEvents = useViewportEventsContext();
37
37
 
38
38
  const {
@@ -47,13 +47,22 @@ function ViewportAwareComponent(props: Props, ref) {
47
47
  getTestDimensions(testDimensions) || initialDimensions
48
48
  );
49
49
 
50
+ const localRef = React.useRef(null);
51
+
50
52
  const [viewportChangeEvent, setViewportChangeEvent] = React.useState(null);
51
53
 
52
- function assignRef(_ref) {
53
- if (_ref && !ref) {
54
- ref = _ref;
55
- }
56
- }
54
+ const assignRef = React.useCallback(
55
+ (_ref) => {
56
+ localRef.current = _ref;
57
+
58
+ if (typeof forwardedRef === "function") {
59
+ forwardedRef(_ref);
60
+ } else if (forwardedRef) {
61
+ forwardedRef.current = _ref;
62
+ }
63
+ },
64
+ [forwardedRef]
65
+ );
57
66
 
58
67
  const checkInViewport = (viewportChangeEvent, layoutEvent) => {
59
68
  const inVerticalViewport = Utils.isInViewport(
@@ -94,7 +103,7 @@ function ViewportAwareComponent(props: Props, ref) {
94
103
  const onViewportChange = (viewportChangeEvent) => {
95
104
  setViewportChangeEvent(viewportChangeEvent);
96
105
 
97
- const nodeHandle = findNodeHandle(ref);
106
+ const nodeHandle = findNodeHandle(localRef.current);
98
107
 
99
108
  if (!nodeHandle) {
100
109
  return;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { renderHook } from "@testing-library/react-hooks";
2
+ import { renderHook } from "@testing-library/react-native";
3
3
  import {
4
4
  ViewportEvents,
5
5
  useViewportEventsContext,
@@ -1,11 +1,11 @@
1
1
  import React from "react";
2
- import { StyleSheet } from "react-native";
2
+ import { StyleSheet, SafeAreaView as RNSafeAreaView } from "react-native";
3
3
  import { SafeAreaView } from "react-native-safe-area-context";
4
-
5
4
  import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
6
5
  import CloseButton from "./Buttons/CloseButton";
7
6
  import BackButton from "./Buttons/BackButton";
8
7
  import BarTitle from "./BarTitle";
8
+ import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
9
9
 
10
10
  type Props = {
11
11
  screenStyles: {
@@ -24,6 +24,11 @@ const defaultState: NavBarState = {
24
24
  title: "",
25
25
  };
26
26
 
27
+ const SafeAreaViewPlatform = platformSelect({
28
+ ios: RNSafeAreaView,
29
+ android: SafeAreaView,
30
+ });
31
+
27
32
  const BarView = ({ screenStyles, barState = defaultState }: Props) => {
28
33
  const isRTL = useIsRTL();
29
34
 
@@ -45,7 +50,7 @@ const BarView = ({ screenStyles, barState = defaultState }: Props) => {
45
50
  );
46
51
 
47
52
  return (
48
- <SafeAreaView
53
+ <SafeAreaViewPlatform
49
54
  edges={["top", "left", "right"]}
50
55
  style={[style.view, isRTL ? style.rtlStyle : {}]}
51
56
  testID="BarView-safeAreaView"
@@ -53,7 +58,7 @@ const BarView = ({ screenStyles, barState = defaultState }: Props) => {
53
58
  {backButton}
54
59
  <BarTitle title={barState.title} screenStyles={screenStyles} />
55
60
  {closeButton}
56
- </SafeAreaView>
61
+ </SafeAreaViewPlatform>
57
62
  );
58
63
  };
59
64
 
@@ -1,7 +1,6 @@
1
1
  import { DefaultCell } from "./DefaultCell";
2
2
  import { GridCell } from "./GridCell";
3
3
  import { HeroCell } from "./HeroCell";
4
- // import { ScreenSelectorLabel } from "./ScreenSelectorLabel";
5
4
 
6
5
  /**
7
6
  * Return a view tree ready to be injected with styles etc. Mapping is done
@@ -15,8 +14,6 @@ export function viewTreeResolver({ component_type }) {
15
14
  switch (component_type) {
16
15
  case "hero":
17
16
  return HeroCell;
18
- // case "screen_picker":
19
- // return ScreenSelectorLabel;
20
17
  case "grid":
21
18
  return GridCell;
22
19
  case "horizontal_list":
@@ -0,0 +1,154 @@
1
+ import { renderHook, act } from "@testing-library/react-native";
2
+
3
+ type DimensionsStore = {
4
+ setState: (
5
+ partial: { dimensions: Record<string, unknown>; ids: string[] },
6
+ replace?: boolean
7
+ ) => void;
8
+ };
9
+
10
+ const createdStores: DimensionsStore[] = [];
11
+
12
+ jest.mock("zustand", () => {
13
+ const actual = jest.requireActual<typeof import("zustand")>("zustand");
14
+
15
+ return {
16
+ ...actual,
17
+ create: ((initializer: Parameters<typeof actual.create>[0]) => {
18
+ const store = actual.create(initializer);
19
+ createdStores.push(store);
20
+
21
+ return store;
22
+ }) as typeof actual.create,
23
+ };
24
+ });
25
+
26
+ import { useCachedDimensions } from "../index";
27
+
28
+ const resetStore = () => {
29
+ const store = createdStores[createdStores.length - 1];
30
+
31
+ act(() => {
32
+ store?.setState({ dimensions: {}, ids: [] });
33
+ });
34
+ };
35
+
36
+ describe("useCachedDimensions", () => {
37
+ beforeEach(() => {
38
+ resetStore();
39
+ });
40
+
41
+ describe("getCachedDimensions", () => {
42
+ it("returns default dimensions when id has no cached value", () => {
43
+ const { result } = renderHook(() => useCachedDimensions("component-1"));
44
+
45
+ expect(result.current.getCachedDimensions()).toEqual({
46
+ width: undefined,
47
+ height: undefined,
48
+ });
49
+ });
50
+
51
+ it("returns cached dimensions after setCachedDimensions", () => {
52
+ const { result } = renderHook(() => useCachedDimensions("component-1"));
53
+ const dimensions = { width: 100, height: 200 };
54
+
55
+ act(() => {
56
+ result.current.setCachedDimensions(dimensions);
57
+ });
58
+
59
+ expect(result.current.getCachedDimensions()).toEqual(dimensions);
60
+ });
61
+ });
62
+
63
+ describe("setCachedDimensions", () => {
64
+ it("updates dimensions for the hook id", () => {
65
+ const { result } = renderHook(() => useCachedDimensions("component-1"));
66
+
67
+ act(() => {
68
+ result.current.setCachedDimensions({ width: 50, height: 75 });
69
+ });
70
+
71
+ expect(result.current.getCachedDimensions()).toEqual({
72
+ width: 50,
73
+ height: 75,
74
+ });
75
+ });
76
+
77
+ it("shares cached dimensions between hook instances with the same id", () => {
78
+ const { result: first } = renderHook(() =>
79
+ useCachedDimensions("shared-id")
80
+ );
81
+
82
+ const { result: second } = renderHook(() =>
83
+ useCachedDimensions("shared-id")
84
+ );
85
+
86
+ act(() => {
87
+ first.current.setCachedDimensions({ width: 10, height: 20 });
88
+ });
89
+
90
+ expect(second.current.getCachedDimensions()).toEqual({
91
+ width: 10,
92
+ height: 20,
93
+ });
94
+ });
95
+ });
96
+
97
+ describe("getLastCachedDimensions", () => {
98
+ it("returns undefined when no dimensions have been cached", () => {
99
+ const { result } = renderHook(() => useCachedDimensions("component-1"));
100
+
101
+ expect(result.current.getLastCachedDimensions()).toBeUndefined();
102
+ });
103
+
104
+ it("returns the most recently cached dimensions across ids", () => {
105
+ const { result: first } = renderHook(() => useCachedDimensions("first"));
106
+
107
+ const { result: second } = renderHook(() =>
108
+ useCachedDimensions("second")
109
+ );
110
+
111
+ act(() => {
112
+ first.current.setCachedDimensions({ width: 100, height: 100 });
113
+ });
114
+
115
+ act(() => {
116
+ second.current.setCachedDimensions({ width: 200, height: 200 });
117
+ });
118
+
119
+ expect(first.current.getLastCachedDimensions()).toEqual({
120
+ width: 200,
121
+ height: 200,
122
+ });
123
+ });
124
+
125
+ it("returns the latest dimensions when the same id is updated multiple times", () => {
126
+ const { result } = renderHook(() => useCachedDimensions("component-1"));
127
+
128
+ act(() => {
129
+ result.current.setCachedDimensions({ width: 100, height: 100 });
130
+ });
131
+
132
+ act(() => {
133
+ result.current.setCachedDimensions({ width: 300, height: 400 });
134
+ });
135
+
136
+ expect(result.current.getLastCachedDimensions()).toEqual({
137
+ width: 300,
138
+ height: 400,
139
+ });
140
+ });
141
+ });
142
+
143
+ describe("return value", () => {
144
+ it("exposes getCachedDimensions, setCachedDimensions, and getLastCachedDimensions", () => {
145
+ const { result } = renderHook(() => useCachedDimensions("component-1"));
146
+
147
+ expect(result.current).toEqual({
148
+ getCachedDimensions: expect.any(Function),
149
+ setCachedDimensions: expect.any(Function),
150
+ getLastCachedDimensions: expect.any(Function),
151
+ });
152
+ });
153
+ });
154
+ });
@@ -1,6 +1,7 @@
1
1
  import { create, useStore } from "zustand";
2
2
  import { produce } from "immer";
3
3
  import { useCallback, useMemo } from "react";
4
+ import { last } from "@applicaster/zapp-react-native-utils/utils";
4
5
 
5
6
  type Dimensions = {
6
7
  width: Option<number>;
@@ -10,14 +11,17 @@ type Dimensions = {
10
11
  type DimensionsState = {
11
12
  dimensions: Record<string, Dimensions>;
12
13
  setCachedDimensions: (id: string, dimensions: Dimensions) => void;
14
+ ids: string[];
13
15
  };
14
16
 
15
17
  const dimensionsStore = create<DimensionsState>((set) => ({
16
18
  dimensions: {},
19
+ ids: [],
17
20
  setCachedDimensions: (id, dimensions) =>
18
21
  set(
19
22
  produce((draft) => {
20
23
  draft.dimensions[id] = dimensions;
24
+ draft.ids.push(id);
21
25
  })
22
26
  ),
23
27
  }));
@@ -28,7 +32,7 @@ const initialDimensions = () => ({
28
32
  });
29
33
 
30
34
  export const useCachedDimensions = (id: string) => {
31
- const { dimensions, setCachedDimensions } = useStore(
35
+ const { dimensions, setCachedDimensions, ids } = useStore(
32
36
  dimensionsStore
33
37
  ) as DimensionsState;
34
38
 
@@ -40,11 +44,22 @@ export const useCachedDimensions = (id: string) => {
40
44
  setCachedDimensions(id, newDimensions);
41
45
  }, []);
42
46
 
47
+ const getLastCachedDimensions = useCallback(() => {
48
+ const previousId = last(ids);
49
+
50
+ if (!previousId) {
51
+ return undefined;
52
+ }
53
+
54
+ return dimensions[previousId];
55
+ }, [dimensions, ids]);
56
+
43
57
  return useMemo(
44
58
  () => ({
45
59
  getCachedDimensions,
46
60
  setCachedDimensions: handleSetCachedDimensions,
61
+ getLastCachedDimensions,
47
62
  }),
48
- [getCachedDimensions, handleSetCachedDimensions]
63
+ [getCachedDimensions, handleSetCachedDimensions, getLastCachedDimensions]
49
64
  );
50
65
  };
@@ -16,6 +16,7 @@ import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-co
16
16
  import { create } from "zustand";
17
17
  import { subscribeWithSelector } from "zustand/middleware";
18
18
  import { useShallow } from "zustand/react/shallow";
19
+
19
20
  import { Animated } from "react-native";
20
21
 
21
22
  interface NavBarStoreState {
@@ -29,6 +30,8 @@ interface NavBarStoreState {
29
30
  scrollState: number;
30
31
  contentPosition: string;
31
32
  scrollYAnimated: Animated.Value;
33
+ hideOnScrollAnimated: Animated.Value;
34
+ hideOnScroll: boolean;
32
35
  }
33
36
 
34
37
  interface NavBarState {
@@ -62,24 +65,28 @@ const createStateStore = () =>
62
65
  );
63
66
 
64
67
  const createStore = () =>
65
- create<NavBarStoreState>((set) => ({
66
- title: "",
67
- summary: "",
68
- visible: true,
69
- height: 0,
70
- scrollState: 0,
71
- contentPosition: "",
72
- scrollYAnimated: new Animated.Value(0),
73
- setTitle(title) {
74
- set({ title });
75
- },
76
- setSummary(summary) {
77
- set({ summary });
78
- },
79
- setVisible(visible) {
80
- set({ visible });
81
- },
82
- }));
68
+ create(
69
+ subscribeWithSelector<NavBarStoreState>((set) => ({
70
+ title: "",
71
+ summary: "",
72
+ visible: true,
73
+ height: 0,
74
+ scrollState: 0,
75
+ contentPosition: "",
76
+ scrollYAnimated: new Animated.Value(0),
77
+ hideOnScrollAnimated: new Animated.Value(0),
78
+ hideOnScroll: false,
79
+ setTitle(title) {
80
+ set({ title });
81
+ },
82
+ setSummary(summary) {
83
+ set({ summary });
84
+ },
85
+ setVisible(visible) {
86
+ set({ visible });
87
+ },
88
+ }))
89
+ );
83
90
 
84
91
  const createScreenComponentsStore = () =>
85
92
  create(subscribeWithSelector<Record<string, unknown>>((_) => ({})));
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-hooks";
1
+ import { renderHook } from "@testing-library/react-native";
2
2
  import {
3
3
  useScreenTrackedViewPositionsContext,
4
4
  ScreenTrackedViewPositionsContext,
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
2
 
3
3
  import { getAnalyticsFunctions } from "@applicaster/zapp-react-native-utils/analyticsUtils";
4
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
4
 
6
5
  type ComponentProps = {
7
6
  component: {
@@ -21,11 +20,13 @@ type ComponentProps = {
21
20
 
22
21
  function withAnalytics(Component) {
23
22
  return function WithAnalytics(props: ComponentProps) {
24
- const { appData } = usePickFromState(["appData"]);
25
-
26
23
  const analyticsFunctions = React.useMemo(
27
- () => getAnalyticsFunctions({ props, appData }),
28
- [props, appData]
24
+ () =>
25
+ getAnalyticsFunctions({
26
+ component: props.component,
27
+ zappPipesData: props.zappPipesData,
28
+ } as any),
29
+ [props.component, props.zappPipesData]
29
30
  );
30
31
 
31
32
  return (
@@ -88,6 +88,7 @@ exports[`withConfigurationProvider correctly passes all the configuration keys c
88
88
  tab_cell_padding_right={10}
89
89
  tab_cell_padding_top={14}
90
90
  tablet_theme={false}
91
+ tabs_screen_background_color="transparent"
91
92
  target={false}
92
93
  target_screen_switch={false}
93
94
  text_label_active_font_color="rgba(239, 239, 239, 0.5)"
@@ -208,4 +208,5 @@ export const keysMap: Record<string, Function> = {
208
208
  tab_bar_item_margin_right: castOrDefaultValue(Number, 0),
209
209
  tab_bar_item_margin_bottom: castOrDefaultValue(Number, 0),
210
210
  tab_bar_item_margin_left: castOrDefaultValue(Number, 0),
211
+ tabs_screen_background_color: castOrDefaultValue(R.identity, "transparent"),
211
212
  };