@applicaster/zapp-react-native-utils 14.0.0-alpha.6242515303 → 14.0.0-alpha.6391068513

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 (53) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +60 -83
  2. package/actionsExecutor/ScreenActions.ts +163 -0
  3. package/actionsExecutor/StorageActions.ts +110 -0
  4. package/actionsExecutor/feedDecorator.ts +171 -0
  5. package/actionsExecutor/screenResolver.ts +11 -0
  6. package/analyticsUtils/AnalyticsEvents/helper.ts +1 -1
  7. package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
  8. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -1
  9. package/analyticsUtils/index.tsx +3 -4
  10. package/analyticsUtils/manager.ts +1 -1
  11. package/appUtils/HooksManager/Hook.ts +4 -4
  12. package/appUtils/HooksManager/index.ts +11 -1
  13. package/appUtils/accessibilityManager/index.ts +3 -3
  14. package/appUtils/contextKeysManager/contextResolver.ts +14 -1
  15. package/appUtils/focusManager/treeDataStructure/Tree/index.js +1 -1
  16. package/arrayUtils/index.ts +1 -1
  17. package/componentsUtils/__tests__/isTabsScreen.test.ts +38 -0
  18. package/componentsUtils/index.ts +4 -1
  19. package/configurationUtils/__tests__/manifestKeyParser.test.ts +547 -0
  20. package/configurationUtils/manifestKeyParser.ts +57 -32
  21. package/index.d.ts +0 -9
  22. package/manifestUtils/defaultManifestConfigurations/player.js +0 -148
  23. package/manifestUtils/keys.js +0 -12
  24. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +0 -6
  25. package/navigationUtils/__tests__/mapContentTypesToRivers.test.ts +130 -0
  26. package/navigationUtils/index.ts +6 -4
  27. package/package.json +2 -2
  28. package/playerUtils/index.ts +51 -0
  29. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +15 -14
  30. package/reactHooks/cell-click/index.ts +8 -1
  31. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +39 -88
  32. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +20 -0
  33. package/reactHooks/feed/useBatchLoading.ts +8 -6
  34. package/reactHooks/feed/useFeedLoader.tsx +25 -12
  35. package/reactHooks/feed/usePipesCacheReset.ts +2 -2
  36. package/reactHooks/flatList/useSequentialRenderItem.tsx +3 -3
  37. package/reactHooks/layout/__tests__/index.test.tsx +3 -1
  38. package/reactHooks/layout/isTablet/index.ts +7 -3
  39. package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +34 -36
  40. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -3
  41. package/reactHooks/layout/useLayoutVersion.ts +5 -5
  42. package/reactHooks/navigation/index.ts +7 -5
  43. package/reactHooks/navigation/useRoute.ts +7 -2
  44. package/reactHooks/navigation/useScreenStateStore.ts +8 -0
  45. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +4 -0
  46. package/reactHooks/state/useRivers.ts +7 -8
  47. package/storage/ScreenSingleValueProvider.ts +201 -0
  48. package/storage/ScreenStateMultiSelectProvider.ts +290 -0
  49. package/storage/StorageMultiSelectProvider.ts +192 -0
  50. package/storage/StorageSingleSelectProvider.ts +108 -0
  51. package/testUtils/index.tsx +7 -8
  52. package/time/BackgroundTimer.ts +1 -1
  53. package/utils/index.ts +1 -0
@@ -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(
@@ -138,6 +138,11 @@ describe("useFeedLoader", () => {
138
138
  expect(loadPipesDataSpy).toBeCalledWith(feedUrl, {
139
139
  clearCache: true,
140
140
  riverId: undefined,
141
+ resolvers: {
142
+ screen: {
143
+ screenStateStore: undefined,
144
+ },
145
+ },
141
146
  });
142
147
 
143
148
  const store2 = mockStore({
@@ -179,6 +184,11 @@ describe("useFeedLoader", () => {
179
184
  expect(loadPipesDataSpy).toBeCalledWith(feedUrl, {
180
185
  clearCache: true,
181
186
  riverId: undefined,
187
+ resolvers: {
188
+ screen: {
189
+ screenStateStore: undefined,
190
+ },
191
+ },
182
192
  });
183
193
 
184
194
  const store2 = mockStore({
@@ -228,6 +238,11 @@ describe("useFeedLoader", () => {
228
238
  expect(loadPipesDataSpy).toBeCalledWith(feedUrl, {
229
239
  clearCache: true,
230
240
  silentRefresh: true,
241
+ resolvers: {
242
+ screen: {
243
+ screenStateStore: undefined,
244
+ },
245
+ },
231
246
  });
232
247
 
233
248
  loadPipesDataSpy.mockRestore();
@@ -267,6 +282,11 @@ describe("useFeedLoader", () => {
267
282
  expect(loadPipesDataSpy).toBeCalledWith(nextUrl, {
268
283
  parentFeed: feedUrlWithNext,
269
284
  silentRefresh: true,
285
+ resolvers: {
286
+ screen: {
287
+ screenStateStore: undefined,
288
+ },
289
+ },
270
290
  });
271
291
 
272
292
  loadPipesDataSpy.mockRestore();
@@ -1,8 +1,10 @@
1
1
  import { complement, compose, isNil, map, min, prop, take, uniq } from "ramda";
2
- import { useDispatch } from "react-redux";
3
2
  import * as React from "react";
4
- import { useZappPipesFeeds } from "@applicaster/zapp-react-native-redux/hooks";
5
- import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
3
+ import {
4
+ ZappPipes,
5
+ useAppDispatch,
6
+ useZappPipesFeed,
7
+ } from "@applicaster/zapp-react-native-redux";
6
8
  import { isNilOrEmpty } from "../../reactUtils/helpers";
7
9
  import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
8
10
  import {
@@ -63,7 +65,7 @@ export const useBatchLoading = (
63
65
  componentsToRender: { data?: ZappDataSource; component_type: string }[],
64
66
  options: Options
65
67
  ) => {
66
- const dispatch = useDispatch();
68
+ const dispatch = useAppDispatch();
67
69
  const { screen: screenContext, entry: entryContext } = useScreenContext();
68
70
  const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
69
71
  const [hasEverBeenReady, setHasEverBeenReady] = React.useState(false);
@@ -118,7 +120,7 @@ export const useBatchLoading = (
118
120
  []
119
121
  );
120
122
 
121
- const feeds = useZappPipesFeeds(feedUrls);
123
+ const feeds = useZappPipesFeed(feedUrls);
122
124
 
123
125
  // dispatch loadPipesData for each feed that is not loaded
124
126
  const runBatchLoading = React.useCallback(() => {
@@ -139,7 +141,7 @@ export const useBatchLoading = (
139
141
  if (mappedFeedUrl) {
140
142
  // 4. load data
141
143
  return dispatch(
142
- loadPipesData(mappedFeedUrl, { riverId: options.riverId })
144
+ ZappPipes.loadPipesData(mappedFeedUrl, { riverId: options.riverId })
143
145
  );
144
146
  }
145
147
  }
@@ -1,13 +1,16 @@
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";
9
11
  import { useInflatedUrl } from "./useInflatedUrl";
10
12
  import { useRoute } from "../navigation";
13
+ import { useScreenResolvers } from "@applicaster/zapp-react-native-utils/actionsExecutor/screenResolver";
11
14
 
12
15
  const logger = reactHooksLogger.addSubsystem("useFeedLoader");
13
16
 
@@ -49,8 +52,9 @@ export const useFeedLoader = ({
49
52
  }, []);
50
53
 
51
54
  const isInitialRender = useIsInitialRender();
52
- const dispatch = useDispatch();
55
+ const dispatch = useAppDispatch();
53
56
  const { screenData } = useRoute();
57
+ const resolvers = useScreenResolvers();
54
58
 
55
59
  const callableFeedUrl = useInflatedUrl({ feedUrl, mapping });
56
60
 
@@ -64,16 +68,17 @@ export const useFeedLoader = ({
64
68
  (silentRefresh = true, callback) => {
65
69
  if (callableFeedUrl) {
66
70
  dispatch(
67
- loadPipesData(callableFeedUrl, {
71
+ ZappPipes.loadPipesData(callableFeedUrl, {
68
72
  clearCache: true,
69
73
  silentRefresh,
70
74
  callback,
71
75
  riverId,
76
+ resolvers,
72
77
  })
73
78
  );
74
79
  }
75
80
  },
76
- [callableFeedUrl]
81
+ [callableFeedUrl, resolvers]
77
82
  );
78
83
 
79
84
  const loadNext: FeedLoaderResponse["loadNext"] = React.useCallback(() => {
@@ -82,15 +87,16 @@ export const useFeedLoader = ({
82
87
 
83
88
  if (nextFeed) {
84
89
  dispatch(
85
- loadPipesData(nextFeed, {
90
+ ZappPipes.loadPipesData(nextFeed, {
86
91
  silentRefresh: true,
87
92
  parentFeed: callableFeedUrl,
88
93
  riverId,
94
+ resolvers,
89
95
  })
90
96
  );
91
97
  }
92
98
  }
93
- }, [callableFeedUrl, currentFeed?.data?.next]);
99
+ }, [callableFeedUrl, currentFeed?.data?.next, resolvers]);
94
100
 
95
101
  useEffect(() => {
96
102
  if (
@@ -98,10 +104,11 @@ export const useFeedLoader = ({
98
104
  ) {
99
105
  if (callableFeedUrl && !pipesOptions.skipLoading) {
100
106
  dispatch(
101
- loadPipesData(callableFeedUrl, {
107
+ ZappPipes.loadPipesData(callableFeedUrl, {
102
108
  ...pipesOptions,
103
109
  clearCache: true,
104
110
  riverId,
111
+ resolvers,
105
112
  })
106
113
  );
107
114
  } else if (!callableFeedUrl) {
@@ -126,14 +133,20 @@ export const useFeedLoader = ({
126
133
  jsOnly: true,
127
134
  });
128
135
  }
129
- }, []);
136
+ }, [resolvers]);
130
137
 
131
138
  // Reload feed when feedUrl changes, unless skipLoading is true
132
139
  useEffect(() => {
133
140
  if (!isInitialRender && callableFeedUrl && !pipesOptions.skipLoading) {
134
- dispatch(loadPipesData(callableFeedUrl, { ...pipesOptions, riverId }));
141
+ dispatch(
142
+ ZappPipes.loadPipesData(callableFeedUrl, {
143
+ ...pipesOptions,
144
+ riverId,
145
+ resolvers,
146
+ })
147
+ );
135
148
  }
136
- }, [callableFeedUrl]);
149
+ }, [callableFeedUrl, resolvers]);
137
150
 
138
151
  return React.useMemo(() => {
139
152
  if (!callableFeedUrl || !feedUrl) {
@@ -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
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";
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
 
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
- import { View } from "react-native";
3
+ import { View, ViewStyle } from "react-native";
4
4
 
5
5
  import { platformSelect } from "../../reactUtils";
6
6
 
@@ -49,13 +49,13 @@ export const useSequentialRenderItem = (data: Data) => {
49
49
  const readyToDisplay =
50
50
  index === 0 ? true : arePreviousComponentsReady(index);
51
51
 
52
- const displayStyle = {
52
+ const displayStyle: ViewStyle = {
53
53
  display: readyToDisplay ? "flex" : "none",
54
54
  };
55
55
 
56
56
  const readyStyle = {
57
57
  visibility: readyToDisplay ? "visible" : "hidden",
58
- };
58
+ } as ViewStyle;
59
59
 
60
60
  const style = platformSelect({
61
61
  tvos: readyStyle,
@@ -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
 
@@ -1,5 +1,11 @@
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
@@ -13,9 +19,7 @@ export const isTablet = (
13
19
  if (Platform?.OS === "ios") {
14
20
  return Platform?.isPad;
15
21
  } else if (Platform?.OS === "android") {
16
- const { initialProps } = NativeModules.QuickBrickCommunicationModule;
17
-
18
- return initialProps?.is_tablet;
22
+ return isAndroidTablet();
19
23
  }
20
24
 
21
25
  const { width } = dimensions || {};
@@ -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