@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.
- package/actionsExecutor/ActionExecutor.ts +16 -9
- package/actionsExecutor/ActionExecutorContext.tsx +74 -9
- package/alertUtils/alert.ts +148 -0
- package/alertUtils/index.ts +1 -148
- package/analyticsUtils/AnalyticPlayerListener.ts +18 -1
- package/analyticsUtils/__tests__/__snapshots__/analyticsManagerNoModule.test.js.snap +9 -9
- package/analyticsUtils/helpers/hooks.ts +1 -1
- package/appUtils/HooksManager/{Hook.js → Hook.ts} +35 -23
- package/appUtils/HooksManager/__tests__/__snapshots__/hook.test.js.snap +10 -8
- package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +693 -0
- package/appUtils/HooksManager/__tests__/hook.test.js +196 -184
- package/appUtils/HooksManager/__tests__/hooksManager.test.js +96 -99
- package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
- package/appUtils/HooksManager/{index.js → index.ts} +121 -112
- package/appUtils/HooksManager/types.ts +119 -0
- package/appUtils/RiverFocusManager/index.js +17 -12
- package/appUtils/accessibilityManager/index.ts +42 -1
- package/appUtils/contextKeysManager/contextResolver.ts +73 -0
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +6 -6
- package/appUtils/focusManager/index.ts +90 -63
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +25 -3
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -3
- package/appUtils/focusManager/utils/enums.ts +4 -0
- package/appUtils/focusManagerAux/utils/index.ts +4 -3
- package/appUtils/{index.js → index.ts} +1 -1
- package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +2 -2
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +4 -4
- package/appUtils/keyCodes/{index.js → index.ts} +2 -0
- package/appUtils/keyCodes/keys/index.ts +3 -0
- package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
- package/appUtils/keyCodes/keys/keys.android.ts +18 -0
- package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
- package/appUtils/keyCodes/keys/keys.ts +15 -0
- package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +4 -0
- package/appUtils/keyCodes/keysByPlatform.ts +8 -0
- package/appUtils/keyInputHandler/KeyInputHandler.ts +68 -0
- package/appUtils/orientationHelper.ts +1 -1
- package/appUtils/platform/const.ts +14 -0
- package/appUtils/platform/platformUtils.ts +17 -15
- package/appUtils/playerManager/index.ts +6 -2
- package/appUtils/playerManager/player.ts +17 -5
- package/appUtils/playerManager/playerFactory.ts +5 -4
- package/appUtils/playerManager/playerNative.ts +3 -2
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +3 -3
- package/arrayUtils/__tests__/__snapshots__/arrayUtils.test.ts.snap +4 -4
- package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
- package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +4 -4
- package/functionUtils/index.ts +15 -11
- package/idleUtils/__tests__/withTimeout$.test.ts +37 -0
- package/idleUtils/index.ts +1 -1
- package/idleUtils/withTimeout.ts +15 -2
- package/logger/const.ts +9 -67
- package/manifestUtils/__tests__/createConfig.test.js +18 -16
- package/modalState/index.ts +1 -5
- package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +6 -6
- package/navigationUtils/__tests__/itemTypes.test.js +2 -2
- package/navigationUtils/__tests__/navigationUtils.test.js +2 -2
- package/navigationUtils/index.ts +14 -5
- package/package.json +3 -2
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -1
- package/reactHooks/cell-click/__tests__/index.test.js +10 -2
- package/reactHooks/cell-click/index.ts +7 -1
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +4 -4
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +20 -13
- package/reactHooks/feed/useFeedLoader.tsx +12 -8
- package/reactHooks/feed/usePipesCacheReset.ts +5 -5
- package/reactHooks/flatList/__tests__/index.test.tsx +30 -21
- package/reactHooks/layout/__tests__/index.test.tsx +10 -10
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +14 -28
- package/reactHooks/navigation/__tests__/index.test.tsx +0 -4
- package/reactHooks/navigation/index.ts +29 -218
- package/reactHooks/navigation/useGetBottomTabBarHeight.ts +12 -0
- package/reactHooks/navigation/useGetNavBarTopBorderWidth.ts +14 -0
- package/reactHooks/navigation/useGetTabBarHeight.ts +12 -0
- package/reactHooks/navigation/useIsScreenActive.ts +17 -0
- package/reactHooks/navigation/useNavigationPluginData.ts +15 -0
- package/reactHooks/navigation/useNavigationType.ts +15 -0
- package/reactHooks/navigation/usePathname.ts +4 -0
- package/reactHooks/navigation/useRoute.ts +100 -0
- package/reactHooks/navigation/useUniqueRouteSuffix.ts +41 -0
- package/reactHooks/player/TVSeekControlller/ISeekController.ts +32 -0
- package/reactHooks/player/TVSeekControlller/LongPressSeekController.ts +71 -0
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +258 -0
- package/reactHooks/player/TVSeekControlller/TapSeekController.ts +53 -0
- package/reactHooks/player/__tests__/{useAutoSeek.test.tsx → useAutoSeek._test.tsx} +2 -3
- package/reactHooks/player/const.ts +0 -4
- package/reactHooks/player/index.ts +0 -6
- package/reactHooks/utils/index.ts +13 -0
- package/reactUtils/__tests__/reactUtils.test.js +10 -28
- package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +19 -19
- package/reactUtils/createContext/__tests__/__snapshots__/index.test.js.snap +2 -2
- package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -3
- package/reactUtils/createContext/__tests__/helpers.test.js +8 -8
- package/reactUtils/index.ts +0 -14
- package/theme/__mocks__/index.ts +4 -0
- package/time/Timer.ts +1 -1
- package/types.ts +1 -0
- package/appUtils/keyCodes/keys.ios.js +0 -46
- package/reactHooks/player/useAutoSeek.tsx +0 -87
- package/reactHooks/player/useSeek.tsx +0 -66
- package/reactHooks/player/useTapSeek.tsx +0 -58
- /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
- /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
- /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
- /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
- /package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +0 -0
- /package/domUtils/{logger.js → logger.ts} +0 -0
- /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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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).
|
|
119
|
-
{ hookPlugin: expect.objectContaining(headlessPlayerHook), payload },
|
|
120
|
-
expect.any(Function)
|
|
121
|
-
);
|
|
119
|
+
expect(successHandler.mock.calls[0]).toMatchSnapshot();
|
|
122
120
|
|
|
123
|
-
expect(completeHandler).
|
|
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
|
-
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
172
|
-
payload,
|
|
173
|
-
hookPlugin: expect.objectContaining(hookScreen),
|
|
174
|
-
callback: expect.any(Function),
|
|
175
|
-
},
|
|
169
|
+
callback: expect.any(Function),
|
|
176
170
|
},
|
|
177
|
-
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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).
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
507
|
+
.on(HOOKS_EVENTS.SUCCESS, successHandler);
|
|
508
|
+
|
|
509
|
+
hooksManager.handleHooks(payload);
|
|
514
510
|
|
|
515
511
|
expect(successHandler).toHaveBeenCalledTimes(3);
|
|
516
512
|
|
|
517
|
-
expect(successHandler).
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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).
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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).
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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).
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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(
|
|
@@ -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 =
|
|
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
|
-
|
|
134
|
-
|
|
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
|
|
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
|
-
:
|
|
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
|
-
|
|
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
|
}
|