@applicaster/zapp-react-native-utils 14.0.0-alpha.2847632144 → 14.0.0-alpha.3038031102

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 (63) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +1 -1
  2. package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
  3. package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
  4. package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
  5. package/analyticsUtils/events.ts +8 -0
  6. package/appUtils/accessibilityManager/index.ts +5 -2
  7. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
  8. package/appUtils/playerManager/useChapterMarker.tsx +0 -1
  9. package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
  10. package/arrayUtils/__tests__/isEmptyArray.test.ts +63 -0
  11. package/arrayUtils/__tests__/isFilledArray.test.ts +1 -1
  12. package/arrayUtils/index.ts +7 -2
  13. package/audioPlayerUtils/__tests__/getArtworkImage.test.ts +144 -0
  14. package/audioPlayerUtils/__tests__/getBackgroundImage.test.ts +72 -0
  15. package/audioPlayerUtils/__tests__/getImageFromEntry.test.ts +110 -0
  16. package/audioPlayerUtils/assets/index.ts +2 -0
  17. package/audioPlayerUtils/index.ts +242 -0
  18. package/conf/player/__tests__/selectors.test.ts +34 -0
  19. package/conf/player/selectors.ts +10 -0
  20. package/configurationUtils/__tests__/configurationUtils.test.js +0 -31
  21. package/configurationUtils/__tests__/getMediaItems.test.ts +65 -0
  22. package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +34 -0
  23. package/configurationUtils/index.ts +63 -34
  24. package/focusManager/FocusManager.ts +26 -16
  25. package/focusManager/Tree.ts +25 -21
  26. package/focusManager/__tests__/FocusManager.test.ts +50 -8
  27. package/manifestUtils/_internals/getDefaultConfiguration.js +28 -0
  28. package/manifestUtils/{_internals.js → _internals/index.js} +2 -25
  29. package/manifestUtils/createConfig.js +4 -1
  30. package/manifestUtils/defaultManifestConfigurations/player.js +1239 -200
  31. package/manifestUtils/progressBar/__tests__/mobileProgressBar.test.js +0 -30
  32. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +1 -2
  33. package/navigationUtils/__tests__/mapContentTypesToRivers.test.ts +130 -0
  34. package/navigationUtils/index.ts +6 -4
  35. package/package.json +2 -2
  36. package/playerUtils/__tests__/configurationUtils.test.ts +1 -65
  37. package/playerUtils/__tests__/getPlayerActionButtons.test.ts +54 -0
  38. package/playerUtils/_internals/__tests__/utils.test.ts +71 -0
  39. package/playerUtils/_internals/index.ts +1 -0
  40. package/playerUtils/_internals/utils.ts +31 -0
  41. package/playerUtils/configurationUtils.ts +0 -44
  42. package/playerUtils/getPlayerActionButtons.ts +17 -0
  43. package/playerUtils/index.ts +2 -0
  44. package/playerUtils/useValidatePlayerConfig.tsx +22 -19
  45. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +3 -1
  46. package/reactHooks/feed/useBatchLoading.ts +11 -9
  47. package/reactHooks/feed/useFeedLoader.tsx +12 -8
  48. package/reactHooks/feed/usePipesCacheReset.ts +3 -3
  49. package/reactHooks/layout/__tests__/index.test.tsx +3 -1
  50. package/reactHooks/layout/isTablet/index.ts +5 -2
  51. package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +34 -36
  52. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -3
  53. package/reactHooks/layout/useLayoutVersion.ts +5 -5
  54. package/reactHooks/navigation/useIsScreenActive.ts +9 -5
  55. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +4 -0
  56. package/reactHooks/screen/useScreenContext.ts +1 -1
  57. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
  58. package/reactHooks/state/useRivers.ts +7 -8
  59. package/riverComponetsMeasurementProvider/index.tsx +1 -1
  60. package/services/js2native.ts +1 -0
  61. package/time/BackgroundTimer.ts +5 -3
  62. package/utils/index.ts +17 -1
  63. package/playerUtils/configurationGenerator.ts +0 -2572
@@ -1,8 +1,10 @@
1
1
  import React, { useEffect } from "react";
2
- import { useDispatch } from "react-redux";
3
2
 
4
- import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
5
- import { useZappPipesFeed } from "@applicaster/zapp-react-native-redux/hooks";
3
+ import {
4
+ ZappPipes,
5
+ useAppDispatch,
6
+ useZappPipesFeed,
7
+ } from "@applicaster/zapp-react-native-redux";
6
8
 
7
9
  import { reactHooksLogger } from "../logger";
8
10
  import { shouldDispatchData, useIsInitialRender } from "../utils";
@@ -49,7 +51,7 @@ export const useFeedLoader = ({
49
51
  }, []);
50
52
 
51
53
  const isInitialRender = useIsInitialRender();
52
- const dispatch = useDispatch();
54
+ const dispatch = useAppDispatch();
53
55
  const { screenData } = useRoute();
54
56
 
55
57
  const callableFeedUrl = useInflatedUrl({ feedUrl, mapping });
@@ -64,7 +66,7 @@ export const useFeedLoader = ({
64
66
  (silentRefresh = true, callback) => {
65
67
  if (callableFeedUrl) {
66
68
  dispatch(
67
- loadPipesData(callableFeedUrl, {
69
+ ZappPipes.loadPipesData(callableFeedUrl, {
68
70
  clearCache: true,
69
71
  silentRefresh,
70
72
  callback,
@@ -82,7 +84,7 @@ export const useFeedLoader = ({
82
84
 
83
85
  if (nextFeed) {
84
86
  dispatch(
85
- loadPipesData(nextFeed, {
87
+ ZappPipes.loadPipesData(nextFeed, {
86
88
  silentRefresh: true,
87
89
  parentFeed: callableFeedUrl,
88
90
  riverId,
@@ -98,7 +100,7 @@ export const useFeedLoader = ({
98
100
  ) {
99
101
  if (callableFeedUrl && !pipesOptions.skipLoading) {
100
102
  dispatch(
101
- loadPipesData(callableFeedUrl, {
103
+ ZappPipes.loadPipesData(callableFeedUrl, {
102
104
  ...pipesOptions,
103
105
  clearCache: true,
104
106
  riverId,
@@ -131,7 +133,9 @@ export const useFeedLoader = ({
131
133
  // Reload feed when feedUrl changes, unless skipLoading is true
132
134
  useEffect(() => {
133
135
  if (!isInitialRender && callableFeedUrl && !pipesOptions.skipLoading) {
134
- dispatch(loadPipesData(callableFeedUrl, { ...pipesOptions, riverId }));
136
+ dispatch(
137
+ ZappPipes.loadPipesData(callableFeedUrl, { ...pipesOptions, riverId })
138
+ );
135
139
  }
136
140
  }, [callableFeedUrl]);
137
141
 
@@ -1,11 +1,11 @@
1
1
  import React from "react";
2
- import { useDispatch } from "react-redux";
3
2
 
4
3
  import { getDatasourceUrl } from "@applicaster/zapp-react-native-ui-components/Decorators/RiverFeedLoader/utils/getDatasourceUrl";
5
4
  import { usePipesContexts } from "@applicaster/zapp-react-native-ui-components/Decorators/RiverFeedLoader/utils/usePipesContexts";
6
5
  import { clearPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
7
6
 
8
- import { useRoute } from "../navigation/useRoute";
7
+ import { useRoute } from "../navigation";
8
+ import { useAppDispatch } from "@applicaster/zapp-react-native-redux";
9
9
 
10
10
  /**
11
11
  * reset river components cache when screen is unmounted
@@ -13,7 +13,7 @@ import { useRoute } from "../navigation/useRoute";
13
13
  * @param {Array} riverComponents list of UI components
14
14
  */
15
15
  export const usePipesCacheReset = (riverId, riverComponents) => {
16
- const dispatch = useDispatch();
16
+ const dispatch = useAppDispatch();
17
17
  const { screenData, pathname } = useRoute();
18
18
  const pipesContexts = usePipesContexts(riverId, pathname);
19
19
 
@@ -42,15 +42,17 @@ jest.mock("react-native-safe-area-context", () => ({
42
42
  }));
43
43
 
44
44
  jest.mock("../../../reactUtils", () => ({
45
+ ...jest.requireActual("../../../reactUtils"),
45
46
  platformSelect: jest.fn((specs) => specs[platform] || specs.default),
46
47
  isTV: jest.fn(() => mock_tv_flag),
47
48
  }));
48
49
 
49
50
  jest.mock("../../navigation", () => ({
50
- useNavigation: () => null,
51
51
  useIsScreenActive: () => true,
52
52
  }));
53
53
 
54
+ jest.mock("../../navigation/useNavigation");
55
+
54
56
  const { Dimensions } = require("react-native");
55
57
  const { useDimensions } = require("..");
56
58
 
@@ -6,7 +6,10 @@ import { NativeModules, Platform } from "react-native";
6
6
  * @param {String} orientation - Orientation enum passed to the function
7
7
  * @returns {Boolean} isTablet - returns whether the given device is a tablet
8
8
  */
9
- export const isTablet = (dimensions, orientation) => {
9
+ export const isTablet = (
10
+ dimensions?: { width: number; height: number },
11
+ orientation?: string
12
+ ) => {
10
13
  if (Platform?.OS === "ios") {
11
14
  return Platform?.isPad;
12
15
  } else if (Platform?.OS === "android") {
@@ -15,7 +18,7 @@ export const isTablet = (dimensions, orientation) => {
15
18
  return initialProps?.is_tablet;
16
19
  }
17
20
 
18
- const { width } = dimensions;
21
+ const { width } = dimensions || {};
19
22
 
20
23
  if (width < 600) return false;
21
24
  if (width >= 600 && width < 840) return orientation === "portrait";
@@ -1,46 +1,48 @@
1
1
  import { renderHook } from "@testing-library/react-hooks";
2
2
  import { Dimensions, StatusBar } from "react-native";
3
+ import { useDimensions } from "../useDimensions";
4
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux";
3
5
 
4
- const mockUsePickFromState = jest.fn();
5
- const mockUseIsScreenActive = jest.fn();
6
- const mockGetInitialDimensions = jest.fn();
7
- const mockGetDeviceInfo = jest.fn();
6
+ import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive";
8
7
 
9
- jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
10
- ...(jest.requireActual("@applicaster/zapp-react-native-redux/hooks") as {}),
11
- usePickFromState: mockUsePickFromState,
12
- }));
13
-
14
- jest.mock("../../../navigation", () => ({
15
- useIsScreenActive: mockUseIsScreenActive,
16
- }));
8
+ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => {
9
+ return {
10
+ ...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
11
+ usePickFromState: jest.fn(),
12
+ };
13
+ });
17
14
 
18
- jest.mock("../helpers", () => ({
19
- getInitialDimensions: mockGetInitialDimensions,
15
+ jest.mock(
16
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
17
+ () => ({
18
+ useIsScreenActive: jest.fn().mockReturnValue(true),
19
+ })
20
+ );
21
+
22
+ jest.doMock("../helpers", () => ({
23
+ getInitialDimensions: jest
24
+ .fn()
25
+ .mockReturnValue({ width: 100, height: 200, scale: 1, fontScale: 1 }),
20
26
  }));
21
27
 
22
28
  jest.mock("../../getDeviceInfo", () => ({
23
- getDeviceInfo: mockGetDeviceInfo,
29
+ getDeviceInfo: jest.fn().mockReturnValue({ deviceInfo: "testDeviceInfo" }),
24
30
  }));
25
31
 
26
- const { useDimensions } = require("../useDimensions");
32
+ const mockDimensions = { width: 100, height: 200, scale: 1, fontScale: 1 };
33
+
34
+ Dimensions.get = jest.fn().mockReturnValue(mockDimensions);
35
+
36
+ Dimensions.addEventListener = jest.fn().mockReturnValue({
37
+ remove: jest.fn(),
38
+ });
27
39
 
28
40
  describe("useDimensions", () => {
29
- const mockDimensions = { width: 100, height: 200, scale: 1, fontScale: 1 };
30
41
  const mockAppData = { someData: "test" };
31
42
 
32
43
  beforeEach(() => {
33
- jest.clearAllMocks();
34
- Dimensions.get = jest.fn().mockReturnValue(mockDimensions);
35
-
36
- Dimensions.addEventListener = jest.fn().mockReturnValue({
37
- remove: jest.fn(),
38
- });
39
-
40
- mockUsePickFromState.mockReturnValue({ appData: mockAppData });
41
- mockUseIsScreenActive.mockReturnValue(true);
42
- mockGetInitialDimensions.mockReturnValue(mockDimensions);
43
- mockGetDeviceInfo.mockReturnValue({ deviceInfo: "testDeviceInfo" });
44
+ StatusBar.currentHeight = 20;
45
+ (usePickFromState as jest.Mock).mockReturnValue({ appData: mockAppData });
44
46
  });
45
47
 
46
48
  it("returns correct initial dimensions", () => {
@@ -48,12 +50,9 @@ describe("useDimensions", () => {
48
50
  useDimensions("window", { fullDimensions: false })
49
51
  );
50
52
 
51
- expect(result.current).toEqual({
52
- ...mockDimensions,
53
+ expect(result.current).toMatchObject({
53
54
  statusBarHeight: StatusBar.currentHeight,
54
55
  });
55
-
56
- expect(mockGetInitialDimensions).toHaveBeenCalledWith("window");
57
56
  });
58
57
 
59
58
  it("calls handler on mount", () => {
@@ -70,7 +69,7 @@ describe("useDimensions", () => {
70
69
  useDimensions("window", { fullDimensions: false })
71
70
  );
72
71
 
73
- mockUseIsScreenActive.mockReturnValue(false);
72
+ (useIsScreenActive as jest.Mock).mockReturnValue(false);
74
73
  rerender();
75
74
 
76
75
  expect(Dimensions.addEventListener).toHaveBeenCalledWith(
@@ -84,8 +83,7 @@ describe("useDimensions", () => {
84
83
  useDimensions("window", { fullDimensions: true })
85
84
  );
86
85
 
87
- expect(result.current).toEqual({
88
- ...mockDimensions,
86
+ expect(result.current).toMatchObject({
89
87
  scale: 1,
90
88
  fontScale: 1,
91
89
  statusBarHeight: StatusBar.currentHeight,
@@ -98,7 +96,7 @@ describe("useDimensions", () => {
98
96
  );
99
97
 
100
98
  expect(result.current.height).toBe(
101
- mockDimensions.height - StatusBar.currentHeight ?? 0
99
+ mockDimensions.height - (StatusBar?.currentHeight ?? 0)
102
100
  );
103
101
  });
104
102
 
@@ -10,7 +10,7 @@ import { isTV } from "../../../reactUtils";
10
10
  import { Options, UseDimensions } from "../types";
11
11
  import { getDeviceInfo } from "../getDeviceInfo";
12
12
  import { getInitialDimensions } from "./helpers";
13
- import { useIsScreenActive } from "../../navigation";
13
+ import { useIsScreenActive } from "../../navigation/useIsScreenActive";
14
14
 
15
15
  function compensateForScaleIfNeeded(context) {
16
16
  return function () {
@@ -24,8 +24,6 @@ const applyScaleToDimensions = R.unless(R.propEq("scale", 1), (dimensions) => ({
24
24
  scale: 1,
25
25
  }));
26
26
 
27
- const statusBarHeight = StatusBar?.currentHeight;
28
-
29
27
  /**
30
28
  * Returns React-native Dimensions object and updates it on any dimension change
31
29
  * @param {('screen'|'window')} [context=window] - Dimensions context passed to Dimensions.get method
@@ -37,6 +35,7 @@ export const useDimensions: UseDimensions = (
37
35
  context = "window",
38
36
  fullDimensions = { fullDimensions: false, updateForInactiveScreens: true }
39
37
  ) => {
38
+ const statusBarHeight = StatusBar?.currentHeight;
40
39
  const isActive = useIsScreenActive();
41
40
  const { appData } = usePickFromState(["appData"]);
42
41
 
@@ -1,6 +1,8 @@
1
1
  /* eslint-disable no-redeclare */
2
- import { useSelector } from "react-redux";
3
- import * as R from "ramda";
2
+ import {
3
+ useAppSelector,
4
+ selectLayoutVersion,
5
+ } from "@applicaster/zapp-react-native-redux";
4
6
 
5
7
  export function useLayoutVersion(): ZappLayoutVersions;
6
8
 
@@ -23,9 +25,7 @@ export function useLayoutVersion({
23
25
  isV2?: boolean;
24
26
  isV1?: boolean;
25
27
  } = {}): boolean | ZappLayoutVersions {
26
- const layoutVersion = useSelector<any, ZappLayoutVersions>(
27
- R.path(["appData", "layoutVersion"])
28
- );
28
+ const layoutVersion = useAppSelector(selectLayoutVersion);
29
29
 
30
30
  if (isV2) {
31
31
  return layoutVersion === "v2";
@@ -1,3 +1,4 @@
1
+ import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
1
2
  import { useNavigation } from "./useNavigation";
2
3
  import { usePathname } from "./usePathname";
3
4
 
@@ -6,11 +7,14 @@ export const useIsScreenActive = () => {
6
7
  const pathname = usePathname();
7
8
  const { currentRoute, videoModalState } = useNavigation();
8
9
 
9
- if (
10
- videoModalState.visible &&
11
- ["FULLSCREEN", "MAXIMIZED", "PIP"].includes(videoModalState.mode)
12
- ) {
13
- return false;
10
+ if (videoModalState.visible) {
11
+ if (pathname.includes(ROUTE_TYPES.VIDEO_MODAL)) {
12
+ return true;
13
+ }
14
+
15
+ if (["FULLSCREEN", "MAXIMIZED", "PIP"].includes(videoModalState.mode)) {
16
+ return false;
17
+ }
14
18
  }
15
19
 
16
20
  return pathname === currentRoute;
@@ -14,6 +14,10 @@ jest.mock("@applicaster/zapp-react-native-utils/localizationUtils", () => ({
14
14
 
15
15
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
16
16
 
17
+ jest.mock(
18
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation"
19
+ );
20
+
17
21
  const { useCellResolver } = require("../useCellResolver");
18
22
 
19
23
  describe("cellResolver", () => {
@@ -2,7 +2,7 @@ import { useContext, useMemo } from "react";
2
2
 
3
3
  import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
4
4
  import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
5
- import { useNavigation } from "../navigation/useNavigation";
5
+ import { useNavigation } from "../navigation";
6
6
 
7
7
  import { ScreenContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenContext";
8
8
  import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
@@ -1,7 +1,8 @@
1
+ /* eslint-disable no-console */
1
2
  import React from "react";
2
3
  import { render, screen } from "@testing-library/react-native";
3
4
  import { Text } from "react-native";
4
- import { ZStoreProvider, useZStore } from "../ZStoreProvider";
5
+ import { useZStore, ZStoreProvider } from "../ZStoreProvider";
5
6
  import { useStore } from "zustand";
6
7
 
7
8
  interface TestState {
@@ -1,9 +1,8 @@
1
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
1
+ import {
2
+ useAppSelector,
3
+ selectRivers,
4
+ } from "@applicaster/zapp-react-native-redux";
2
5
 
3
- const riversSelector = ["rivers"];
4
-
5
- export const useRivers = () => {
6
- const { rivers } = usePickFromState(riversSelector as any);
7
-
8
- return rivers;
9
- };
6
+ export function useRivers(): Record<string, ZappRiver> {
7
+ return useAppSelector(selectRivers);
8
+ }
@@ -3,7 +3,7 @@ import { NativeModules, StyleSheet, View } from "react-native";
3
3
  import { getXray } from "@applicaster/zapp-react-native-utils/logger";
4
4
 
5
5
  import { isApplePlatform, isWeb } from "../reactUtils";
6
- import { useRivers } from "../reactHooks/state";
6
+ import { useRivers } from "../reactHooks";
7
7
 
8
8
  const layoutReducer = (state, { payload }) => {
9
9
  return state.map((item, index, _state) => ({
@@ -496,6 +496,7 @@ async function removeStorageListenerHandler(payload: { listenerId?: string }) {
496
496
  function log({ level, messages }) {
497
497
  try {
498
498
  const parsedMessages = parseJsonIfNeeded(messages);
499
+ // eslint-disable-next-line no-console
499
500
  const logFn = console[level] || console.log;
500
501
 
501
502
  if (Array.isArray(parsedMessages)) {
@@ -13,13 +13,15 @@ class BackgroundTimer {
13
13
 
14
14
  const EventEmitter = platformSelect({
15
15
  android: DeviceEventEmitter,
16
- ios: undefined,
16
+ android_tv: DeviceEventEmitter,
17
+ amazon: DeviceEventEmitter, // probably does not exist and uses android_tv
17
18
  default: undefined,
18
19
  });
19
20
 
20
21
  EventEmitter?.addListener("BackgroundTimer.timer.fired", (id: number) => {
21
- if (this.callbacks[id]) {
22
- const callback = this.callbacks[id];
22
+ const callback = this.callbacks[id];
23
+
24
+ if (callback) {
23
25
  delete this.callbacks[id];
24
26
  callback();
25
27
  }
package/utils/index.ts CHANGED
@@ -2,4 +2,20 @@ export { chunk } from "./chunk";
2
2
 
3
3
  export { times } from "./times";
4
4
 
5
- export { cloneDeep as clone, flatten, drop, size, isNil } from "lodash";
5
+ export {
6
+ cloneDeep as clone,
7
+ flatten,
8
+ drop,
9
+ size,
10
+ isNil,
11
+ isEmpty,
12
+ get,
13
+ has,
14
+ flatMap,
15
+ difference,
16
+ take,
17
+ pick,
18
+ map,
19
+ trim,
20
+ toString,
21
+ } from "lodash";