@applicaster/zapp-react-native-utils 12.0.0-alpha.5035843303 → 12.0.0-alpha.5050333009
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/ActionExecutorContext.tsx +16 -8
- package/analyticsUtils/AnalyticsEvents/index.ts +13 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
- package/analyticsUtils/__tests__/analyticsManager.test.js +75 -73
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +12 -0
- package/analyticsUtils/helpers/hooks.ts +1 -1
- package/analyticsUtils/index.tsx +12 -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} +121 -112
- 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 -38
- 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/__tests__/__snapshots__/keyCodes.test.js.snap +1 -1
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +80 -85
- 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} +9 -0
- package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +11 -1
- package/appUtils/orientationHelper.ts +1 -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/OverlayObserver/OverlaysObserver.ts +53 -0
- package/appUtils/playerManager/conts.ts +5 -0
- package/appUtils/playerManager/index.ts +11 -5
- package/appUtils/playerManager/nativePlayerManager.ts +12 -0
- package/appUtils/playerManager/player.ts +48 -7
- package/appUtils/playerManager/playerFactory.ts +15 -1
- package/appUtils/playerManager/playerNative.ts +40 -14
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +7 -1
- package/appUtils/playerManager/usePlayerState.tsx +13 -1
- package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +50 -0
- package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
- package/arrayUtils/index.ts +5 -0
- package/booleanUtils/index.ts +4 -4
- package/cellUtils/__tests__/cellUtils.test.ts +48 -0
- package/cellUtils/__tests__/fixtures.ts +13 -0
- package/cellUtils/index.ts +40 -2
- package/dateUtils/index.ts +11 -0
- package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
- package/focusManager/index.ts +1 -1
- package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +2 -2
- package/functionUtils/__tests__/functionUtils.test.js +244 -248
- package/functionUtils/index.ts +15 -11
- package/headersUtils/index.ts +1 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/keyboardState/index.ts +0 -0
- package/localizationUtils/__tests__/localizationUtils.test.ts +78 -55
- package/localizationUtils/index.ts +13 -19
- package/logger/index.ts +1 -1
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +10 -1
- package/manifestUtils/index.js +5 -1
- package/manifestUtils/secondaryImage/index.js +18 -15
- package/modalState/index.ts +53 -0
- package/navigationUtils/index.ts +118 -12
- package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
- package/numberUtils/index.ts +9 -18
- package/package.json +3 -2
- package/playerUtils/configurationGenerator.ts +11 -1
- package/pluginUtils/index.ts +20 -7
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +2 -0
- package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +18 -1
- package/reactHooks/cell-click/__tests__/index.test.js +16 -3
- package/reactHooks/cell-click/index.ts +14 -14
- package/reactHooks/device/index.ts +0 -1
- package/reactHooks/device/useIsTablet.tsx +28 -3
- package/reactHooks/device/useMemoizedIsTablet.ts +1 -1
- package/reactHooks/device/useOrientation.tsx +3 -1
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
- package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
- package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
- package/reactHooks/feed/useFeedRefresh.tsx +9 -7
- package/reactHooks/feed/useInflatedUrl.ts +44 -15
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -9
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +66 -59
- package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
- package/reactHooks/layout/index.ts +2 -1
- package/reactHooks/layout/types/index.ts +2 -0
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +11 -16
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +12 -14
- package/reactHooks/layout/useDimensions/useDimensions.ts +13 -7
- package/reactHooks/navigation/__mocks__/index.ts +15 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +7 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +240 -81
- package/reactHooks/navigation/index.ts +246 -84
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +3 -1
- package/reactHooks/screen/__mocks__/useScreenContext.ts +3 -1
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
- package/reactHooks/screen/index.ts +4 -0
- package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
- package/reactHooks/screen/useScreenContext.ts +4 -4
- package/reactHooks/screen/useScreenData.ts +1 -1
- package/reactHooks/screen/useTargetScreenData.ts +7 -0
- package/reactHooks/state/useRivers.ts +3 -1
- package/reactHooks/useListenEventBusEvent.ts +6 -15
- package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +10 -9
- package/reactUtils/index.ts +91 -0
- package/riverComponetsMeasurementProvider/index.tsx +2 -2
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +38 -23
- package/types.ts +4 -0
- package/zappFrameworkUtils/loginPluginUtils.ts +12 -2
- 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/reactHooks/device/useIsTablet.android.tsx +0 -14
- package/reactHooks/device/useIsTablet.ios.tsx +0 -7
- package/reactHooks/device/useIsTablet.web.tsx +0 -3
- /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
|
@@ -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,
|
|
@@ -270,7 +311,9 @@ export function HooksManager({
|
|
|
270
311
|
});
|
|
271
312
|
|
|
272
313
|
const isHookInHomescreen = payload?.home;
|
|
273
|
-
|
|
314
|
+
|
|
315
|
+
const isHookFlowBlocker =
|
|
316
|
+
hookPlugin?.module?.isFlowBlocker?.() ?? false;
|
|
274
317
|
|
|
275
318
|
// TODO: We technically need to also support the case where there is more than one hook in the stack,
|
|
276
319
|
// if needed we could add differentiation explicit user cancellation (when we should go to background) and other types of cancellation
|
|
@@ -299,6 +342,18 @@ export function HooksManager({
|
|
|
299
342
|
}
|
|
300
343
|
);
|
|
301
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
|
+
|
|
302
357
|
hookPlugin.setStateAndNotify(HOOKS_EVENTS.SUCCESS, {
|
|
303
358
|
hookPlugin,
|
|
304
359
|
payload,
|
|
@@ -307,37 +362,11 @@ export function HooksManager({
|
|
|
307
362
|
|
|
308
363
|
isLastHook(hookPlugin, restOfHooks)
|
|
309
364
|
? completeHook(hookPlugin, payload, callback)
|
|
310
|
-
:
|
|
365
|
+
: executeOnNextHook(restOfHooks, payload, callback);
|
|
311
366
|
}
|
|
312
367
|
};
|
|
313
368
|
}
|
|
314
369
|
|
|
315
|
-
/**
|
|
316
|
-
* flags a hook as succeeded, and pass hook data along
|
|
317
|
-
* @param {Hook} hookPlugin
|
|
318
|
-
* @param {object} payload returned by the hook plugin
|
|
319
|
-
*/
|
|
320
|
-
function completeHook(hookPlugin, payload, callback) {
|
|
321
|
-
logHookEvent(
|
|
322
|
-
hooksManagerLogger.info,
|
|
323
|
-
`completeHook: hook sequence completed successfully: ${hookPlugin["identifier"]}`,
|
|
324
|
-
{
|
|
325
|
-
payload,
|
|
326
|
-
hook: hookPlugin,
|
|
327
|
-
}
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
// eslint-disable-next-line
|
|
331
|
-
// TODO: Temporary hack to pass getLoginProtocol to other plugins to refresh in case token expired, need be deleted later
|
|
332
|
-
delete payload.getLoginProtocol;
|
|
333
|
-
|
|
334
|
-
hookPlugin.setStateAndNotify(HOOKS_EVENTS.COMPLETE, {
|
|
335
|
-
hookPlugin,
|
|
336
|
-
payload,
|
|
337
|
-
callback,
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
|
|
341
370
|
/**
|
|
342
371
|
* presents a screen hook by triggering an event invoking the handler with
|
|
343
372
|
* the appropriate route & payload
|
|
@@ -374,9 +403,6 @@ export function HooksManager({
|
|
|
374
403
|
|
|
375
404
|
/**
|
|
376
405
|
* executes a headless hook
|
|
377
|
-
* @param {Hook} hookPlugin to present
|
|
378
|
-
* @param {object} payload to pass to the hook module
|
|
379
|
-
* @param {function} callback to invoke when the hook is successful
|
|
380
406
|
*/
|
|
381
407
|
hooksManager.executeHook = function (hookPlugin, payload, callback) {
|
|
382
408
|
logHookEvent(
|
|
@@ -442,30 +468,13 @@ export function HooksManager({
|
|
|
442
468
|
}
|
|
443
469
|
};
|
|
444
470
|
|
|
445
|
-
/**
|
|
446
|
-
* handles the next hook in the list of provided hooks, passing the payload along
|
|
447
|
-
* @param {Array<Hook>} hooks to process
|
|
448
|
-
* @param {object} payload to pass to the hook
|
|
449
|
-
*/
|
|
450
|
-
function handleNextHook(hooks, payload) {
|
|
451
|
-
const [hookPlugin, ...restOfHooks] = orderHooksByWeight(hooks);
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Commenting out part of the code which is trying to run the next hook
|
|
455
|
-
* in parallel - it's not in use, and it's creating unexpected side
|
|
456
|
-
* effects
|
|
457
|
-
* */
|
|
458
|
-
|
|
459
|
-
hookPlugin.execute(payload, hookCallback(hookPlugin, restOfHooks, payload));
|
|
460
|
-
}
|
|
461
|
-
|
|
462
471
|
/**
|
|
463
472
|
* function exposes on the hooks manager to trigger the handling of the hooks for
|
|
464
473
|
* the given targetScreen
|
|
465
474
|
* @param {object} payload to send to the hooks
|
|
466
475
|
* @returns {object} returns the hooks manager so methods can be chained
|
|
467
476
|
*/
|
|
468
|
-
hooksManager.handleHooks = function (payload) {
|
|
477
|
+
hooksManager.handleHooks = function (payload: object) {
|
|
469
478
|
const preloadHooks = getHooks(HOOKS_TYPE.PRELOAD, targetScreen);
|
|
470
479
|
|
|
471
480
|
if (preloadHooks?.length) {
|
|
@@ -480,9 +489,9 @@ export function HooksManager({
|
|
|
480
489
|
}
|
|
481
490
|
);
|
|
482
491
|
|
|
483
|
-
|
|
492
|
+
executeOnNextHook(preloadHooks, payload, hookCallback);
|
|
484
493
|
} else {
|
|
485
|
-
hooksManager.invokeHandler(HOOKS_EVENTS.COMPLETE, {
|
|
494
|
+
hooksManager.subscriber.invokeHandler(HOOKS_EVENTS.COMPLETE, {
|
|
486
495
|
hookPlugin: { lastHook: true },
|
|
487
496
|
payload,
|
|
488
497
|
});
|
|
@@ -491,5 +500,5 @@ export function HooksManager({
|
|
|
491
500
|
return hooksManager;
|
|
492
501
|
};
|
|
493
502
|
|
|
494
|
-
return hooksManager;
|
|
503
|
+
return hooksManager as HookManager;
|
|
495
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
|
+
}
|
|
@@ -26,7 +26,7 @@ export const riverFocusManager = (function () {
|
|
|
26
26
|
/**
|
|
27
27
|
* Retrieve screen focus data by id
|
|
28
28
|
*
|
|
29
|
-
* @param {
|
|
29
|
+
* @param {{screenFocusableGroupId: string}} screenFocusableGroupId Unique Id of the screen from layout.json
|
|
30
30
|
*
|
|
31
31
|
*/
|
|
32
32
|
function screenFocusableData({ screenFocusableGroupId }) {
|
|
@@ -36,8 +36,9 @@ export const riverFocusManager = (function () {
|
|
|
36
36
|
/**
|
|
37
37
|
* Clear screen data for specific screen
|
|
38
38
|
*
|
|
39
|
-
* @param {
|
|
40
|
-
*
|
|
39
|
+
* @param {{ screenId: string, isInsideContainer: boolean }}
|
|
40
|
+
* screenId Unique Id of the screen from layout.json
|
|
41
|
+
* isInsideContainer If this screen a screen picker child
|
|
41
42
|
*
|
|
42
43
|
*/
|
|
43
44
|
function clearScreenData({ screenId, isInsideContainer }) {
|
|
@@ -60,9 +61,13 @@ export const riverFocusManager = (function () {
|
|
|
60
61
|
/**
|
|
61
62
|
* Focus on selected items
|
|
62
63
|
*
|
|
63
|
-
* @param {
|
|
64
|
-
*
|
|
65
|
-
*
|
|
64
|
+
* @param {{
|
|
65
|
+
* screenFocusableGroupId: string,
|
|
66
|
+
* screenFocusedOnItem: () => void,
|
|
67
|
+
* previousAction: QuickBrickNavigationActionType,
|
|
68
|
+
* isDeepLink: boolean }} object contains data for focus
|
|
69
|
+
* - `screenFocusedOnItem` focusable item to focus
|
|
70
|
+
* - `previousActionhistory` navigator history object
|
|
66
71
|
*
|
|
67
72
|
*/
|
|
68
73
|
function focusOnSelectedItem({
|
|
@@ -115,15 +120,15 @@ export const riverFocusManager = (function () {
|
|
|
115
120
|
|
|
116
121
|
/**
|
|
117
122
|
* Create unique key that will be used for save focused group data inside specific screen
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
123
|
+
* @param {{ screenId: string, isInsideContainer: boolean }}
|
|
124
|
+
* screenId Unique Id of the screen from layout.json
|
|
125
|
+
* isInsideContainer If this screen a screen picker child
|
|
121
126
|
*
|
|
122
127
|
*/
|
|
123
128
|
function screenFocusableGroupId({ screenId, isInsideContainer }) {
|
|
124
|
-
return
|
|
125
|
-
?
|
|
126
|
-
|
|
129
|
+
return `RiverFocusableGroup-${screenId}${
|
|
130
|
+
R.isNil(isInsideContainer) ? "" : "-isInsideContainer"
|
|
131
|
+
}`;
|
|
127
132
|
}
|
|
128
133
|
|
|
129
134
|
return {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const BUTTON_ACCESSIBILITY_KEYS = {
|
|
2
|
+
play: {
|
|
3
|
+
label: "accessibility_play_label",
|
|
4
|
+
hint: "accessibility_play_hint",
|
|
5
|
+
mini: {
|
|
6
|
+
label: "accessibility_play_mini_label",
|
|
7
|
+
hint: "accessibility_play_mini_hint",
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
pause: {
|
|
11
|
+
label: "accessibility_pause_label",
|
|
12
|
+
hint: "accessibility_pause_hint",
|
|
13
|
+
mini: {
|
|
14
|
+
label: "accessibility_pause_mini_label",
|
|
15
|
+
hint: "accessibility_pause_mini_hint",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
rewind: {
|
|
19
|
+
label: "accessibility_rewind_label",
|
|
20
|
+
hint: "accessibility_rewind_hint",
|
|
21
|
+
},
|
|
22
|
+
forward: {
|
|
23
|
+
label: "accessibility_forward_label",
|
|
24
|
+
hint: "accessibility_forward_hint",
|
|
25
|
+
},
|
|
26
|
+
close: {
|
|
27
|
+
label: "accessibility_close_label",
|
|
28
|
+
hint: "accessibility_close_hint",
|
|
29
|
+
mini: {
|
|
30
|
+
label: "accessibility_close_mini_label",
|
|
31
|
+
hint: "accessibility_close_mini_hint",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
maximize: {
|
|
35
|
+
label: "accessibility_maximize_label",
|
|
36
|
+
hint: "accessibility_maximize_hint",
|
|
37
|
+
},
|
|
38
|
+
subtitles: {
|
|
39
|
+
label: "accessibility_subtitle_label",
|
|
40
|
+
hint: "accessibility_subtitle_hint",
|
|
41
|
+
},
|
|
42
|
+
back: {
|
|
43
|
+
label: "accessibility_back_label",
|
|
44
|
+
hint: "accessibility_back_hint",
|
|
45
|
+
},
|
|
46
|
+
fullscreen: {
|
|
47
|
+
label: "accessibility_fullscreen_label",
|
|
48
|
+
hint: "accessibility_fullscreen_hint",
|
|
49
|
+
},
|
|
50
|
+
} as const;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useMemo } from "react";
|
|
2
|
+
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
3
|
+
import { AccessibilityManager } from "./index";
|
|
4
|
+
|
|
5
|
+
export const useAccessibilityManager = () => {
|
|
6
|
+
const { remoteConfigurations } = usePickFromState(["remoteConfigurations"]);
|
|
7
|
+
const { localizations } = remoteConfigurations;
|
|
8
|
+
|
|
9
|
+
const accessibilityManager = useMemo(() => {
|
|
10
|
+
return AccessibilityManager.getInstance();
|
|
11
|
+
}, []);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
accessibilityManager.updateLocalizations(localizations);
|
|
15
|
+
}, [localizations]);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const subscription = accessibilityManager.getStateAsObservable().subscribe({
|
|
19
|
+
next: () => {
|
|
20
|
+
// TODO: handle accessibility states
|
|
21
|
+
// screenReaderEnabled: false
|
|
22
|
+
// reduceMotionEnabled: false
|
|
23
|
+
// boldTextEnabled: false
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return () => subscription.unsubscribe();
|
|
28
|
+
}, [accessibilityManager]);
|
|
29
|
+
|
|
30
|
+
return accessibilityManager;
|
|
31
|
+
};
|