@applicaster/zapp-react-native-utils 13.0.0-alpha.3637360334 → 13.0.0-alpha.3732093334

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 (51) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +34 -1
  2. package/actionsExecutor/consts.ts +4 -0
  3. package/appUtils/HooksManager/Hook.ts +4 -0
  4. package/appUtils/HooksManager/index.ts +2 -0
  5. package/appUtils/__tests__/__snapshots__/localizationsHelper.test.ts.snap +151 -0
  6. package/appUtils/__tests__/allZappLocales.ts +79 -0
  7. package/appUtils/__tests__/{localizationsHelper.test.js → localizationsHelper.test.ts} +11 -0
  8. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -0
  9. package/appUtils/focusManager/index.ios.ts +14 -4
  10. package/appUtils/focusManager/index.ts +13 -0
  11. package/appUtils/focusManager/utils/__tests__/findChild.test.ts +35 -0
  12. package/appUtils/focusManager/utils/index.ts +5 -0
  13. package/appUtils/localizationsHelper.ts +31 -0
  14. package/appUtils/playerManager/playerHooks/usePlayerCurrentTime.tsx +11 -7
  15. package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +7 -1
  16. package/cellUtils/index.ts +9 -5
  17. package/componentsUtils/__tests__/isFirstComponentGallery.test.ts +33 -0
  18. package/componentsUtils/__tests__/isFirstComponentScreenPicker.test.ts +33 -0
  19. package/componentsUtils/__tests__/isGallery.test.ts +33 -0
  20. package/componentsUtils/__tests__/isScreenPicker.test.ts +33 -0
  21. package/componentsUtils/index.ts +39 -0
  22. package/dateUtils/index.ts +19 -0
  23. package/focusManager/FocusManager.ts +3 -1
  24. package/focusManager/index.ts +4 -30
  25. package/functionUtils/index.ts +25 -0
  26. package/index.d.ts +0 -12
  27. package/localizationUtils/index.ts +8 -13
  28. package/manifestUtils/defaultManifestConfigurations/generalContent.js +13 -0
  29. package/manifestUtils/defaultManifestConfigurations/player.js +6 -8
  30. package/manifestUtils/keys.js +27 -2
  31. package/modalState/__tests__/index.test.ts +51 -0
  32. package/modalState/index.ts +32 -2
  33. package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +1 -0
  34. package/navigationUtils/index.ts +3 -1
  35. package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +23 -3
  36. package/numberUtils/index.ts +4 -0
  37. package/package.json +2 -2
  38. package/playerUtils/configurationGenerator.ts +6 -16
  39. package/reactHooks/advertising/index.ts +5 -5
  40. package/reactHooks/feed/useBatchLoading.ts +10 -12
  41. package/reactHooks/feed/useFeedLoader.tsx +13 -6
  42. package/reactHooks/navigation/useRoute.ts +2 -2
  43. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +69 -0
  44. package/reactHooks/screen/useScreenBackgroundColor.ts +3 -15
  45. package/reactHooks/useListenEventBusEvent.ts +1 -1
  46. package/utils/README.md +30 -0
  47. package/utils/chunk.ts +5 -0
  48. package/utils/index.ts +5 -0
  49. package/utils/times.ts +5 -0
  50. package/zappFrameworkUtils/localStorageHelper.ts +6 -0
  51. package/zappFrameworkUtils/types.ts +11 -0
@@ -39,22 +39,6 @@ function getPlayerConfiguration({ platform }) {
39
39
  label_tooltip:
40
40
  "Disable if you don't want the content to have a right orientation",
41
41
  },
42
- {
43
- key: "magic_background",
44
- label: "Enable Magic Background",
45
- initial_value: false,
46
- type: "switch",
47
- label_tooltip:
48
- "Enable if you want to have adaptive background gradient based on audio background image.",
49
- },
50
- {
51
- key: "audio_player_background_image_query",
52
- label: "Audio Player Image Query",
53
- initial_value: "",
54
- type: "text_input",
55
- label_tooltip:
56
- "Set the query params which control the size of the image e.g width, height. This will help to optimize the loading time, when magic background is enabled.",
57
- },
58
42
  {
59
43
  key: "audio_player_background_image_default_color",
60
44
  label: "Audio Player Background Image Default Color",
@@ -2557,6 +2541,12 @@ function getPlayerConfiguration({ platform }) {
2557
2541
  multiple: false,
2558
2542
  label_tooltip: "Choose the default aspect ratio for the artwork",
2559
2543
  },
2544
+ {
2545
+ key: "audio_player_artwork_border_radius",
2546
+ label: "Audio Player Artwork Corner Radius",
2547
+ type: "number_input",
2548
+ initial_value: 16,
2549
+ },
2560
2550
  ]
2561
2551
  )
2562
2552
  );
@@ -5,6 +5,7 @@ import * as R from "ramda";
5
5
  import { useNavigation } from "../navigation";
6
6
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
7
7
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
8
+ import { dismissModal, openModal } from "../../modalState";
8
9
 
9
10
  const GOOGLE_ADS_IDENTIFIER = "google-admob-ads-qb";
10
11
 
@@ -14,9 +15,8 @@ const ModalContainer = platformSelect({
14
15
  });
15
16
 
16
17
  export function useAdvertisingInterstitial() {
17
- const navigator = useNavigation();
18
+ const { screenData, currentRoute } = useNavigation();
18
19
  const { plugins } = usePickFromState();
19
- const { screenData } = navigator;
20
20
 
21
21
  return useEffect(() => {
22
22
  // TODD: typing problem: fix any type
@@ -26,7 +26,7 @@ export function useAdvertisingInterstitial() {
26
26
  plugins
27
27
  );
28
28
 
29
- navigator.openModal({
29
+ openModal({
30
30
  item: {},
31
31
  options: {
32
32
  ModalContainer,
@@ -36,11 +36,11 @@ export function useAdvertisingInterstitial() {
36
36
  screenType: "hooks",
37
37
  screenData: {
38
38
  payload: screenData,
39
- callback: navigator.dismissModal,
39
+ callback: dismissModal,
40
40
  hookPlugin: GoogleAdsPlugin,
41
41
  },
42
42
  },
43
43
  });
44
44
  }
45
- }, [navigator.currentRoute, screenData?.id]);
45
+ }, [currentRoute, screenData?.id]);
46
46
  }
@@ -1,7 +1,7 @@
1
- import { isNil, complement, compose, map, min, prop, take, uniq } from "ramda";
1
+ import { complement, compose, isNil, map, min, prop, take, uniq } from "ramda";
2
2
  import { useDispatch } from "react-redux";
3
3
  import * as React from "react";
4
- import { useZappPipesFeeds } from "@applicaster/zapp-react-native-redux/hooks/useZappPipesFeeds";
4
+ import { useZappPipesFeeds } from "@applicaster/zapp-react-native-redux/hooks";
5
5
  import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
6
6
  import { isNilOrEmpty } from "../../reactUtils/helpers";
7
7
  import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
@@ -9,6 +9,7 @@ import {
9
9
  getInflatedDataSourceUrl,
10
10
  getSearchContext,
11
11
  } from "@applicaster/zapp-react-native-utils/reactHooks";
12
+ import { isGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
12
13
  import { useScreenContext } from "../screen/useScreenContext";
13
14
 
14
15
  type Options = {
@@ -46,9 +47,7 @@ const filterEmptyData = (data) => {
46
47
  };
47
48
 
48
49
  const getData = (rawData) =>
49
- rawData.component_type === "gallery-qb"
50
- ? rawData.ui_components[0].data
51
- : rawData.data;
50
+ isGallery(rawData) ? rawData.ui_components[0].data : rawData.data;
52
51
 
53
52
  const extractData = compose(uniq, map(getData));
54
53
 
@@ -70,13 +69,12 @@ export const useBatchLoading = (
70
69
  const [hasEverBeenReady, setHasEverBeenReady] = React.useState(false);
71
70
 
72
71
  // if first component is gallery-qb, take only one component for initial load
73
- const takeSize =
74
- componentsToRender?.[0]?.component_type === "gallery-qb"
75
- ? 1
76
- : min(
77
- options.initialBatchSize ?? DEFAULT_BATCH_SIZE,
78
- componentsToRender.length
79
- );
72
+ const takeSize = isGallery(componentsToRender?.[0])
73
+ ? 1
74
+ : min(
75
+ options.initialBatchSize ?? DEFAULT_BATCH_SIZE,
76
+ componentsToRender.length
77
+ );
80
78
 
81
79
  const takeBatchSize = React.useCallback(take(takeSize), [takeSize]);
82
80
 
@@ -20,6 +20,7 @@ type Props = {
20
20
  silentRefresh?: boolean;
21
21
  method?: "get" | "post";
22
22
  bodyParams?: Record<string, unknown>;
23
+ skipLoading?: boolean;
23
24
  };
24
25
  };
25
26
 
@@ -95,7 +96,7 @@ export const useFeedLoader = ({
95
96
  if (
96
97
  shouldDispatchData(callableFeedUrl, currentFeed, pipesOptions.clearCache)
97
98
  ) {
98
- if (callableFeedUrl) {
99
+ if (callableFeedUrl && !pipesOptions.skipLoading) {
99
100
  dispatch(
100
101
  loadPipesData(callableFeedUrl, {
101
102
  ...pipesOptions,
@@ -103,26 +104,33 @@ export const useFeedLoader = ({
103
104
  riverId,
104
105
  })
105
106
  );
106
- } else {
107
+ } else if (!callableFeedUrl) {
107
108
  logger.info({
108
109
  message:
109
110
  "Feed is not defined or not inflated, skipping loading. \nMake sure you have correct feedUrl and mapping.",
110
111
  jsOnly: true,
111
112
  });
113
+ } else {
114
+ logger.info({
115
+ message:
116
+ "Loading skipped as per pipesOptions.skipLoading configuration.",
117
+ data: { url: callableFeedUrl },
118
+ jsOnly: true,
119
+ });
112
120
  }
113
121
  } else {
114
122
  logger.info({
115
123
  message:
116
- "Feed already exist, skipping loading. \nCall reloadData() if you want to refresh data.",
124
+ "Feed already exists, skipping loading. \nCall reloadData() if you want to refresh data.",
117
125
  data: { url: callableFeedUrl },
118
126
  jsOnly: true,
119
127
  });
120
128
  }
121
129
  }, []);
122
130
 
123
- // Reload feed when feedUrl changes
131
+ // Reload feed when feedUrl changes, unless skipLoading is true
124
132
  useEffect(() => {
125
- if (!isInitialRender && callableFeedUrl) {
133
+ if (!isInitialRender && callableFeedUrl && !pipesOptions.skipLoading) {
126
134
  dispatch(loadPipesData(callableFeedUrl, { ...pipesOptions, riverId }));
127
135
  }
128
136
  }, [callableFeedUrl]);
@@ -158,7 +166,6 @@ export const useFeedLoader = ({
158
166
  currentFeed?.data,
159
167
  currentFeed?.error,
160
168
  currentFeed?.loading,
161
-
162
169
  reloadData,
163
170
  loadNext,
164
171
  ]);
@@ -11,7 +11,7 @@ import { getTargetScreenData } from "../screen/useTargetScreenData";
11
11
  import { useHookModalScreenData } from "../hookModal/hooks/useHookModalScreenData";
12
12
 
13
13
  import { useNavigation } from "./useNavigation";
14
- import { useModalStore } from "../../modalState";
14
+ import { useModalStoreState } from "../../modalState";
15
15
  import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
16
16
  import { usePathname } from "./usePathname";
17
17
 
@@ -43,7 +43,7 @@ export const useRoute = (): {
43
43
  "contentTypes",
44
44
  ]);
45
45
 
46
- const { modalState } = useModalStore();
46
+ const modalState = useModalStoreState();
47
47
 
48
48
  const modalScreenData = modalState.screen;
49
49
 
@@ -0,0 +1,69 @@
1
+ import { renderHook } from "@testing-library/react-hooks";
2
+
3
+ jest.mock(
4
+ "@applicaster/zapp-react-native-ui-components/Components/River/useScreenConfiguration",
5
+ () => ({
6
+ useScreenConfiguration: jest.fn(),
7
+ })
8
+ );
9
+
10
+ const {
11
+ useScreenConfiguration,
12
+ } = require("@applicaster/zapp-react-native-ui-components/Components/River/useScreenConfiguration");
13
+
14
+ const { useScreenBackgroundColor } = require("../useScreenBackgroundColor");
15
+
16
+ describe("useScreenBackgroundColor", () => {
17
+ afterEach(() => {
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ it("should return the background color from screen configuration", () => {
22
+ useScreenConfiguration.mockReturnValue({
23
+ backgroundColor: "#FF0000",
24
+ });
25
+
26
+ // Render the hook with a screen ID
27
+ const { result } = renderHook(() =>
28
+ useScreenBackgroundColor("test-screen-id")
29
+ );
30
+
31
+ expect(result.current).toBe("#FF0000");
32
+
33
+ expect(useScreenConfiguration).toHaveBeenCalledWith("test-screen-id");
34
+ });
35
+
36
+ it("should return 'transparent' when background color is empty", () => {
37
+ useScreenConfiguration.mockReturnValue({
38
+ backgroundColor: "",
39
+ });
40
+
41
+ const { result } = renderHook(() =>
42
+ useScreenBackgroundColor("test-screen-id")
43
+ );
44
+
45
+ expect(result.current).toBe("transparent");
46
+ });
47
+
48
+ it("should return 'transparent' when background color is null", () => {
49
+ useScreenConfiguration.mockReturnValue({
50
+ backgroundColor: null,
51
+ });
52
+
53
+ const { result } = renderHook(() =>
54
+ useScreenBackgroundColor("test-screen-id")
55
+ );
56
+
57
+ expect(result.current).toBe("transparent");
58
+ });
59
+
60
+ it("should return 'transparent' when background color is undefined", () => {
61
+ useScreenConfiguration.mockReturnValue({});
62
+
63
+ const { result } = renderHook(() =>
64
+ useScreenBackgroundColor("test-screen-id")
65
+ );
66
+
67
+ expect(result.current).toBe("transparent");
68
+ });
69
+ });
@@ -1,23 +1,11 @@
1
- import * as React from "react";
2
- import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
3
1
  import { useScreenConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/River/useScreenConfiguration";
4
2
  import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
5
3
 
4
+ const DEFAULT_BACKGROUND_FALLBACK = "transparent";
5
+
6
6
  export const useScreenBackgroundColor = (screenId: string): string => {
7
7
  const { backgroundColor: screenBackgroundColor } =
8
8
  useScreenConfiguration(screenId);
9
9
 
10
- const theme = useTheme();
11
-
12
- const themeBackgroundColor = React.useMemo(
13
- () => theme.app_background_color,
14
- [theme.app_background_color]
15
- );
16
-
17
- const backgroundColor = ifEmptyUseFallback(
18
- screenBackgroundColor,
19
- themeBackgroundColor
20
- );
21
-
22
- return backgroundColor;
10
+ return ifEmptyUseFallback(screenBackgroundColor, DEFAULT_BACKGROUND_FALLBACK);
23
11
  };
@@ -23,5 +23,5 @@ export const useListenEventBusEvent = (
23
23
  sub.remove(); // stop listening to DeviceEventEmitter
24
24
  };
25
25
  }
26
- }, []);
26
+ }, [handler, subscriptionID, source, events]);
27
27
  };
@@ -0,0 +1,30 @@
1
+ ### ramda replacement utils
2
+
3
+ See contribution guide below
4
+
5
+ ## Reference
6
+
7
+ Prefer non-fp variant as it more performant - if refactoring assumes you need more efforts rewrite ramda sample to lodash and it can be easily replaced with lodash-fp - use lodash-fp.
8
+
9
+ ### Ramda alternatives:
10
+
11
+ Custom
12
+ - `splitEvery` => `chunk`
13
+ - `times` => `times`
14
+
15
+ From `lodash`
16
+ - `clone` => `clone`
17
+ - `flatten` => `flatten`
18
+ - `drop` => `drop`
19
+ - `length` => `size`
20
+
21
+
22
+ ## Contribution
23
+
24
+ To add new helper function as ramda replacement
25
+
26
+ 1. Search for replacement ( you can use lodash or pure JS solution), arguments should match with Ramda definition (for easier transition).
27
+ 2. Add new file if needed, add test, update exports in index file. 2.1. Make sure it's well-typed.
28
+ 3. If the function can-be reexported from other 3rd party lib - update index.ts to re-export it.
29
+ 4. Make sure README is updated and contains reference for newly added function.
30
+ 5. You can use AI's help. Use query like 'lodash & lodash/fp equivalent of Ramda's R.clone function' to get an options you can use.
package/utils/chunk.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { chunk as _chunk } from "lodash";
2
+
3
+ export const chunk = <T>(size: number, array: T[]): T[][] => {
4
+ return _chunk(array, size);
5
+ };
package/utils/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { chunk } from "./chunk";
2
+
3
+ export { times } from "./times";
4
+
5
+ export { cloneDeep as clone, flatten, drop, size } from "lodash";
package/utils/times.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { times as _times } from "lodash";
2
+
3
+ export const times = <T>(iteratee: (index: number) => T, n: number) => {
4
+ return _times(n, iteratee);
5
+ };
@@ -1,6 +1,12 @@
1
1
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
2
2
  import { isNilOrEmpty } from "../reactUtils/helpers";
3
3
  import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
4
+ import {
5
+ StorageOwnedValues,
6
+ NamespaceValues,
7
+ StorageValuesToRemove,
8
+ StorageValuesToAdd,
9
+ } from "./types";
4
10
 
5
11
  const defaultOwnedKey = "owned_keys";
6
12
  const DEFAULT_NAMESPACE = "applicaster.v2";
@@ -0,0 +1,11 @@
1
+ export type StorageValuesToAdd = Record<string, NamespaceValues>;
2
+
3
+ export type StorageValuesToRemove = {
4
+ string?: string[];
5
+ };
6
+
7
+ export type StorageOwnedValues = {
8
+ string?: string[];
9
+ };
10
+
11
+ export type NamespaceValues = Record<string, string>;