@applicaster/zapp-react-native-utils 14.0.0-alpha.8387612031 → 14.0.0-alpha.8583696651

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 (54) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +1 -1
  2. package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
  3. package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
  4. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -1
  5. package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
  6. package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
  7. package/analyticsUtils/events.ts +8 -0
  8. package/analyticsUtils/index.tsx +3 -4
  9. package/analyticsUtils/manager.ts +1 -1
  10. package/appUtils/HooksManager/Hook.ts +4 -4
  11. package/appUtils/HooksManager/index.ts +11 -1
  12. package/appUtils/accessibilityManager/index.ts +5 -5
  13. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
  14. package/appUtils/playerManager/useChapterMarker.tsx +0 -1
  15. package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
  16. package/arrayUtils/index.ts +1 -1
  17. package/audioPlayerUtils/index.ts +104 -0
  18. package/componentsUtils/__tests__/isTabsScreen.test.ts +38 -0
  19. package/componentsUtils/index.ts +4 -1
  20. package/configurationUtils/__tests__/manifestKeyParser.test.ts +547 -0
  21. package/configurationUtils/manifestKeyParser.ts +57 -32
  22. package/focusManager/FocusManager.ts +26 -16
  23. package/focusManager/Tree.ts +25 -21
  24. package/focusManager/__tests__/FocusManager.test.ts +50 -8
  25. package/index.d.ts +0 -9
  26. package/manifestUtils/_internals/getDefaultConfiguration.js +28 -0
  27. package/manifestUtils/{_internals.js → _internals/index.js} +2 -25
  28. package/manifestUtils/createConfig.js +4 -1
  29. package/manifestUtils/defaultManifestConfigurations/player.js +1239 -200
  30. package/manifestUtils/progressBar/__tests__/mobileProgressBar.test.js +0 -30
  31. package/package.json +2 -2
  32. package/playerUtils/__tests__/configurationUtils.test.ts +1 -65
  33. package/playerUtils/_internals/__tests__/utils.test.ts +71 -0
  34. package/playerUtils/_internals/index.ts +1 -0
  35. package/playerUtils/_internals/utils.ts +31 -0
  36. package/playerUtils/configurationUtils.ts +0 -44
  37. package/playerUtils/getPlayerActionButtons.ts +1 -1
  38. package/playerUtils/index.ts +51 -0
  39. package/playerUtils/useValidatePlayerConfig.tsx +22 -19
  40. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +12 -13
  41. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +39 -88
  42. package/reactHooks/feed/useBatchLoading.ts +1 -1
  43. package/reactHooks/feed/usePipesCacheReset.ts +1 -1
  44. package/reactHooks/layout/isTablet/index.ts +12 -5
  45. package/reactHooks/navigation/index.ts +7 -5
  46. package/reactHooks/navigation/useIsScreenActive.ts +9 -5
  47. package/reactHooks/screen/useScreenContext.ts +1 -1
  48. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
  49. package/riverComponetsMeasurementProvider/index.tsx +1 -1
  50. package/services/js2native.ts +1 -0
  51. package/testUtils/index.tsx +7 -8
  52. package/time/BackgroundTimer.ts +5 -3
  53. package/utils/index.ts +7 -0
  54. package/playerUtils/configurationGenerator.ts +0 -2572
@@ -1,8 +1,7 @@
1
1
  import { renderHook } from "@testing-library/react-hooks";
2
- import * as reduxMockStore from "redux-mock-store";
3
- import thunk from "redux-thunk";
4
- import React from "react";
5
- import * as ReactRedux from "react-redux";
2
+ import { allFeedsIsReady, useBatchLoading } from "../useBatchLoading";
3
+ import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
4
+ import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
6
5
 
7
6
  jest.mock("../../navigation");
8
7
 
@@ -13,17 +12,18 @@ jest.mock(
13
12
  })
14
13
  );
15
14
 
16
- const useBatchLoading = require("../useBatchLoading").useBatchLoading;
17
- const allFeedsIsReady = require("../useBatchLoading").allFeedsIsReady;
18
-
19
- const mockStore = reduxMockStore.default([thunk]);
20
-
21
- const wrapper: React.FC<any> = ({ children, store }) => (
22
- <ReactRedux.Provider store={store}>{children}</ReactRedux.Provider>
23
- );
15
+ const wrapper = WrappedWithProviders;
24
16
 
25
17
  describe("useBatchLoading", () => {
26
- const useDispatchSpy = jest.spyOn(ReactRedux, "useDispatch");
18
+ const data = [
19
+ { data: { source: "url1" }, component_type: "any" },
20
+ { data: { source: "url2" }, component_type: "any" },
21
+ { data: { source: "url3" }, component_type: "any" },
22
+ { data: { source: "url4" }, component_type: "any" },
23
+ { data: { source: "url5" }, component_type: "any" },
24
+ { data: { source: "url6" }, component_type: "any" },
25
+ // ... more items
26
+ ];
27
27
 
28
28
  beforeAll(() => {
29
29
  jest.useFakeTimers();
@@ -34,7 +34,7 @@ describe("useBatchLoading", () => {
34
34
  });
35
35
 
36
36
  it("loadPipesData start loading not started requests", () => {
37
- const store = mockStore({
37
+ const store = {
38
38
  zappPipes: {
39
39
  url1: {
40
40
  loading: true,
@@ -53,29 +53,17 @@ describe("useBatchLoading", () => {
53
53
  },
54
54
  },
55
55
  test: "true",
56
- });
57
-
58
- useDispatchSpy.mockReturnValue(store.dispatch);
56
+ };
59
57
 
60
58
  const initialBatchSize = 3;
61
59
  const riverId = "123";
62
60
 
63
- const data = [
64
- { data: { source: "url1" } },
65
- { data: { source: "url2" } },
66
- { data: { source: "url3" } },
67
- { data: { source: "url4" } },
68
- { data: { source: "url5" } },
69
- { data: { source: "url6" } },
70
- // ... more items
71
- ];
72
-
73
61
  renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
74
62
  wrapper,
75
63
  initialProps: { store },
76
64
  });
77
65
 
78
- const actions = store.getActions();
66
+ const actions = (appStore.getStore() as any).getActions();
79
67
 
80
68
  expect(actions).toHaveLength(2);
81
69
 
@@ -91,7 +79,7 @@ describe("useBatchLoading", () => {
91
79
  });
92
80
 
93
81
  it("loadPipesData start loading new feed when 1 feed is done loading and 1 is in loading state", () => {
94
- const store = mockStore({
82
+ const store = {
95
83
  zappPipes: {
96
84
  url1: {
97
85
  loading: false,
@@ -110,31 +98,17 @@ describe("useBatchLoading", () => {
110
98
  },
111
99
  },
112
100
  test: "true",
113
- });
114
-
115
- useDispatchSpy.mockReturnValue(store.dispatch);
101
+ };
116
102
 
117
103
  const initialBatchSize = 3;
118
104
  const riverId = "123";
119
105
 
120
- const data = [
121
- { data: { source: "url1" } },
122
- { data: { source: "url2" } },
123
- { data: { source: "url3" } },
124
- { data: { source: "url4" } },
125
- { data: { source: "url5" } },
126
- { data: { source: "url6" } },
127
- // ... more items
128
- ];
129
-
130
- expect(useDispatchSpy).toBeCalledTimes(0);
131
-
132
106
  renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
133
107
  wrapper,
134
108
  initialProps: { store },
135
109
  });
136
110
 
137
- const actions = store.getActions();
111
+ const actions = (appStore.getStore() as any).getActions();
138
112
 
139
113
  expect(actions).toHaveLength(1);
140
114
 
@@ -145,38 +119,26 @@ describe("useBatchLoading", () => {
145
119
  });
146
120
 
147
121
  it("loadPipesData has been called when no data cached", () => {
148
- const store = mockStore({
122
+ const store = {
149
123
  zappPipes: {},
150
124
  test: "true",
151
- });
152
-
153
- useDispatchSpy.mockReturnValue(store.dispatch);
125
+ };
154
126
 
155
127
  const initialBatchSize = 3;
156
128
  const riverId = "123";
157
129
 
158
- const data = [
159
- { data: { source: "url1" } },
160
- { data: { source: "url2" } },
161
- { data: { source: "url3" } },
162
- { data: { source: "url4" } },
163
- { data: { source: "url5" } },
164
- { data: { source: "url6" } },
165
- // ... more items
166
- ];
167
-
168
130
  renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
169
131
  wrapper,
170
132
  initialProps: { store },
171
133
  });
172
134
 
173
- const actions = store.getActions();
135
+ const actions = (appStore.getStore() as any).getActions();
174
136
 
175
137
  expect(actions).toHaveLength(3);
176
138
  });
177
139
 
178
140
  it("initial batch ready when all initial items loaded", () => {
179
- const store = mockStore({
141
+ const store = {
180
142
  zappPipes: {
181
143
  url1: {
182
144
  loading: false,
@@ -194,19 +156,11 @@ describe("useBatchLoading", () => {
194
156
  data: {},
195
157
  },
196
158
  },
197
- });
198
-
199
- useDispatchSpy.mockReturnValue(store.dispatch);
159
+ };
200
160
 
201
161
  const initialBatchSize = 3;
202
162
  const riverId = "123";
203
163
 
204
- const data: Partial<ZappUIComponent>[] = [
205
- { data: { source: "url1" } },
206
- { data: { source: "url2" } },
207
- { data: { source: "url3" } },
208
- ];
209
-
210
164
  const { result } = renderHook(
211
165
  () => useBatchLoading(data, { initialBatchSize, riverId }),
212
166
  { wrapper, initialProps: { store } }
@@ -216,12 +170,10 @@ describe("useBatchLoading", () => {
216
170
  });
217
171
 
218
172
  it("gallery-qb: loadPipesData should be called only once for first component in the gallery", () => {
219
- const store = mockStore({
173
+ const store = {
220
174
  zappPipes: {},
221
175
  test: "true",
222
- });
223
-
224
- useDispatchSpy.mockReturnValue(store.dispatch);
176
+ };
225
177
 
226
178
  const initialBatchSize = 3;
227
179
  const riverId = "123";
@@ -231,11 +183,11 @@ describe("useBatchLoading", () => {
231
183
  component_type: "gallery-qb",
232
184
  ui_components: [{ data: { source: "url1" } }],
233
185
  },
234
- { data: { source: "url2" } },
235
- { data: { source: "url3" } },
236
- { data: { source: "url4" } },
237
- { data: { source: "url5" } },
238
- { data: { source: "url6" } },
186
+ { data: { source: "url2" }, component_type: "any" },
187
+ { data: { source: "url3" }, component_type: "any" },
188
+ { data: { source: "url4" }, component_type: "any" },
189
+ { data: { source: "url5" }, component_type: "any" },
190
+ { data: { source: "url6" }, component_type: "any" },
239
191
  // ... more items
240
192
  ];
241
193
 
@@ -244,13 +196,13 @@ describe("useBatchLoading", () => {
244
196
  initialProps: { store },
245
197
  });
246
198
 
247
- const actions = store.getActions();
199
+ const actions = (appStore.getStore() as any).getActions();
248
200
 
249
201
  expect(actions).toHaveLength(1);
250
202
  });
251
203
 
252
204
  it("gallery-qb: initial batch ready when all initial items loaded", () => {
253
- const store = mockStore({
205
+ const store = {
254
206
  zappPipes: {
255
207
  url1: {
256
208
  loading: false,
@@ -258,20 +210,19 @@ describe("useBatchLoading", () => {
258
210
  data: {},
259
211
  },
260
212
  },
261
- });
262
-
263
- useDispatchSpy.mockReturnValue(store.dispatch);
213
+ };
264
214
 
265
215
  const initialBatchSize = 3;
266
216
  const riverId = "123";
267
217
 
268
- const data: Partial<ZappUIComponent>[] = [
218
+ const data = [
269
219
  {
270
220
  component_type: "gallery-qb",
271
- ui_components: [{ data: { source: "url1" } }],
221
+ data: {},
222
+ ui_components: [{ data: { source: "url1" } }] as any,
272
223
  },
273
- { data: { source: "url2" } },
274
- { data: { source: "url3" } },
224
+ { data: { source: "url2" }, component_type: "any" },
225
+ { data: { source: "url3" }, component_type: "any" },
275
226
  ];
276
227
 
277
228
  const { result } = renderHook(
@@ -10,7 +10,7 @@ import {
10
10
  getSearchContext,
11
11
  } from "@applicaster/zapp-react-native-utils/reactHooks";
12
12
  import { isGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
13
- import { useScreenContext } from "../screen/useScreenContext";
13
+ import { useScreenContext } from "../screen";
14
14
 
15
15
  type Options = {
16
16
  initialBatchSize?: number;
@@ -5,7 +5,7 @@ import { getDatasourceUrl } from "@applicaster/zapp-react-native-ui-components/D
5
5
  import { usePipesContexts } from "@applicaster/zapp-react-native-ui-components/Decorators/RiverFeedLoader/utils/usePipesContexts";
6
6
  import { clearPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
7
7
 
8
- import { useRoute } from "../navigation/useRoute";
8
+ import { useRoute } from "../navigation";
9
9
 
10
10
  /**
11
11
  * reset river components cache when screen is unmounted
@@ -1,21 +1,28 @@
1
1
  import { NativeModules, Platform } from "react-native";
2
2
 
3
+ export const isAndroidTablet = () => {
4
+ const { initialProps } = NativeModules.QuickBrickCommunicationModule;
5
+
6
+ return initialProps?.is_tablet;
7
+ };
8
+
3
9
  /**
4
10
  * Determines wether the given device is a tablet based on dimensions, orientation, and platform
5
11
  * @param {Object} dimensions - Dimensions object passed to the function
6
12
  * @param {String} orientation - Orientation enum passed to the function
7
13
  * @returns {Boolean} isTablet - returns whether the given device is a tablet
8
14
  */
9
- export const isTablet = (dimensions, orientation) => {
15
+ export const isTablet = (
16
+ dimensions?: { width: number; height: number },
17
+ orientation?: string
18
+ ) => {
10
19
  if (Platform?.OS === "ios") {
11
20
  return Platform?.isPad;
12
21
  } else if (Platform?.OS === "android") {
13
- const { initialProps } = NativeModules.QuickBrickCommunicationModule;
14
-
15
- return initialProps?.is_tablet;
22
+ return isAndroidTablet();
16
23
  }
17
24
 
18
- const { width } = dimensions;
25
+ const { width } = dimensions || {};
19
26
 
20
27
  if (width < 600) return false;
21
28
  if (width >= 600 && width < 840) return orientation === "portrait";
@@ -14,7 +14,7 @@ import { HOOKS_EVENTS } from "../../appUtils/HooksManager/constants";
14
14
  import { getRiverFromRoute, getTargetRoute } from "../../navigationUtils";
15
15
  import { useConnectionInfo } from "../connection";
16
16
 
17
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
17
+ import { isTV, isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
18
18
  import { useNavbarState } from "../screen";
19
19
 
20
20
  export { useNavigation } from "./useNavigation";
@@ -127,11 +127,13 @@ export function isNavBarVisible(
127
127
 
128
128
  export const useBackHandler = (cb: () => boolean) => {
129
129
  useEffect(() => {
130
- BackHandler.addEventListener("hardwareBackPress", cb);
130
+ if (!isWeb()) {
131
+ const unsubscribe = BackHandler.addEventListener("hardwareBackPress", cb);
131
132
 
132
- return () => {
133
- BackHandler.removeEventListener("hardwareBackPress", cb);
134
- };
133
+ return () => {
134
+ unsubscribe.remove();
135
+ };
136
+ }
135
137
  }, [cb]);
136
138
  };
137
139
 
@@ -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;
@@ -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 {
@@ -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)) {
@@ -1,17 +1,16 @@
1
- import * as R from "ramda";
2
-
1
+ import { SafeAreaProvider } from "react-native-safe-area-context";
2
+ import { render } from "@testing-library/react-native";
3
3
  import React, { PropsWithChildren } from "react";
4
- import { View } from "react-native";
5
-
4
+ import configureStore from "redux-mock-store";
6
5
  import { Provider } from "react-redux";
6
+ import { View } from "react-native";
7
7
  import thunk from "redux-thunk";
8
- import configureStore from "redux-mock-store";
9
- import { SafeAreaProvider } from "react-native-safe-area-context";
8
+ import * as R from "ramda";
9
+
10
10
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
11
11
 
12
- import { render } from "@testing-library/react-native";
13
- import { AnalyticsProvider } from "../analyticsUtils";
14
12
  import { ThemeContext } from "../theme";
13
+ import { AnalyticsProvider } from "../analyticsUtils";
15
14
 
16
15
  export { getByTestId } from "./getByTestId";
17
16
 
@@ -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
@@ -10,4 +10,11 @@ export {
10
10
  isNil,
11
11
  isEmpty,
12
12
  get,
13
+ has,
14
+ flatMap,
15
+ difference,
16
+ take,
17
+ map,
18
+ trim,
19
+ toString,
13
20
  } from "lodash";