@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.
- package/analyticsUtils/AnalyticsEvents/index.ts +7 -0
- package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
- package/analyticsUtils/events.ts +6 -0
- package/analyticsUtils/index.tsx +6 -0
- package/appUtils/HooksManager/{Hook.js → Hook.ts} +35 -23
- package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
- package/appUtils/HooksManager/{index.js → index.ts} +118 -111
- package/appUtils/HooksManager/types.ts +116 -0
- package/appUtils/RiverFocusManager/index.js +17 -12
- package/appUtils/accessibilityManager/const.ts +50 -0
- package/appUtils/accessibilityManager/hooks.ts +31 -0
- package/appUtils/accessibilityManager/index.ts +150 -0
- package/appUtils/accessibilityManager/logger.ts +5 -0
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
- package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
- package/appUtils/focusManager/__tests__/index.test.ts +2 -3
- package/appUtils/focusManager/index.ts +76 -57
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +2 -3
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +76 -47
- package/appUtils/focusManager/utils/index.ts +100 -0
- package/appUtils/focusManagerAux/index.ts +76 -0
- package/appUtils/focusManagerAux/utils/index.ts +100 -0
- package/appUtils/{index.js → index.ts} +2 -0
- 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/{keys.web.js → keys/keys.web.ts} +8 -0
- package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +11 -1
- package/appUtils/platform/const.ts +25 -0
- package/appUtils/platform/index.ts +3 -0
- package/appUtils/platform/platformUtils.ts +171 -0
- package/appUtils/playerManager/conts.ts +1 -0
- package/appUtils/playerManager/index.ts +11 -5
- package/appUtils/playerManager/nativePlayerManager.ts +12 -0
- package/appUtils/playerManager/player.ts +9 -3
- package/appUtils/playerManager/playerNative.ts +5 -14
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +1 -0
- package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
- package/arrayUtils/index.ts +5 -0
- package/booleanUtils/index.ts +4 -4
- package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
- package/functionUtils/index.ts +15 -11
- package/keyboardState/index.ts +0 -0
- package/modalState/index.ts +1 -5
- package/navigationUtils/index.ts +62 -5
- package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
- package/numberUtils/index.ts +5 -18
- package/package.json +2 -2
- package/pluginUtils/index.ts +9 -0
- package/reactHooks/cell-click/__tests__/index.test.js +9 -5
- package/reactHooks/cell-click/index.ts +11 -11
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
- package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
- package/reactHooks/feed/useFeedRefresh.tsx +9 -7
- package/reactHooks/navigation/index.ts +51 -11
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
- package/reactHooks/screen/index.ts +2 -0
- package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
- package/reactHooks/screen/useScreenContext.ts +1 -2
- package/reactUtils/index.ts +91 -0
- package/appUtils/focusManager/FocusableEvents.ts +0 -8
- package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
- package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
- package/appUtils/keyCodes/keys.ios.js +0 -46
- /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/{localizationsHelper.js → localizationsHelper.ts} +0 -0
- /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
|
+
};
|
package/analyticsUtils/events.ts
CHANGED
|
@@ -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 = {
|
package/analyticsUtils/index.tsx
CHANGED
|
@@ -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
|
|
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
|
|
34
|
+
* Representation of a hook plugin
|
|
32
35
|
*/
|
|
33
|
-
export class Hook {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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(
|
|
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
|
|
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
|
|
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() &&
|
|
@@ -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,
|
|
@@ -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
|
-
:
|
|
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
|
-
|
|
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
|
+
}
|