@applicaster/zapp-react-native-utils 12.0.0-alpha.4433422595 → 12.0.0-alpha.4440903139

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 (100) hide show
  1. package/analyticsUtils/AnalyticPlayerListener.ts +141 -0
  2. package/analyticsUtils/AnalyticsEvents/index.ts +13 -0
  3. package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
  4. package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
  5. package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
  6. package/analyticsUtils/analyticsPlugins.ts +25 -0
  7. package/analyticsUtils/events.ts +12 -0
  8. package/analyticsUtils/index.tsx +12 -0
  9. package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
  10. package/appUtils/accessibilityManager/const.ts +50 -0
  11. package/appUtils/accessibilityManager/hooks.ts +40 -0
  12. package/appUtils/accessibilityManager/index.ts +166 -0
  13. package/appUtils/accessibilityManager/logger.ts +5 -0
  14. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
  15. package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
  16. package/appUtils/focusManager/__tests__/index.test.ts +2 -3
  17. package/appUtils/focusManager/index.ts +76 -78
  18. package/appUtils/focusManager/treeDataStructure/Utils/index.js +31 -16
  19. package/appUtils/focusManager/utils/index.ts +100 -0
  20. package/appUtils/focusManagerAux/index.ts +76 -0
  21. package/appUtils/focusManagerAux/utils/index.ts +100 -0
  22. package/appUtils/index.js +2 -0
  23. package/appUtils/keyCodes/keys.web.js +8 -0
  24. package/appUtils/keyCodes/keysByPlatform.js +11 -1
  25. package/appUtils/platform/const.ts +25 -0
  26. package/appUtils/platform/index.ts +3 -0
  27. package/appUtils/platform/platformUtils.ts +218 -0
  28. package/appUtils/playerManager/conts.ts +1 -0
  29. package/appUtils/playerManager/index.ts +20 -32
  30. package/appUtils/playerManager/nativePlayerManager.ts +12 -0
  31. package/appUtils/playerManager/player.ts +10 -3
  32. package/appUtils/playerManager/playerHooks/usePlayerCurrentTime.tsx +57 -0
  33. package/appUtils/playerManager/playerNative.ts +11 -15
  34. package/appUtils/playerManager/usePlayerControllerSetup.tsx +8 -2
  35. package/appUtils/playerManager/usePlayerState.tsx +19 -34
  36. package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
  37. package/arrayUtils/index.ts +16 -0
  38. package/booleanUtils/index.ts +4 -4
  39. package/cellUtils/__tests__/cellUtils.test.ts +9 -20
  40. package/cellUtils/index.ts +44 -17
  41. package/dateUtils/index.ts +11 -0
  42. package/focusManager/FocusManager.ts +20 -5
  43. package/focusManager/__tests__/FocusManager.test.ts +0 -1
  44. package/functionUtils/index.ts +38 -0
  45. package/headersUtils/index.ts +1 -0
  46. package/index.d.ts +15 -0
  47. package/inflatedUrlUtils/index.ts +4 -4
  48. package/keyboardState/index.ts +0 -0
  49. package/localizationUtils/__tests__/localizationUtils.test.ts +72 -53
  50. package/localizationUtils/index.ts +13 -22
  51. package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
  52. package/manifestUtils/defaultManifestConfigurations/player.js +123 -1
  53. package/manifestUtils/keys.js +2 -1
  54. package/navigationUtils/index.ts +49 -1
  55. package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
  56. package/numberUtils/__tests__/toNumber.test.ts +2 -2
  57. package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +66 -0
  58. package/numberUtils/__tests__/toPositiveNumberWithDefaultZero.test.ts +66 -0
  59. package/numberUtils/index.ts +27 -16
  60. package/package.json +2 -2
  61. package/playerUtils/configurationGenerator.ts +123 -1
  62. package/playerUtils/imaScriptDom.ts +59 -0
  63. package/pluginUtils/index.ts +9 -0
  64. package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +16 -1
  65. package/reactHooks/cell-click/__tests__/index.test.js +13 -4
  66. package/reactHooks/cell-click/index.ts +28 -14
  67. package/reactHooks/debugging/__tests__/index.test.js +81 -11
  68. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +69 -6
  69. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
  70. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
  71. package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
  72. package/reactHooks/feed/useBatchLoading.ts +52 -28
  73. package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
  74. package/reactHooks/feed/useFeedRefresh.tsx +9 -7
  75. package/reactHooks/feed/useInflatedUrl.ts +44 -15
  76. package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +43 -29
  77. package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
  78. package/reactHooks/layout/types/index.ts +1 -0
  79. package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +134 -0
  80. package/reactHooks/layout/useDimensions/useDimensions.ts +7 -2
  81. package/reactHooks/navigation/__mocks__/index.ts +13 -0
  82. package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
  83. package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
  84. package/reactHooks/navigation/index.ts +48 -65
  85. package/reactHooks/player/useAutoSeek.tsx +9 -7
  86. package/reactHooks/resolvers/useCellResolver.ts +5 -1
  87. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
  88. package/reactHooks/screen/index.ts +2 -0
  89. package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
  90. package/reactHooks/screen/useScreenContext.ts +3 -3
  91. package/reactHooks/useConfiguration.ts +2 -2
  92. package/reactUtils/index.ts +104 -0
  93. package/screenState/index.ts +0 -8
  94. package/stringUtils/index.ts +5 -0
  95. package/testUtils/getByTestId.ts +14 -0
  96. package/testUtils/index.tsx +65 -30
  97. package/types.ts +4 -0
  98. package/appUtils/focusManager/FocusableEvents.ts +0 -8
  99. package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
  100. package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
@@ -0,0 +1,66 @@
1
+ import { toPositiveNumberWithDefaultZero } from "..";
2
+
3
+ const DEFAULT = 0;
4
+
5
+ describe("toNumber", () => {
6
+ it("return number if input is positive number", () => {
7
+ const inputs = [0, 1, 2, 100, 200.12];
8
+ expect.assertions(inputs.length);
9
+
10
+ inputs.forEach((input) => {
11
+ const output = toPositiveNumberWithDefaultZero(input);
12
+ expect(output).toBe(input);
13
+ });
14
+ });
15
+
16
+ it("return number if input is positive number as string", () => {
17
+ const inputs = ["0", "1", "2", "100", "200.12"];
18
+ expect.assertions(inputs.length);
19
+
20
+ inputs.forEach((input) => {
21
+ const output = toPositiveNumberWithDefaultZero(input);
22
+ expect(output).toBe(Number(input));
23
+ });
24
+ });
25
+
26
+ it("return default number if input is negative number", () => {
27
+ const inputs = [-1, -2, -100];
28
+ expect.assertions(inputs.length);
29
+
30
+ inputs.forEach((input) => {
31
+ const output = toPositiveNumberWithDefaultZero(input);
32
+ expect(output).toBe(DEFAULT);
33
+ });
34
+ });
35
+
36
+ it("return default number if input is negative number as string", () => {
37
+ const inputs = ["-1", "-2", "-100"];
38
+ expect.assertions(inputs.length);
39
+
40
+ inputs.forEach((input) => {
41
+ const output = toPositiveNumberWithDefaultZero(input);
42
+ expect(output).toBe(DEFAULT);
43
+ });
44
+ });
45
+
46
+ it("return default if input is not a number or infinite", () => {
47
+ const inputs = [
48
+ "vfdvf",
49
+ null,
50
+ undefined,
51
+ NaN,
52
+ "",
53
+ {},
54
+ { test: 1 },
55
+ [],
56
+ [1],
57
+ ];
58
+
59
+ expect.assertions(inputs.length);
60
+
61
+ inputs.forEach((input) => {
62
+ const output = toPositiveNumberWithDefaultZero(input);
63
+ expect(output).toBe(DEFAULT);
64
+ });
65
+ });
66
+ });
@@ -50,28 +50,39 @@ export const toFiniteNumberWithDefault = (
50
50
  return possibleNumber;
51
51
  };
52
52
 
53
- export const isLikeNumber = (value: any): boolean => {
54
- if (R.isEmpty(value)) {
53
+ export const isLikeNumber = (value: unknown): boolean => {
54
+ const possibleNumber = toNumber(value);
55
+
56
+ if (R.isNil(possibleNumber)) {
55
57
  return false;
56
58
  }
57
59
 
58
- if (R.is(Number, value)) {
59
- return true;
60
- }
60
+ return true;
61
+ };
61
62
 
62
- if (R.is(String, value)) {
63
- const onlyDigit = value
64
- .split("")
65
- .filter((char) =>
66
- ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(char)
67
- )
68
- .join("");
63
+ export const isZero = (value: unknown): boolean =>
64
+ Object.is(value, -0) || Object.is(value, 0);
69
65
 
70
- return value === onlyDigit;
66
+ export const isMinusZero = (value: number) => {
67
+ return 1 / value === -Infinity;
68
+ };
69
+
70
+ export const toPositiveNumberWithDefault = (
71
+ defaultValue: number,
72
+ value: unknown
73
+ ): number => {
74
+ const possibleNumber = toNumber(value);
75
+
76
+ if (R.isNil(possibleNumber)) {
77
+ return defaultValue;
78
+ }
79
+
80
+ if (possibleNumber < 0) {
81
+ return defaultValue;
71
82
  }
72
83
 
73
- return false;
84
+ return possibleNumber;
74
85
  };
75
86
 
76
- export const isZero = (value: unknown): boolean =>
77
- Object.is(value, -0) || Object.is(value, 0);
87
+ export const toPositiveNumberWithDefaultZero = (value: unknown): number =>
88
+ toPositiveNumberWithDefault(0, value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "12.0.0-alpha.4433422595",
3
+ "version": "12.0.0-alpha.4440903139",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "12.0.0-alpha.4433422595",
31
+ "@applicaster/applicaster-types": "12.0.0-alpha.4440903139",
32
32
  "buffer": "^5.2.1",
33
33
  "camelize": "^1.0.0",
34
34
  "create-react-context": "^0.2.3",
@@ -22,6 +22,7 @@ function getDevice(platform) {
22
22
  case "android_tv_for_quickbrick":
23
23
  case "lg_tv":
24
24
  case "samsung_tv":
25
+ case "vizio":
25
26
  case "web":
26
27
  return "tv";
27
28
  }
@@ -1659,7 +1660,8 @@ function getPlayerConfiguration({ platform }) {
1659
1660
  platform.includes("lg") ||
1660
1661
  platform.includes("samsung") ||
1661
1662
  platform.includes("android_tv") ||
1662
- platform.includes("amazon")
1663
+ platform.includes("amazon") ||
1664
+ platform.includes("vizio")
1663
1665
  ) {
1664
1666
  styles.fields.push(
1665
1667
  // Captions Menu for TV
@@ -1796,6 +1798,30 @@ function getPlayerConfiguration({ platform }) {
1796
1798
  key: "menu_header_samsung_letter_spacing",
1797
1799
  initial_value: 0,
1798
1800
  },
1801
+ {
1802
+ type: "vizio_font_selector",
1803
+ label: "Vizio Font Family",
1804
+ key: "menu_header_vizio_font_family",
1805
+ initial_value: "Ubuntu-Bold",
1806
+ },
1807
+ {
1808
+ type: "number_input",
1809
+ label: "Vizio Font Size",
1810
+ key: "menu_header_vizio_font_size",
1811
+ initial_value: 30,
1812
+ },
1813
+ {
1814
+ type: "number_input",
1815
+ label: "Vizio Line Height",
1816
+ key: "menu_header_vizio_line_height",
1817
+ initial_value: 60,
1818
+ },
1819
+ {
1820
+ type: "number_input",
1821
+ label: "Vizio Letter Spacing",
1822
+ key: "menu_header_vizio_letter_spacing",
1823
+ initial_value: 0,
1824
+ },
1799
1825
  ]
1800
1826
  ),
1801
1827
  // Captions Menu - Item Text Label
@@ -1875,6 +1901,30 @@ function getPlayerConfiguration({ platform }) {
1875
1901
  key: "menu_item_samsung_letter_spacing",
1876
1902
  initial_value: 0,
1877
1903
  },
1904
+ {
1905
+ type: "vizio_font_selector",
1906
+ label: "Vizio Font Family",
1907
+ key: "menu_item_vizio_font_family",
1908
+ initial_value: "Ubuntu-Medium",
1909
+ },
1910
+ {
1911
+ type: "number_input",
1912
+ label: "Vizio Font Size",
1913
+ key: "menu_item_vizio_font_size",
1914
+ initial_value: 25,
1915
+ },
1916
+ {
1917
+ type: "number_input",
1918
+ label: "Vizio Line Height",
1919
+ key: "menu_item_vizio_line_height",
1920
+ initial_value: 40,
1921
+ },
1922
+ {
1923
+ type: "number_input",
1924
+ label: "Vizio Letter Spacing",
1925
+ key: "menu_item_vizio_letter_spacing",
1926
+ initial_value: 0,
1927
+ },
1878
1928
  ]
1879
1929
  ),
1880
1930
  // Captions Menu - Item Border
@@ -2018,6 +2068,18 @@ function getPlayerConfiguration({ platform }) {
2018
2068
  key: "samsung_tv_video_player_title_font_size",
2019
2069
  initial_value: 58,
2020
2070
  },
2071
+ {
2072
+ type: "vizio_font_selector",
2073
+ label: "Vizio Font Family",
2074
+ key: "vizio_video_player_title_font_family",
2075
+ initial_value: "Ubuntu-Bold",
2076
+ },
2077
+ {
2078
+ type: "number_input",
2079
+ label: "Vizio Font Size",
2080
+ key: "vizio_video_player_title_font_size",
2081
+ initial_value: 58,
2082
+ },
2021
2083
  {
2022
2084
  type: "tvos_font_selector",
2023
2085
  label: "tvOS Font Family",
@@ -2091,6 +2153,18 @@ function getPlayerConfiguration({ platform }) {
2091
2153
  key: "samsung_tv_video_player_summary_font_size",
2092
2154
  initial_value: 30,
2093
2155
  },
2156
+ {
2157
+ type: "vizio_font_selector",
2158
+ label: "Vizio Font Family",
2159
+ key: "vizio_video_player_summary_font_family",
2160
+ initial_value: "Ubuntu-Medium",
2161
+ },
2162
+ {
2163
+ type: "number_input",
2164
+ label: "Vizio Font Size",
2165
+ key: "vizio_video_player_summary_font_size",
2166
+ initial_value: 30,
2167
+ },
2094
2168
  {
2095
2169
  type: "tvos_font_selector",
2096
2170
  label: "tvOS Font Family",
@@ -2158,6 +2232,18 @@ function getPlayerConfiguration({ platform }) {
2158
2232
  key: "samsung_tv_audio_player_title_font_size",
2159
2233
  initial_value: 40,
2160
2234
  },
2235
+ {
2236
+ type: "vizio_font_selector",
2237
+ label: "Vizio Font Family",
2238
+ key: "vizio_audio_player_title_font_family",
2239
+ initial_value: "Ubuntu-Bold",
2240
+ },
2241
+ {
2242
+ type: "number_input",
2243
+ label: "Vizio Font Size",
2244
+ key: "vizio_audio_player_title_font_size",
2245
+ initial_value: 40,
2246
+ },
2161
2247
  {
2162
2248
  type: "tvos_font_selector",
2163
2249
  label: "tvOS Font Family",
@@ -2213,6 +2299,18 @@ function getPlayerConfiguration({ platform }) {
2213
2299
  key: "samsung_tv_audio_player_summary_font_size",
2214
2300
  initial_value: 22,
2215
2301
  },
2302
+ {
2303
+ type: "vizio_font_selector",
2304
+ label: "Vizio Font Family",
2305
+ key: "vizio_audio_player_summary_font_family",
2306
+ initial_value: "Ubuntu-Medium",
2307
+ },
2308
+ {
2309
+ type: "number_input",
2310
+ label: "Vizio Font Size",
2311
+ key: "vizio_audio_player_summary_font_size",
2312
+ initial_value: 22,
2313
+ },
2216
2314
  {
2217
2315
  type: "tvos_font_selector",
2218
2316
  label: "tvOS Font Family",
@@ -2268,6 +2366,18 @@ function getPlayerConfiguration({ platform }) {
2268
2366
  key: "samsung_tv_player_time_font_size",
2269
2367
  initial_value: 20,
2270
2368
  },
2369
+ {
2370
+ type: "vizio_font_selector",
2371
+ label: "Vizio Font Family",
2372
+ key: "vizio_player_time_font_family",
2373
+ initial_value: "Ubuntu-Medium",
2374
+ },
2375
+ {
2376
+ type: "number_input",
2377
+ label: "Vizio Font Size",
2378
+ key: "vizio_player_time_font_size",
2379
+ initial_value: 20,
2380
+ },
2271
2381
  {
2272
2382
  type: "android_font_selector",
2273
2383
  label: "Android TV Font Family",
@@ -2323,6 +2433,18 @@ function getPlayerConfiguration({ platform }) {
2323
2433
  key: "samsung_tv_audio_player_run_time_font_size",
2324
2434
  initial_value: 20,
2325
2435
  },
2436
+ {
2437
+ type: "vizio_font_selector",
2438
+ label: "Vizio Font Family",
2439
+ key: "vizio_audio_player_run_time_font_family",
2440
+ initial_value: "Ubuntu-Medium",
2441
+ },
2442
+ {
2443
+ type: "number_input",
2444
+ label: "Vizio Font Size",
2445
+ key: "vizio_audio_player_run_time_font_size",
2446
+ initial_value: 20,
2447
+ },
2326
2448
  {
2327
2449
  type: "tvos_font_selector",
2328
2450
  label: "tvOS Font Family",
@@ -0,0 +1,59 @@
1
+ import { createLogger } from "../logger";
2
+
3
+ export const logger = createLogger({
4
+ category: "ImaDomUtils",
5
+ subsystem: "Player/ImaDomUtils",
6
+ });
7
+
8
+ const { log_debug, log_error, log_verbose } = logger;
9
+
10
+ const removeElement = (node) => {
11
+ if (node) {
12
+ const parentNode = node.parentNode;
13
+
14
+ if (parentNode) {
15
+ parentNode.removeChild(node);
16
+ }
17
+ }
18
+ };
19
+
20
+ // TODO: This should probably be loaded to root of project before player init
21
+ export const loadIMAScript = async () => {
22
+ return new Promise((resolve) => {
23
+ // If ima script is already loaded, resolve
24
+ const imaScript = document.getElementById("ima-script");
25
+
26
+ if (imaScript) {
27
+ log_verbose("loadIMAScript: IMA script already loaded");
28
+
29
+ return resolve(true);
30
+ }
31
+
32
+ const script = document.createElement("script");
33
+
34
+ if (__DEV__) {
35
+ script.src = "https://imasdk.googleapis.com/js/sdkloader/ima3_debug.js";
36
+ } else {
37
+ script.src = "https://imasdk.googleapis.com/js/sdkloader/ima3.js";
38
+ }
39
+
40
+ script.async = true;
41
+ script.id = "ima-script";
42
+
43
+ script.onload = () => {
44
+ removeElement(script);
45
+ log_debug("loadIMAScript: Loaded ima script", script.src);
46
+ resolve(true);
47
+ };
48
+
49
+ script.onerror = (_e) => {
50
+ removeElement(script);
51
+ log_error("loadIMAScript: Failed to load ima script", script.src);
52
+ resolve(false);
53
+ };
54
+
55
+ if (document.head) {
56
+ document.head.appendChild(script);
57
+ }
58
+ });
59
+ };
@@ -245,3 +245,12 @@ export function generateManifest({ manifestConfig, version }) {
245
245
 
246
246
  return manifestConfig({ platform, version });
247
247
  }
248
+
249
+ const getPluginType = R.pathOr("unknown_plugin_type", [
250
+ "state",
251
+ "screen",
252
+ "plugin_type",
253
+ ]);
254
+
255
+ export const isPlayerPlugin = (routeState): boolean =>
256
+ getPluginType(routeState) === "player";
@@ -1,4 +1,8 @@
1
+ import React from "react";
2
+
1
3
  import { act, renderHook } from "@testing-library/react-hooks";
4
+ import { Provider } from "react-redux";
5
+ import configureStore from "redux-mock-store";
2
6
 
3
7
  const mockUpdateComponentsPositions = jest.fn();
4
8
 
@@ -19,11 +23,22 @@ jest.useFakeTimers();
19
23
 
20
24
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
21
25
 
26
+ const mockStore = configureStore();
27
+
28
+ const store = mockStore({ appData: {} });
29
+
30
+ const Wrapper = ({ children }: { children: React.ReactChild }) => (
31
+ /* @ts-ignore */
32
+ <Provider store={store}>{children}</Provider>
33
+ );
34
+
22
35
  const { useTrackedView } = require("../useTrackedView");
23
36
 
24
37
  describe("useTrackCurrentAutoScrollingElement", () => {
25
38
  it("should update position for selected component", async () => {
26
- const { result } = renderHook(() => useTrackedView("123"));
39
+ const { result } = renderHook(() => useTrackedView("123"), {
40
+ wrapper: Wrapper,
41
+ });
27
42
 
28
43
  // Fast-forward until all timers have been executed
29
44
  jest.advanceTimersByTime(3000);
@@ -1,11 +1,14 @@
1
1
  import * as React from "react";
2
2
  import { cleanup, renderHook } from "@testing-library/react-hooks";
3
3
  import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
4
+ import { ActionExecutorContext } from "@applicaster/zapp-react-native-utils/actionsExecutor/ActionExecutorContext";
5
+
4
6
  import { waitFor } from "@testing-library/react-native";
5
7
 
6
8
  const navigator = {
7
9
  getPathname: () => "pathnameMock",
8
10
  push: jest.fn(),
11
+ data: {},
9
12
  };
10
13
 
11
14
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
@@ -42,22 +45,28 @@ const mockProps = {
42
45
 
43
46
  const onCellTap = jest.fn();
44
47
 
48
+ const actionExecutor = {
49
+ handleEntryActions: jest.fn(() => Promise.resolve()),
50
+ };
51
+
45
52
  const wrapper = ({ children }) => (
46
53
  <CellTapContext.Provider value={onCellTap}>
47
- {children}
54
+ <ActionExecutorContext.Provider value={actionExecutor}>
55
+ {children}
56
+ </ActionExecutorContext.Provider>
48
57
  </CellTapContext.Provider>
49
58
  );
50
59
 
51
60
  describe("useCellClick", () => {
52
61
  it("returns a function", () => {
53
62
  const { result } = renderHook(() => useCellClick(mockProps));
54
- expect(typeof result.current).toBe("function");
63
+ expect(typeof result.current.current).toBe("function");
55
64
  cleanup();
56
65
  });
57
66
 
58
67
  it("runs default logic", () => {
59
68
  const { result } = renderHook(() => useCellClick(mockProps));
60
- const useCellClickHook = result.current;
69
+ const useCellClickHook = result.current.current;
61
70
 
62
71
  useCellClickHook();
63
72
 
@@ -67,7 +76,7 @@ describe("useCellClick", () => {
67
76
 
68
77
  it("runs onCellTap", async () => {
69
78
  const { result } = renderHook(() => useCellClick(mockProps), { wrapper });
70
- const useCellClickHook = result.current;
79
+ const useCellClickHook = result.current.current;
71
80
 
72
81
  useCellClickHook();
73
82
 
@@ -11,9 +11,9 @@ import {
11
11
  } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
12
12
  import { ZappPipesEntryContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
13
13
  import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
14
- import { noop } from "../../functionUtils";
15
- import { useContext } from "react";
16
- import { ActionExecutorContext } from "../../actionsExecutor/ActionExecutorContext";
14
+ import { ActionExecutorContext } from "@applicaster/zapp-react-native-utils/actionsExecutor/ActionExecutorContext";
15
+
16
+ import { isFunction, noop } from "../../functionUtils";
17
17
  import { useSendAnalyticsOnPress } from "../analytics";
18
18
  import { logOnPress, warnEmptyContentType } from "./helpers";
19
19
 
@@ -30,12 +30,20 @@ type Props = {
30
30
  zappPipesData?: ZappPipesData;
31
31
  };
32
32
 
33
- export const useCellClick = (props: Props) => {
34
- const { component, zappPipesData } = props;
33
+ type onPressReturnFn =
34
+ | ((_item?: ZappEntry | any, _index?: number) => Promise<void>)
35
+ | (() => void);
36
+
37
+ export const useCellClick = ({
38
+ component,
39
+ zappPipesData,
40
+ item,
41
+ }: Props): React.MutableRefObject<onPressReturnFn> => {
35
42
  const { push, currentRoute } = useNavigation();
36
43
  const { pathname } = useRoute();
37
- const onCellTap = React.useContext(CellTapContext);
38
- const actionExecutor = useContext(ActionExecutorContext);
44
+
45
+ const onCellTap: Option<Function> = React.useContext(CellTapContext);
46
+ const actionExecutor = React.useContext(ActionExecutorContext);
39
47
 
40
48
  const cellSelectable = toBooleanWithDefaultTrue(
41
49
  component?.rules?.component_cells_selectable
@@ -47,7 +55,7 @@ export const useCellClick = (props: Props) => {
47
55
  const logTimestamp = useProfilerLogging();
48
56
 
49
57
  const sendAnalyticsOnPress = useSendAnalyticsOnPress(
50
- props.item,
58
+ item,
51
59
  component,
52
60
  zappPipesData
53
61
  );
@@ -56,7 +64,7 @@ export const useCellClick = (props: Props) => {
56
64
  async (_item?: ZappEntry | any, _index?: number) => {
57
65
  // Making sure we are not getting GestureResponderEvent in here.
58
66
  const isZappEntry = _item?.id && _item?.type;
59
- const selectedItem = isZappEntry ? _item : props.item;
67
+ const selectedItem = isZappEntry ? _item : item;
60
68
  setEntryContext?.(selectedItem);
61
69
 
62
70
  if (!selectedItem?.type?.value) {
@@ -80,10 +88,10 @@ export const useCellClick = (props: Props) => {
80
88
  });
81
89
  }
82
90
  } else {
83
- if (typeof onCellTap === "function") {
84
- onCellTap(selectedItem, _index);
91
+ if (isFunction(onCellTap)) {
92
+ onCellTap?.(selectedItem, _index);
85
93
  } else {
86
- if (currentRoute === pathname || pathname === "videoModal") {
94
+ if (currentRoute === pathname || pathname.includes("video-modal")) {
87
95
  const targetScreen = component?.data?.target;
88
96
 
89
97
  push(
@@ -106,9 +114,15 @@ export const useCellClick = (props: Props) => {
106
114
  ]
107
115
  );
108
116
 
117
+ const onPressRef = React.useRef<onPressReturnFn>();
118
+
109
119
  if (!cellSelectable) {
110
- return noop;
120
+ // update ref with dummy function
121
+ onPressRef.current = noop;
122
+ } else {
123
+ // update ref with the latest onPress function
124
+ onPressRef.current = onPress;
111
125
  }
112
126
 
113
- return onPress;
127
+ return onPressRef;
114
128
  };