@applicaster/zapp-react-native-utils 12.0.0-alpha.4337072244 → 12.0.0-alpha.4355141911
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/appUtils/focusManager/index.ts +6 -6
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +5 -4
- package/appUtils/focusManager/utils/index.ts +8 -2
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +6 -1
- package/package.json +2 -2
- package/reactHooks/cell-click/__tests__/index.test.js +2 -1
- package/reactHooks/cell-click/index.ts +1 -1
- package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
- package/reactHooks/navigation/index.ts +34 -66
- package/reactHooks/screen/useScreenContext.ts +1 -2
|
@@ -8,7 +8,7 @@ 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";
|
|
@@ -474,19 +474,19 @@ export const focusManager = (function () {
|
|
|
474
474
|
}
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
-
function
|
|
477
|
+
function isCurrentFocusOnTheTopScreen() {
|
|
478
478
|
const routes = R.pathOr([], ["root", "children"], focusableTree);
|
|
479
479
|
|
|
480
480
|
if (routes.length <= 1) {
|
|
481
481
|
// there is only one or zero routes
|
|
482
|
-
return
|
|
482
|
+
return true;
|
|
483
483
|
}
|
|
484
484
|
|
|
485
|
-
return
|
|
485
|
+
return haveSameParentBeforeRoot(currentFocusNode, R.last(routes));
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
function recoverFocus() {
|
|
489
|
-
if (
|
|
489
|
+
if (!isCurrentFocusOnTheTopScreen()) {
|
|
490
490
|
// We've failed to set focused node on the new screen => run focus recovery
|
|
491
491
|
setInitialFocus();
|
|
492
492
|
}
|
|
@@ -498,7 +498,7 @@ export const focusManager = (function () {
|
|
|
498
498
|
* @param {Object} direction of the scroll
|
|
499
499
|
*/
|
|
500
500
|
function moveFocus(direction) {
|
|
501
|
-
if (
|
|
501
|
+
if (!isCurrentFocusOnTheTopScreen()) {
|
|
502
502
|
// We are opening new screen. We need to ignore movement of focus.
|
|
503
503
|
return false;
|
|
504
504
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { allPass, pathOr, startsWith, isNil } from "ramda";
|
|
2
2
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
3
3
|
import { isZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
4
|
+
import { QUICK_BRICK_NAVBAR } from "@applicaster/quick-brick-core/const";
|
|
4
5
|
|
|
5
6
|
import { rejectItemByPath } from "../../../../objectUtils";
|
|
6
7
|
import {
|
|
@@ -154,10 +155,10 @@ const excludeFromFocusSearching = pathOr(false, [
|
|
|
154
155
|
"excludeFromFocusSearching",
|
|
155
156
|
]);
|
|
156
157
|
|
|
157
|
-
const isNavBar = (target) => startsWith(
|
|
158
|
+
const isNavBar = (target) => startsWith(QUICK_BRICK_NAVBAR, target?.id);
|
|
158
159
|
|
|
159
160
|
const ignoreMenuIfMultipleTargets = (nodes) => {
|
|
160
|
-
if (nodes.length > 1
|
|
161
|
+
if (nodes.length > 1) {
|
|
161
162
|
return nodes.filter((n) => !isNavBar(n?.target));
|
|
162
163
|
}
|
|
163
164
|
|
|
@@ -333,9 +334,9 @@ export const getNodeBeforeRoot = (node) => {
|
|
|
333
334
|
return getNodeBeforeRoot(node.parent);
|
|
334
335
|
};
|
|
335
336
|
|
|
336
|
-
export const
|
|
337
|
+
export const haveSameParentBeforeRoot = (currentNode, nextNode) => {
|
|
337
338
|
const routeForCurrentNode = getNodeBeforeRoot(currentNode);
|
|
338
339
|
const routeForNextNode = getNodeBeforeRoot(nextNode);
|
|
339
340
|
|
|
340
|
-
return routeForCurrentNode?.id
|
|
341
|
+
return routeForCurrentNode?.id === routeForNextNode?.id;
|
|
341
342
|
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { isNotNil } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
2
2
|
import { find, last, startsWith, pathOr } from "ramda";
|
|
3
|
+
import {
|
|
4
|
+
QUICK_BRICK_NAVBAR,
|
|
5
|
+
QUICK_BRICK_CONTENT,
|
|
6
|
+
} from "@applicaster/quick-brick-core/const";
|
|
3
7
|
|
|
4
8
|
// run check each 300 ms
|
|
5
9
|
// run this check too often could lead to performance penalty on low-end devices
|
|
@@ -60,7 +64,9 @@ const getActiveScreenChildren = (focusableTree) => {
|
|
|
60
64
|
|
|
61
65
|
export const getContentNode = (focusableTree) => {
|
|
62
66
|
const content = find(
|
|
63
|
-
(child) =>
|
|
67
|
+
(child) =>
|
|
68
|
+
startsWith(QUICK_BRICK_CONTENT, child.id) ||
|
|
69
|
+
startsWith("player", child.id),
|
|
64
70
|
getActiveScreenChildren(focusableTree)
|
|
65
71
|
);
|
|
66
72
|
|
|
@@ -69,7 +75,7 @@ export const getContentNode = (focusableTree) => {
|
|
|
69
75
|
|
|
70
76
|
export const getNavbarNode = (focusableTree) => {
|
|
71
77
|
const navbar = find(
|
|
72
|
-
(child) => startsWith(
|
|
78
|
+
(child) => startsWith(QUICK_BRICK_NAVBAR, child.id),
|
|
73
79
|
getActiveScreenChildren(focusableTree)
|
|
74
80
|
);
|
|
75
81
|
|
|
@@ -4,6 +4,7 @@ import { useEffect } from "react";
|
|
|
4
4
|
import { playerManager } from "./index";
|
|
5
5
|
import { useValidatePlayerConfig } from "../../playerUtils/useValidatePlayerConfig";
|
|
6
6
|
import { PlayerRole } from "./conts";
|
|
7
|
+
import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
|
|
7
8
|
|
|
8
9
|
// TODO: Rename to ControllerType
|
|
9
10
|
export const usePlayerControllerSetup = ({
|
|
@@ -34,10 +35,14 @@ export const usePlayerControllerSetup = ({
|
|
|
34
35
|
useValidatePlayerConfig(config);
|
|
35
36
|
|
|
36
37
|
useEffect(() => {
|
|
38
|
+
const newConfig = isAppleTV()
|
|
39
|
+
? { supports_native_controls: true, ...config }
|
|
40
|
+
: config;
|
|
41
|
+
|
|
37
42
|
const newPlayerController = new ControllerType({
|
|
38
43
|
player: ref,
|
|
39
44
|
listener: props as any,
|
|
40
|
-
config,
|
|
45
|
+
config: newConfig,
|
|
41
46
|
playerId,
|
|
42
47
|
entry,
|
|
43
48
|
playerPluginId: pluginId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.4355141911",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "12.0.0-alpha.
|
|
31
|
+
"@applicaster/applicaster-types": "12.0.0-alpha.4355141911",
|
|
32
32
|
"buffer": "^5.2.1",
|
|
33
33
|
"camelize": "^1.0.0",
|
|
34
34
|
"create-react-context": "^0.2.3",
|
|
@@ -8,6 +8,7 @@ import { waitFor } from "@testing-library/react-native";
|
|
|
8
8
|
const navigator = {
|
|
9
9
|
getPathname: () => "pathnameMock",
|
|
10
10
|
push: jest.fn(),
|
|
11
|
+
data: {},
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
@@ -30,7 +31,7 @@ jest.mock("@applicaster/zapp-react-native-ui-components/Contexts", () => ({
|
|
|
30
31
|
},
|
|
31
32
|
}));
|
|
32
33
|
|
|
33
|
-
const { useCellClick } = require("
|
|
34
|
+
const { useCellClick } = require("../");
|
|
34
35
|
|
|
35
36
|
const mockProps = {
|
|
36
37
|
item: {},
|
|
@@ -83,7 +83,7 @@ export const useCellClick = ({ component, zappPipesData, item }: Props) => {
|
|
|
83
83
|
if (isFunction(onCellTap)) {
|
|
84
84
|
onCellTap?.(selectedItem, _index);
|
|
85
85
|
} else {
|
|
86
|
-
if (currentRoute === pathname || pathname
|
|
86
|
+
if (currentRoute === pathname || pathname.includes("video-modal")) {
|
|
87
87
|
const targetScreen = component?.data?.target;
|
|
88
88
|
|
|
89
89
|
push(
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
|
|
3
3
|
import { renderHook } from "@testing-library/react-hooks";
|
|
4
|
-
import {
|
|
4
|
+
import { isNavBarVisible, useRoute } from "../";
|
|
5
5
|
import { Provider } from "react-redux";
|
|
6
6
|
import configureMockStore from "redux-mock-store";
|
|
7
7
|
import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
|
|
8
8
|
import { ZappHookModalContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
9
9
|
import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
|
|
10
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
10
11
|
|
|
11
12
|
const plugins = [];
|
|
12
13
|
|
|
@@ -100,13 +101,15 @@ const mainStackWrapper = ({
|
|
|
100
101
|
pathname = homeStack.route,
|
|
101
102
|
}) => (
|
|
102
103
|
<Provider store={store}>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
<ScreenDataContext.Provider value={homeStack.state}>
|
|
105
|
+
<NavigationContext.Provider
|
|
106
|
+
value={{ ...mainStackNavigator, ...navigator, currentRoute: pathname }}
|
|
107
|
+
>
|
|
108
|
+
<PathnameContext.Provider value={pathname}>
|
|
109
|
+
{children}
|
|
110
|
+
</PathnameContext.Provider>
|
|
111
|
+
</NavigationContext.Provider>
|
|
112
|
+
</ScreenDataContext.Provider>
|
|
110
113
|
</Provider>
|
|
111
114
|
);
|
|
112
115
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
/* eslint max-len: off */
|
|
3
3
|
|
|
4
|
-
import React, { useEffect, useMemo } from "react";
|
|
4
|
+
import React, { useContext, useEffect, useMemo } from "react";
|
|
5
5
|
import { BackHandler, InteractionManager, NativeModules } from "react-native";
|
|
6
6
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
7
7
|
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
import { HooksManager } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager";
|
|
13
13
|
|
|
14
14
|
import { legacyScreenData } from "@applicaster/quick-brick-core/App/NavigationProvider/utils";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
LONG_KEY_PRESS_TIMEOUT,
|
|
17
|
+
QUICK_BRICK_NAVBAR,
|
|
18
|
+
QUICK_BRICK_CONTENT,
|
|
19
|
+
} from "@applicaster/quick-brick-core/const";
|
|
16
20
|
import { useZappHooksModalState } from "@applicaster/zapp-react-dom-ui-components/Components/ZappHooksModal/ZappHooksModal";
|
|
17
21
|
import { ZappHookModalContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
18
22
|
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
|
|
@@ -31,6 +35,7 @@ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
|
31
35
|
import { useNavbarState } from "../screen";
|
|
32
36
|
import { useNavigation } from "./useNavigation";
|
|
33
37
|
import { useModalStore } from "../../modalState";
|
|
38
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
34
39
|
|
|
35
40
|
export { useNavigation } from "./useNavigation";
|
|
36
41
|
|
|
@@ -146,16 +151,8 @@ export const useRoute = (): {
|
|
|
146
151
|
pathname: string;
|
|
147
152
|
} => {
|
|
148
153
|
const pathname = usePathname() || "";
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* compose `useRoute()` output data
|
|
152
|
-
*/
|
|
153
|
-
const composeRouteData = (screenData: VariousScreenData) => ({
|
|
154
|
-
screenData,
|
|
155
|
-
pathname,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
154
|
const navigator = useNavigation();
|
|
155
|
+
const screenDataContext = legacyScreenData(useContext(ScreenDataContext));
|
|
159
156
|
|
|
160
157
|
const { plugins, contentTypes, rivers } = usePickFromState([
|
|
161
158
|
"plugins",
|
|
@@ -163,10 +160,11 @@ export const useRoute = (): {
|
|
|
163
160
|
"contentTypes",
|
|
164
161
|
]);
|
|
165
162
|
|
|
166
|
-
const currentStack = navigator.getStackForPathname(pathname);
|
|
167
163
|
const { modalState } = useModalStore();
|
|
168
164
|
const hookModalState = useZappHooksModalState();
|
|
165
|
+
|
|
169
166
|
const modalScreenData = modalState.screen;
|
|
167
|
+
|
|
170
168
|
const hookModalScreenData = hookModalState.state.screenData?.payload;
|
|
171
169
|
|
|
172
170
|
const videoModalScreenData =
|
|
@@ -183,15 +181,6 @@ export const useRoute = (): {
|
|
|
183
181
|
plugins
|
|
184
182
|
);
|
|
185
183
|
|
|
186
|
-
const currentRouteScreenData = legacyScreenData(
|
|
187
|
-
{
|
|
188
|
-
screen: currentStack?.state?.screen ?? navigator.data?.screen ?? {},
|
|
189
|
-
entry: currentStack?.state?.entry ?? {},
|
|
190
|
-
} as NavigationScreenData,
|
|
191
|
-
|
|
192
|
-
plugins
|
|
193
|
-
);
|
|
194
|
-
|
|
195
184
|
// There are 4 route scenarios
|
|
196
185
|
// For regular screens take date from navigator stack.
|
|
197
186
|
// is path is model grab screenData from modal state
|
|
@@ -200,63 +189,30 @@ export const useRoute = (): {
|
|
|
200
189
|
// if path is hook grab screenData from screenData
|
|
201
190
|
|
|
202
191
|
if (isModalPathname(pathname)) {
|
|
203
|
-
|
|
192
|
+
const screenData = modalScreenData ?? ({} as ZappEntry);
|
|
193
|
+
|
|
194
|
+
return { screenData, pathname };
|
|
204
195
|
}
|
|
205
196
|
|
|
206
197
|
if (isVideoModalPathname(pathname)) {
|
|
207
|
-
|
|
198
|
+
const screenData = videoModalScreenData as LegacyNavigationScreenData;
|
|
199
|
+
|
|
200
|
+
return { screenData, pathname };
|
|
208
201
|
}
|
|
209
202
|
|
|
210
203
|
if (isHookModalPathname(pathname)) {
|
|
211
|
-
|
|
204
|
+
const screenData = hookModalScreenData;
|
|
205
|
+
|
|
206
|
+
return { screenData, pathname };
|
|
212
207
|
}
|
|
213
208
|
|
|
214
209
|
if (isHookPathname(pathname)) {
|
|
215
|
-
|
|
216
|
-
* HACK
|
|
217
|
-
*
|
|
218
|
-
* This condition relies on hacky approach to get the current hook screen data
|
|
219
|
-
* using navigator.screenData for some cases.
|
|
220
|
-
* This is used when hook is in sequence.
|
|
221
|
-
*/
|
|
222
|
-
|
|
223
|
-
// case 1: stack not yet updated in navigator context, but navigator.screenData is updated already.
|
|
224
|
-
if (!currentStack) {
|
|
225
|
-
return composeRouteData(navigator.screenData);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const isValidHookInCurrentRouteScreenData =
|
|
229
|
-
"hookPlugin" in currentRouteScreenData &&
|
|
230
|
-
!!currentRouteScreenData.hookPlugin?.module;
|
|
231
|
-
|
|
232
|
-
let screenData;
|
|
233
|
-
|
|
234
|
-
// case 2: stack has valid hook data
|
|
235
|
-
if (isValidHookInCurrentRouteScreenData) {
|
|
236
|
-
screenData = currentRouteScreenData;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const navigatorScreenData = navigator.screenData as NavigatorEntry;
|
|
240
|
-
|
|
241
|
-
// case 3: current hookPlugin is missing weight, but navigator.screenData has weight, use navigator.screenData
|
|
242
|
-
if (
|
|
243
|
-
screenData.hookPlugin.identifier ===
|
|
244
|
-
navigatorScreenData?.hookPlugin?.identifier &&
|
|
245
|
-
!screenData.hookPlugin?.weight &&
|
|
246
|
-
navigatorScreenData?.hookPlugin?.weight
|
|
247
|
-
) {
|
|
248
|
-
screenData = navigator.screenData;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return composeRouteData(screenData);
|
|
210
|
+
return { screenData: screenDataContext, pathname };
|
|
252
211
|
}
|
|
253
212
|
|
|
254
|
-
|
|
255
|
-
if (!currentStack) {
|
|
256
|
-
return composeRouteData(navigator.screenData);
|
|
257
|
-
}
|
|
213
|
+
const screenData = screenDataContext;
|
|
258
214
|
|
|
259
|
-
return
|
|
215
|
+
return { screenData, pathname };
|
|
260
216
|
};
|
|
261
217
|
|
|
262
218
|
type Callbacks = Partial<{
|
|
@@ -511,3 +467,15 @@ export const useUniqueRouteSuffix = (): Return => {
|
|
|
511
467
|
|
|
512
468
|
return withUniqueRouteSuffix;
|
|
513
469
|
};
|
|
470
|
+
|
|
471
|
+
export const useNavbarId = () => {
|
|
472
|
+
const withUniqueRouteSuffix = useUniqueRouteSuffix();
|
|
473
|
+
|
|
474
|
+
return withUniqueRouteSuffix(QUICK_BRICK_NAVBAR);
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
export const useContentId = () => {
|
|
478
|
+
const withUniqueRouteSuffix = useUniqueRouteSuffix();
|
|
479
|
+
|
|
480
|
+
return withUniqueRouteSuffix(QUICK_BRICK_CONTENT);
|
|
481
|
+
};
|
|
@@ -5,7 +5,7 @@ import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-co
|
|
|
5
5
|
import { useNavigation } from "../navigation/useNavigation";
|
|
6
6
|
|
|
7
7
|
import { ScreenContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenContext";
|
|
8
|
-
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/
|
|
8
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
9
9
|
|
|
10
10
|
export function useScreenContextV2() {
|
|
11
11
|
return useContext(ScreenContext);
|
|
@@ -45,7 +45,6 @@ export function useSetNavbarState() {
|
|
|
45
45
|
|
|
46
46
|
export function useScreenContext(): NavigationScreenData {
|
|
47
47
|
const navigator = useNavigation();
|
|
48
|
-
|
|
49
48
|
const screenData = useContext(ScreenDataContext);
|
|
50
49
|
|
|
51
50
|
const modalScreenData = navigator?.modalData;
|