@applicaster/zapp-react-native-utils 12.0.0-alpha.4342066143 → 12.0.0-alpha.4354608902

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 (73) hide show
  1. package/analyticsUtils/AnalyticsEvents/index.ts +7 -0
  2. package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
  3. package/analyticsUtils/events.ts +6 -0
  4. package/analyticsUtils/index.tsx +6 -0
  5. package/appUtils/HooksManager/{Hook.js → Hook.ts} +35 -23
  6. package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
  7. package/appUtils/HooksManager/{index.js → index.ts} +118 -111
  8. package/appUtils/HooksManager/types.ts +116 -0
  9. package/appUtils/RiverFocusManager/index.js +17 -12
  10. package/appUtils/accessibilityManager/const.ts +50 -0
  11. package/appUtils/accessibilityManager/hooks.ts +31 -0
  12. package/appUtils/accessibilityManager/index.ts +150 -0
  13. package/appUtils/accessibilityManager/logger.ts +5 -0
  14. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
  15. package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
  16. package/appUtils/focusManager/__tests__/index.test.ts +2 -3
  17. package/appUtils/focusManager/index.ts +76 -57
  18. package/appUtils/focusManager/treeDataStructure/Tree/index.js +2 -3
  19. package/appUtils/focusManager/treeDataStructure/Utils/index.js +76 -47
  20. package/appUtils/focusManager/utils/index.ts +100 -0
  21. package/appUtils/focusManagerAux/index.ts +76 -0
  22. package/appUtils/focusManagerAux/utils/index.ts +100 -0
  23. package/appUtils/{index.js → index.ts} +2 -0
  24. package/appUtils/keyCodes/{index.js → index.ts} +2 -0
  25. package/appUtils/keyCodes/keys/index.ts +3 -0
  26. package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
  27. package/appUtils/keyCodes/keys/keys.android.ts +18 -0
  28. package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
  29. package/appUtils/keyCodes/keys/keys.ts +15 -0
  30. package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +8 -0
  31. package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +11 -1
  32. package/appUtils/platform/const.ts +25 -0
  33. package/appUtils/platform/index.ts +3 -0
  34. package/appUtils/platform/platformUtils.ts +171 -0
  35. package/appUtils/playerManager/conts.ts +1 -0
  36. package/appUtils/playerManager/index.ts +11 -5
  37. package/appUtils/playerManager/nativePlayerManager.ts +12 -0
  38. package/appUtils/playerManager/player.ts +9 -3
  39. package/appUtils/playerManager/playerNative.ts +5 -14
  40. package/appUtils/playerManager/usePlayerControllerSetup.tsx +1 -0
  41. package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
  42. package/arrayUtils/index.ts +5 -0
  43. package/booleanUtils/index.ts +4 -4
  44. package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
  45. package/functionUtils/index.ts +15 -11
  46. package/keyboardState/index.ts +0 -0
  47. package/modalState/index.ts +1 -5
  48. package/navigationUtils/index.ts +62 -5
  49. package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
  50. package/numberUtils/index.ts +5 -18
  51. package/package.json +2 -2
  52. package/pluginUtils/index.ts +9 -0
  53. package/reactHooks/cell-click/__tests__/index.test.js +9 -5
  54. package/reactHooks/cell-click/index.ts +11 -11
  55. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
  56. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
  57. package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
  58. package/reactHooks/feed/useFeedRefresh.tsx +9 -7
  59. package/reactHooks/navigation/index.ts +51 -11
  60. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
  61. package/reactHooks/screen/index.ts +2 -0
  62. package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
  63. package/reactHooks/screen/useScreenContext.ts +1 -2
  64. package/reactUtils/index.ts +91 -0
  65. package/appUtils/focusManager/FocusableEvents.ts +0 -8
  66. package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
  67. package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
  68. package/appUtils/keyCodes/keys.ios.js +0 -46
  69. /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
  70. /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
  71. /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
  72. /package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +0 -0
  73. /package/domUtils/{logger.js → logger.ts} +0 -0
@@ -12,6 +12,11 @@ import {
12
12
  sendSearchExecutedEvent,
13
13
  } from "./searchEvents";
14
14
 
15
+ import {
16
+ sendShareInitiatedEvent,
17
+ sendShareSuccessEvent,
18
+ } from "./sendShareEvent";
19
+
15
20
  export {
16
21
  sendScreenEvent,
17
22
  sendOnClickEvent,
@@ -24,4 +29,6 @@ export {
24
29
  sendDownloadsEvent,
25
30
  sendSearchCanceledEvent,
26
31
  sendSearchExecutedEvent,
32
+ sendShareInitiatedEvent,
33
+ sendShareSuccessEvent,
27
34
  };
@@ -0,0 +1,21 @@
1
+ import { log_debug } from "../logger";
2
+ import { postAnalyticEvent } from "../manager";
3
+ import { ANALYTICS_CORE_EVENTS } from "../events";
4
+
5
+ export const sendShareInitiatedEvent = (analyticsProps) => {
6
+ const eventName = ANALYTICS_CORE_EVENTS.SHARE_INITIATED;
7
+ postAnalyticEvent(eventName, analyticsProps);
8
+
9
+ log_debug(`sendShareInitiatedEvent: send event: ${eventName}`, {
10
+ analyticsProps,
11
+ });
12
+ };
13
+
14
+ export const sendShareSuccessEvent = (analyticsProps) => {
15
+ const eventName = ANALYTICS_CORE_EVENTS.SHARE_SUCCESS;
16
+ postAnalyticEvent(eventName, analyticsProps);
17
+
18
+ log_debug(`sendShareSuccessEvent: send event: ${eventName}`, {
19
+ analyticsProps,
20
+ });
21
+ };
@@ -28,11 +28,17 @@ export const SEARCH_EVENTS = {
28
28
  SEARCH_CANCELED: "search_canceled",
29
29
  };
30
30
 
31
+ export const SHARE_EVENTS = {
32
+ SHARE_INITIATED: "share_initiated",
33
+ SHARE_SUCCESS: "share_success",
34
+ };
35
+
31
36
  export const ANALYTICS_CORE_EVENTS = {
32
37
  ...LEGACY_EVENTS,
33
38
  ...SCREEN_VIEW_EVENTS,
34
39
  ...TAPPING_EVENTS,
35
40
  ...SEARCH_EVENTS,
41
+ ...SHARE_EVENTS,
36
42
  };
37
43
 
38
44
  export const WEBVIEW_EVENTS = {
@@ -20,6 +20,8 @@ import {
20
20
  sendScreenEvent,
21
21
  sendSearchCanceledEvent,
22
22
  sendSearchExecutedEvent,
23
+ sendShareInitiatedEvent,
24
+ sendShareSuccessEvent,
23
25
  } from "./AnalyticsEvents";
24
26
 
25
27
  import { postAnalyticEvent } from "./manager";
@@ -70,6 +72,8 @@ type AnalyticsFunctions = {
70
72
  }) => void;
71
73
  sendSearchCanceledEvent: (props: AnalyticsDefaultProperties) => void;
72
74
  sendSearchExecutedEvent: (props: AnalyticsDefaultProperties) => void;
75
+ sendShareInitiatedEvent: (props: AnalyticsDefaultProperties) => void;
76
+ sendShareSuccessEvent: (props: AnalyticsDefaultProperties) => void;
73
77
  };
74
78
 
75
79
  type GetAnalyticsFunctions = (
@@ -108,6 +112,8 @@ export function getAnalyticsFunctions({
108
112
  sendDownloadsEvent,
109
113
  sendSearchCanceledEvent,
110
114
  sendSearchExecutedEvent,
115
+ sendShareInitiatedEvent,
116
+ sendShareSuccessEvent,
111
117
  };
112
118
  }
113
119
 
@@ -4,6 +4,7 @@ import { isFunction } from "../../functionUtils";
4
4
  import { HOOKS_EVENTS, HOOKS_TRANSITION_TYPE } from "./constants";
5
5
 
6
6
  import { hooksManagerLogger } from "./logger";
7
+ import type { Hook as HookInterface, HookIniObj } from "./types";
7
8
 
8
9
  const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
9
10
 
@@ -14,7 +15,9 @@ const BASE_HOOK_PROPERTIES = ["screen_id", "identifier", "weight"];
14
15
  * @param {string} hookEventName
15
16
  * @returns {number} index
16
17
  */
17
- const hookState = R.indexOf(R.__, R.values(HOOKS_EVENTS));
18
+ const hookState: (
19
+ arg0: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS]
20
+ ) => number = R.indexOf(R.__, R.values(HOOKS_EVENTS));
18
21
 
19
22
  /**
20
23
  * assigns property to a given context
@@ -28,17 +31,20 @@ function assignProp(context) {
28
31
  }
29
32
 
30
33
  /**
31
- * Representation of a hook plugin with full data
34
+ * Representation of a hook plugin
32
35
  */
33
- export class Hook {
34
- /**
35
- * constructs the hook
36
- * @param {object} Options
37
- * @param {object} Options.hook hook object
38
- * @param {Array<Object>} Options.hooks array of hooks siblings in the current process
39
- * @param {object} manager hook manager to process the hooks
40
- */
41
- constructor({ hook, hooks, manager }) {
36
+ export class Hook implements HookInterface {
37
+ public manager: HookInterface["manager"];
38
+ public lastHook: HookInterface["lastHook"];
39
+ public state: HookInterface["state"];
40
+ public screen_id: HookInterface["screen_id"];
41
+ public identifier: HookInterface["identifier"];
42
+ public module: HookInterface["module"];
43
+ public general: HookInterface["general"];
44
+ public weight: number;
45
+ public configuration: HookInterface["configuration"];
46
+
47
+ constructor({ hook, hooks, manager }: HookIniObj) {
42
48
  R.forEachObjIndexed(assignProp(this), hook);
43
49
  this.manager = manager;
44
50
 
@@ -55,25 +61,28 @@ export class Hook {
55
61
  * @param {string} event name
56
62
  * @param {Array<Any>} args variadic arguments to invoke the handler with
57
63
  */
58
- setStateAndNotify(event, ...args) {
64
+ setStateAndNotify(
65
+ event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
66
+ ...args
67
+ ) {
59
68
  this.state = hookState(event);
60
- this.manager.invokeHandler(event, ...args);
69
+ this.manager.subscriber.invokeHandler(event, ...args);
61
70
  }
62
71
 
63
72
  /**
64
73
  * returns react component of the the hook modal presenter
65
74
  * @returns {React.ComponentType<any>}
66
75
  */
67
- getModalContainer() {
68
- return this.module && this.module.ModalContainer;
76
+ getModalContainer(): HookInterface["module"]["ModalContainer"] | undefined {
77
+ return this.module ? this.module.ModalContainer : undefined;
69
78
  }
70
79
 
71
80
  /**
72
81
  * tells whether the hook should be presented as a screen
73
82
  * @returns {boolean}
74
83
  */
75
- shouldPresentScreenHook() {
76
- return (
84
+ shouldPresentScreenHook(): boolean {
85
+ return !!(
77
86
  (this.screen_id && this.general?.allow_screen_plugin_presentation) ||
78
87
  (this.module && this.module.presentFullScreen) ||
79
88
  (!this.module?.presentFullScreen &&
@@ -87,7 +96,7 @@ export class Hook {
87
96
  * tells whether the hook should be presented as a modal screen
88
97
  * @returns {boolean}
89
98
  */
90
- isModalHook() {
99
+ isModalHook(): boolean {
91
100
  return (
92
101
  this.screen_id &&
93
102
  this.general?.transition_type === HOOKS_TRANSITION_TYPE.MODAL
@@ -99,7 +108,7 @@ export class Hook {
99
108
  * if it doesn't return success
100
109
  * @returns { boolean}
101
110
  */
102
- isFlowBlocker() {
111
+ isFlowBlocker(): boolean {
103
112
  return (
104
113
  (this.general && this.general.is_flow_blocker) ||
105
114
  (this.module && this.module.isFlowBlocker && this.module.isFlowBlocker())
@@ -111,7 +120,7 @@ export class Hook {
111
120
  * @param {object} payload to pass to the hook
112
121
  * @returns { boolean}
113
122
  */
114
- skipHook(payload) {
123
+ skipHook(payload: object): boolean {
115
124
  const _skipHook = R.compose(
116
125
  R.ifElse(isFunction, R.apply(R.__, [payload]), R.F),
117
126
  R.path(["module", "skipHook"])
@@ -133,7 +142,10 @@ export class Hook {
133
142
  * @param {object} payload to pass to the hook
134
143
  * @param {function} next callback to invoke for processing next hook
135
144
  */
136
- execute(payload, next) {
145
+ execute<T extends object>(
146
+ payload: T,
147
+ next: (arg0: { payload: T; success?: boolean }) => void
148
+ ): void {
137
149
  if (this.skipHook(payload)) {
138
150
  next({ payload, success: true });
139
151
 
@@ -152,7 +164,7 @@ export class Hook {
152
164
 
153
165
  this.setStateAndNotify(HOOKS_EVENTS.START_BACKGROUND_HOOK, this);
154
166
 
155
- this.manager.runInBackground(this, payload, next, (_payload) =>
167
+ this.manager.runInBackground(this, payload, next, (_payload: any) =>
156
168
  this.manager.presentScreenHook(this, _payload || payload, next)
157
169
  );
158
170
  } else if (this.shouldPresentScreenHook()) {
@@ -175,7 +187,7 @@ export class Hook {
175
187
  * - AND next hook has the same weight as the current one
176
188
  * @returns {boolean}
177
189
  */
178
- shouldStartNextHook(nextHook) {
190
+ shouldStartNextHook(nextHook: Hook): boolean {
179
191
  return (
180
192
  nextHook &&
181
193
  !this.shouldPresentScreenHook() &&
@@ -12,7 +12,7 @@ export const HOOKS_EVENTS = {
12
12
  CANCEL: "cancel",
13
13
  SUCCESS: "success",
14
14
  COMPLETE: "complete",
15
- };
15
+ } as const;
16
16
 
17
17
  export const HOOKS_TRANSITION_TYPE = {
18
18
  PUSH: "push",
@@ -10,14 +10,72 @@ import { Hook } from "./Hook";
10
10
  import { HOOKS_EVENTS, HOOKS_TYPE } from "./constants";
11
11
 
12
12
  import { hooksManagerLogger } from "./logger";
13
+ import { HookManager, HookManagerArgs } from "./types";
14
+
15
+ /**
16
+ * orders the hooks according to their weight
17
+ * @param {Array<object>} hooks to sort out
18
+ * @returns {Array<object>} sorted hooks
19
+ */
20
+ function orderHooksByWeight(hooks: Hook[]) {
21
+ return R.sortBy(R.compose(Number, R.prop("weight")), hooks);
22
+ }
23
+
24
+ function executeOnNextHook(
25
+ hooks: Hook[],
26
+ payload: object,
27
+ callback: (hookPlugin: Hook, restOfHooks: Hook[], payload: object) => void
28
+ ) {
29
+ const [nextHook, ...restOfHooks] = orderHooksByWeight(hooks);
30
+
31
+ if (nextHook) {
32
+ nextHook.execute(payload, callback(nextHook, restOfHooks, payload));
33
+ }
34
+ }
35
+
36
+ /**
37
+ * tells wether the current river is related to a player plugin, or the default player
38
+ * @param {Object} river
39
+ * @returns {boolean}
40
+ */
41
+ function riverIsPlayer(river, plugins) {
42
+ const { screenType, plugin_type } = river;
43
+
44
+ if (screenType || plugin_type) {
45
+ return screenType === "playable" || plugin_type === "player";
46
+ }
47
+
48
+ const { type } = river;
49
+
50
+ return R.compose(
51
+ R.propEq("type", "player"),
52
+ R.defaultTo({}),
53
+ R.find(R.propEq("identifier", type))
54
+ )(plugins);
55
+ }
56
+
57
+ /**
58
+ * Injects the hooks for the player
59
+ * @param _hookType type of hook
60
+ * @param plugins plugins
61
+ * @returns {Array<Object>}
62
+ */
63
+ function injectPlayerHooks(_hookType: string, plugins): Hook[] {
64
+ const playerhooks: Hook[] = R.compose(
65
+ R.sortBy(R.prop("weight")),
66
+ R.map((plugin) => ({
67
+ identifier: plugin.identifier,
68
+ weight: R.path(["module", "weight"], plugin) || 1,
69
+ })),
70
+ R.filter(R.pathEq(["module", "hasPlayerHook"], true))
71
+ )(plugins);
72
+
73
+ return playerhooks;
74
+ }
13
75
 
14
76
  /**
15
77
  * creates a hooksManager object to handle the hooks process.
16
78
  * it is based on the `subscriber` object
17
- * @param {object} options
18
- * @param {object} rivers map of rivers in the app
19
- * @param {object} targetScreen rivers which we are navigating to
20
- * @param {Array<object>} plugins array of plugins in the app
21
79
  * @returns {object} hooksManager object - see Navigator for usage
22
80
  */
23
81
  export function HooksManager({
@@ -25,7 +83,7 @@ export function HooksManager({
25
83
  targetScreen,
26
84
  plugins,
27
85
  startUpHooksData = {},
28
- }) {
86
+ }: HookManagerArgs): HookManager {
29
87
  hooksManagerLogger.addContext({ targetScreen });
30
88
 
31
89
  function logHookEvent(func, message, data) {
@@ -35,7 +93,8 @@ export function HooksManager({
35
93
  });
36
94
  }
37
95
 
38
- const hooksManager = subscriber();
96
+ const hooksManager: Partial<HookManager> = {};
97
+ hooksManager.subscriber = subscriber();
39
98
 
40
99
  /**
41
100
  * attaches the screen data to the hook object if the hook
@@ -100,15 +159,6 @@ export function HooksManager({
100
159
  };
101
160
  }
102
161
 
103
- /**
104
- * orders the hooks according to their weight
105
- * @param {Array<object>} hooks to sort out
106
- * @returns {Array<object>} sorted hooks
107
- */
108
- function orderHooksByWeight(hooks) {
109
- return R.sortBy(R.compose(Number, R.prop("weight")), hooks);
110
- }
111
-
112
162
  /**
113
163
  * extracts the hooks form the target river. returns null if there are none
114
164
  * if there are hooks, gathers all required data and constructs a Hook object
@@ -117,10 +167,10 @@ export function HooksManager({
117
167
  * @returns {Array<Hooks>} list of hooks to go through
118
168
  */
119
169
  function getHooks(hookType, river) {
120
- const playerhooks = [];
170
+ const playerhooks: Hook[] = [];
121
171
 
122
- if (riverIsPlayer(river)) {
123
- playerhooks.push(...injectPlayerHooks(hookType));
172
+ if (riverIsPlayer(river, plugins)) {
173
+ playerhooks.push(...injectPlayerHooks(hookType, plugins));
124
174
  }
125
175
 
126
176
  let hooks = R.concat(playerhooks, R.pathOr([], ["hooks", hookType], river));
@@ -130,8 +180,10 @@ export function HooksManager({
130
180
  const { startUpHooks, setStartUpHooks } = startUpHooksData;
131
181
 
132
182
  if (startUpHooks && startUpHooks !== "in_process") {
133
- hooks.unshift(...startUpHooks);
134
- setStartUpHooks("in_process");
183
+ if (Array.isArray(startUpHooks)) {
184
+ hooks.unshift(...startUpHooks);
185
+ setStartUpHooks("in_process");
186
+ }
135
187
  }
136
188
 
137
189
  if (!R.length(hooks)) {
@@ -158,45 +210,6 @@ export function HooksManager({
158
210
  )(hooks);
159
211
  }
160
212
 
161
- /**
162
- * tells wether the current river is related to a player plugin, or the default player
163
- * @param {Object} river
164
- * @returns {boolean}
165
- */
166
- function riverIsPlayer(river) {
167
- const { screenType, plugin_type } = river;
168
-
169
- if (screenType || plugin_type) {
170
- return screenType === "playable" || plugin_type === "player";
171
- }
172
-
173
- const { type } = river;
174
-
175
- return R.compose(
176
- R.propEq("type", "player"),
177
- R.defaultTo({}),
178
- R.find(R.propEq("identifier", type))
179
- )(plugins);
180
- }
181
-
182
- /**
183
- * Injects the hooks for the player
184
- * @param {String} hookType type of hook
185
- * @returns {Array<Object>}
186
- */
187
- function injectPlayerHooks(_hookType) {
188
- const playerhooks = R.compose(
189
- R.sortBy(R.prop("weight")),
190
- R.map((plugin) => ({
191
- identifier: plugin.identifier,
192
- weight: R.path(["module", "weight"], plugin) || 1,
193
- })),
194
- R.filter(R.pathEq(["module", "hasPlayerHook"], true))
195
- )(plugins);
196
-
197
- return playerhooks;
198
- }
199
-
200
213
  /**
201
214
  * tells wether the given hook is the last one or not
202
215
  * @param {Hook} hookPlugin
@@ -209,6 +222,32 @@ export function HooksManager({
209
222
  return hookPlugin.lastHook;
210
223
  }
211
224
 
225
+ /**
226
+ * flags a hook as succeeded, and pass hook data along
227
+ * @param {Hook} hookPlugin
228
+ * @param {object} payload returned by the hook plugin
229
+ */
230
+ function completeHook(hookPlugin, payload, callback) {
231
+ logHookEvent(
232
+ hooksManagerLogger.info,
233
+ `completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
234
+ {
235
+ payload,
236
+ hook: hookPlugin,
237
+ }
238
+ );
239
+
240
+ // eslint-disable-next-line
241
+ // TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
242
+ delete payload.getLoginProtocol;
243
+
244
+ hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
245
+ hookPlugin,
246
+ payload,
247
+ callback,
248
+ });
249
+ }
250
+
212
251
  /**
213
252
  * creates the callback to invoke in order to proceed to the next hook
214
253
  * covers the scenarios of failure & flow blocking
@@ -228,9 +267,11 @@ export function HooksManager({
228
267
  success,
229
268
  error,
230
269
  payload = initialPayload,
231
- callback,
270
+ callback: callbackArg,
232
271
  cancelled,
233
272
  }) {
273
+ let callback = callbackArg;
274
+
234
275
  if (error) {
235
276
  logHookEvent(
236
277
  hooksManagerLogger.error,
@@ -301,6 +342,18 @@ export function HooksManager({
301
342
  }
302
343
  );
303
344
 
345
+ if (!callback) {
346
+ logHookEvent(
347
+ hooksManagerLogger.warn,
348
+ `hookCallback: ${hookPlugin["identifier"]} is missing \`callback\`, using hookCallback(default one)`,
349
+ {
350
+ hookPlugin,
351
+ }
352
+ );
353
+
354
+ callback = hookCallback;
355
+ }
356
+
304
357
  hookPlugin.setStateAndNotify(HOOKS_EVENTS.SUCCESS, {
305
358
  hookPlugin,
306
359
  payload,
@@ -309,37 +362,11 @@ export function HooksManager({
309
362
 
310
363
  isLastHook(hookPlugin, restOfHooks)
311
364
  ? completeHook(hookPlugin, payload, callback)
312
- : handleNextHook(restOfHooks, payload);
365
+ : executeOnNextHook(restOfHooks, payload, callback);
313
366
  }
314
367
  };
315
368
  }
316
369
 
317
- /**
318
- * flags a hook as succeeded, and pass hook data along
319
- * @param {Hook} hookPlugin
320
- * @param {object} payload returned by the hook plugin
321
- */
322
- function completeHook(hookPlugin, payload, callback) {
323
- logHookEvent(
324
- hooksManagerLogger.info,
325
- `completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
326
- {
327
- payload,
328
- hook: hookPlugin,
329
- }
330
- );
331
-
332
- // eslint-disable-next-line
333
- // TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
334
- delete payload.getLoginProtocol;
335
-
336
- hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
337
- hookPlugin,
338
- payload,
339
- callback,
340
- });
341
- }
342
-
343
370
  /**
344
371
  * presents a screen hook by triggering an event invoking the handler with
345
372
  * the appropriate route & payload
@@ -376,9 +403,6 @@ export function HooksManager({
376
403
 
377
404
  /**
378
405
  * executes a headless hook
379
- * @param {Hook} hookPlugin to present
380
- * @param {object} payload to pass to the hook module
381
- * @param {function} callback to invoke when the hook is successful
382
406
  */
383
407
  hooksManager.executeHook = function (hookPlugin, payload, callback) {
384
408
  logHookEvent(
@@ -444,30 +468,13 @@ export function HooksManager({
444
468
  }
445
469
  };
446
470
 
447
- /**
448
- * handles the next hook in the list of provided hooks, passing the payload along
449
- * @param {Array<Hook>} hooks to process
450
- * @param {object} payload to pass to the hook
451
- */
452
- function handleNextHook(hooks, payload) {
453
- const [hookPlugin, ...restOfHooks] = orderHooksByWeight(hooks);
454
-
455
- /**
456
- * Commenting out part of the code which is trying to run the next hook
457
- * in parallel - it's not in use, and it's creating unexpected side
458
- * effects
459
- * */
460
-
461
- hookPlugin.execute(payload, hookCallback(hookPlugin, restOfHooks, payload));
462
- }
463
-
464
471
  /**
465
472
  * function exposes on the hooks manager to trigger the handling of the hooks for
466
473
  * the given targetScreen
467
474
  * @param {object} payload to send to the hooks
468
475
  * @returns {object} returns the hooks manager so methods can be chained
469
476
  */
470
- hooksManager.handleHooks = function (payload) {
477
+ hooksManager.handleHooks = function (payload: object) {
471
478
  const preloadHooks = getHooks(HOOKS_TYPE.PRELOAD, targetScreen);
472
479
 
473
480
  if (preloadHooks?.length) {
@@ -482,9 +489,9 @@ export function HooksManager({
482
489
  }
483
490
  );
484
491
 
485
- handleNextHook(preloadHooks, payload);
492
+ executeOnNextHook(preloadHooks, payload, hookCallback);
486
493
  } else {
487
- hooksManager.invokeHandler(HOOKS_EVENTS.COMPLETE, {
494
+ hooksManager.subscriber.invokeHandler(HOOKS_EVENTS.COMPLETE, {
488
495
  hookPlugin: { lastHook: true },
489
496
  payload,
490
497
  });
@@ -493,5 +500,5 @@ export function HooksManager({
493
500
  return hooksManager;
494
501
  };
495
502
 
496
- return hooksManager;
503
+ return hooksManager as HookManager;
497
504
  }
@@ -0,0 +1,116 @@
1
+ import { SubscriberObj } from "../../functionUtils";
2
+ import { HOOKS_EVENTS } from "./constants";
3
+
4
+ export interface HookConfiguration {}
5
+
6
+ /* existing Hook Plugn props: sample */
7
+ interface _HookModulePlugin {
8
+ Component:
9
+ | React.FC<HookPluginProps>
10
+ | React.Component<HookPluginProps, any>
11
+ | React.ReactNode;
12
+ ModalContainer?: React.FC<ModalProps> | React.Component<ModalProps, any>;
13
+ skipHook?: (payload: ZappRiver | ZappEntry) => boolean;
14
+ presentFullScreen: boolean;
15
+ showNavBar?: boolean;
16
+ isFlowBlocker: (() => boolean) | boolean; // narrow this
17
+ hasPlayerHook?: boolean;
18
+ name: string;
19
+ runInBackground?: (
20
+ item: HookPluginProps["payload"],
21
+ callback: hookCallback,
22
+ hookPlugin: HookScreenData,
23
+ presentUI: (payload?: HookPluginProps["payload"]) => void
24
+ ) => any;
25
+ }
26
+
27
+ //* Derived from usage */
28
+ export interface HookModule {
29
+ ModalContainer?: React.ComponentType<any>;
30
+ Component: React.ComponentType<any>;
31
+ presentFullScreen: boolean;
32
+ run?: (
33
+ arg0: unknown,
34
+ callback: () => void,
35
+ configuration: HookConfiguration
36
+ ) => void; // not sure about optional parameter
37
+ hasPlayerHook?: boolean;
38
+ configuration?: HookConfiguration;
39
+ isFlowBlocker: () => boolean;
40
+ skipHook?: (payload?: ZappRiver | ZappEntry) => boolean;
41
+ runInBackground?: (
42
+ arg0: unknown,
43
+ callback: () => void,
44
+ hookPlugin: Hook,
45
+ presentUI: (payload?: HookPluginProps["payload"]) => void
46
+ ) => void;
47
+ name: string;
48
+ showNavBar?: boolean; // unsure
49
+ }
50
+
51
+ export type HookManagerArgs = {
52
+ rivers: Record<string, ZappRiver>;
53
+ plugins: ZappPlugin[];
54
+ targetScreen: ZappRiver;
55
+ startUpHooksData?: {
56
+ startUpHooks?: unknown[] | "in_process";
57
+ setStartUpHooks?: (arg0: string) => void;
58
+ };
59
+ };
60
+
61
+ export interface HookManager {
62
+ subscriber: SubscriberObj;
63
+ presentScreenHook: (
64
+ hook: Hook,
65
+ payload: unknown,
66
+ callback: (...any) => void
67
+ ) => void;
68
+ executeHook: (
69
+ hook: Hook,
70
+ payload: unknown,
71
+ callback: (...any) => void
72
+ ) => void;
73
+ handleHooks: (payload: unknown) => void;
74
+ runInBackground: (
75
+ hook: Hook,
76
+ payload: unknown,
77
+ callback: (...any) => void,
78
+ presentUI: (payload?: HookPluginProps["payload"]) => void
79
+ ) => void;
80
+ }
81
+
82
+ export type HookIniObj = {
83
+ hook: HookModule & {
84
+ module: HookModule;
85
+ general: unknown;
86
+ screen_id?: string;
87
+ identifier?: string;
88
+ weight?: number | string;
89
+ };
90
+ hooks: Hook<any>[];
91
+ manager: HookManager;
92
+ };
93
+
94
+ export interface Hook<T extends HookModule = HookModule> {
95
+ manager: HookManager;
96
+ lastHook: boolean;
97
+ state: number;
98
+ module: T;
99
+ screen_id: string;
100
+ identifier: string;
101
+ configuration: T["configuration"];
102
+ setStateAndNotify(
103
+ event: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS],
104
+ opts: {
105
+ error?: typeof Error;
106
+ route?: string;
107
+ hookPlugin: Hook<T>;
108
+ payload: unknown;
109
+ }
110
+ );
111
+ general?: {
112
+ transition_type: typeof HOOKS_EVENTS[keyof typeof HOOKS_EVENTS];
113
+ allow_screen_plugin_presentation: boolean;
114
+ is_flow_blocker: boolean;
115
+ };
116
+ }