@applicaster/zapp-react-native-utils 14.0.0-alpha.2247415563 → 14.0.0-alpha.2292190333

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 (83) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +60 -84
  2. package/actionsExecutor/ScreenActions.ts +164 -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 +81 -0
  7. package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
  8. package/analyticsUtils/__tests__/analyticsUtils.test.js +3 -0
  9. package/analyticsUtils/events.ts +8 -0
  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/contextKeysManager/contextResolver.ts +42 -1
  14. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +5 -0
  15. package/appUtils/focusManager/__tests__/focusManager.test.js +1 -1
  16. package/appUtils/focusManager/index.ios.ts +10 -0
  17. package/appUtils/focusManager/index.ts +82 -11
  18. package/appUtils/focusManager/treeDataStructure/Tree/index.js +1 -1
  19. package/appUtils/focusManagerAux/utils/index.ts +106 -3
  20. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
  21. package/appUtils/playerManager/useChapterMarker.tsx +0 -1
  22. package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
  23. package/arrayUtils/index.ts +1 -1
  24. package/componentsUtils/__tests__/isTabsScreen.test.ts +38 -0
  25. package/componentsUtils/index.ts +4 -1
  26. package/configurationUtils/__tests__/manifestKeyParser.test.ts +546 -0
  27. package/configurationUtils/manifestKeyParser.ts +57 -32
  28. package/focusManager/FocusManager.ts +95 -20
  29. package/focusManager/Tree.ts +25 -21
  30. package/focusManager/__tests__/FocusManager.test.ts +50 -8
  31. package/focusManager/aux/index.ts +170 -0
  32. package/index.d.ts +0 -9
  33. package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
  34. package/navigationUtils/__tests__/mapContentTypesToRivers.test.ts +130 -0
  35. package/navigationUtils/index.ts +6 -4
  36. package/package.json +2 -3
  37. package/playerUtils/getPlayerActionButtons.ts +1 -1
  38. package/playerUtils/index.ts +51 -0
  39. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +3 -1
  40. package/reactHooks/cell-click/__tests__/index.test.js +3 -0
  41. package/reactHooks/cell-click/index.ts +8 -1
  42. package/reactHooks/debugging/__tests__/index.test.js +0 -1
  43. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +8 -2
  44. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +71 -31
  45. package/reactHooks/feed/index.ts +2 -0
  46. package/reactHooks/feed/useBatchLoading.ts +16 -9
  47. package/reactHooks/feed/useFeedLoader.tsx +36 -34
  48. package/reactHooks/feed/useLoadPipesDataDispatch.ts +57 -0
  49. package/reactHooks/feed/usePipesCacheReset.ts +3 -3
  50. package/reactHooks/flatList/useSequentialRenderItem.tsx +3 -3
  51. package/reactHooks/layout/__tests__/index.test.tsx +3 -1
  52. package/reactHooks/layout/isTablet/index.ts +12 -5
  53. package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +34 -36
  54. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -3
  55. package/reactHooks/layout/useLayoutVersion.ts +5 -5
  56. package/reactHooks/navigation/index.ts +7 -5
  57. package/reactHooks/navigation/useIsScreenActive.ts +9 -5
  58. package/reactHooks/navigation/useRoute.ts +7 -2
  59. package/reactHooks/navigation/useScreenStateStore.ts +8 -0
  60. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +4 -0
  61. package/reactHooks/screen/useScreenContext.ts +1 -1
  62. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
  63. package/reactHooks/state/index.ts +1 -1
  64. package/reactHooks/state/useHomeRiver.ts +4 -2
  65. package/reactHooks/state/useRivers.ts +7 -8
  66. package/riverComponetsMeasurementProvider/index.tsx +1 -1
  67. package/screenPickerUtils/index.ts +13 -0
  68. package/services/js2native.ts +1 -0
  69. package/storage/ScreenSingleValueProvider.ts +204 -0
  70. package/storage/ScreenStateMultiSelectProvider.ts +293 -0
  71. package/storage/StorageMultiSelectProvider.ts +192 -0
  72. package/storage/StorageSingleSelectProvider.ts +108 -0
  73. package/time/BackgroundTimer.ts +6 -4
  74. package/utils/__tests__/find.test.ts +36 -0
  75. package/utils/__tests__/omit.test.ts +19 -0
  76. package/utils/__tests__/pathOr.test.ts +37 -0
  77. package/utils/__tests__/startsWith.test.ts +30 -0
  78. package/utils/endsWith.ts +9 -0
  79. package/utils/find.ts +3 -0
  80. package/utils/index.ts +16 -0
  81. package/utils/omit.ts +5 -0
  82. package/utils/pathOr.ts +5 -0
  83. package/utils/startsWith.ts +9 -0
@@ -7,6 +7,13 @@ import { TreeNode } from "./TreeNode";
7
7
  import { Tree } from "./Tree";
8
8
  import { subscriber } from "../functionUtils";
9
9
  import { getFocusableId, toFocusDirection } from "./utils";
10
+ import {
11
+ isCurrentFocusOnMenu,
12
+ isCurrentFocusOnContent,
13
+ findSelectedMenuId,
14
+ isTabsScreenContentFocused,
15
+ findSelectedTabId,
16
+ } from "./aux";
10
17
 
11
18
  export {
12
19
  toFocusDirection,
@@ -176,18 +183,30 @@ class FocusManager {
176
183
  }
177
184
  }
178
185
 
179
- registerFocusable(
180
- component: FocusManager.TouchableReactRef,
181
- parentFocusable: FocusManager.TouchableReactRef,
182
- isFocusableCell: boolean
183
- ) {
184
- const focusableId = getFocusableId(component);
186
+ registerFocusable({
187
+ touchableRef,
188
+ parentFocusableRef,
189
+ isFocusableCell,
190
+ parentFocusableId,
191
+ }: {
192
+ touchableRef: FocusManager.TouchableReactRef;
193
+ parentFocusableRef: FocusManager.TouchableReactRef;
194
+ isFocusableCell: boolean;
195
+ parentFocusableId: string;
196
+ }) {
197
+ const focusableId = getFocusableId(touchableRef);
198
+
185
199
  const focusableComponent = FocusManager.findFocusable(focusableId);
186
200
 
187
- if (!focusableComponent && component) {
188
- this.focusableComponents.push(component);
201
+ if (!focusableComponent && touchableRef) {
202
+ this.focusableComponents.push(touchableRef);
189
203
 
190
- this.tree.add(component, parentFocusable, isFocusableCell);
204
+ this.tree.add(
205
+ touchableRef,
206
+ parentFocusableRef,
207
+ isFocusableCell,
208
+ parentFocusableId
209
+ );
191
210
  } else {
192
211
  logger.warning("Focusable component already registered", {
193
212
  id: focusableId,
@@ -209,7 +228,8 @@ class FocusManager {
209
228
 
210
229
  private setNextFocus(
211
230
  nextFocus: FocusManager.TouchableReactRef,
212
- options?: FocusManager.Android.CallbackOptions
231
+ options?: FocusManager.Android.CallbackOptions,
232
+ context?: FocusManager.FocusContext
213
233
  ) {
214
234
  if (nextFocus?.current?.props?.blockFocus) {
215
235
  return;
@@ -238,17 +258,15 @@ class FocusManager {
238
258
 
239
259
  FocusManager.instance.setPreviousNavigationDirection(options ?? null);
240
260
 
241
- nextFocus?.current?.onFocus?.(nextFocus.current, options ?? {});
261
+ nextFocus?.current?.onFocus?.(nextFocus.current, options ?? {}, context);
242
262
  }
243
263
  }
244
264
 
245
265
  blurPrevious(options?: FocusManager.Android.CallbackOptions) {
246
- if (options) {
247
- FocusManager.instance.prevFocused?.onBlur?.(
248
- FocusManager.instance.prevFocused,
249
- options
250
- );
251
- }
266
+ FocusManager.instance.prevFocused?.onBlur?.(
267
+ FocusManager.instance.prevFocused,
268
+ options ?? {} // Adding fallback to avoid potential regression caused by #7509
269
+ );
252
270
  }
253
271
 
254
272
  onDisableFocusChange = (id) => {
@@ -269,7 +287,7 @@ class FocusManager {
269
287
 
270
288
  if (nextFocus) {
271
289
  // HACK: hack to fix the hack below
272
- // HACK: putting call to the end of the event loop so the next component has a chane to be registered
290
+ // HACK: putting call to the end of the event loop so the next component has a chance to be registered
273
291
  setTimeout(() => {
274
292
  FocusManager.instance.setFocus(nextFocus, {
275
293
  direction: "down",
@@ -281,7 +299,8 @@ class FocusManager {
281
299
 
282
300
  setFocus(
283
301
  newFocus: FocusManager.TouchableReactRef | string,
284
- options?: FocusManager.Android.CallbackOptions
302
+ options?: FocusManager.Android.CallbackOptions,
303
+ context?: FocusManager.FocusContext
285
304
  ) {
286
305
  // Checks if element is focusable
287
306
  const { isFocusable, error } = FocusManager.isFocusable(newFocus);
@@ -306,7 +325,7 @@ class FocusManager {
306
325
  }
307
326
 
308
327
  if (newFocusRef) {
309
- FocusManager.instance.setNextFocus(newFocusRef, options);
328
+ FocusManager.instance.setNextFocus(newFocusRef, options, context);
310
329
  }
311
330
  }
312
331
  }
@@ -407,6 +426,62 @@ class FocusManager {
407
426
  throw new Error(`Group with id ${id} not found`);
408
427
  }
409
428
  }
429
+
430
+ isFocusOnMenu(): boolean {
431
+ // FIXME
432
+ return isCurrentFocusOnMenu(this.tree, FocusManager.instance.focusedId);
433
+ }
434
+
435
+ isFocusOnContent(): boolean {
436
+ // FIXME
437
+ return isCurrentFocusOnContent(this.tree, FocusManager.instance.focusedId);
438
+ }
439
+
440
+ // Move focus to appropriate top navigation tab with context
441
+ focusTopNavigation(isTabsScreen: boolean, item: ZappEntry): void {
442
+ const landFocusTo = (id) => {
443
+ console.log("debug_2", "FM - landFocusTo", { id });
444
+
445
+ if (id) {
446
+ // set focus on selected menu item
447
+ const direction = undefined;
448
+
449
+ const context: FocusManager.FocusContext = {
450
+ source: "back",
451
+ preserveScroll: true,
452
+ };
453
+
454
+ logger.log({ message: "landFocusTo", data: { id } });
455
+
456
+ // blur(direction); ???
457
+ this.setFocus(id, direction, context);
458
+ }
459
+ };
460
+
461
+ if (
462
+ isTabsScreen &&
463
+ isTabsScreenContentFocused(this.tree, FocusManager.instance.focusedId)
464
+ ) {
465
+ const selectedTabId = findSelectedTabId(this.tree, item);
466
+
467
+ // Set focus with back button context to tabs-menu
468
+ landFocusTo(selectedTabId);
469
+
470
+ return;
471
+ }
472
+
473
+ const selectedMenuItemId = findSelectedMenuId(this.tree);
474
+
475
+ console.log("debug_2", "FM - focusTopNavigation", {
476
+ isTabsScreen,
477
+ item,
478
+ tree: this.tree,
479
+ selectedMenuItemId,
480
+ });
481
+
482
+ // Set focus with back button context to top-menu
483
+ landFocusTo(selectedMenuItemId);
484
+ }
410
485
  }
411
486
 
412
487
  export const focusManager = FocusManager.getInstance();
@@ -8,37 +8,41 @@ export class Tree {
8
8
  this.tree = focusManagerTree;
9
9
  }
10
10
 
11
- add(component, parentFocusable, isFocusableCell) {
12
- const focusableId = getFocusableId(component);
13
- const parentId = getFocusableId(parentFocusable);
11
+ add(
12
+ touchableRef: FocusManager.TouchableReactRef,
13
+ parentFocusableRef: FocusManager.TouchableReactRef,
14
+ isFocusableCell: boolean,
15
+ parentFocusableId: string
16
+ ) {
17
+ const focusableId = getFocusableId(touchableRef);
18
+ const parentId = getFocusableId(parentFocusableRef) || parentFocusableId;
14
19
  const focusableComponentInTree = this.find(focusableId);
15
20
 
16
21
  // update node if it already exists
17
22
  if (focusableComponentInTree) {
18
- focusableComponentInTree.updateNode(component);
23
+ focusableComponentInTree.updateNode(touchableRef);
19
24
  }
20
25
 
21
- if (parentFocusable?.current) {
22
- if (!this.find(parentId)) {
23
- this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
24
- }
26
+ if (!this.find(parentId)) {
27
+ // create temporary node to the root of the tree
28
+ this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
29
+ }
25
30
 
26
- const parentNode = this.find(parentId);
31
+ const parentNode = this.find(parentId);
27
32
 
28
- if (parentNode) {
29
- if (focusableComponentInTree) {
30
- focusableComponentInTree.isFocusableCell = isFocusableCell;
31
- focusableComponentInTree.parentId = parentNode.id;
33
+ if (parentNode) {
34
+ if (focusableComponentInTree) {
35
+ focusableComponentInTree.isFocusableCell = isFocusableCell;
36
+ focusableComponentInTree.parentId = parentNode.id;
32
37
 
33
- parentNode.addChild(focusableComponentInTree);
38
+ parentNode.addChild(focusableComponentInTree);
34
39
 
35
- // remove root object from the list
36
- this.tree = this.tree.filter(
37
- (node) => node !== focusableComponentInTree
38
- );
39
- } else {
40
- parentNode.addChild(component, focusableId, isFocusableCell);
41
- }
40
+ // remove root object from the list
41
+ this.tree = this.tree.filter(
42
+ (node) => node !== focusableComponentInTree
43
+ );
44
+ } else {
45
+ parentNode.addChild(touchableRef, focusableId, isFocusableCell);
42
46
  }
43
47
  }
44
48
  }
@@ -1,5 +1,8 @@
1
1
  import { focusManager } from "../FocusManager";
2
2
 
3
+ const isFocusableCell = true;
4
+ const parentFocusableId = "parentFocusableId";
5
+
3
6
  const group = {
4
7
  current: {
5
8
  props: {
@@ -62,13 +65,47 @@ jest.useFakeTimers();
62
65
 
63
66
  describe("FocusManager", () => {
64
67
  beforeAll(() => {
65
- focusManager.registerFocusable(group, { current: null });
66
- focusManager.registerFocusable(child1, group);
67
- focusManager.registerFocusable(child2, group);
68
- focusManager.registerFocusable(child3, child2);
69
-
70
- focusManager.registerFocusable(child4, child2);
71
- focusManager.registerFocusable(child5, child2);
68
+ focusManager.registerFocusable({
69
+ touchableRef: group,
70
+ parentFocusableRef: { current: null },
71
+ isFocusableCell,
72
+ parentFocusableId,
73
+ });
74
+
75
+ focusManager.registerFocusable({
76
+ touchableRef: child1,
77
+ parentFocusableRef: group,
78
+ isFocusableCell,
79
+ parentFocusableId,
80
+ });
81
+
82
+ focusManager.registerFocusable({
83
+ touchableRef: child2,
84
+ parentFocusableRef: group,
85
+ isFocusableCell,
86
+ parentFocusableId,
87
+ });
88
+
89
+ focusManager.registerFocusable({
90
+ touchableRef: child3,
91
+ parentFocusableRef: child2,
92
+ isFocusableCell,
93
+ parentFocusableId,
94
+ });
95
+
96
+ focusManager.registerFocusable({
97
+ touchableRef: child4,
98
+ parentFocusableRef: child2,
99
+ isFocusableCell,
100
+ parentFocusableId,
101
+ });
102
+
103
+ focusManager.registerFocusable({
104
+ touchableRef: child5,
105
+ parentFocusableRef: child2,
106
+ isFocusableCell,
107
+ parentFocusableId,
108
+ });
72
109
  });
73
110
 
74
111
  it("focusManager should be defined", () => {
@@ -199,7 +236,12 @@ describe("FocusManager", () => {
199
236
  });
200
237
 
201
238
  it("focusManager registerFocusable should register", () => {
202
- focusManager.registerFocusable(child5, child2);
239
+ focusManager.registerFocusable({
240
+ touchableRef: child5,
241
+ parentFocusableRef: child2,
242
+ isFocusableCell,
243
+ parentFocusableId,
244
+ });
203
245
 
204
246
  expect(
205
247
  focusManager.isFocusableChildOf(child5.current.props.id, child2)
@@ -0,0 +1,170 @@
1
+ import {
2
+ isNil,
3
+ startsWith,
4
+ find,
5
+ pathOr,
6
+ } from "@applicaster/zapp-react-native-utils/utils";
7
+
8
+ import {
9
+ QUICK_BRICK_CONTENT,
10
+ QUICK_BRICK_NAVBAR,
11
+ } from "@applicaster/quick-brick-core/const";
12
+
13
+ const isNavBar = (node) => startsWith(QUICK_BRICK_NAVBAR, node?.id);
14
+ const isContent = (node) => startsWith(QUICK_BRICK_CONTENT, node?.id);
15
+
16
+ // FIXME
17
+ const sectionIds = {
18
+ right: "nav-bar-right",
19
+ menu: "navbar-items",
20
+ left: "nav-bar-left",
21
+ };
22
+
23
+ // SCREEN_PICKER_SELECTOR_CONTAINER
24
+ let screenPickerSelectorContainerId;
25
+
26
+ export const onRegisterScreenPickerSelectorContainer = (id) => {
27
+ screenPickerSelectorContainerId = id;
28
+ };
29
+
30
+ export const onUnRegisterScreenPickerSelectorContainer = (id) => {
31
+ // reset screenSelectorId on unregistration
32
+ if (screenPickerSelectorContainerId === id) {
33
+ screenPickerSelectorContainerId = undefined;
34
+ }
35
+ };
36
+ // SCREEN_PICKER_SELECTOR_CONTAINER
37
+
38
+ // SCREEN_PICKER_CONTENT_CONTAINER
39
+ let screenPickerContentContainerId;
40
+
41
+ export const onRegisterScreenPickerContentContainer = (id) => {
42
+ screenPickerContentContainerId = id;
43
+ };
44
+
45
+ export const onUnRegisterScreenPickerContentContainer = (id) => {
46
+ // reset screenSelectorId on unregistration
47
+ if (screenPickerContentContainerId === id) {
48
+ screenPickerContentContainerId = undefined;
49
+ }
50
+ };
51
+
52
+ const isScreenPickerContentContainer = (node) =>
53
+ screenPickerContentContainerId === node?.id;
54
+
55
+ // SCREEN_PICKER_CONTENT_CONTAINER
56
+
57
+ const findSelectedMenuIdInSection = (focusableTree, section) => {
58
+ const children = pathOr([], ["children"], focusableTree.find(section));
59
+
60
+ return find((child) => child.component.current.props.isSelected(), children)
61
+ ?.id;
62
+ };
63
+
64
+ export const findSelectedMenuId = (focusableTree) => {
65
+ const selectedMenuItemIdInLeftSection = findSelectedMenuIdInSection(
66
+ focusableTree,
67
+ sectionIds.left
68
+ );
69
+
70
+ if (selectedMenuItemIdInLeftSection) {
71
+ return selectedMenuItemIdInLeftSection;
72
+ }
73
+
74
+ const selectedMenuItemIdInMenuSection = findSelectedMenuIdInSection(
75
+ focusableTree,
76
+ sectionIds.menu
77
+ );
78
+
79
+ if (selectedMenuItemIdInMenuSection) {
80
+ return selectedMenuItemIdInMenuSection;
81
+ }
82
+
83
+ const selectedMenuItemIdInRightSection = findSelectedMenuIdInSection(
84
+ focusableTree,
85
+ sectionIds.right
86
+ );
87
+
88
+ if (selectedMenuItemIdInRightSection) {
89
+ return selectedMenuItemIdInRightSection;
90
+ }
91
+
92
+ return undefined;
93
+ };
94
+
95
+ export const findSelectedTabId = (focusableTree, item: ZappEntry): string => {
96
+ const screenSelectorContainerNode = focusableTree.find(
97
+ screenPickerSelectorContainerId
98
+ );
99
+
100
+ // console.log("debug_2", "findSelectedTabId", {
101
+ // focusableTree,
102
+ // item,
103
+ // screenSelectorContainerNode,
104
+ // });
105
+
106
+ const selectedTabId = find(
107
+ (child) => child.component.current.props.isSelected(item.id),
108
+ screenSelectorContainerNode.children
109
+ )?.id;
110
+
111
+ return selectedTabId;
112
+ };
113
+
114
+ export const isTabsScreenContentFocused = (focusableTree, id) => {
115
+ const node = focusableTree.find(id);
116
+
117
+ if (isNil(node)) {
118
+ return false;
119
+ }
120
+
121
+ if (isNavBar(node)) {
122
+ return false;
123
+ }
124
+
125
+ if (isContent(node)) {
126
+ return false;
127
+ }
128
+
129
+ if (isScreenPickerContentContainer(node)) {
130
+ return true;
131
+ }
132
+
133
+ return isTabsScreenContentFocused(focusableTree, node.parentId);
134
+ };
135
+
136
+ export const isCurrentFocusOnMenu = (focusableTree, id): boolean => {
137
+ const node = focusableTree.find(id);
138
+
139
+ if (isNil(node)) {
140
+ return false;
141
+ }
142
+
143
+ if (isNavBar(node)) {
144
+ return true;
145
+ }
146
+
147
+ if (isContent(node)) {
148
+ return false;
149
+ }
150
+
151
+ return isCurrentFocusOnMenu(focusableTree, node.parentId);
152
+ };
153
+
154
+ export const isCurrentFocusOnContent = (focusableTree, id) => {
155
+ const node = focusableTree.find(id);
156
+
157
+ if (isNil(node)) {
158
+ return false;
159
+ }
160
+
161
+ if (isNavBar(node)) {
162
+ return false;
163
+ }
164
+
165
+ if (isContent(node)) {
166
+ return true;
167
+ }
168
+
169
+ return isCurrentFocusOnContent(focusableTree, node.parentId);
170
+ };
package/index.d.ts CHANGED
@@ -137,12 +137,3 @@ declare type AccessibilityState = {
137
137
  reduceMotionEnabled: boolean;
138
138
  boldTextEnabled: boolean;
139
139
  };
140
-
141
- declare type AccessibilityProps = {
142
- accessibilityLabel?: string;
143
- accessibilityHint?: string;
144
- "aria-label"?: string;
145
- "aria-description"?: string;
146
- accessibilityRole?: string;
147
- "aria-role"?: string;
148
- };
@@ -2985,6 +2985,14 @@ function getPlayerConfiguration({ platform, version }) {
2985
2985
  type: "uploader",
2986
2986
  default: "",
2987
2987
  },
2988
+ {
2989
+ key: "audio_player_background_image_overlay",
2990
+ label: "Background Image Overlay",
2991
+ label_tooltip:
2992
+ "Add a semi-transparent color overlay to improve text readability over the background image.",
2993
+ type: "color_picker_rgba",
2994
+ initial_value: "rgba(17, 17, 17, 0.5)",
2995
+ },
2988
2996
  {
2989
2997
  type: "text_input",
2990
2998
  label: "Item Image Key",
@@ -0,0 +1,130 @@
1
+ import { mapContentTypesToRivers } from "../index";
2
+
3
+ describe("mapContentTypesToRivers", () => {
4
+ it("should return the correct content types mapped to rivers", () => {
5
+ const state = {
6
+ rivers: {
7
+ "river-1": {
8
+ plugin_type: "river",
9
+ },
10
+ },
11
+ contentTypes: {
12
+ "content-type-1": {
13
+ screen_id: "river-1",
14
+ },
15
+ },
16
+ };
17
+
18
+ const result = mapContentTypesToRivers(state);
19
+
20
+ expect(result).toEqual({
21
+ "content-type-1": {
22
+ screenType: "river",
23
+ screen_id: "river-1",
24
+ },
25
+ });
26
+ });
27
+
28
+ it("should return null if contentTypes is undefined", () => {
29
+ const state = {
30
+ rivers: {
31
+ "river-1": {
32
+ plugin_type: "river",
33
+ },
34
+ },
35
+ // contentTypes is missing
36
+ };
37
+
38
+ const result = mapContentTypesToRivers(state);
39
+
40
+ expect(result).toBeNull();
41
+ });
42
+
43
+ it("should skip content types whose screen does not exist in rivers", () => {
44
+ const state = {
45
+ rivers: {
46
+ "river-1": {
47
+ plugin_type: "river",
48
+ },
49
+ },
50
+ contentTypes: {
51
+ "content-type-1": {
52
+ screen_id: "river-1",
53
+ },
54
+ "content-type-2": {
55
+ screen_id: "river-2", // river-2 does not exist
56
+ },
57
+ },
58
+ };
59
+
60
+ const result = mapContentTypesToRivers(state);
61
+
62
+ expect(result).toEqual({
63
+ "content-type-1": {
64
+ screenType: "river",
65
+ screen_id: "river-1",
66
+ },
67
+ });
68
+
69
+ // result is not null, but may be undefined for missing keys
70
+ expect(result && result["content-type-2"]).toBeUndefined();
71
+ });
72
+
73
+ it("should use 'type' if 'plugin_type' is not present in river", () => {
74
+ const state = {
75
+ rivers: {
76
+ "river-1": {
77
+ type: "custom-type",
78
+ },
79
+ },
80
+ contentTypes: {
81
+ "content-type-1": {
82
+ screen_id: "river-1",
83
+ },
84
+ },
85
+ };
86
+
87
+ const result = mapContentTypesToRivers(state);
88
+
89
+ expect(result).toEqual({
90
+ "content-type-1": {
91
+ screenType: "custom-type",
92
+ screen_id: "river-1",
93
+ },
94
+ });
95
+ });
96
+
97
+ it("should skip content types if neither plugin_type nor type is present in river", () => {
98
+ const state = {
99
+ rivers: {
100
+ "river-1": {
101
+ // no plugin_type or type
102
+ },
103
+ },
104
+ contentTypes: {
105
+ "content-type-1": {
106
+ screen_id: "river-1",
107
+ },
108
+ },
109
+ };
110
+
111
+ const result = mapContentTypesToRivers(state);
112
+
113
+ expect(result).toEqual({});
114
+ });
115
+
116
+ it("should handle empty contentTypes object", () => {
117
+ const state = {
118
+ rivers: {
119
+ "river-1": {
120
+ plugin_type: "river",
121
+ },
122
+ },
123
+ contentTypes: {},
124
+ };
125
+
126
+ const result = mapContentTypesToRivers(state);
127
+
128
+ expect(result).toEqual({});
129
+ });
130
+ });
@@ -13,6 +13,7 @@ import {
13
13
  isPlayable,
14
14
  isV2River,
15
15
  } from "./itemTypeMatchers";
16
+ import { RootState } from "@applicaster/zapp-react-native-redux/store";
16
17
 
17
18
  type PathAttribute = {
18
19
  screenType: string;
@@ -377,10 +378,11 @@ export const usesVideoModal = (
377
378
  return targetScreenConfiguration?.styles?.use_video_modal;
378
379
  };
379
380
 
380
- export const mapContentTypesToRivers = ({
381
- rivers,
382
- contentTypes,
383
- }): ZappContentTypesMapped | null => {
381
+ export const mapContentTypesToRivers = (
382
+ state: Partial<RootState>
383
+ ): ZappContentTypesMapped | null => {
384
+ const { rivers, contentTypes } = state;
385
+
384
386
  if (!contentTypes) {
385
387
  return null;
386
388
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "14.0.0-alpha.2247415563",
3
+ "version": "14.0.0-alpha.2292190333",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/applicaster/quickbrick#readme",
29
29
  "dependencies": {
30
- "@applicaster/applicaster-types": "14.0.0-alpha.2247415563",
30
+ "@applicaster/applicaster-types": "14.0.0-alpha.2292190333",
31
31
  "buffer": "^5.2.1",
32
32
  "camelize": "^1.0.0",
33
33
  "dayjs": "^1.11.10",
@@ -38,7 +38,6 @@
38
38
  "peerDependencies": {
39
39
  "@applicaster/zapp-pipes-v2-client": "*",
40
40
  "@react-native-community/netinfo": "*",
41
- "immer": "*",
42
41
  "react": "*",
43
42
  "react-native": "*",
44
43
  "uglify-js": "*",
@@ -1,4 +1,4 @@
1
- import { take, map, trim } from "lodash";
1
+ import { map, take, trim } from "../utils";
2
2
  import { selectActionButtons } from "../conf/player/selectors";
3
3
 
4
4
  /**