@applicaster/zapp-react-native-utils 12.0.0-alpha.9233494544 → 12.0.0-alpha.9262177070
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 +13 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +12 -0
- package/analyticsUtils/index.tsx +12 -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 +23 -125
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +11 -21
- package/appUtils/focusManager/utils/index.ts +31 -8
- package/appUtils/focusManagerAux/index.ts +76 -0
- package/appUtils/focusManagerAux/utils/index.ts +100 -0
- package/appUtils/keyCodes/keys.web.js +8 -0
- package/appUtils/keyCodes/keysByPlatform.js +11 -1
- package/appUtils/platform/const.ts +25 -0
- package/appUtils/platform/index.ts +3 -0
- package/appUtils/platform/platformUtils.ts +223 -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 +8 -3
- package/appUtils/playerManager/playerNative.ts +5 -14
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +6 -1
- 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 +9 -20
- package/cellUtils/index.ts +6 -12
- package/dateUtils/index.ts +11 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/keyboardState/index.ts +0 -0
- package/localizationUtils/__tests__/localizationUtils.test.ts +72 -53
- package/localizationUtils/index.ts +13 -22
- package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
- package/numberUtils/index.ts +9 -18
- package/package.json +2 -2
- package/reactHooks/cell-click/__tests__/index.test.js +10 -1
- package/reactHooks/cell-click/index.ts +12 -12
- 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/navigation/__tests__/index.test.tsx +11 -8
- package/reactHooks/navigation/index.ts +42 -68
- 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/helpers.tsx +1 -1
- package/reactUtils/index.ts +102 -0
- package/types.ts +4 -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
|
@@ -7,6 +7,15 @@ import { sendHeaderClickEvent } from "./sendHeaderClickEvent";
|
|
|
7
7
|
import { sendHardwareBackButtonClickEvent } from "./sendHardwareBackButtonClickEvent";
|
|
8
8
|
import { sendDownloadsEvent } from "./sendDownloadsEvent";
|
|
9
9
|
import { sendScreenEvent } from "./sendScreenEvent";
|
|
10
|
+
import {
|
|
11
|
+
sendSearchCanceledEvent,
|
|
12
|
+
sendSearchExecutedEvent,
|
|
13
|
+
} from "./searchEvents";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
sendShareInitiatedEvent,
|
|
17
|
+
sendShareSuccessEvent,
|
|
18
|
+
} from "./sendShareEvent";
|
|
10
19
|
|
|
11
20
|
export {
|
|
12
21
|
sendScreenEvent,
|
|
@@ -18,4 +27,8 @@ export {
|
|
|
18
27
|
sendHeaderClickEvent,
|
|
19
28
|
sendHardwareBackButtonClickEvent,
|
|
20
29
|
sendDownloadsEvent,
|
|
30
|
+
sendSearchCanceledEvent,
|
|
31
|
+
sendSearchExecutedEvent,
|
|
32
|
+
sendShareInitiatedEvent,
|
|
33
|
+
sendShareSuccessEvent,
|
|
21
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 sendSearchCanceledEvent = (analyticsProps) => {
|
|
6
|
+
const eventName = ANALYTICS_CORE_EVENTS.SEARCH_CANCELED;
|
|
7
|
+
postAnalyticEvent(eventName, analyticsProps);
|
|
8
|
+
|
|
9
|
+
log_debug(`sendSearchCanceledEvent: send event: ${eventName}`, {
|
|
10
|
+
analyticsProps,
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const sendSearchExecutedEvent = (analyticsProps) => {
|
|
15
|
+
const eventName = ANALYTICS_CORE_EVENTS.SEARCH_EXECUTED;
|
|
16
|
+
postAnalyticEvent(eventName, analyticsProps);
|
|
17
|
+
|
|
18
|
+
log_debug(`sendSearchExecutedEvent: send event: ${eventName}`, {
|
|
19
|
+
analyticsProps,
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as R from "ramda";
|
|
2
|
+
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
3
|
+
|
|
4
|
+
export const getVideojsAnalyticPluginsConfig = async (entry: ZappEntry) => {
|
|
5
|
+
let videojsConfiguration = {};
|
|
6
|
+
|
|
7
|
+
const plugins = appStore.get("plugins");
|
|
8
|
+
const analyticPlugins = R.filter(R.propEq("type", "analytics"), plugins);
|
|
9
|
+
|
|
10
|
+
const configurations = await Promise.all(
|
|
11
|
+
analyticPlugins.map(async (plugin) => {
|
|
12
|
+
const { configuration, module } = plugin;
|
|
13
|
+
|
|
14
|
+
return module?.getPlayerConfiguration?.(configuration, entry);
|
|
15
|
+
})
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
configurations.forEach((analyticConfig) => {
|
|
19
|
+
if (typeof analyticConfig === "object" && analyticConfig !== null) {
|
|
20
|
+
videojsConfiguration = { ...videojsConfiguration, ...analyticConfig };
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return videojsConfiguration;
|
|
25
|
+
};
|
package/analyticsUtils/events.ts
CHANGED
|
@@ -23,10 +23,22 @@ export const TAPPING_EVENTS = {
|
|
|
23
23
|
TAP_NAVBAR_BACK_BUTTON: "tap_navbar_back_button",
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
export const SEARCH_EVENTS = {
|
|
27
|
+
SEARCH_EXECUTED: "search_executed",
|
|
28
|
+
SEARCH_CANCELED: "search_canceled",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const SHARE_EVENTS = {
|
|
32
|
+
SHARE_INITIATED: "share_initiated",
|
|
33
|
+
SHARE_SUCCESS: "share_success",
|
|
34
|
+
};
|
|
35
|
+
|
|
26
36
|
export const ANALYTICS_CORE_EVENTS = {
|
|
27
37
|
...LEGACY_EVENTS,
|
|
28
38
|
...SCREEN_VIEW_EVENTS,
|
|
29
39
|
...TAPPING_EVENTS,
|
|
40
|
+
...SEARCH_EVENTS,
|
|
41
|
+
...SHARE_EVENTS,
|
|
30
42
|
};
|
|
31
43
|
|
|
32
44
|
export const WEBVIEW_EVENTS = {
|
package/analyticsUtils/index.tsx
CHANGED
|
@@ -18,6 +18,10 @@ import {
|
|
|
18
18
|
sendHardwareBackButtonClickEvent,
|
|
19
19
|
sendDownloadsEvent,
|
|
20
20
|
sendScreenEvent,
|
|
21
|
+
sendSearchCanceledEvent,
|
|
22
|
+
sendSearchExecutedEvent,
|
|
23
|
+
sendShareInitiatedEvent,
|
|
24
|
+
sendShareSuccessEvent,
|
|
21
25
|
} from "./AnalyticsEvents";
|
|
22
26
|
|
|
23
27
|
import { postAnalyticEvent } from "./manager";
|
|
@@ -66,6 +70,10 @@ type AnalyticsFunctions = {
|
|
|
66
70
|
item: ZappEntry;
|
|
67
71
|
state: OfflineItemState;
|
|
68
72
|
}) => void;
|
|
73
|
+
sendSearchCanceledEvent: (props: AnalyticsDefaultProperties) => void;
|
|
74
|
+
sendSearchExecutedEvent: (props: AnalyticsDefaultProperties) => void;
|
|
75
|
+
sendShareInitiatedEvent: (props: AnalyticsDefaultProperties) => void;
|
|
76
|
+
sendShareSuccessEvent: (props: AnalyticsDefaultProperties) => void;
|
|
69
77
|
};
|
|
70
78
|
|
|
71
79
|
type GetAnalyticsFunctions = (
|
|
@@ -102,6 +110,10 @@ export function getAnalyticsFunctions({
|
|
|
102
110
|
sendHardwareBackButtonClickEvent,
|
|
103
111
|
sendScreenEvent,
|
|
104
112
|
sendDownloadsEvent,
|
|
113
|
+
sendSearchCanceledEvent,
|
|
114
|
+
sendSearchExecutedEvent,
|
|
115
|
+
sendShareInitiatedEvent,
|
|
116
|
+
sendShareSuccessEvent,
|
|
105
117
|
};
|
|
106
118
|
}
|
|
107
119
|
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
exports[`focusManager should be defined 1`] = `
|
|
4
4
|
Object {
|
|
5
5
|
"blur": [Function],
|
|
6
|
-
"disableAutomaticFocus": [Function],
|
|
7
6
|
"disableFocus": [Function],
|
|
8
|
-
"enableAutomaticFocus": [Function],
|
|
9
7
|
"enableFocus": [Function],
|
|
10
8
|
"focusableTree": Tree {
|
|
11
9
|
"loadingCounter": 0,
|
|
@@ -23,6 +21,7 @@ Object {
|
|
|
23
21
|
"getGroupById": [Function],
|
|
24
22
|
"getGroupRootById": [Function],
|
|
25
23
|
"invokeHandler": [Function],
|
|
24
|
+
"isCurrentFocusOnTheTopScreen": [Function],
|
|
26
25
|
"isFocusDisabled": [Function],
|
|
27
26
|
"isGroupItemFocused": [Function],
|
|
28
27
|
"longPress": [Function],
|
|
@@ -30,11 +29,11 @@ Object {
|
|
|
30
29
|
"on": [Function],
|
|
31
30
|
"press": [Function],
|
|
32
31
|
"pressOut": [Function],
|
|
32
|
+
"recoverFocus": [Function],
|
|
33
33
|
"register": [Function],
|
|
34
34
|
"removeHandler": [Function],
|
|
35
35
|
"setFocus": [Function],
|
|
36
36
|
"setInitialFocus": [Function],
|
|
37
|
-
"setupInitialFocus": [Function],
|
|
38
37
|
"unregister": [Function],
|
|
39
38
|
}
|
|
40
39
|
`;
|
|
@@ -14,10 +14,8 @@ describe("focusManager", () => {
|
|
|
14
14
|
expect(focusManager).toMatchSnapshot();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it("
|
|
17
|
+
it("manages to land initial focus", () => {
|
|
18
18
|
const mockSetFocus = jest.fn();
|
|
19
|
-
focusManager.setupInitialFocus("1", true);
|
|
20
|
-
focusManager.enableAutomaticFocus();
|
|
21
19
|
|
|
22
20
|
focusManager.register({
|
|
23
21
|
id: "1",
|
|
@@ -31,31 +29,13 @@ describe("focusManager", () => {
|
|
|
31
29
|
},
|
|
32
30
|
});
|
|
33
31
|
|
|
32
|
+
const { success } = focusManager.setInitialFocus();
|
|
33
|
+
|
|
34
|
+
expect(success).toBe(true);
|
|
34
35
|
expect(mockSetFocus).toBeCalledTimes(1);
|
|
35
36
|
expect(mockSetFocus).toBeCalledWith(null);
|
|
36
37
|
});
|
|
37
38
|
|
|
38
|
-
it("enableAutomaticFocus should block setting focus", () => {
|
|
39
|
-
const mockSetFocus = jest.fn();
|
|
40
|
-
focusManager.setupInitialFocus("1", true);
|
|
41
|
-
focusManager.disableAutomaticFocus();
|
|
42
|
-
|
|
43
|
-
focusManager.register({
|
|
44
|
-
id: "1",
|
|
45
|
-
component: {
|
|
46
|
-
setFocus: mockSetFocus,
|
|
47
|
-
willReceiveFocus: function () {},
|
|
48
|
-
isMounted: function () {
|
|
49
|
-
return true;
|
|
50
|
-
},
|
|
51
|
-
props: { groupId: "121" },
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
expect(mockSetFocus).toBeCalledTimes(0);
|
|
56
|
-
expect(mockSetFocus).not.toBeCalledWith(null);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
39
|
describe("register", () => {});
|
|
60
40
|
describe("unregister", () => {});
|
|
61
41
|
describe("find", () => {});
|
|
@@ -18,7 +18,6 @@ describe("focusManager", () => {
|
|
|
18
18
|
"on",
|
|
19
19
|
"invokeHandler",
|
|
20
20
|
"removeHandler",
|
|
21
|
-
"setupInitialFocus",
|
|
22
21
|
"longPress",
|
|
23
22
|
"pressOut",
|
|
24
23
|
"enableFocus",
|
|
@@ -27,10 +26,10 @@ describe("focusManager", () => {
|
|
|
27
26
|
"isFocusDisabled",
|
|
28
27
|
"getCurrentFocusNode",
|
|
29
28
|
"focusableTree",
|
|
30
|
-
"disableAutomaticFocus",
|
|
31
|
-
"enableAutomaticFocus",
|
|
32
29
|
"getGroupRootById",
|
|
33
30
|
"isGroupItemFocused",
|
|
31
|
+
"recoverFocus",
|
|
32
|
+
"isCurrentFocusOnTheTopScreen",
|
|
34
33
|
];
|
|
35
34
|
|
|
36
35
|
expectedMethods.forEach((method) => {
|
|
@@ -8,17 +8,11 @@ import { Tree } from "./treeDataStructure/Tree";
|
|
|
8
8
|
import {
|
|
9
9
|
findFocusableNode,
|
|
10
10
|
findPriorityItem,
|
|
11
|
-
|
|
11
|
+
haveSameParentBeforeRoot,
|
|
12
12
|
} from "./treeDataStructure/Utils";
|
|
13
13
|
import { subscriber } from "../../functionUtils";
|
|
14
14
|
import * as FOCUS_EVENTS from "./events";
|
|
15
15
|
import { coreLogger } from "../../logger";
|
|
16
|
-
import {
|
|
17
|
-
waitForActiveScreen,
|
|
18
|
-
waitForContent,
|
|
19
|
-
getContentNode,
|
|
20
|
-
getActiveScreen,
|
|
21
|
-
} from "./utils";
|
|
22
16
|
|
|
23
17
|
const logger = coreLogger.addSubsystem("focusManager");
|
|
24
18
|
|
|
@@ -59,21 +53,9 @@ export const focusManager = (function () {
|
|
|
59
53
|
// focusable node which currently holds the focus
|
|
60
54
|
let currentFocusNode = null;
|
|
61
55
|
let lastFocusedId = null;
|
|
62
|
-
let initialFocusOnContent = null;
|
|
63
56
|
let focusDisabled = false;
|
|
64
|
-
let focusAutoEnabled = false;
|
|
65
57
|
const eventHandler = subscriber();
|
|
66
58
|
|
|
67
|
-
function disableAutomaticFocus() {
|
|
68
|
-
logger.log({ message: "disableAutomaticFocus" });
|
|
69
|
-
focusAutoEnabled = false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function enableAutomaticFocus() {
|
|
73
|
-
logger.log({ message: "focusManager: enableAutomaticFocus" });
|
|
74
|
-
focusAutoEnabled = true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
59
|
function enableFocus() {
|
|
78
60
|
focusDisabled = false;
|
|
79
61
|
}
|
|
@@ -251,13 +233,17 @@ export const focusManager = (function () {
|
|
|
251
233
|
const currentFocusedId = R.path(["props", "id"], getCurrentFocus());
|
|
252
234
|
const nextFocusedId = R.path(["props", "id"], focusableItem);
|
|
253
235
|
|
|
254
|
-
if (
|
|
236
|
+
if (
|
|
237
|
+
isNotNil(currentFocusedId) &&
|
|
238
|
+
isNotNil(nextFocusedId) &&
|
|
239
|
+
currentFocusedId === nextFocusedId
|
|
240
|
+
) {
|
|
255
241
|
// we are going to move focus to the same node(already focused) -> nothing to do
|
|
256
242
|
return { success: true };
|
|
257
243
|
}
|
|
258
244
|
|
|
259
|
-
if (
|
|
260
|
-
//
|
|
245
|
+
if (focusableItem?.isGroup) {
|
|
246
|
+
// focusCandidate is a FocusableGroup, we are not able to land focus on group(only on Focusable)
|
|
261
247
|
return { success: false };
|
|
262
248
|
}
|
|
263
249
|
|
|
@@ -266,10 +252,7 @@ export const focusManager = (function () {
|
|
|
266
252
|
!focusableItem.isGroup &&
|
|
267
253
|
isFocusEnabled(focusableItem)
|
|
268
254
|
) {
|
|
269
|
-
|
|
270
|
-
blur();
|
|
271
|
-
initialFocusOnContent = false;
|
|
272
|
-
}
|
|
255
|
+
blur();
|
|
273
256
|
|
|
274
257
|
logger.log({
|
|
275
258
|
message: "setInitialFocus – currentFocusNode",
|
|
@@ -295,17 +278,8 @@ export const focusManager = (function () {
|
|
|
295
278
|
val,
|
|
296
279
|
node,
|
|
297
280
|
currentFocusNode,
|
|
298
|
-
initialFocusOnContent,
|
|
299
281
|
},
|
|
300
282
|
});
|
|
301
|
-
|
|
302
|
-
if ((val && !currentFocusNode) || initialFocusOnContent) {
|
|
303
|
-
logger.log({ message: `focusAutoEnabled ${focusAutoEnabled}` });
|
|
304
|
-
|
|
305
|
-
if (focusAutoEnabled) {
|
|
306
|
-
setInitialFocus(initialFocusOnContent ? node : undefined);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
283
|
}
|
|
310
284
|
|
|
311
285
|
/**
|
|
@@ -357,8 +331,6 @@ export const focusManager = (function () {
|
|
|
357
331
|
* @returns {React.Component} the registered component
|
|
358
332
|
*/
|
|
359
333
|
function registerGroup(id, component) {
|
|
360
|
-
// console.log("debug_2", "FM registerGroup", { id, component });
|
|
361
|
-
|
|
362
334
|
focusableTree.addNode({ id, component });
|
|
363
335
|
|
|
364
336
|
return component;
|
|
@@ -374,8 +346,6 @@ export const focusManager = (function () {
|
|
|
374
346
|
* @returns {React.Component} the registered component
|
|
375
347
|
*/
|
|
376
348
|
function registerItem(id, component) {
|
|
377
|
-
// console.log("debug_2", "FM registerItem", { id, component });
|
|
378
|
-
|
|
379
349
|
focusableTree.addNode({ id, component });
|
|
380
350
|
|
|
381
351
|
if (!currentFocusNode && id === lastFocusedId && !id.includes("menu")) {
|
|
@@ -392,8 +362,6 @@ export const focusManager = (function () {
|
|
|
392
362
|
* @param {String} id of the group to unregister
|
|
393
363
|
*/
|
|
394
364
|
function unregisterGroup(id) {
|
|
395
|
-
// console.log("debug_2", "FM unregisterGroup", { id });
|
|
396
|
-
|
|
397
365
|
focusableTree.findAndRemoveNode(id);
|
|
398
366
|
}
|
|
399
367
|
|
|
@@ -405,8 +373,6 @@ export const focusManager = (function () {
|
|
|
405
373
|
* @param {String} id of the Focusable to unregister
|
|
406
374
|
*/
|
|
407
375
|
function unregisterItem(id) {
|
|
408
|
-
// console.log("debug_2", "FM unregisterItem", { id });
|
|
409
|
-
|
|
410
376
|
focusableTree.findAndRemoveNode(id);
|
|
411
377
|
|
|
412
378
|
if (currentFocusNode && currentFocusNode.id === id) {
|
|
@@ -444,80 +410,20 @@ export const focusManager = (function () {
|
|
|
444
410
|
group ? unregisterGroup(id) : unregisterItem(id);
|
|
445
411
|
}
|
|
446
412
|
|
|
447
|
-
function
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (focusOnContent) {
|
|
451
|
-
initialFocusOnContent = focusOnContent;
|
|
452
|
-
} else {
|
|
453
|
-
setFocus(id);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
async function setFocusOnMenu(currentRoute: string) {
|
|
458
|
-
console.log("debug_2", "FM - setFocusOnMenu", { currentRoute });
|
|
413
|
+
function isCurrentFocusOnTheTopScreen() {
|
|
414
|
+
const routes = R.pathOr([], ["root", "children"], focusableTree);
|
|
459
415
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
const navbar = R.find(
|
|
464
|
-
(child) => R.startsWith("navbar", child.id),
|
|
465
|
-
getActiveScreen(focusableTree).children
|
|
466
|
-
);
|
|
467
|
-
|
|
468
|
-
const selectedMenuItemId = R.find(
|
|
469
|
-
(child) => child.component.props.selected,
|
|
470
|
-
navbar?.children || []
|
|
471
|
-
)?.id;
|
|
472
|
-
|
|
473
|
-
if (selectedMenuItemId) {
|
|
474
|
-
// set focus on selected menu item
|
|
475
|
-
setFocus(selectedMenuItemId);
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const firstMenuItemId = R.path(["children", 0, "id"], navbar);
|
|
480
|
-
|
|
481
|
-
if (firstMenuItemId) {
|
|
482
|
-
// set focus on first menu item
|
|
483
|
-
setFocus(firstMenuItemId);
|
|
484
|
-
}
|
|
485
|
-
} catch (error) {
|
|
486
|
-
// failed to put focus on top-menu => log it
|
|
416
|
+
if (routes.length <= 1) {
|
|
417
|
+
// there is only one or zero routes
|
|
418
|
+
return true;
|
|
487
419
|
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
async function setFocusOnContent(currentRoute: string) {
|
|
491
|
-
console.log("debug_2", "FM - setFocusOnContent", { currentRoute });
|
|
492
|
-
|
|
493
|
-
// we need to put focus on content here
|
|
494
|
-
// For doing it we have to wait registration of first focusable node into focusableTree
|
|
495
|
-
// this is the temporary hack with waiting until content node starts having children
|
|
496
|
-
try {
|
|
497
|
-
await waitForActiveScreen(currentRoute, focusableTree);
|
|
498
|
-
await waitForContent(focusableTree);
|
|
499
420
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
const { success } = setInitialFocus(content);
|
|
503
|
-
|
|
504
|
-
if (!success) {
|
|
505
|
-
// we've failed to put initial focus on content, re-run "setFocusOnContent" again
|
|
506
|
-
throw Error(
|
|
507
|
-
"we've failed to put initial focus on content, re-run 'setFocusOnContent' again"
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
} catch (e) {
|
|
511
|
-
setFocusOnContent(currentRoute);
|
|
512
|
-
}
|
|
421
|
+
return haveSameParentBeforeRoot(currentFocusNode, R.last(routes));
|
|
513
422
|
}
|
|
514
423
|
|
|
515
424
|
function recoverFocus() {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (!onSameScreen) {
|
|
520
|
-
// currentFocusedNode is not from the last route. We need to run recover focus.
|
|
425
|
+
if (!isCurrentFocusOnTheTopScreen()) {
|
|
426
|
+
// We've failed to set focused node on the new screen => run focus recovery
|
|
521
427
|
setInitialFocus();
|
|
522
428
|
}
|
|
523
429
|
}
|
|
@@ -528,19 +434,17 @@ export const focusManager = (function () {
|
|
|
528
434
|
* @param {Object} direction of the scroll
|
|
529
435
|
*/
|
|
530
436
|
function moveFocus(direction) {
|
|
437
|
+
if (!isCurrentFocusOnTheTopScreen()) {
|
|
438
|
+
// We are opening new screen. We need to ignore movement of focus.
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
|
|
531
442
|
if (focusDisabled) return false;
|
|
532
443
|
|
|
533
444
|
if (currentFocusNode) {
|
|
534
445
|
currentFocusNode.component.willLoseFocus(currentFocusNode, direction);
|
|
535
446
|
const nextFocusable = findFocusableNode(direction, currentFocusNode);
|
|
536
447
|
|
|
537
|
-
// console.log("debug_2", "FM moveFocus", {
|
|
538
|
-
// direction: direction?.value,
|
|
539
|
-
// currentFocusNode,
|
|
540
|
-
// focusableTree,
|
|
541
|
-
// nextFocusable,
|
|
542
|
-
// });
|
|
543
|
-
|
|
544
448
|
if (nextFocusable?.component?.isMounted?.()) {
|
|
545
449
|
const nextRect = nextFocusable.component.getRect();
|
|
546
450
|
|
|
@@ -563,8 +467,6 @@ export const focusManager = (function () {
|
|
|
563
467
|
} else {
|
|
564
468
|
currentFocusNode.component.failedLostFocus(currentFocusNode, direction);
|
|
565
469
|
}
|
|
566
|
-
} else {
|
|
567
|
-
setInitialFocus();
|
|
568
470
|
}
|
|
569
471
|
}
|
|
570
472
|
|
|
@@ -624,7 +526,6 @@ export const focusManager = (function () {
|
|
|
624
526
|
on,
|
|
625
527
|
invokeHandler,
|
|
626
528
|
removeHandler,
|
|
627
|
-
setupInitialFocus,
|
|
628
529
|
longPress,
|
|
629
530
|
pressOut,
|
|
630
531
|
enableFocus,
|
|
@@ -633,12 +534,9 @@ export const focusManager = (function () {
|
|
|
633
534
|
isFocusDisabled,
|
|
634
535
|
getCurrentFocusNode,
|
|
635
536
|
focusableTree,
|
|
636
|
-
disableAutomaticFocus,
|
|
637
|
-
enableAutomaticFocus,
|
|
638
537
|
getGroupRootById,
|
|
639
538
|
isGroupItemFocused,
|
|
640
|
-
setFocusOnMenu,
|
|
641
|
-
setFocusOnContent,
|
|
642
539
|
recoverFocus,
|
|
540
|
+
isCurrentFocusOnTheTopScreen,
|
|
643
541
|
};
|
|
644
542
|
})();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { allPass, pathOr, startsWith, isNil } from "ramda";
|
|
2
2
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
3
|
+
import { isZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
4
|
+
import { QUICK_BRICK_NAVBAR } from "@applicaster/quick-brick-core/const";
|
|
3
5
|
|
|
4
6
|
import { rejectItemByPath } from "../../../../objectUtils";
|
|
5
7
|
import {
|
|
@@ -145,7 +147,7 @@ const hasComponent = (target) => !!target?.component;
|
|
|
145
147
|
|
|
146
148
|
const hasComponentAndChildren = allPass([hasComponent, hasChildren]);
|
|
147
149
|
|
|
148
|
-
const positiveOrZero = (value) => value
|
|
150
|
+
const positiveOrZero = (value) => value > 0 || isZero(value);
|
|
149
151
|
|
|
150
152
|
const excludeFromFocusSearching = pathOr(false, [
|
|
151
153
|
"component",
|
|
@@ -153,12 +155,10 @@ const excludeFromFocusSearching = pathOr(false, [
|
|
|
153
155
|
"excludeFromFocusSearching",
|
|
154
156
|
]);
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const isNavBar = (target) => startsWith("navbar", target?.id);
|
|
158
|
+
const isNavBar = (target) => startsWith(QUICK_BRICK_NAVBAR, target?.id);
|
|
159
159
|
|
|
160
160
|
const ignoreMenuIfMultipleTargets = (nodes) => {
|
|
161
|
-
if (nodes.length > 1
|
|
161
|
+
if (nodes.length > 1) {
|
|
162
162
|
return nodes.filter((n) => !isNavBar(n?.target));
|
|
163
163
|
}
|
|
164
164
|
|
|
@@ -222,24 +222,10 @@ export function getTargetInDirection(
|
|
|
222
222
|
}))
|
|
223
223
|
.filter(({ distance }) => positiveOrZero(distance));
|
|
224
224
|
|
|
225
|
-
// if (isAllScreens(targets)) {
|
|
226
|
-
// return last(targets);
|
|
227
|
-
// }
|
|
228
|
-
|
|
229
225
|
const match = distances
|
|
230
226
|
.sort((a, b) => a.distance - b.distance) // sorts the distances
|
|
231
227
|
.filter(ignoreMenuIfMultipleTargets)[0]; // filters out multiple targets if necessary // gets the first element
|
|
232
228
|
|
|
233
|
-
// console.log("debug_2", "FM getTargetInDirection", {
|
|
234
|
-
// direction: direction?.value,
|
|
235
|
-
// currentNode,
|
|
236
|
-
// targetNodes,
|
|
237
|
-
// targets,
|
|
238
|
-
// comparisonRect,
|
|
239
|
-
// distances,
|
|
240
|
-
// match,
|
|
241
|
-
// });
|
|
242
|
-
|
|
243
229
|
return match?.target;
|
|
244
230
|
}
|
|
245
231
|
|
|
@@ -337,6 +323,10 @@ export const getNodeBeforeRoot = (node) => {
|
|
|
337
323
|
return undefined;
|
|
338
324
|
}
|
|
339
325
|
|
|
326
|
+
if (isNil(node.parent)) {
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
|
|
340
330
|
if (node.parent.id === "root") {
|
|
341
331
|
return node;
|
|
342
332
|
}
|
|
@@ -344,9 +334,9 @@ export const getNodeBeforeRoot = (node) => {
|
|
|
344
334
|
return getNodeBeforeRoot(node.parent);
|
|
345
335
|
};
|
|
346
336
|
|
|
347
|
-
export const
|
|
337
|
+
export const haveSameParentBeforeRoot = (currentNode, nextNode) => {
|
|
348
338
|
const routeForCurrentNode = getNodeBeforeRoot(currentNode);
|
|
349
339
|
const routeForNextNode = getNodeBeforeRoot(nextNode);
|
|
350
340
|
|
|
351
|
-
return routeForCurrentNode
|
|
341
|
+
return routeForCurrentNode?.id === routeForNextNode?.id;
|
|
352
342
|
};
|