@applicaster/zapp-react-native-utils 13.0.0-alpha.4244205068 → 13.0.0-alpha.4302300656

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 (132) hide show
  1. package/README.md +0 -10
  2. package/actionsExecutor/ActionExecutor.ts +16 -9
  3. package/actionsExecutor/ActionExecutorContext.tsx +202 -15
  4. package/actionsExecutor/consts.ts +4 -0
  5. package/analyticsUtils/currentScreenProperities.ts +6 -4
  6. package/appUtils/HooksManager/Hook.ts +6 -2
  7. package/appUtils/HooksManager/index.ts +3 -1
  8. package/appUtils/HooksManager/types.ts +5 -2
  9. package/appUtils/__tests__/__snapshots__/localizationsHelper.test.ts.snap +151 -0
  10. package/appUtils/__tests__/allZappLocales.ts +79 -0
  11. package/appUtils/__tests__/{localizationsHelper.test.js → localizationsHelper.test.ts} +11 -0
  12. package/appUtils/accessibilityManager/const.ts +18 -0
  13. package/appUtils/accessibilityManager/index.ts +42 -1
  14. package/appUtils/contextKeysManager/contextResolver.ts +7 -14
  15. package/appUtils/contextKeysManager/index.ts +2 -2
  16. package/appUtils/contextKeysManager/utils/index.ts +2 -1
  17. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +3 -0
  18. package/appUtils/focusManager/index.ios.ts +14 -4
  19. package/appUtils/focusManager/index.ts +24 -12
  20. package/appUtils/focusManager/utils/__tests__/findChild.test.ts +35 -0
  21. package/appUtils/focusManager/utils/index.ts +5 -0
  22. package/appUtils/focusManagerAux/utils/index.ts +4 -3
  23. package/appUtils/keyCodes/index.ts +11 -7
  24. package/appUtils/localizationsHelper.ts +31 -0
  25. package/appUtils/orientationHelper.ts +11 -13
  26. package/appUtils/platform/const.ts +14 -0
  27. package/appUtils/platform/platformUtils.ts +47 -4
  28. package/appUtils/playerManager/index.ts +1 -1
  29. package/appUtils/playerManager/player.ts +26 -14
  30. package/appUtils/playerManager/playerHooks/usePlayerCurrentTime.tsx +11 -7
  31. package/appUtils/playerManager/playerNative.ts +18 -3
  32. package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +7 -1
  33. package/cellUtils/index.ts +9 -5
  34. package/componentsUtils/__tests__/isFirstComponentGallery.test.ts +33 -0
  35. package/componentsUtils/__tests__/isFirstComponentScreenPicker.test.ts +33 -0
  36. package/componentsUtils/__tests__/isGallery.test.ts +33 -0
  37. package/componentsUtils/__tests__/isScreenPicker.test.ts +33 -0
  38. package/componentsUtils/index.ts +39 -0
  39. package/dateUtils/index.ts +19 -0
  40. package/equalUtils/__tests__/isEqual/combination.test.ts +263 -0
  41. package/equalUtils/index.ts +49 -30
  42. package/focusManager/FocusManager.ts +14 -2
  43. package/focusManager/index.ts +23 -4
  44. package/functionUtils/index.ts +46 -8
  45. package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
  46. package/idleUtils/index.ts +1 -1
  47. package/idleUtils/withTimeout.ts +15 -2
  48. package/index.d.ts +0 -12
  49. package/localizationUtils/index.ts +8 -13
  50. package/logger/const.ts +9 -67
  51. package/manifestUtils/__tests__/createConfig.test.js +0 -2
  52. package/manifestUtils/defaultManifestConfigurations/generalContent.js +13 -0
  53. package/manifestUtils/defaultManifestConfigurations/player.js +9 -3
  54. package/manifestUtils/fonts/index.js +5 -6
  55. package/manifestUtils/index.js +2 -0
  56. package/manifestUtils/keys.js +27 -2
  57. package/manifestUtils/sharedConfiguration/screenPicker/__tests__/utils.test.js +304 -0
  58. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +874 -0
  59. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +130 -0
  60. package/modalState/__tests__/index.test.ts +51 -0
  61. package/modalState/index.ts +32 -2
  62. package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +1 -0
  63. package/navigationUtils/index.ts +6 -4
  64. package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +23 -3
  65. package/numberUtils/index.ts +11 -5
  66. package/package.json +4 -10
  67. package/playerUtils/configurationGenerator.ts +9 -11
  68. package/playerUtils/index.ts +23 -0
  69. package/reactHooks/advertising/index.ts +5 -5
  70. package/reactHooks/app/useAppState.ts +2 -2
  71. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +5 -7
  72. package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
  73. package/reactHooks/cell-click/__tests__/index.test.js +5 -0
  74. package/reactHooks/cell-click/index.ts +7 -1
  75. package/reactHooks/feed/useBatchLoading.ts +10 -12
  76. package/reactHooks/feed/useFeedLoader.tsx +18 -9
  77. package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +39 -0
  78. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +1 -1
  79. package/reactHooks/layout/useDimensions/useDimensions.ts +8 -0
  80. package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
  81. package/reactHooks/navigation/__tests__/index.test.tsx +6 -17
  82. package/reactHooks/navigation/{useGetTabBarHeight.ts → getTabBarHeight.ts} +2 -4
  83. package/reactHooks/navigation/index.ts +13 -23
  84. package/reactHooks/navigation/useGetBottomTabBarHeight.ts +10 -3
  85. package/reactHooks/navigation/useNavigationPluginData.ts +8 -4
  86. package/reactHooks/navigation/useNavigationType.ts +4 -2
  87. package/reactHooks/navigation/useProfilerLogging.ts +15 -0
  88. package/reactHooks/navigation/useRoute.ts +4 -6
  89. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +69 -0
  90. package/reactHooks/screen/useScreenBackgroundColor.ts +3 -15
  91. package/reactHooks/state/README.md +79 -0
  92. package/reactHooks/state/ZStoreProvider.tsx +71 -0
  93. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +66 -0
  94. package/reactHooks/state/index.ts +2 -0
  95. package/reactHooks/state/useRefWithInitialValue.ts +14 -0
  96. package/reactHooks/state/useStateFromSubscribe.ts +23 -0
  97. package/reactHooks/useListenEventBusEvent.ts +1 -1
  98. package/reactHooks/usePluginConfiguration.ts +1 -1
  99. package/reactHooks/useSubscriberFor.ts +4 -3
  100. package/reactUtils/__tests__/__snapshots__/reactUtilsHelpers.test.js.snap +16 -4
  101. package/reactUtils/__tests__/reactUtils.test.js +1 -19
  102. package/reactUtils/__tests__/reactUtilsHelpers.test.js +72 -71
  103. package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +6 -72
  104. package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -28
  105. package/reactUtils/createContext/__tests__/__snapshots__/withConsumer.test.js.snap +3 -4
  106. package/reactUtils/createContext/__tests__/__snapshots__/withProvider.test.js.snap +7 -3
  107. package/reactUtils/createContext/__tests__/helpers.test.js +107 -121
  108. package/reactUtils/createContext/__tests__/{index.test.js → index.test.ts} +2 -2
  109. package/reactUtils/createContext/__tests__/provider.test.js +4 -6
  110. package/reactUtils/createContext/__tests__/withConsumer.test.js +12 -12
  111. package/reactUtils/createContext/__tests__/withProvider.test.js +4 -4
  112. package/reactUtils/createContext/helpers.ts +6 -1
  113. package/reactUtils/createContext/index.ts +11 -25
  114. package/reactUtils/index.ts +9 -11
  115. package/screenState/index.ts +24 -10
  116. package/services/js2native.ts +673 -0
  117. package/testUtils/index.tsx +0 -10
  118. package/theme/index.ts +1 -1
  119. package/time/BackgroundTimer.ts +55 -0
  120. package/time/Timer.ts +9 -6
  121. package/typeGuards/index.ts +3 -0
  122. package/types.ts +1 -0
  123. package/utils/README.md +30 -0
  124. package/utils/chunk.ts +5 -0
  125. package/utils/index.ts +5 -0
  126. package/utils/times.ts +5 -0
  127. package/zappFrameworkUtils/localStorageHelper.ts +38 -10
  128. package/zappFrameworkUtils/loginPluginUtils.ts +6 -2
  129. package/zappFrameworkUtils/presentPluginOneTime.ts +2 -3
  130. package/zappFrameworkUtils/types.ts +11 -0
  131. package/reactUtils/createContext/__tests__/index-no-react.test.js +0 -27
  132. /package/reactUtils/createContext/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
package/README.md CHANGED
@@ -376,16 +376,6 @@ useEffect(() => {
376
376
  }, []);
377
377
  ```
378
378
 
379
- ### testUtils
380
-
381
- `@applicaster/zapp-react-native-utils/testUtils`
382
-
383
- - `testIDEquals: (testId: any) => boolean | { width: number, height: number }` - Function to be used in tandem with enzyme findWhere
384
-
385
- ```javascript
386
- wrapper.findWhere(testIDEquals("text"));
387
- ```
388
-
389
379
  ### appUtils - contextKeysManager
390
380
 
391
381
  `@applicaster/zapp-react-native-utils/appUtils/contextKeyManager`
@@ -17,9 +17,10 @@ class ActionExecutor {
17
17
 
18
18
  handleAction = async (
19
19
  action: ActionType,
20
- entry: ZappEntry = null
20
+ context?: Record<string, any>
21
21
  ): Promise<ActionResult> => {
22
22
  const handler = this.registeredActions[action.type];
23
+ const entry = context?.entry as ZappEntry;
23
24
 
24
25
  if (!handler) {
25
26
  log_error(
@@ -38,11 +39,11 @@ class ActionExecutor {
38
39
  );
39
40
 
40
41
  try {
41
- return handler(action, entry);
42
+ return handler(action, context);
42
43
  } catch (error) {
43
44
  log_error(
44
45
  `handleAction: error handling action type: ${action.type}, message: ${error.message}`,
45
- { action, entry, error }
46
+ { action, context, error }
46
47
  );
47
48
 
48
49
  throw error;
@@ -51,11 +52,11 @@ class ActionExecutor {
51
52
 
52
53
  handleActions = async (
53
54
  actionTypes: ActionType[],
54
- entry: ZappEntry = null
55
+ context?: Record<string, any>
55
56
  ): Promise<ActionResult> => {
56
57
  for (const action of actionTypes) {
57
58
  // TODO: Handle action result error
58
- const result = await this.handleAction(action, entry);
59
+ const result = await this.handleAction(action, context);
59
60
 
60
61
  if (result === ActionResult.Cancel) {
61
62
  log_info(`handleActions: action: ${action.type} canceled`);
@@ -67,7 +68,10 @@ class ActionExecutor {
67
68
  return ActionResult.Success;
68
69
  };
69
70
 
70
- handleEntryActions = async (entry: ZappEntry): Promise<ActionResult> => {
71
+ handleEntryActions = async (
72
+ entry: ZappEntry,
73
+ context?: Record<string, any>
74
+ ): Promise<ActionResult> => {
71
75
  const tapActions = entry.extensions?.tap_actions?.actions;
72
76
 
73
77
  if (!tapActions) {
@@ -77,7 +81,7 @@ class ActionExecutor {
77
81
  if (!Array.isArray(tapActions)) {
78
82
  log_error(
79
83
  `handleEntryActions: tapActions is not an array for id: ${entry.id} title: ${entry.title}`,
80
- { entry }
84
+ { context, entry }
81
85
  );
82
86
 
83
87
  return;
@@ -87,7 +91,7 @@ class ActionExecutor {
87
91
  return;
88
92
  }
89
93
 
90
- await this.handleActions(tapActions, entry);
94
+ await this.handleActions(tapActions, { ...context, entry });
91
95
  };
92
96
 
93
97
  unregisterAction = (actionType: string) => {
@@ -96,7 +100,10 @@ class ActionExecutor {
96
100
 
97
101
  registerAction = (
98
102
  type: string,
99
- handler: (action: ActionType, entry?: ZappEntry) => Promise<ActionResult>
103
+ handler: (
104
+ action: ActionType,
105
+ context?: Record<string, any>
106
+ ) => Promise<ActionResult>
100
107
  ) => {
101
108
  if (this.registeredActions[type]) {
102
109
  log_error(`registerAction: action type: ${type} already registered`);
@@ -1,24 +1,41 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
3
- import React, { createContext, useMemo } from "react";
3
+ import React, { createContext, useEffect, useMemo } from "react";
4
4
  import {
5
5
  actionExecutor as _actionExecutor,
6
6
  ActionResult,
7
7
  } from "./ActionExecutor";
8
- import { batchSaveToLocalStorage } from "../zappFrameworkUtils/localStorageHelper";
9
- import { QUICK_BRICK_EVENTS } from "@applicaster/zapp-react-native-bridge/QuickBrick";
8
+ import {
9
+ batchRemoveAllFromNamespaceForStorage,
10
+ batchSave,
11
+ } from "../zappFrameworkUtils/localStorageHelper";
12
+ import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";
13
+
10
14
  import * as QuickBrickManager from "@applicaster/zapp-react-native-bridge/QuickBrick";
15
+ import { QUICK_BRICK_EVENTS } from "@applicaster/zapp-react-native-bridge/QuickBrick";
11
16
  import { showConfirmationDialog } from "../alertUtils";
12
17
  import { createCloudEvent, sendCloudEvent } from "../cloudEventsUtils";
13
18
  import { createLogger } from "../logger";
14
19
  import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
15
20
  import { ACTIVE_LAYOUT_ID_STORAGE_KEY } from "@applicaster/quick-brick-core/App/remoteContextReloader/consts";
21
+ import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
22
+ import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
16
23
  import {
17
24
  EntryResolver,
18
25
  resolveObjectValues,
19
26
  } from "../appUtils/contextKeysManager/contextResolver";
27
+ import { useNavigation } from "../reactHooks";
28
+ import { get } from "lodash";
20
29
 
21
- const { log_error, log_info } = createLogger({
30
+ import {
31
+ useContentTypes,
32
+ usePickFromState,
33
+ } from "@applicaster/zapp-react-native-redux/hooks";
34
+ import { TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT } from "./consts";
35
+ import { postEvent, useSubscriberFor } from "../reactHooks/useSubscriberFor";
36
+ import { APP_EVENTS } from "../appUtils/events";
37
+
38
+ export const { log_error, log_info, log_debug } = createLogger({
22
39
  subsystem: "ActionExecutorContext",
23
40
  category: "General",
24
41
  });
@@ -26,29 +43,102 @@ const { log_error, log_info } = createLogger({
26
43
  type ActionExecutorContextType = {
27
44
  registerAction: (
28
45
  type: string,
29
- handler: (action: ActionType, entry: ZappEntry) => Promise<ActionResult>
46
+ handler: (
47
+ action: ActionType,
48
+ context?: Record<string, any>
49
+ ) => Promise<ActionResult>
30
50
  ) => void;
31
51
  unregisterAction: (type: string) => void;
32
- handleAction: (action: ActionType, entry: ZappEntry) => Promise<ActionResult>;
52
+ handleAction: (
53
+ action: ActionType,
54
+ context?: Record<string, any>
55
+ ) => Promise<ActionResult>;
33
56
  handleActions: (
34
57
  actions: ActionType[],
35
- entry: ZappEntry
58
+ context: Record<string, any>
59
+ ) => Promise<ActionResult>;
60
+ handleEntryActions: (
61
+ entry: ZappEntry,
62
+ context?: Record<string, any>
36
63
  ) => Promise<ActionResult>;
37
- handleEntryActions: (entry: ZappEntry) => Promise<ActionResult>;
38
64
  };
39
65
  type Props = {
40
66
  children: React.ReactNode;
41
67
  };
42
68
 
69
+ function findParentComponent(
70
+ childId: string,
71
+ parent: ZappRiver | ZappUIComponent
72
+ ): ZappRiver | ZappUIComponent | null {
73
+ for (const child of parent.ui_components) {
74
+ if (child.id === childId) return parent;
75
+
76
+ if (child.ui_components) {
77
+ const found = findParentComponent(childId, child);
78
+ if (found) return found;
79
+ }
80
+ }
81
+
82
+ return null;
83
+ }
84
+
85
+ // send all data just in case (like for message string formatting)
86
+ // Type is not exported for now
87
+ type MaxTagsReachedEvent = {
88
+ selectedItems: string[];
89
+ maxItems: number;
90
+ tag: string;
91
+ keyNamespace: string;
92
+ };
93
+
94
+ async function onMaxTagsReached(data: MaxTagsReachedEvent) {
95
+ postEvent(TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT, [data]);
96
+ }
97
+
43
98
  const prepareDefaultActions = (actionExecutor) => {
44
99
  actionExecutor.registerAction("localStorageSet", async (action) => {
45
100
  const namespaces = action.options.content;
46
- await batchSaveToLocalStorage(namespaces);
101
+ await batchSave(namespaces, localStorage);
47
102
  // TODO: Add support for ownershipKey and ownershipNamespace
48
103
 
49
104
  return ActionResult.Success;
50
105
  });
51
106
 
107
+ actionExecutor.registerAction("sessionStorageSet", async (action) => {
108
+ const namespaces = action.options.content;
109
+ await batchSave(namespaces, sessionStorage);
110
+ // TODO: Add support for ownershipKey and ownershipNamespace
111
+
112
+ return ActionResult.Success;
113
+ });
114
+
115
+ actionExecutor.registerAction(
116
+ "refreshComponent",
117
+ async (_action, context) => {
118
+ const dispatch = appStore.getDispatch();
119
+
120
+ const dataSource =
121
+ context?.component?.data?.source ||
122
+ findParentComponent(context?.component.id, context?.screenData)?.data
123
+ ?.source;
124
+
125
+ log_info(`handleAction: refreshComponent for dataSource:${dataSource}`);
126
+
127
+ // TODO: In theory we should wait callback to complete, before completing the action, but now it's not needed
128
+ // TODO: handle focused item removal
129
+ dispatch(
130
+ loadPipesData(dataSource, {
131
+ silentRefresh: false,
132
+ clearCache: true,
133
+ callback: (_data) => {},
134
+ riverId: context?.screenData?.id,
135
+ })
136
+ );
137
+
138
+ return ActionResult.Success;
139
+ }
140
+ );
141
+
52
142
  actionExecutor.registerAction("switchLayout", async (action) => {
53
143
  log_info("handleAction: switchLayout event");
54
144
 
@@ -73,21 +163,20 @@ const prepareDefaultActions = (actionExecutor) => {
73
163
  actionExecutor.registerAction("confirmDialog", async (action) => {
74
164
  log_info("handleAction: confirmDialog event");
75
165
 
76
- const confirmationPromise = new Promise<ActionResult>((resolve) => {
166
+ return new Promise<ActionResult>((resolve) => {
77
167
  showConfirmationDialog({
78
168
  ...action.options,
79
169
  confirmCompletion: () => resolve(ActionResult.Success),
80
170
  cancelCompletion: () => resolve(ActionResult.Cancel),
81
171
  });
82
172
  });
83
-
84
- return confirmationPromise;
85
173
  });
86
174
 
87
- actionExecutor.registerAction("sendCloudEvent", async (action, entry) => {
175
+ actionExecutor.registerAction("sendCloudEvent", async (action, context) => {
88
176
  try {
89
177
  const options = action.options;
90
178
 
179
+ const entry = context?.entry || {};
91
180
  const entryResolver = new EntryResolver(entry);
92
181
 
93
182
  const data =
@@ -128,9 +217,33 @@ const prepareDefaultActions = (actionExecutor) => {
128
217
 
129
218
  actionExecutor.registerAction(
130
219
  "localStorageToggleFlag",
131
- async (action: ActionType, entry?: ZappEntry): Promise<ActionResult> => {
220
+ async (
221
+ action: ActionType,
222
+ context?: Record<string, any>
223
+ ): Promise<ActionResult> => {
224
+ if (!context) {
225
+ log_error(
226
+ "handleAction: localStorageToggleFlag action missing context"
227
+ );
228
+
229
+ return ActionResult.Error;
230
+ }
231
+
232
+ const entry = context?.entry as ZappEntry;
233
+
234
+ if (!entry) {
235
+ log_error(
236
+ "handleAction: localStorageToggleFlag action missing entry. Entry is required to get the tag."
237
+ );
238
+
239
+ return ActionResult.Error;
240
+ }
241
+
242
+ const tag = action.options?.selector
243
+ ? get(entry, action.options.selector)
244
+ : (entry.extensions?.tag ?? entry.id);
245
+
132
246
  const keyNamespace = action.options?.key;
133
- const tag = entry?.extensions?.tag;
134
247
 
135
248
  if (keyNamespace && tag) {
136
249
  const multiSelectProvider =
@@ -148,6 +261,23 @@ const prepareDefaultActions = (actionExecutor) => {
148
261
  if (selectedItems.includes(tag)) {
149
262
  await multiSelectProvider.removeItem(tag);
150
263
  } else {
264
+ const maxItems = action.options?.max_items;
265
+
266
+ if (maxItems && selectedItems.length >= maxItems) {
267
+ log_info(
268
+ `handleAction: localStorageToggleFlag event reached max items limit: ${maxItems}, cannot add tag: ${tag}`
269
+ );
270
+
271
+ await onMaxTagsReached({
272
+ selectedItems,
273
+ maxItems,
274
+ tag,
275
+ keyNamespace,
276
+ });
277
+
278
+ return ActionResult.Cancel;
279
+ }
280
+
151
281
  await multiSelectProvider.addItem(tag);
152
282
  }
153
283
  } else {
@@ -171,6 +301,10 @@ export function withActionExecutor(Component) {
171
301
  prepareDefaultActions(_actionExecutor);
172
302
 
173
303
  return function ActionExecutorComponent(props: Props) {
304
+ const navigator = useNavigation();
305
+ const { rivers } = usePickFromState(["rivers"]);
306
+ const contentTypes = useContentTypes();
307
+
174
308
  const handlers = useMemo(() => {
175
309
  return {
176
310
  unregisterAction: _actionExecutor.unregisterAction,
@@ -181,6 +315,59 @@ export function withActionExecutor(Component) {
181
315
  };
182
316
  }, []);
183
317
 
318
+ useSubscriberFor(APP_EVENTS.onLogout, () => {
319
+ log_debug(
320
+ "User profile: onLogout event received, clearing user profile data"
321
+ );
322
+
323
+ const userAccountKey = "user_account";
324
+ void batchRemoveAllFromNamespaceForStorage(userAccountKey, localStorage);
325
+
326
+ void batchRemoveAllFromNamespaceForStorage(
327
+ userAccountKey,
328
+ sessionStorage
329
+ );
330
+ });
331
+
332
+ useEffect(() => {
333
+ return _actionExecutor.registerAction(
334
+ "navigateToScreen",
335
+
336
+ async (action: ActionType, context?: Record<string, any>) => {
337
+ const screenType = action.options?.typeMapping;
338
+
339
+ if (!screenType) {
340
+ log_error("navigateToScreen: typeMapping option is missing");
341
+
342
+ return ActionResult.Error;
343
+ }
344
+
345
+ const screenId = contentTypes?.[screenType]?.screen_id || null;
346
+
347
+ if (!screenId) {
348
+ log_error(
349
+ `navigateToScreen: can not resolve screen type mapping: ${screenType}`
350
+ );
351
+
352
+ return ActionResult.Error;
353
+ }
354
+
355
+ const river = rivers[screenId];
356
+
357
+ if (!river) {
358
+ log_error("navigateToScreen: can not resolve river");
359
+
360
+ return ActionResult.Error;
361
+ }
362
+
363
+ context?.callback?.({ success: false, error: null, abort: true });
364
+ navigator.replace(river);
365
+
366
+ return ActionResult.Success;
367
+ }
368
+ );
369
+ }, [navigator, rivers, contentTypes]);
370
+
184
371
  return (
185
372
  <ActionExecutorContext.Provider value={handlers}>
186
373
  <Component {...props} />
@@ -0,0 +1,4 @@
1
+ export const TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT =
2
+ "action.localStorageToggleFlag.maxItemsReached";
3
+
4
+ export const ACTION_EXECUTOR_EVENT_SOURCE = "ActionExecutor";
@@ -72,12 +72,14 @@ const mappedScreenPropertiesScreen = (
72
72
  screenData
73
73
  ): AnalyticsScreenProperties => {
74
74
  return {
75
- screen_name: screenData?.targetScreen?.name,
75
+ screen_name: screenData?.targetScreen?.name || screenData?.name,
76
76
  screen_entry_title: screenData?.title,
77
77
  screen_entry_id: R.isNil(screenData?.type) ? null : screenData?.id,
78
- screen_layout_id: screenData?.targetScreen?.id,
79
- screen_type: screenData?.targetScreen?.type,
80
- home_screen: screenData?.targetScreen?.home,
78
+ screen_layout_id: screenData?.targetScreen?.id || screenData?.id,
79
+ screen_type: screenData?.targetScreen?.type || screenData?.type,
80
+ home_screen: !R.isNil(screenData?.targetScreen?.home)
81
+ ? screenData?.targetScreen?.home
82
+ : screenData?.home,
81
83
  };
82
84
  };
83
85
 
@@ -16,7 +16,7 @@ const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
16
16
  * @returns {number} index
17
17
  */
18
18
  const hookState: (
19
- arg0: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS]
19
+ arg0: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS]
20
20
  ) => number = R.indexOf(R.__, R.values(HOOKS_EVENTS));
21
21
 
22
22
  /**
@@ -62,9 +62,13 @@ export class Hook implements HookInterface {
62
62
  * @param {Array<Any>} args variadic arguments to invoke the handler with
63
63
  */
64
64
  setStateAndNotify(
65
- event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
65
+ event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
66
66
  ...args
67
67
  ) {
68
+ if (this.state === hookState(HOOKS_EVENTS.CANCEL)) {
69
+ return;
70
+ }
71
+
68
72
  this.state = hookState(event);
69
73
  this.manager.subscriber.invokeHandler(event, ...args);
70
74
  }
@@ -84,7 +84,7 @@ export function HooksManager({
84
84
  plugins,
85
85
  startUpHooksData = {},
86
86
  }: HookManagerArgs): HookManager {
87
- hooksManagerLogger.addContext({ targetScreen });
87
+ hooksManagerLogger.addContext({ targetScreenId: targetScreen.id });
88
88
 
89
89
  function logHookEvent(func, message, data) {
90
90
  func({
@@ -269,6 +269,7 @@ export function HooksManager({
269
269
  payload = initialPayload,
270
270
  callback: callbackArg,
271
271
  cancelled,
272
+ abort,
272
273
  }) {
273
274
  let callback = callbackArg;
274
275
 
@@ -308,6 +309,7 @@ export function HooksManager({
308
309
  hookPlugin.setStateAndNotify(HOOKS_EVENTS.CANCEL, {
309
310
  hookPlugin,
310
311
  payload,
312
+ abort,
311
313
  });
312
314
 
313
315
  const isHookInHomescreen = payload?.home;
@@ -4,6 +4,8 @@ import { HOOKS_EVENTS } from "./constants";
4
4
  export interface HookConfiguration {}
5
5
 
6
6
  /* existing Hook Plugn props: sample */
7
+
8
+ /*
7
9
  interface _HookModulePlugin {
8
10
  Component:
9
11
  | React.FC<HookPluginProps>
@@ -23,6 +25,7 @@ interface _HookModulePlugin {
23
25
  presentUI: (payload?: HookPluginProps["payload"]) => void
24
26
  ) => any;
25
27
  }
28
+ */
26
29
 
27
30
  //* Derived from usage */
28
31
  export interface HookModule {
@@ -100,7 +103,7 @@ export interface Hook<T extends HookModule = HookModule> {
100
103
  identifier: string;
101
104
  configuration: T["configuration"];
102
105
  setStateAndNotify(
103
- event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
106
+ event: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS],
104
107
  opts: {
105
108
  error?: typeof Error;
106
109
  route?: string;
@@ -109,7 +112,7 @@ export interface Hook<T extends HookModule = HookModule> {
109
112
  }
110
113
  );
111
114
  general?: {
112
- transition_type: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS];
115
+ transition_type: (typeof HOOKS_EVENTS)[keyof typeof HOOKS_EVENTS];
113
116
  allow_screen_plugin_presentation: boolean;
114
117
  is_flow_blocker: boolean;
115
118
  };
@@ -0,0 +1,151 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`toDayJSLocaleMap [af] returns a valid dayjs locale 1`] = `"af"`;
4
+
5
+ exports[`toDayJSLocaleMap [ar] returns a valid dayjs locale 1`] = `"ar"`;
6
+
7
+ exports[`toDayJSLocaleMap [bg] returns a valid dayjs locale 1`] = `"bg"`;
8
+
9
+ exports[`toDayJSLocaleMap [bn] returns a valid dayjs locale 1`] = `"bn"`;
10
+
11
+ exports[`toDayJSLocaleMap [bo] returns a valid dayjs locale 1`] = `"bo"`;
12
+
13
+ exports[`toDayJSLocaleMap [ca] returns a valid dayjs locale 1`] = `"ca"`;
14
+
15
+ exports[`toDayJSLocaleMap [cs] returns a valid dayjs locale 1`] = `"cs"`;
16
+
17
+ exports[`toDayJSLocaleMap [da] returns a valid dayjs locale 1`] = `"da"`;
18
+
19
+ exports[`toDayJSLocaleMap [de] returns a valid dayjs locale 1`] = `"de"`;
20
+
21
+ exports[`toDayJSLocaleMap [el] returns a valid dayjs locale 1`] = `"el"`;
22
+
23
+ exports[`toDayJSLocaleMap [en] returns a valid dayjs locale 1`] = `"en"`;
24
+
25
+ exports[`toDayJSLocaleMap [en-GB] returns a valid dayjs locale 1`] = `"en-gb"`;
26
+
27
+ exports[`toDayJSLocaleMap [en-UK] returns a valid dayjs locale 1`] = `"en-gb"`;
28
+
29
+ exports[`toDayJSLocaleMap [es] returns a valid dayjs locale 1`] = `"es"`;
30
+
31
+ exports[`toDayJSLocaleMap [es-LA] returns a valid dayjs locale 1`] = `"es"`;
32
+
33
+ exports[`toDayJSLocaleMap [es-MX] returns a valid dayjs locale 1`] = `"es-mx"`;
34
+
35
+ exports[`toDayJSLocaleMap [es-US] returns a valid dayjs locale 1`] = `"es-us"`;
36
+
37
+ exports[`toDayJSLocaleMap [et] returns a valid dayjs locale 1`] = `"et"`;
38
+
39
+ exports[`toDayJSLocaleMap [eu] returns a valid dayjs locale 1`] = `"eu"`;
40
+
41
+ exports[`toDayJSLocaleMap [fa] returns a valid dayjs locale 1`] = `"fa"`;
42
+
43
+ exports[`toDayJSLocaleMap [fi] returns a valid dayjs locale 1`] = `"fi"`;
44
+
45
+ exports[`toDayJSLocaleMap [fj] returns a valid dayjs locale 1`] = `"en"`;
46
+
47
+ exports[`toDayJSLocaleMap [fr] returns a valid dayjs locale 1`] = `"fr"`;
48
+
49
+ exports[`toDayJSLocaleMap [ga] returns a valid dayjs locale 1`] = `"ga"`;
50
+
51
+ exports[`toDayJSLocaleMap [gu] returns a valid dayjs locale 1`] = `"gu"`;
52
+
53
+ exports[`toDayJSLocaleMap [he] returns a valid dayjs locale 1`] = `"he"`;
54
+
55
+ exports[`toDayJSLocaleMap [hi] returns a valid dayjs locale 1`] = `"hi"`;
56
+
57
+ exports[`toDayJSLocaleMap [hr] returns a valid dayjs locale 1`] = `"hr"`;
58
+
59
+ exports[`toDayJSLocaleMap [hu] returns a valid dayjs locale 1`] = `"hu"`;
60
+
61
+ exports[`toDayJSLocaleMap [hy] returns a valid dayjs locale 1`] = `"hy-am"`;
62
+
63
+ exports[`toDayJSLocaleMap [id] returns a valid dayjs locale 1`] = `"id"`;
64
+
65
+ exports[`toDayJSLocaleMap [is] returns a valid dayjs locale 1`] = `"is"`;
66
+
67
+ exports[`toDayJSLocaleMap [it] returns a valid dayjs locale 1`] = `"it"`;
68
+
69
+ exports[`toDayJSLocaleMap [ja] returns a valid dayjs locale 1`] = `"ja"`;
70
+
71
+ exports[`toDayJSLocaleMap [ka] returns a valid dayjs locale 1`] = `"ka"`;
72
+
73
+ exports[`toDayJSLocaleMap [km] returns a valid dayjs locale 1`] = `"km"`;
74
+
75
+ exports[`toDayJSLocaleMap [ko] returns a valid dayjs locale 1`] = `"ko"`;
76
+
77
+ exports[`toDayJSLocaleMap [la] returns a valid dayjs locale 1`] = `"en"`;
78
+
79
+ exports[`toDayJSLocaleMap [lt] returns a valid dayjs locale 1`] = `"lt"`;
80
+
81
+ exports[`toDayJSLocaleMap [lv] returns a valid dayjs locale 1`] = `"lv"`;
82
+
83
+ exports[`toDayJSLocaleMap [mi] returns a valid dayjs locale 1`] = `"mi"`;
84
+
85
+ exports[`toDayJSLocaleMap [mk] returns a valid dayjs locale 1`] = `"mk"`;
86
+
87
+ exports[`toDayJSLocaleMap [ml] returns a valid dayjs locale 1`] = `"ml"`;
88
+
89
+ exports[`toDayJSLocaleMap [mn] returns a valid dayjs locale 1`] = `"mn"`;
90
+
91
+ exports[`toDayJSLocaleMap [mr] returns a valid dayjs locale 1`] = `"mr"`;
92
+
93
+ exports[`toDayJSLocaleMap [ms] returns a valid dayjs locale 1`] = `"ms"`;
94
+
95
+ exports[`toDayJSLocaleMap [mt] returns a valid dayjs locale 1`] = `"mt"`;
96
+
97
+ exports[`toDayJSLocaleMap [ne] returns a valid dayjs locale 1`] = `"ne"`;
98
+
99
+ exports[`toDayJSLocaleMap [nl] returns a valid dayjs locale 1`] = `"nl"`;
100
+
101
+ exports[`toDayJSLocaleMap [no] returns a valid dayjs locale 1`] = `"en"`;
102
+
103
+ exports[`toDayJSLocaleMap [pa] returns a valid dayjs locale 1`] = `"pa-in"`;
104
+
105
+ exports[`toDayJSLocaleMap [pl] returns a valid dayjs locale 1`] = `"pl"`;
106
+
107
+ exports[`toDayJSLocaleMap [pt] returns a valid dayjs locale 1`] = `"pt"`;
108
+
109
+ exports[`toDayJSLocaleMap [pt-BR] returns a valid dayjs locale 1`] = `"pt-br"`;
110
+
111
+ exports[`toDayJSLocaleMap [qu] returns a valid dayjs locale 1`] = `"en"`;
112
+
113
+ exports[`toDayJSLocaleMap [ro] returns a valid dayjs locale 1`] = `"ro"`;
114
+
115
+ exports[`toDayJSLocaleMap [ru] returns a valid dayjs locale 1`] = `"ru"`;
116
+
117
+ exports[`toDayJSLocaleMap [sk] returns a valid dayjs locale 1`] = `"sk"`;
118
+
119
+ exports[`toDayJSLocaleMap [sl] returns a valid dayjs locale 1`] = `"sl"`;
120
+
121
+ exports[`toDayJSLocaleMap [sm] returns a valid dayjs locale 1`] = `"en"`;
122
+
123
+ exports[`toDayJSLocaleMap [sq] returns a valid dayjs locale 1`] = `"sq"`;
124
+
125
+ exports[`toDayJSLocaleMap [sr] returns a valid dayjs locale 1`] = `"sr"`;
126
+
127
+ exports[`toDayJSLocaleMap [sv] returns a valid dayjs locale 1`] = `"sv"`;
128
+
129
+ exports[`toDayJSLocaleMap [sw] returns a valid dayjs locale 1`] = `"sw"`;
130
+
131
+ exports[`toDayJSLocaleMap [ta] returns a valid dayjs locale 1`] = `"ta"`;
132
+
133
+ exports[`toDayJSLocaleMap [te] returns a valid dayjs locale 1`] = `"te"`;
134
+
135
+ exports[`toDayJSLocaleMap [th] returns a valid dayjs locale 1`] = `"th"`;
136
+
137
+ exports[`toDayJSLocaleMap [to] returns a valid dayjs locale 1`] = `"en"`;
138
+
139
+ exports[`toDayJSLocaleMap [tr] returns a valid dayjs locale 1`] = `"tr"`;
140
+
141
+ exports[`toDayJSLocaleMap [tt] returns a valid dayjs locale 1`] = `"en"`;
142
+
143
+ exports[`toDayJSLocaleMap [uk] returns a valid dayjs locale 1`] = `"uk"`;
144
+
145
+ exports[`toDayJSLocaleMap [ur] returns a valid dayjs locale 1`] = `"ur"`;
146
+
147
+ exports[`toDayJSLocaleMap [uz] returns a valid dayjs locale 1`] = `"uz"`;
148
+
149
+ exports[`toDayJSLocaleMap [vi] returns a valid dayjs locale 1`] = `"vi"`;
150
+
151
+ exports[`toDayJSLocaleMap [zh] returns a valid dayjs locale 1`] = `"zh"`;