@applicaster/zapp-react-native-utils 14.0.0-alpha.8419134002 → 14.0.0-alpha.8583696651
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/sendHeaderClickEvent.ts +1 -1
- package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -1
- package/analyticsUtils/index.tsx +3 -4
- package/analyticsUtils/manager.ts +1 -1
- package/appUtils/HooksManager/Hook.ts +4 -4
- package/appUtils/HooksManager/index.ts +11 -1
- package/appUtils/accessibilityManager/index.ts +3 -3
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
- package/appUtils/playerManager/useChapterMarker.tsx +0 -1
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
- package/arrayUtils/index.ts +1 -1
- package/componentsUtils/__tests__/isTabsScreen.test.ts +38 -0
- package/componentsUtils/index.ts +4 -1
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +547 -0
- package/configurationUtils/manifestKeyParser.ts +57 -32
- package/focusManager/FocusManager.ts +22 -10
- package/focusManager/Tree.ts +25 -21
- package/focusManager/__tests__/FocusManager.test.ts +50 -8
- package/index.d.ts +0 -9
- package/package.json +2 -2
- package/playerUtils/index.ts +51 -0
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +12 -13
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +39 -88
- package/reactHooks/layout/isTablet/index.ts +12 -5
- package/reactHooks/navigation/index.ts +7 -5
- package/testUtils/index.tsx +7 -8
|
@@ -176,18 +176,30 @@ class FocusManager {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
registerFocusable(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
isFocusableCell
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
registerFocusable({
|
|
180
|
+
touchableRef,
|
|
181
|
+
parentFocusableRef,
|
|
182
|
+
isFocusableCell,
|
|
183
|
+
parentFocusableId,
|
|
184
|
+
}: {
|
|
185
|
+
touchableRef: FocusManager.TouchableReactRef;
|
|
186
|
+
parentFocusableRef: FocusManager.TouchableReactRef;
|
|
187
|
+
isFocusableCell: boolean;
|
|
188
|
+
parentFocusableId: string;
|
|
189
|
+
}) {
|
|
190
|
+
const focusableId = getFocusableId(touchableRef);
|
|
191
|
+
|
|
185
192
|
const focusableComponent = FocusManager.findFocusable(focusableId);
|
|
186
193
|
|
|
187
|
-
if (!focusableComponent &&
|
|
188
|
-
this.focusableComponents.push(
|
|
194
|
+
if (!focusableComponent && touchableRef) {
|
|
195
|
+
this.focusableComponents.push(touchableRef);
|
|
189
196
|
|
|
190
|
-
this.tree.add(
|
|
197
|
+
this.tree.add(
|
|
198
|
+
touchableRef,
|
|
199
|
+
parentFocusableRef,
|
|
200
|
+
isFocusableCell,
|
|
201
|
+
parentFocusableId
|
|
202
|
+
);
|
|
191
203
|
} else {
|
|
192
204
|
logger.warning("Focusable component already registered", {
|
|
193
205
|
id: focusableId,
|
|
@@ -267,7 +279,7 @@ class FocusManager {
|
|
|
267
279
|
|
|
268
280
|
if (nextFocus) {
|
|
269
281
|
// HACK: hack to fix the hack below
|
|
270
|
-
// HACK: putting call to the end of the event loop so the next component has a
|
|
282
|
+
// HACK: putting call to the end of the event loop so the next component has a chance to be registered
|
|
271
283
|
setTimeout(() => {
|
|
272
284
|
FocusManager.instance.setFocus(nextFocus, {
|
|
273
285
|
direction: "down",
|
package/focusManager/Tree.ts
CHANGED
|
@@ -8,37 +8,41 @@ export class Tree {
|
|
|
8
8
|
this.tree = focusManagerTree;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
add(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
add(
|
|
12
|
+
touchableRef: FocusManager.TouchableReactRef,
|
|
13
|
+
parentFocusableRef: FocusManager.TouchableReactRef,
|
|
14
|
+
isFocusableCell: boolean,
|
|
15
|
+
parentFocusableId: string
|
|
16
|
+
) {
|
|
17
|
+
const focusableId = getFocusableId(touchableRef);
|
|
18
|
+
const parentId = getFocusableId(parentFocusableRef) || parentFocusableId;
|
|
14
19
|
const focusableComponentInTree = this.find(focusableId);
|
|
15
20
|
|
|
16
21
|
// update node if it already exists
|
|
17
22
|
if (focusableComponentInTree) {
|
|
18
|
-
focusableComponentInTree.updateNode(
|
|
23
|
+
focusableComponentInTree.updateNode(touchableRef);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
if (!this.find(parentId)) {
|
|
27
|
+
// create temporary node to the root of the tree
|
|
28
|
+
this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
|
|
29
|
+
}
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
const parentNode = this.find(parentId);
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
if (parentNode) {
|
|
34
|
+
if (focusableComponentInTree) {
|
|
35
|
+
focusableComponentInTree.isFocusableCell = isFocusableCell;
|
|
36
|
+
focusableComponentInTree.parentId = parentNode.id;
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
parentNode.addChild(focusableComponentInTree);
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
40
|
+
// remove root object from the list
|
|
41
|
+
this.tree = this.tree.filter(
|
|
42
|
+
(node) => node !== focusableComponentInTree
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
parentNode.addChild(touchableRef, focusableId, isFocusableCell);
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { focusManager } from "../FocusManager";
|
|
2
2
|
|
|
3
|
+
const isFocusableCell = true;
|
|
4
|
+
const parentFocusableId = "parentFocusableId";
|
|
5
|
+
|
|
3
6
|
const group = {
|
|
4
7
|
current: {
|
|
5
8
|
props: {
|
|
@@ -62,13 +65,47 @@ jest.useFakeTimers();
|
|
|
62
65
|
|
|
63
66
|
describe("FocusManager", () => {
|
|
64
67
|
beforeAll(() => {
|
|
65
|
-
focusManager.registerFocusable(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
focusManager.registerFocusable({
|
|
69
|
+
touchableRef: group,
|
|
70
|
+
parentFocusableRef: { current: null },
|
|
71
|
+
isFocusableCell,
|
|
72
|
+
parentFocusableId,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
focusManager.registerFocusable({
|
|
76
|
+
touchableRef: child1,
|
|
77
|
+
parentFocusableRef: group,
|
|
78
|
+
isFocusableCell,
|
|
79
|
+
parentFocusableId,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
focusManager.registerFocusable({
|
|
83
|
+
touchableRef: child2,
|
|
84
|
+
parentFocusableRef: group,
|
|
85
|
+
isFocusableCell,
|
|
86
|
+
parentFocusableId,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
focusManager.registerFocusable({
|
|
90
|
+
touchableRef: child3,
|
|
91
|
+
parentFocusableRef: child2,
|
|
92
|
+
isFocusableCell,
|
|
93
|
+
parentFocusableId,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
focusManager.registerFocusable({
|
|
97
|
+
touchableRef: child4,
|
|
98
|
+
parentFocusableRef: child2,
|
|
99
|
+
isFocusableCell,
|
|
100
|
+
parentFocusableId,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
focusManager.registerFocusable({
|
|
104
|
+
touchableRef: child5,
|
|
105
|
+
parentFocusableRef: child2,
|
|
106
|
+
isFocusableCell,
|
|
107
|
+
parentFocusableId,
|
|
108
|
+
});
|
|
72
109
|
});
|
|
73
110
|
|
|
74
111
|
it("focusManager should be defined", () => {
|
|
@@ -199,7 +236,12 @@ describe("FocusManager", () => {
|
|
|
199
236
|
});
|
|
200
237
|
|
|
201
238
|
it("focusManager registerFocusable should register", () => {
|
|
202
|
-
focusManager.registerFocusable(
|
|
239
|
+
focusManager.registerFocusable({
|
|
240
|
+
touchableRef: child5,
|
|
241
|
+
parentFocusableRef: child2,
|
|
242
|
+
isFocusableCell,
|
|
243
|
+
parentFocusableId,
|
|
244
|
+
});
|
|
203
245
|
|
|
204
246
|
expect(
|
|
205
247
|
focusManager.isFocusableChildOf(child5.current.props.id, child2)
|
package/index.d.ts
CHANGED
|
@@ -137,12 +137,3 @@ declare type AccessibilityState = {
|
|
|
137
137
|
reduceMotionEnabled: boolean;
|
|
138
138
|
boldTextEnabled: boolean;
|
|
139
139
|
};
|
|
140
|
-
|
|
141
|
-
declare type AccessibilityProps = {
|
|
142
|
-
accessibilityLabel?: string;
|
|
143
|
-
accessibilityHint?: string;
|
|
144
|
-
"aria-label"?: string;
|
|
145
|
-
"aria-description"?: string;
|
|
146
|
-
accessibilityRole?: string;
|
|
147
|
-
"aria-role"?: string;
|
|
148
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.8583696651",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@applicaster/applicaster-types": "14.0.0-alpha.
|
|
30
|
+
"@applicaster/applicaster-types": "14.0.0-alpha.8583696651",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
package/playerUtils/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { isFilledArray } from "@applicaster/zapp-react-native-utils/arrayUtils";
|
|
|
5
5
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
6
6
|
|
|
7
7
|
import { getBoolFromConfigValue } from "../configurationUtils";
|
|
8
|
+
import { Dimensions } from "react-native";
|
|
8
9
|
|
|
9
10
|
export { getPlayerActionButtons } from "./getPlayerActionButtons";
|
|
10
11
|
|
|
@@ -97,3 +98,53 @@ export const isAudioItem = (item: Option<ZappEntry>) => {
|
|
|
97
98
|
export const isInlineTV = (screenData) => {
|
|
98
99
|
return isTV() && isFilledArray(screenData?.ui_components);
|
|
99
100
|
};
|
|
101
|
+
|
|
102
|
+
const isPercentage = (value: string | number): boolean => {
|
|
103
|
+
if (typeof value === "string") {
|
|
104
|
+
return value.includes("%");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const getPercentageOf = (percent: string, value: number) => {
|
|
111
|
+
const percentageValue = parseFloat(percent.replace("%", ""));
|
|
112
|
+
|
|
113
|
+
if (isNaN(percentageValue)) {
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return (value * percentageValue) / 100;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
type DimensionsT = {
|
|
121
|
+
width: number | string;
|
|
122
|
+
height: number | string | undefined;
|
|
123
|
+
aspectRatio?: number;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const getTabletWidth = (
|
|
127
|
+
tablet_landscape_sidebar_width,
|
|
128
|
+
dimensions: DimensionsT
|
|
129
|
+
) => {
|
|
130
|
+
const { width: SCREEN_WIDTH } = Dimensions.get("screen");
|
|
131
|
+
|
|
132
|
+
const { width } = dimensions;
|
|
133
|
+
let widthValue = Number(width);
|
|
134
|
+
|
|
135
|
+
if (isPercentage(width)) {
|
|
136
|
+
widthValue = getPercentageOf(width.toString(), SCREEN_WIDTH);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const sidebarWidth = Number(tablet_landscape_sidebar_width?.replace("%", ""));
|
|
140
|
+
|
|
141
|
+
if (tablet_landscape_sidebar_width?.includes("%")) {
|
|
142
|
+
return widthValue * (1 - sidebarWidth / 100);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (Number.isNaN(sidebarWidth)) {
|
|
146
|
+
return widthValue * 0.65;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return widthValue - sidebarWidth;
|
|
150
|
+
};
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { renderHook } from "@testing-library/react-hooks";
|
|
4
|
+
import { act, waitFor } from "@testing-library/react-native";
|
|
4
5
|
import { Provider } from "react-redux";
|
|
5
6
|
import configureStore from "redux-mock-store";
|
|
7
|
+
import { useTrackedView } from "../useTrackedView";
|
|
6
8
|
|
|
7
9
|
const mockUpdateComponentsPositions = jest.fn();
|
|
8
10
|
|
|
9
11
|
jest.mock(
|
|
10
12
|
"@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext",
|
|
11
13
|
() => ({
|
|
12
|
-
useScreenTrackedViewPositionsContext: jest.fn()
|
|
14
|
+
useScreenTrackedViewPositionsContext: jest.fn(() => ({
|
|
13
15
|
updateComponentsPositions: mockUpdateComponentsPositions,
|
|
14
16
|
value: {
|
|
15
17
|
"123": { componentId: "123", centerX: 0.4, centerY: 0.5 },
|
|
16
18
|
"124": { componentId: "124", centerX: 0.2, centerY: 0.3 },
|
|
17
19
|
},
|
|
18
|
-
}),
|
|
20
|
+
})),
|
|
19
21
|
})
|
|
20
22
|
);
|
|
21
23
|
|
|
22
|
-
jest.useFakeTimers(
|
|
24
|
+
jest.useFakeTimers();
|
|
23
25
|
|
|
24
26
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
|
|
25
27
|
|
|
@@ -32,10 +34,8 @@ const Wrapper = ({ children }: { children: React.ReactChild }) => (
|
|
|
32
34
|
<Provider store={store}>{children}</Provider>
|
|
33
35
|
);
|
|
34
36
|
|
|
35
|
-
const { useTrackedView } = require("../useTrackedView");
|
|
36
|
-
|
|
37
37
|
describe("useTrackCurrentAutoScrollingElement", () => {
|
|
38
|
-
it("should update position for selected component - onViewportEnter", () => {
|
|
38
|
+
it("should update position for selected component - onViewportEnter", async () => {
|
|
39
39
|
const { result } = renderHook(() => useTrackedView("123"), {
|
|
40
40
|
wrapper: Wrapper,
|
|
41
41
|
});
|
|
@@ -46,14 +46,13 @@ describe("useTrackCurrentAutoScrollingElement", () => {
|
|
|
46
46
|
rect: { left: 1, right: 1, top: 1, bottom: 1 },
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
act(
|
|
50
|
-
|
|
49
|
+
act(() => {
|
|
50
|
+
result.current.onPositionUpdated(mockRect);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
expect(result.current.inViewPort).toBe(true);
|
|
53
|
+
await waitFor(() => {
|
|
54
|
+
expect(result.current.inViewPort).toBe(true);
|
|
55
|
+
});
|
|
57
56
|
|
|
58
57
|
expect(mockUpdateComponentsPositions).toHaveBeenCalledWith(
|
|
59
58
|
"123",
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { renderHook } from "@testing-library/react-hooks";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import * as ReactRedux from "react-redux";
|
|
2
|
+
import { allFeedsIsReady, useBatchLoading } from "../useBatchLoading";
|
|
3
|
+
import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
4
|
+
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
6
5
|
|
|
7
6
|
jest.mock("../../navigation");
|
|
8
7
|
|
|
@@ -13,17 +12,18 @@ jest.mock(
|
|
|
13
12
|
})
|
|
14
13
|
);
|
|
15
14
|
|
|
16
|
-
const
|
|
17
|
-
const allFeedsIsReady = require("../useBatchLoading").allFeedsIsReady;
|
|
18
|
-
|
|
19
|
-
const mockStore = reduxMockStore.default([thunk]);
|
|
20
|
-
|
|
21
|
-
const wrapper: React.FC<any> = ({ children, store }) => (
|
|
22
|
-
<ReactRedux.Provider store={store}>{children}</ReactRedux.Provider>
|
|
23
|
-
);
|
|
15
|
+
const wrapper = WrappedWithProviders;
|
|
24
16
|
|
|
25
17
|
describe("useBatchLoading", () => {
|
|
26
|
-
const
|
|
18
|
+
const data = [
|
|
19
|
+
{ data: { source: "url1" }, component_type: "any" },
|
|
20
|
+
{ data: { source: "url2" }, component_type: "any" },
|
|
21
|
+
{ data: { source: "url3" }, component_type: "any" },
|
|
22
|
+
{ data: { source: "url4" }, component_type: "any" },
|
|
23
|
+
{ data: { source: "url5" }, component_type: "any" },
|
|
24
|
+
{ data: { source: "url6" }, component_type: "any" },
|
|
25
|
+
// ... more items
|
|
26
|
+
];
|
|
27
27
|
|
|
28
28
|
beforeAll(() => {
|
|
29
29
|
jest.useFakeTimers();
|
|
@@ -34,7 +34,7 @@ describe("useBatchLoading", () => {
|
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it("loadPipesData start loading not started requests", () => {
|
|
37
|
-
const store =
|
|
37
|
+
const store = {
|
|
38
38
|
zappPipes: {
|
|
39
39
|
url1: {
|
|
40
40
|
loading: true,
|
|
@@ -53,29 +53,17 @@ describe("useBatchLoading", () => {
|
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
test: "true",
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
56
|
+
};
|
|
59
57
|
|
|
60
58
|
const initialBatchSize = 3;
|
|
61
59
|
const riverId = "123";
|
|
62
60
|
|
|
63
|
-
const data = [
|
|
64
|
-
{ data: { source: "url1" } },
|
|
65
|
-
{ data: { source: "url2" } },
|
|
66
|
-
{ data: { source: "url3" } },
|
|
67
|
-
{ data: { source: "url4" } },
|
|
68
|
-
{ data: { source: "url5" } },
|
|
69
|
-
{ data: { source: "url6" } },
|
|
70
|
-
// ... more items
|
|
71
|
-
];
|
|
72
|
-
|
|
73
61
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
74
62
|
wrapper,
|
|
75
63
|
initialProps: { store },
|
|
76
64
|
});
|
|
77
65
|
|
|
78
|
-
const actions =
|
|
66
|
+
const actions = (appStore.getStore() as any).getActions();
|
|
79
67
|
|
|
80
68
|
expect(actions).toHaveLength(2);
|
|
81
69
|
|
|
@@ -91,7 +79,7 @@ describe("useBatchLoading", () => {
|
|
|
91
79
|
});
|
|
92
80
|
|
|
93
81
|
it("loadPipesData start loading new feed when 1 feed is done loading and 1 is in loading state", () => {
|
|
94
|
-
const store =
|
|
82
|
+
const store = {
|
|
95
83
|
zappPipes: {
|
|
96
84
|
url1: {
|
|
97
85
|
loading: false,
|
|
@@ -110,31 +98,17 @@ describe("useBatchLoading", () => {
|
|
|
110
98
|
},
|
|
111
99
|
},
|
|
112
100
|
test: "true",
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
101
|
+
};
|
|
116
102
|
|
|
117
103
|
const initialBatchSize = 3;
|
|
118
104
|
const riverId = "123";
|
|
119
105
|
|
|
120
|
-
const data = [
|
|
121
|
-
{ data: { source: "url1" } },
|
|
122
|
-
{ data: { source: "url2" } },
|
|
123
|
-
{ data: { source: "url3" } },
|
|
124
|
-
{ data: { source: "url4" } },
|
|
125
|
-
{ data: { source: "url5" } },
|
|
126
|
-
{ data: { source: "url6" } },
|
|
127
|
-
// ... more items
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
expect(useDispatchSpy).toBeCalledTimes(0);
|
|
131
|
-
|
|
132
106
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
133
107
|
wrapper,
|
|
134
108
|
initialProps: { store },
|
|
135
109
|
});
|
|
136
110
|
|
|
137
|
-
const actions =
|
|
111
|
+
const actions = (appStore.getStore() as any).getActions();
|
|
138
112
|
|
|
139
113
|
expect(actions).toHaveLength(1);
|
|
140
114
|
|
|
@@ -145,38 +119,26 @@ describe("useBatchLoading", () => {
|
|
|
145
119
|
});
|
|
146
120
|
|
|
147
121
|
it("loadPipesData has been called when no data cached", () => {
|
|
148
|
-
const store =
|
|
122
|
+
const store = {
|
|
149
123
|
zappPipes: {},
|
|
150
124
|
test: "true",
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
125
|
+
};
|
|
154
126
|
|
|
155
127
|
const initialBatchSize = 3;
|
|
156
128
|
const riverId = "123";
|
|
157
129
|
|
|
158
|
-
const data = [
|
|
159
|
-
{ data: { source: "url1" } },
|
|
160
|
-
{ data: { source: "url2" } },
|
|
161
|
-
{ data: { source: "url3" } },
|
|
162
|
-
{ data: { source: "url4" } },
|
|
163
|
-
{ data: { source: "url5" } },
|
|
164
|
-
{ data: { source: "url6" } },
|
|
165
|
-
// ... more items
|
|
166
|
-
];
|
|
167
|
-
|
|
168
130
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
169
131
|
wrapper,
|
|
170
132
|
initialProps: { store },
|
|
171
133
|
});
|
|
172
134
|
|
|
173
|
-
const actions =
|
|
135
|
+
const actions = (appStore.getStore() as any).getActions();
|
|
174
136
|
|
|
175
137
|
expect(actions).toHaveLength(3);
|
|
176
138
|
});
|
|
177
139
|
|
|
178
140
|
it("initial batch ready when all initial items loaded", () => {
|
|
179
|
-
const store =
|
|
141
|
+
const store = {
|
|
180
142
|
zappPipes: {
|
|
181
143
|
url1: {
|
|
182
144
|
loading: false,
|
|
@@ -194,19 +156,11 @@ describe("useBatchLoading", () => {
|
|
|
194
156
|
data: {},
|
|
195
157
|
},
|
|
196
158
|
},
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
159
|
+
};
|
|
200
160
|
|
|
201
161
|
const initialBatchSize = 3;
|
|
202
162
|
const riverId = "123";
|
|
203
163
|
|
|
204
|
-
const data: Partial<ZappUIComponent>[] = [
|
|
205
|
-
{ data: { source: "url1" } },
|
|
206
|
-
{ data: { source: "url2" } },
|
|
207
|
-
{ data: { source: "url3" } },
|
|
208
|
-
];
|
|
209
|
-
|
|
210
164
|
const { result } = renderHook(
|
|
211
165
|
() => useBatchLoading(data, { initialBatchSize, riverId }),
|
|
212
166
|
{ wrapper, initialProps: { store } }
|
|
@@ -216,12 +170,10 @@ describe("useBatchLoading", () => {
|
|
|
216
170
|
});
|
|
217
171
|
|
|
218
172
|
it("gallery-qb: loadPipesData should be called only once for first component in the gallery", () => {
|
|
219
|
-
const store =
|
|
173
|
+
const store = {
|
|
220
174
|
zappPipes: {},
|
|
221
175
|
test: "true",
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
176
|
+
};
|
|
225
177
|
|
|
226
178
|
const initialBatchSize = 3;
|
|
227
179
|
const riverId = "123";
|
|
@@ -231,11 +183,11 @@ describe("useBatchLoading", () => {
|
|
|
231
183
|
component_type: "gallery-qb",
|
|
232
184
|
ui_components: [{ data: { source: "url1" } }],
|
|
233
185
|
},
|
|
234
|
-
{ data: { source: "url2" } },
|
|
235
|
-
{ data: { source: "url3" } },
|
|
236
|
-
{ data: { source: "url4" } },
|
|
237
|
-
{ data: { source: "url5" } },
|
|
238
|
-
{ data: { source: "url6" } },
|
|
186
|
+
{ data: { source: "url2" }, component_type: "any" },
|
|
187
|
+
{ data: { source: "url3" }, component_type: "any" },
|
|
188
|
+
{ data: { source: "url4" }, component_type: "any" },
|
|
189
|
+
{ data: { source: "url5" }, component_type: "any" },
|
|
190
|
+
{ data: { source: "url6" }, component_type: "any" },
|
|
239
191
|
// ... more items
|
|
240
192
|
];
|
|
241
193
|
|
|
@@ -244,13 +196,13 @@ describe("useBatchLoading", () => {
|
|
|
244
196
|
initialProps: { store },
|
|
245
197
|
});
|
|
246
198
|
|
|
247
|
-
const actions =
|
|
199
|
+
const actions = (appStore.getStore() as any).getActions();
|
|
248
200
|
|
|
249
201
|
expect(actions).toHaveLength(1);
|
|
250
202
|
});
|
|
251
203
|
|
|
252
204
|
it("gallery-qb: initial batch ready when all initial items loaded", () => {
|
|
253
|
-
const store =
|
|
205
|
+
const store = {
|
|
254
206
|
zappPipes: {
|
|
255
207
|
url1: {
|
|
256
208
|
loading: false,
|
|
@@ -258,20 +210,19 @@ describe("useBatchLoading", () => {
|
|
|
258
210
|
data: {},
|
|
259
211
|
},
|
|
260
212
|
},
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
213
|
+
};
|
|
264
214
|
|
|
265
215
|
const initialBatchSize = 3;
|
|
266
216
|
const riverId = "123";
|
|
267
217
|
|
|
268
|
-
const data
|
|
218
|
+
const data = [
|
|
269
219
|
{
|
|
270
220
|
component_type: "gallery-qb",
|
|
271
|
-
|
|
221
|
+
data: {},
|
|
222
|
+
ui_components: [{ data: { source: "url1" } }] as any,
|
|
272
223
|
},
|
|
273
|
-
{ data: { source: "url2" } },
|
|
274
|
-
{ data: { source: "url3" } },
|
|
224
|
+
{ data: { source: "url2" }, component_type: "any" },
|
|
225
|
+
{ data: { source: "url3" }, component_type: "any" },
|
|
275
226
|
];
|
|
276
227
|
|
|
277
228
|
const { result } = renderHook(
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import { NativeModules, Platform } from "react-native";
|
|
2
2
|
|
|
3
|
+
export const isAndroidTablet = () => {
|
|
4
|
+
const { initialProps } = NativeModules.QuickBrickCommunicationModule;
|
|
5
|
+
|
|
6
|
+
return initialProps?.is_tablet;
|
|
7
|
+
};
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Determines wether the given device is a tablet based on dimensions, orientation, and platform
|
|
5
11
|
* @param {Object} dimensions - Dimensions object passed to the function
|
|
6
12
|
* @param {String} orientation - Orientation enum passed to the function
|
|
7
13
|
* @returns {Boolean} isTablet - returns whether the given device is a tablet
|
|
8
14
|
*/
|
|
9
|
-
export const isTablet = (
|
|
15
|
+
export const isTablet = (
|
|
16
|
+
dimensions?: { width: number; height: number },
|
|
17
|
+
orientation?: string
|
|
18
|
+
) => {
|
|
10
19
|
if (Platform?.OS === "ios") {
|
|
11
20
|
return Platform?.isPad;
|
|
12
21
|
} else if (Platform?.OS === "android") {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return initialProps?.is_tablet;
|
|
22
|
+
return isAndroidTablet();
|
|
16
23
|
}
|
|
17
24
|
|
|
18
|
-
const { width } = dimensions;
|
|
25
|
+
const { width } = dimensions || {};
|
|
19
26
|
|
|
20
27
|
if (width < 600) return false;
|
|
21
28
|
if (width >= 600 && width < 840) return orientation === "portrait";
|
|
@@ -14,7 +14,7 @@ import { HOOKS_EVENTS } from "../../appUtils/HooksManager/constants";
|
|
|
14
14
|
import { getRiverFromRoute, getTargetRoute } from "../../navigationUtils";
|
|
15
15
|
import { useConnectionInfo } from "../connection";
|
|
16
16
|
|
|
17
|
-
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
17
|
+
import { isTV, isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
18
18
|
import { useNavbarState } from "../screen";
|
|
19
19
|
|
|
20
20
|
export { useNavigation } from "./useNavigation";
|
|
@@ -127,11 +127,13 @@ export function isNavBarVisible(
|
|
|
127
127
|
|
|
128
128
|
export const useBackHandler = (cb: () => boolean) => {
|
|
129
129
|
useEffect(() => {
|
|
130
|
-
|
|
130
|
+
if (!isWeb()) {
|
|
131
|
+
const unsubscribe = BackHandler.addEventListener("hardwareBackPress", cb);
|
|
131
132
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
return () => {
|
|
134
|
+
unsubscribe.remove();
|
|
135
|
+
};
|
|
136
|
+
}
|
|
135
137
|
}, [cb]);
|
|
136
138
|
};
|
|
137
139
|
|