@applicaster/zapp-react-native-utils 13.0.0-rc.2 → 13.0.0-rc.21

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 (109) hide show
  1. package/actionsExecutor/ActionExecutor.ts +16 -9
  2. package/actionsExecutor/ActionExecutorContext.tsx +74 -9
  3. package/alertUtils/alert.ts +148 -0
  4. package/alertUtils/index.ts +1 -148
  5. package/analyticsUtils/AnalyticPlayerListener.ts +18 -1
  6. package/analyticsUtils/__tests__/__snapshots__/analyticsManagerNoModule.test.js.snap +9 -9
  7. package/analyticsUtils/helpers/hooks.ts +1 -1
  8. package/appUtils/HooksManager/{Hook.js → Hook.ts} +35 -23
  9. package/appUtils/HooksManager/__tests__/__snapshots__/hook.test.js.snap +10 -8
  10. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +693 -0
  11. package/appUtils/HooksManager/__tests__/hook.test.js +196 -184
  12. package/appUtils/HooksManager/__tests__/hooksManager.test.js +96 -99
  13. package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
  14. package/appUtils/HooksManager/{index.js → index.ts} +121 -112
  15. package/appUtils/HooksManager/types.ts +119 -0
  16. package/appUtils/RiverFocusManager/index.js +17 -12
  17. package/appUtils/accessibilityManager/index.ts +42 -1
  18. package/appUtils/contextKeysManager/contextResolver.ts +73 -0
  19. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +6 -6
  20. package/appUtils/focusManager/index.ts +90 -63
  21. package/appUtils/focusManager/treeDataStructure/Tree/index.js +25 -3
  22. package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -3
  23. package/appUtils/focusManager/utils/enums.ts +4 -0
  24. package/appUtils/focusManagerAux/utils/index.ts +4 -3
  25. package/appUtils/{index.js → index.ts} +1 -1
  26. package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +2 -2
  27. package/appUtils/keyCodes/__tests__/keyCodes.test.js +4 -4
  28. package/appUtils/keyCodes/{index.js → index.ts} +2 -0
  29. package/appUtils/keyCodes/keys/index.ts +3 -0
  30. package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
  31. package/appUtils/keyCodes/keys/keys.android.ts +18 -0
  32. package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
  33. package/appUtils/keyCodes/keys/keys.ts +15 -0
  34. package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +4 -0
  35. package/appUtils/keyCodes/keysByPlatform.ts +8 -0
  36. package/appUtils/keyInputHandler/KeyInputHandler.ts +68 -0
  37. package/appUtils/orientationHelper.ts +1 -1
  38. package/appUtils/platform/const.ts +14 -0
  39. package/appUtils/platform/platformUtils.ts +17 -15
  40. package/appUtils/playerManager/index.ts +6 -2
  41. package/appUtils/playerManager/player.ts +17 -5
  42. package/appUtils/playerManager/playerFactory.ts +5 -4
  43. package/appUtils/playerManager/playerNative.ts +3 -2
  44. package/appUtils/playerManager/usePlayerControllerSetup.tsx +3 -3
  45. package/arrayUtils/__tests__/__snapshots__/arrayUtils.test.ts.snap +4 -4
  46. package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
  47. package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +4 -4
  48. package/functionUtils/index.ts +15 -11
  49. package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
  50. package/idleUtils/index.ts +1 -1
  51. package/idleUtils/withTimeout.ts +15 -2
  52. package/logger/const.ts +9 -67
  53. package/manifestUtils/__tests__/createConfig.test.js +18 -16
  54. package/modalState/index.ts +1 -5
  55. package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +6 -6
  56. package/navigationUtils/__tests__/itemTypes.test.js +2 -2
  57. package/navigationUtils/__tests__/navigationUtils.test.js +2 -2
  58. package/navigationUtils/index.ts +14 -5
  59. package/package.json +3 -2
  60. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  61. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -1
  62. package/reactHooks/cell-click/__tests__/index.test.js +10 -2
  63. package/reactHooks/cell-click/index.ts +7 -1
  64. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +4 -4
  65. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +20 -13
  66. package/reactHooks/feed/useFeedLoader.tsx +12 -8
  67. package/reactHooks/feed/usePipesCacheReset.ts +5 -5
  68. package/reactHooks/flatList/__tests__/index.test.tsx +30 -21
  69. package/reactHooks/layout/__tests__/index.test.tsx +10 -10
  70. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +14 -28
  71. package/reactHooks/navigation/__tests__/index.test.tsx +0 -4
  72. package/reactHooks/navigation/index.ts +29 -218
  73. package/reactHooks/navigation/useGetBottomTabBarHeight.ts +12 -0
  74. package/reactHooks/navigation/useGetNavBarTopBorderWidth.ts +14 -0
  75. package/reactHooks/navigation/useGetTabBarHeight.ts +12 -0
  76. package/reactHooks/navigation/useIsScreenActive.ts +17 -0
  77. package/reactHooks/navigation/useNavigationPluginData.ts +15 -0
  78. package/reactHooks/navigation/useNavigationType.ts +15 -0
  79. package/reactHooks/navigation/usePathname.ts +4 -0
  80. package/reactHooks/navigation/useRoute.ts +100 -0
  81. package/reactHooks/navigation/useUniqueRouteSuffix.ts +41 -0
  82. package/reactHooks/player/TVSeekControlller/ISeekController.ts +32 -0
  83. package/reactHooks/player/TVSeekControlller/LongPressSeekController.ts +71 -0
  84. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +258 -0
  85. package/reactHooks/player/TVSeekControlller/TapSeekController.ts +53 -0
  86. package/reactHooks/player/__tests__/{useAutoSeek.test.tsx → useAutoSeek._test.tsx} +2 -3
  87. package/reactHooks/player/const.ts +0 -4
  88. package/reactHooks/player/index.ts +0 -6
  89. package/reactHooks/utils/index.ts +13 -0
  90. package/reactUtils/__tests__/reactUtils.test.js +10 -28
  91. package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +19 -19
  92. package/reactUtils/createContext/__tests__/__snapshots__/index.test.js.snap +2 -2
  93. package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -3
  94. package/reactUtils/createContext/__tests__/helpers.test.js +8 -8
  95. package/reactUtils/index.ts +0 -14
  96. package/theme/__mocks__/index.ts +4 -0
  97. package/time/Timer.ts +1 -1
  98. package/types.ts +1 -0
  99. package/appUtils/keyCodes/keys.ios.js +0 -46
  100. package/reactHooks/player/useAutoSeek.tsx +0 -87
  101. package/reactHooks/player/useSeek.tsx +0 -66
  102. package/reactHooks/player/useTapSeek.tsx +0 -58
  103. /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
  104. /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
  105. /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
  106. /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
  107. /package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +0 -0
  108. /package/domUtils/{logger.js → logger.ts} +0 -0
  109. /package/reactHooks/player/__tests__/{useTapSeek.test.ts → useTapSeek._test.ts} +0 -0
@@ -62,9 +62,9 @@ describe("HooksManager", () => {
62
62
  const successHandler = jest.fn();
63
63
 
64
64
  it("invokes the success handler directly", () => {
65
- hooksManager
66
- .on(HOOKS_EVENTS.COMPLETE, successHandler)
67
- .handleHooks(payload);
65
+ hooksManager.subscriber.on(HOOKS_EVENTS.COMPLETE, successHandler);
66
+
67
+ hooksManager.handleHooks(payload);
68
68
 
69
69
  expect(successHandler).toHaveBeenCalledTimes(1);
70
70
 
@@ -103,11 +103,12 @@ describe("HooksManager", () => {
103
103
  const presentScreenHandler = jest.fn();
104
104
 
105
105
  it("executes the player hook", () => {
106
- hooksManager
106
+ hooksManager.subscriber
107
107
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
108
108
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
109
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
110
- .handleHooks(payload);
109
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
110
+
111
+ hooksManager.handleHooks(payload);
111
112
 
112
113
  expect(headlessPlayerHook.module.run).toHaveBeenCalledWith(
113
114
  payload,
@@ -115,20 +116,14 @@ describe("HooksManager", () => {
115
116
  headlessPlayerHook.configuration
116
117
  );
117
118
 
118
- expect(successHandler).toHaveBeenCalledWith(
119
- { hookPlugin: expect.objectContaining(headlessPlayerHook), payload },
120
- expect.any(Function)
121
- );
119
+ expect(successHandler.mock.calls[0]).toMatchSnapshot();
122
120
 
123
- expect(completeHandler).toHaveBeenCalledWith(
124
- { hookPlugin: expect.objectContaining(headlessPlayerHook), payload },
125
- expect.any(Function)
126
- );
121
+ expect(completeHandler.mock.calls[0]).toMatchSnapshot();
127
122
  });
128
123
  });
129
124
 
130
125
  describe("when there are preload hooks", () => {
131
- describe("hook with screen", () => {
126
+ it("hook with screen: executes", () => {
132
127
  const hookScreenId = "6e15fcbf-9414-4ea8-b7db-a287593ab6bd";
133
128
  const pluginScreenId = "1bb8ad39-a42e-4096-a134-56aadbd35c83";
134
129
 
@@ -157,36 +152,29 @@ describe("HooksManager", () => {
157
152
  }
158
153
  );
159
154
 
160
- it("executes the hook", () => {
161
- hooksManager
162
- .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
163
- .on(HOOKS_EVENTS.SUCCESS, successHandler)
164
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
165
- .handleHooks(payload);
155
+ hooksManager.subscriber
156
+ .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
157
+ .on(HOOKS_EVENTS.SUCCESS, successHandler)
158
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
166
159
 
167
- expect(presentScreenHandler).toHaveBeenCalledWith(
168
- {
169
- route: `/hooks/${pluginScreenId}`,
160
+ hooksManager.handleHooks(payload);
161
+
162
+ expect(presentScreenHandler).toHaveBeenCalledWith(
163
+ {
164
+ route: `/hooks/${pluginScreenId}`,
165
+ hookPlugin: expect.objectContaining(hookScreen),
166
+ payload: {
167
+ payload,
170
168
  hookPlugin: expect.objectContaining(hookScreen),
171
- payload: {
172
- payload,
173
- hookPlugin: expect.objectContaining(hookScreen),
174
- callback: expect.any(Function),
175
- },
169
+ callback: expect.any(Function),
176
170
  },
177
- expect.any(Function)
178
- );
179
-
180
- expect(successHandler).toHaveBeenCalledWith(
181
- { payload, hookPlugin: expect.objectContaining(hookScreen) },
182
- expect.any(Function)
183
- );
184
-
185
- expect(completeHandler).toHaveBeenCalledWith(
186
- { payload, hookPlugin: expect.objectContaining(hookScreen) },
187
- expect.any(Function)
188
- );
189
- });
171
+ },
172
+ expect.any(Function)
173
+ );
174
+
175
+ expect(successHandler.mock.calls[0]).toMatchSnapshot();
176
+
177
+ expect(completeHandler.mock.calls[0]).toMatchSnapshot();
190
178
  });
191
179
  });
192
180
 
@@ -226,11 +214,12 @@ describe("HooksManager", () => {
226
214
  });
227
215
 
228
216
  it("executes the hook", () => {
229
- hooksManager
217
+ hooksManager.subscriber
230
218
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
231
219
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
232
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
233
- .handleHooks(payload);
220
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
221
+
222
+ hooksManager.handleHooks(payload);
234
223
 
235
224
  expect(presentScreenHandler).toHaveBeenCalledTimes(2);
236
225
 
@@ -341,12 +330,13 @@ describe("HooksManager", () => {
341
330
  );
342
331
 
343
332
  it("stops the flow", () => {
344
- hooksManager
333
+ hooksManager.subscriber
345
334
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, presentScreenHandler)
346
335
  .on(HOOKS_EVENTS.CANCEL, cancelHandler)
347
336
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
348
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
349
- .handleHooks(payload);
337
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
338
+
339
+ hooksManager.handleHooks(payload);
350
340
 
351
341
  expect(cancelHandler).toHaveBeenCalledWith(
352
342
  { hookPlugin: expect.any(Object), payload },
@@ -370,25 +360,28 @@ describe("HooksManager", () => {
370
360
  const payload = { foo: "bar" };
371
361
 
372
362
  it("executes the hook", () => {
373
- hooksManager
363
+ hooksManager.subscriber
374
364
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
375
- .on(HOOKS_EVENTS.COMPLETE, completeHandler)
376
- .handleHooks(payload);
365
+ .on(HOOKS_EVENTS.COMPLETE, completeHandler);
377
366
 
378
- expect(successHandler).toHaveBeenCalledWith(
379
- {
380
- payload: { ...payload, identifier: "hook_plugin" },
381
- hookPlugin: expect.objectContaining(hookPlugin),
382
- },
383
- expect.any(Function)
367
+ hooksManager.handleHooks(payload);
368
+
369
+ expect(successHandler.mock.calls[0][0].payload).toMatchObject({
370
+ ...payload,
371
+ identifier: "hook_plugin",
372
+ });
373
+
374
+ expect(successHandler.mock.calls[0][0].hookPlugin).toMatchObject(
375
+ hookPlugin
384
376
  );
385
377
 
386
- expect(completeHandler).toHaveBeenCalledWith(
387
- {
388
- payload: { ...payload, identifier: "hook_plugin" },
389
- hookPlugin: expect.objectContaining(hookPlugin),
390
- },
391
- expect.any(Function)
378
+ expect(completeHandler.mock.calls[0][0].payload).toMatchObject({
379
+ ...payload,
380
+ identifier: "hook_plugin",
381
+ });
382
+
383
+ expect(completeHandler.mock.calls[0][0].hookPlugin).toMatchObject(
384
+ hookPlugin
392
385
  );
393
386
  });
394
387
  });
@@ -410,11 +403,12 @@ describe("HooksManager", () => {
410
403
  const hooksManager = HooksManager({ rivers, targetScreen, plugins });
411
404
 
412
405
  it("invokes the error handler but not the success handler", () => {
413
- hooksManager
406
+ hooksManager.subscriber
414
407
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
415
408
  .on(HOOKS_EVENTS.COMPLETE, completeHandler)
416
- .on(HOOKS_EVENTS.ERROR, errorHandler)
417
- .handleHooks(payload);
409
+ .on(HOOKS_EVENTS.ERROR, errorHandler);
410
+
411
+ hooksManager.handleHooks(payload);
418
412
 
419
413
  expect(successHandler).not.toHaveBeenCalled();
420
414
 
@@ -447,12 +441,13 @@ describe("HooksManager", () => {
447
441
  const hooksManager = HooksManager({ rivers, targetScreen, plugins });
448
442
 
449
443
  it("invokes the error handler, and stops the flow", () => {
450
- hooksManager
444
+ hooksManager.subscriber
451
445
  .on(HOOKS_EVENTS.SUCCESS, successHandler)
452
446
  .on(HOOKS_EVENTS.COMPLETE, completeHandler)
453
447
  .on(HOOKS_EVENTS.ERROR, errorHandler)
454
- .on(HOOKS_EVENTS.CANCEL, cancelHandler)
455
- .handleHooks(payload);
448
+ .on(HOOKS_EVENTS.CANCEL, cancelHandler);
449
+
450
+ hooksManager.handleHooks(payload);
456
451
 
457
452
  expect(errorHandler).toHaveBeenCalledWith(
458
453
  {
@@ -507,48 +502,50 @@ describe("HooksManager", () => {
507
502
  const hooksManager = HooksManager({ rivers, targetScreen, plugins });
508
503
 
509
504
  it("executes the hook", () => {
510
- hooksManager
505
+ hooksManager.subscriber
511
506
  .on(HOOKS_EVENTS.COMPLETE, completeHandler)
512
- .on(HOOKS_EVENTS.SUCCESS, successHandler)
513
- .handleHooks(payload);
507
+ .on(HOOKS_EVENTS.SUCCESS, successHandler);
508
+
509
+ hooksManager.handleHooks(payload);
514
510
 
515
511
  expect(successHandler).toHaveBeenCalledTimes(3);
516
512
 
517
- expect(successHandler).toHaveBeenNthCalledWith(
518
- 1,
519
- {
520
- payload: { ...payload, identifier: "hook_plugin" },
521
- hookPlugin: expect.objectContaining(hookPlugin),
522
- },
523
- expect.any(Function)
513
+ expect(successHandler.mock.calls[0][0].payload).toMatchObject({
514
+ ...payload,
515
+ identifier: "hook_plugin",
516
+ });
517
+
518
+ expect(successHandler.mock.calls[0][0].hookPlugin).toMatchObject(
519
+ hookPlugin
524
520
  );
525
521
 
526
- expect(successHandler).toHaveBeenNthCalledWith(
527
- 2,
528
- {
529
- payload: { ...payload, identifier: "hook_plugin_2" },
530
- hookPlugin: expect.objectContaining(hookPlugin2),
531
- },
532
- expect.any(Function)
522
+ expect(successHandler.mock.calls[1][0].payload).toMatchObject({
523
+ ...payload,
524
+ identifier: "hook_plugin_2",
525
+ });
526
+
527
+ expect(successHandler.mock.calls[1][0].hookPlugin).toMatchObject(
528
+ hookPlugin2
533
529
  );
534
530
 
535
- expect(successHandler).toHaveBeenNthCalledWith(
536
- 3,
537
- {
538
- payload: { ...payload, identifier: "hook_plugin_3" },
539
- hookPlugin: expect.objectContaining(hookPlugin3),
540
- },
541
- expect.any(Function)
531
+ expect(successHandler.mock.calls[2][0].payload).toMatchObject({
532
+ ...payload,
533
+ identifier: "hook_plugin_3",
534
+ });
535
+
536
+ expect(successHandler.mock.calls[2][0].hookPlugin).toMatchObject(
537
+ hookPlugin3
542
538
  );
543
539
 
544
540
  expect(completeHandler).toHaveBeenCalledTimes(1);
545
541
 
546
- expect(completeHandler).toHaveBeenCalledWith(
547
- {
548
- payload: { ...payload, identifier: "hook_plugin_3" },
549
- hookPlugin: expect.objectContaining(hookPlugin3),
550
- },
551
- expect.any(Function)
542
+ expect(completeHandler.mock.calls[0][0].payload).toMatchObject({
543
+ ...payload,
544
+ identifier: "hook_plugin_3",
545
+ });
546
+
547
+ expect(completeHandler.mock.calls[0][0].hookPlugin).toMatchObject(
548
+ hookPlugin3
552
549
  );
553
550
 
554
551
  expect(hookPlugin.module.run).toHaveBeenCalledWith(
@@ -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,
@@ -272,7 +313,9 @@ export function HooksManager({
272
313
  const isHookInHomescreen = payload?.home;
273
314
 
274
315
  const isHookFlowBlocker =
275
- hookPlugin?.module?.isFlowBlocker?.() ?? false;
316
+ typeof hookPlugin?.module?.isFlowBlocker === "function"
317
+ ? hookPlugin?.module?.isFlowBlocker()
318
+ : hookPlugin?.module?.isFlowBlocker;
276
319
 
277
320
  // TODO: We technically need to also support the case where there is more than one hook in the stack,
278
321
  // if needed we could add differentiation explicit user cancellation (when we should go to background) and other types of cancellation
@@ -301,6 +344,18 @@ export function HooksManager({
301
344
  }
302
345
  );
303
346
 
347
+ if (!callback) {
348
+ logHookEvent(
349
+ hooksManagerLogger.warn,
350
+ `hookCallback: ${hookPlugin["identifier"]} is missing \`callback\`, using hookCallback(default one)`,
351
+ {
352
+ hookPlugin,
353
+ }
354
+ );
355
+
356
+ callback = hookCallback;
357
+ }
358
+
304
359
  hookPlugin.setStateAndNotify(HOOKS_EVENTS.SUCCESS, {
305
360
  hookPlugin,
306
361
  payload,
@@ -309,37 +364,11 @@ export function HooksManager({
309
364
 
310
365
  isLastHook(hookPlugin, restOfHooks)
311
366
  ? completeHook(hookPlugin, payload, callback)
312
- : handleNextHook(restOfHooks, payload);
367
+ : executeOnNextHook(restOfHooks, payload, callback);
313
368
  }
314
369
  };
315
370
  }
316
371
 
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
372
  /**
344
373
  * presents a screen hook by triggering an event invoking the handler with
345
374
  * the appropriate route & payload
@@ -376,9 +405,6 @@ export function HooksManager({
376
405
 
377
406
  /**
378
407
  * 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
408
  */
383
409
  hooksManager.executeHook = function (hookPlugin, payload, callback) {
384
410
  logHookEvent(
@@ -444,30 +470,13 @@ export function HooksManager({
444
470
  }
445
471
  };
446
472
 
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
473
  /**
465
474
  * function exposes on the hooks manager to trigger the handling of the hooks for
466
475
  * the given targetScreen
467
476
  * @param {object} payload to send to the hooks
468
477
  * @returns {object} returns the hooks manager so methods can be chained
469
478
  */
470
- hooksManager.handleHooks = function (payload) {
479
+ hooksManager.handleHooks = function (payload: object) {
471
480
  const preloadHooks = getHooks(HOOKS_TYPE.PRELOAD, targetScreen);
472
481
 
473
482
  if (preloadHooks?.length) {
@@ -482,9 +491,9 @@ export function HooksManager({
482
491
  }
483
492
  );
484
493
 
485
- handleNextHook(preloadHooks, payload);
494
+ executeOnNextHook(preloadHooks, payload, hookCallback);
486
495
  } else {
487
- hooksManager.invokeHandler(HOOKS_EVENTS.COMPLETE, {
496
+ hooksManager.subscriber.invokeHandler(HOOKS_EVENTS.COMPLETE, {
488
497
  hookPlugin: { lastHook: true },
489
498
  payload,
490
499
  });
@@ -493,5 +502,5 @@ export function HooksManager({
493
502
  return hooksManager;
494
503
  };
495
504
 
496
- return hooksManager;
505
+ return hooksManager as HookManager;
497
506
  }