@applicaster/zapp-react-native-utils 14.0.0-alpha.3259144304 → 14.0.0-alpha.3471443312
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 +1 -1
- package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
- package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
- package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +1 -2
- package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
- package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
- package/analyticsUtils/events.ts +8 -0
- package/analyticsUtils/index.tsx +4 -3
- package/analyticsUtils/manager.ts +1 -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/focusManager/FocusManager.ts +26 -16
- package/focusManager/Tree.ts +25 -21
- package/focusManager/__tests__/FocusManager.test.ts +50 -8
- package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
- package/navigationUtils/__tests__/mapContentTypesToRivers.test.ts +130 -0
- package/navigationUtils/index.ts +6 -4
- package/package.json +2 -2
- package/playerUtils/getPlayerActionButtons.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +16 -13
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +88 -39
- package/reactHooks/feed/useBatchLoading.ts +9 -7
- package/reactHooks/feed/useFeedLoader.tsx +12 -8
- package/reactHooks/feed/usePipesCacheReset.ts +3 -3
- package/reactHooks/layout/__tests__/index.test.tsx +3 -1
- package/reactHooks/layout/isTablet/index.ts +5 -2
- package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +34 -36
- package/reactHooks/layout/useDimensions/useDimensions.ts +2 -3
- package/reactHooks/layout/useLayoutVersion.ts +5 -5
- package/reactHooks/navigation/index.ts +2 -2
- package/reactHooks/navigation/useIsScreenActive.ts +9 -5
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +4 -0
- package/reactHooks/screen/useScreenContext.ts +1 -1
- package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
- package/reactHooks/state/useRivers.ts +7 -8
- package/riverComponetsMeasurementProvider/index.tsx +1 -1
- package/services/js2native.ts +1 -0
- package/testUtils/index.tsx +8 -7
- package/time/BackgroundTimer.ts +5 -3
- package/utils/index.ts +5 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { mapContentTypesToRivers } from "../index";
|
|
2
|
+
|
|
3
|
+
describe("mapContentTypesToRivers", () => {
|
|
4
|
+
it("should return the correct content types mapped to rivers", () => {
|
|
5
|
+
const state = {
|
|
6
|
+
rivers: {
|
|
7
|
+
"river-1": {
|
|
8
|
+
plugin_type: "river",
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
contentTypes: {
|
|
12
|
+
"content-type-1": {
|
|
13
|
+
screen_id: "river-1",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const result = mapContentTypesToRivers(state);
|
|
19
|
+
|
|
20
|
+
expect(result).toEqual({
|
|
21
|
+
"content-type-1": {
|
|
22
|
+
screenType: "river",
|
|
23
|
+
screen_id: "river-1",
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should return null if contentTypes is undefined", () => {
|
|
29
|
+
const state = {
|
|
30
|
+
rivers: {
|
|
31
|
+
"river-1": {
|
|
32
|
+
plugin_type: "river",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
// contentTypes is missing
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const result = mapContentTypesToRivers(state);
|
|
39
|
+
|
|
40
|
+
expect(result).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should skip content types whose screen does not exist in rivers", () => {
|
|
44
|
+
const state = {
|
|
45
|
+
rivers: {
|
|
46
|
+
"river-1": {
|
|
47
|
+
plugin_type: "river",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
contentTypes: {
|
|
51
|
+
"content-type-1": {
|
|
52
|
+
screen_id: "river-1",
|
|
53
|
+
},
|
|
54
|
+
"content-type-2": {
|
|
55
|
+
screen_id: "river-2", // river-2 does not exist
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const result = mapContentTypesToRivers(state);
|
|
61
|
+
|
|
62
|
+
expect(result).toEqual({
|
|
63
|
+
"content-type-1": {
|
|
64
|
+
screenType: "river",
|
|
65
|
+
screen_id: "river-1",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// result is not null, but may be undefined for missing keys
|
|
70
|
+
expect(result && result["content-type-2"]).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should use 'type' if 'plugin_type' is not present in river", () => {
|
|
74
|
+
const state = {
|
|
75
|
+
rivers: {
|
|
76
|
+
"river-1": {
|
|
77
|
+
type: "custom-type",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
contentTypes: {
|
|
81
|
+
"content-type-1": {
|
|
82
|
+
screen_id: "river-1",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const result = mapContentTypesToRivers(state);
|
|
88
|
+
|
|
89
|
+
expect(result).toEqual({
|
|
90
|
+
"content-type-1": {
|
|
91
|
+
screenType: "custom-type",
|
|
92
|
+
screen_id: "river-1",
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should skip content types if neither plugin_type nor type is present in river", () => {
|
|
98
|
+
const state = {
|
|
99
|
+
rivers: {
|
|
100
|
+
"river-1": {
|
|
101
|
+
// no plugin_type or type
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
contentTypes: {
|
|
105
|
+
"content-type-1": {
|
|
106
|
+
screen_id: "river-1",
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const result = mapContentTypesToRivers(state);
|
|
112
|
+
|
|
113
|
+
expect(result).toEqual({});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("should handle empty contentTypes object", () => {
|
|
117
|
+
const state = {
|
|
118
|
+
rivers: {
|
|
119
|
+
"river-1": {
|
|
120
|
+
plugin_type: "river",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
contentTypes: {},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const result = mapContentTypesToRivers(state);
|
|
127
|
+
|
|
128
|
+
expect(result).toEqual({});
|
|
129
|
+
});
|
|
130
|
+
});
|
package/navigationUtils/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
isPlayable,
|
|
14
14
|
isV2River,
|
|
15
15
|
} from "./itemTypeMatchers";
|
|
16
|
+
import { RootState } from "@applicaster/zapp-react-native-redux/store";
|
|
16
17
|
|
|
17
18
|
type PathAttribute = {
|
|
18
19
|
screenType: string;
|
|
@@ -377,10 +378,11 @@ export const usesVideoModal = (
|
|
|
377
378
|
return targetScreenConfiguration?.styles?.use_video_modal;
|
|
378
379
|
};
|
|
379
380
|
|
|
380
|
-
export const mapContentTypesToRivers = (
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
381
|
+
export const mapContentTypesToRivers = (
|
|
382
|
+
state: Partial<RootState>
|
|
383
|
+
): ZappContentTypesMapped | null => {
|
|
384
|
+
const { rivers, contentTypes } = state;
|
|
385
|
+
|
|
384
386
|
if (!contentTypes) {
|
|
385
387
|
return null;
|
|
386
388
|
}
|
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.3471443312",
|
|
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.3471443312",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import { renderHook } from "@testing-library/react-hooks";
|
|
4
|
-
import { act, waitFor } from "@testing-library/react-native";
|
|
3
|
+
import { act, renderHook } from "@testing-library/react-hooks";
|
|
5
4
|
import { Provider } from "react-redux";
|
|
6
5
|
import configureStore from "redux-mock-store";
|
|
7
|
-
import { useTrackedView } from "../useTrackedView";
|
|
8
6
|
|
|
9
7
|
const mockUpdateComponentsPositions = jest.fn();
|
|
10
8
|
|
|
11
9
|
jest.mock(
|
|
12
10
|
"@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext",
|
|
13
11
|
() => ({
|
|
14
|
-
useScreenTrackedViewPositionsContext: jest.fn(
|
|
12
|
+
useScreenTrackedViewPositionsContext: jest.fn().mockReturnValue({
|
|
15
13
|
updateComponentsPositions: mockUpdateComponentsPositions,
|
|
16
14
|
value: {
|
|
17
15
|
"123": { componentId: "123", centerX: 0.4, centerY: 0.5 },
|
|
18
16
|
"124": { componentId: "124", centerX: 0.2, centerY: 0.3 },
|
|
19
17
|
},
|
|
20
|
-
})
|
|
18
|
+
}),
|
|
21
19
|
})
|
|
22
20
|
);
|
|
23
21
|
|
|
24
|
-
jest.useFakeTimers();
|
|
22
|
+
jest.useFakeTimers({ legacyFakeTimers: true });
|
|
25
23
|
|
|
26
|
-
jest.mock(
|
|
24
|
+
jest.mock(
|
|
25
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation"
|
|
26
|
+
);
|
|
27
27
|
|
|
28
28
|
const mockStore = configureStore();
|
|
29
29
|
|
|
@@ -34,8 +34,10 @@ const Wrapper = ({ children }: { children: React.ReactChild }) => (
|
|
|
34
34
|
<Provider store={store}>{children}</Provider>
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
+
const { useTrackedView } = require("../useTrackedView");
|
|
38
|
+
|
|
37
39
|
describe("useTrackCurrentAutoScrollingElement", () => {
|
|
38
|
-
it("should update position for selected component - onViewportEnter",
|
|
40
|
+
it("should update position for selected component - onViewportEnter", () => {
|
|
39
41
|
const { result } = renderHook(() => useTrackedView("123"), {
|
|
40
42
|
wrapper: Wrapper,
|
|
41
43
|
});
|
|
@@ -46,13 +48,14 @@ describe("useTrackCurrentAutoScrollingElement", () => {
|
|
|
46
48
|
rect: { left: 1, right: 1, top: 1, bottom: 1 },
|
|
47
49
|
};
|
|
48
50
|
|
|
49
|
-
act(() => {
|
|
50
|
-
result.current.onPositionUpdated(mockRect);
|
|
51
|
+
act(async () => {
|
|
52
|
+
await result.current.onPositionUpdated(mockRect);
|
|
51
53
|
});
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
// Fast-forward until all timers have been executed
|
|
56
|
+
jest.runAllTimers();
|
|
57
|
+
|
|
58
|
+
expect(result.current.inViewPort).toBe(true);
|
|
56
59
|
|
|
57
60
|
expect(mockUpdateComponentsPositions).toHaveBeenCalledWith(
|
|
58
61
|
"123",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { renderHook } from "@testing-library/react-hooks";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import * as reduxMockStore from "redux-mock-store";
|
|
3
|
+
import thunk from "redux-thunk";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import * as ReactRedux from "react-redux";
|
|
5
6
|
|
|
6
7
|
jest.mock("../../navigation");
|
|
7
8
|
|
|
@@ -12,18 +13,17 @@ jest.mock(
|
|
|
12
13
|
})
|
|
13
14
|
);
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
+
const useBatchLoading = require("../useBatchLoading").useBatchLoading;
|
|
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
|
+
);
|
|
16
24
|
|
|
17
25
|
describe("useBatchLoading", () => {
|
|
18
|
-
const
|
|
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
|
-
];
|
|
26
|
+
const useDispatchSpy = jest.spyOn(ReactRedux, "useDispatch");
|
|
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 = mockStore({
|
|
38
38
|
zappPipes: {
|
|
39
39
|
url1: {
|
|
40
40
|
loading: true,
|
|
@@ -53,17 +53,29 @@ describe("useBatchLoading", () => {
|
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
test: "true",
|
|
56
|
-
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
57
59
|
|
|
58
60
|
const initialBatchSize = 3;
|
|
59
61
|
const riverId = "123";
|
|
60
62
|
|
|
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
|
+
|
|
61
73
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
62
74
|
wrapper,
|
|
63
75
|
initialProps: { store },
|
|
64
76
|
});
|
|
65
77
|
|
|
66
|
-
const actions =
|
|
78
|
+
const actions = store.getActions();
|
|
67
79
|
|
|
68
80
|
expect(actions).toHaveLength(2);
|
|
69
81
|
|
|
@@ -79,7 +91,7 @@ describe("useBatchLoading", () => {
|
|
|
79
91
|
});
|
|
80
92
|
|
|
81
93
|
it("loadPipesData start loading new feed when 1 feed is done loading and 1 is in loading state", () => {
|
|
82
|
-
const store = {
|
|
94
|
+
const store = mockStore({
|
|
83
95
|
zappPipes: {
|
|
84
96
|
url1: {
|
|
85
97
|
loading: false,
|
|
@@ -98,17 +110,31 @@ describe("useBatchLoading", () => {
|
|
|
98
110
|
},
|
|
99
111
|
},
|
|
100
112
|
test: "true",
|
|
101
|
-
};
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
102
116
|
|
|
103
117
|
const initialBatchSize = 3;
|
|
104
118
|
const riverId = "123";
|
|
105
119
|
|
|
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
|
+
|
|
106
132
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
107
133
|
wrapper,
|
|
108
134
|
initialProps: { store },
|
|
109
135
|
});
|
|
110
136
|
|
|
111
|
-
const actions =
|
|
137
|
+
const actions = store.getActions();
|
|
112
138
|
|
|
113
139
|
expect(actions).toHaveLength(1);
|
|
114
140
|
|
|
@@ -119,26 +145,38 @@ describe("useBatchLoading", () => {
|
|
|
119
145
|
});
|
|
120
146
|
|
|
121
147
|
it("loadPipesData has been called when no data cached", () => {
|
|
122
|
-
const store = {
|
|
148
|
+
const store = mockStore({
|
|
123
149
|
zappPipes: {},
|
|
124
150
|
test: "true",
|
|
125
|
-
};
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
126
154
|
|
|
127
155
|
const initialBatchSize = 3;
|
|
128
156
|
const riverId = "123";
|
|
129
157
|
|
|
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
|
+
|
|
130
168
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
131
169
|
wrapper,
|
|
132
170
|
initialProps: { store },
|
|
133
171
|
});
|
|
134
172
|
|
|
135
|
-
const actions =
|
|
173
|
+
const actions = store.getActions();
|
|
136
174
|
|
|
137
175
|
expect(actions).toHaveLength(3);
|
|
138
176
|
});
|
|
139
177
|
|
|
140
178
|
it("initial batch ready when all initial items loaded", () => {
|
|
141
|
-
const store = {
|
|
179
|
+
const store = mockStore({
|
|
142
180
|
zappPipes: {
|
|
143
181
|
url1: {
|
|
144
182
|
loading: false,
|
|
@@ -156,11 +194,19 @@ describe("useBatchLoading", () => {
|
|
|
156
194
|
data: {},
|
|
157
195
|
},
|
|
158
196
|
},
|
|
159
|
-
};
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
160
200
|
|
|
161
201
|
const initialBatchSize = 3;
|
|
162
202
|
const riverId = "123";
|
|
163
203
|
|
|
204
|
+
const data: Partial<ZappUIComponent>[] = [
|
|
205
|
+
{ data: { source: "url1" } },
|
|
206
|
+
{ data: { source: "url2" } },
|
|
207
|
+
{ data: { source: "url3" } },
|
|
208
|
+
];
|
|
209
|
+
|
|
164
210
|
const { result } = renderHook(
|
|
165
211
|
() => useBatchLoading(data, { initialBatchSize, riverId }),
|
|
166
212
|
{ wrapper, initialProps: { store } }
|
|
@@ -170,10 +216,12 @@ describe("useBatchLoading", () => {
|
|
|
170
216
|
});
|
|
171
217
|
|
|
172
218
|
it("gallery-qb: loadPipesData should be called only once for first component in the gallery", () => {
|
|
173
|
-
const store = {
|
|
219
|
+
const store = mockStore({
|
|
174
220
|
zappPipes: {},
|
|
175
221
|
test: "true",
|
|
176
|
-
};
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
177
225
|
|
|
178
226
|
const initialBatchSize = 3;
|
|
179
227
|
const riverId = "123";
|
|
@@ -183,11 +231,11 @@ describe("useBatchLoading", () => {
|
|
|
183
231
|
component_type: "gallery-qb",
|
|
184
232
|
ui_components: [{ data: { source: "url1" } }],
|
|
185
233
|
},
|
|
186
|
-
{ data: { source: "url2" }
|
|
187
|
-
{ data: { source: "url3" }
|
|
188
|
-
{ data: { source: "url4" }
|
|
189
|
-
{ data: { source: "url5" }
|
|
190
|
-
{ data: { source: "url6" }
|
|
234
|
+
{ data: { source: "url2" } },
|
|
235
|
+
{ data: { source: "url3" } },
|
|
236
|
+
{ data: { source: "url4" } },
|
|
237
|
+
{ data: { source: "url5" } },
|
|
238
|
+
{ data: { source: "url6" } },
|
|
191
239
|
// ... more items
|
|
192
240
|
];
|
|
193
241
|
|
|
@@ -196,13 +244,13 @@ describe("useBatchLoading", () => {
|
|
|
196
244
|
initialProps: { store },
|
|
197
245
|
});
|
|
198
246
|
|
|
199
|
-
const actions =
|
|
247
|
+
const actions = store.getActions();
|
|
200
248
|
|
|
201
249
|
expect(actions).toHaveLength(1);
|
|
202
250
|
});
|
|
203
251
|
|
|
204
252
|
it("gallery-qb: initial batch ready when all initial items loaded", () => {
|
|
205
|
-
const store = {
|
|
253
|
+
const store = mockStore({
|
|
206
254
|
zappPipes: {
|
|
207
255
|
url1: {
|
|
208
256
|
loading: false,
|
|
@@ -210,19 +258,20 @@ describe("useBatchLoading", () => {
|
|
|
210
258
|
data: {},
|
|
211
259
|
},
|
|
212
260
|
},
|
|
213
|
-
};
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
useDispatchSpy.mockReturnValue(store.dispatch);
|
|
214
264
|
|
|
215
265
|
const initialBatchSize = 3;
|
|
216
266
|
const riverId = "123";
|
|
217
267
|
|
|
218
|
-
const data = [
|
|
268
|
+
const data: Partial<ZappUIComponent>[] = [
|
|
219
269
|
{
|
|
220
270
|
component_type: "gallery-qb",
|
|
221
|
-
data: {},
|
|
222
|
-
ui_components: [{ data: { source: "url1" } }] as any,
|
|
271
|
+
ui_components: [{ data: { source: "url1" } }],
|
|
223
272
|
},
|
|
224
|
-
{ data: { source: "url2" }
|
|
225
|
-
{ data: { source: "url3" }
|
|
273
|
+
{ data: { source: "url2" } },
|
|
274
|
+
{ data: { source: "url3" } },
|
|
226
275
|
];
|
|
227
276
|
|
|
228
277
|
const { result } = renderHook(
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { complement, compose, isNil, map, min, prop, take, uniq } from "ramda";
|
|
2
|
-
import { useDispatch } from "react-redux";
|
|
3
2
|
import * as React from "react";
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
ZappPipes,
|
|
5
|
+
useAppDispatch,
|
|
6
|
+
useZappPipesFeed,
|
|
7
|
+
} from "@applicaster/zapp-react-native-redux";
|
|
6
8
|
import { isNilOrEmpty } from "../../reactUtils/helpers";
|
|
7
9
|
import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
8
10
|
import {
|
|
@@ -10,7 +12,7 @@ import {
|
|
|
10
12
|
getSearchContext,
|
|
11
13
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
14
|
import { isGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
13
|
-
import { useScreenContext } from "../screen
|
|
15
|
+
import { useScreenContext } from "../screen";
|
|
14
16
|
|
|
15
17
|
type Options = {
|
|
16
18
|
initialBatchSize?: number;
|
|
@@ -63,7 +65,7 @@ export const useBatchLoading = (
|
|
|
63
65
|
componentsToRender: { data?: ZappDataSource; component_type: string }[],
|
|
64
66
|
options: Options
|
|
65
67
|
) => {
|
|
66
|
-
const dispatch =
|
|
68
|
+
const dispatch = useAppDispatch();
|
|
67
69
|
const { screen: screenContext, entry: entryContext } = useScreenContext();
|
|
68
70
|
const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
|
|
69
71
|
const [hasEverBeenReady, setHasEverBeenReady] = React.useState(false);
|
|
@@ -118,7 +120,7 @@ export const useBatchLoading = (
|
|
|
118
120
|
[]
|
|
119
121
|
);
|
|
120
122
|
|
|
121
|
-
const feeds =
|
|
123
|
+
const feeds = useZappPipesFeed(feedUrls);
|
|
122
124
|
|
|
123
125
|
// dispatch loadPipesData for each feed that is not loaded
|
|
124
126
|
const runBatchLoading = React.useCallback(() => {
|
|
@@ -139,7 +141,7 @@ export const useBatchLoading = (
|
|
|
139
141
|
if (mappedFeedUrl) {
|
|
140
142
|
// 4. load data
|
|
141
143
|
return dispatch(
|
|
142
|
-
loadPipesData(mappedFeedUrl, { riverId: options.riverId })
|
|
144
|
+
ZappPipes.loadPipesData(mappedFeedUrl, { riverId: options.riverId })
|
|
143
145
|
);
|
|
144
146
|
}
|
|
145
147
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
|
-
import { useDispatch } from "react-redux";
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
ZappPipes,
|
|
5
|
+
useAppDispatch,
|
|
6
|
+
useZappPipesFeed,
|
|
7
|
+
} from "@applicaster/zapp-react-native-redux";
|
|
6
8
|
|
|
7
9
|
import { reactHooksLogger } from "../logger";
|
|
8
10
|
import { shouldDispatchData, useIsInitialRender } from "../utils";
|
|
@@ -49,7 +51,7 @@ export const useFeedLoader = ({
|
|
|
49
51
|
}, []);
|
|
50
52
|
|
|
51
53
|
const isInitialRender = useIsInitialRender();
|
|
52
|
-
const dispatch =
|
|
54
|
+
const dispatch = useAppDispatch();
|
|
53
55
|
const { screenData } = useRoute();
|
|
54
56
|
|
|
55
57
|
const callableFeedUrl = useInflatedUrl({ feedUrl, mapping });
|
|
@@ -64,7 +66,7 @@ export const useFeedLoader = ({
|
|
|
64
66
|
(silentRefresh = true, callback) => {
|
|
65
67
|
if (callableFeedUrl) {
|
|
66
68
|
dispatch(
|
|
67
|
-
loadPipesData(callableFeedUrl, {
|
|
69
|
+
ZappPipes.loadPipesData(callableFeedUrl, {
|
|
68
70
|
clearCache: true,
|
|
69
71
|
silentRefresh,
|
|
70
72
|
callback,
|
|
@@ -82,7 +84,7 @@ export const useFeedLoader = ({
|
|
|
82
84
|
|
|
83
85
|
if (nextFeed) {
|
|
84
86
|
dispatch(
|
|
85
|
-
loadPipesData(nextFeed, {
|
|
87
|
+
ZappPipes.loadPipesData(nextFeed, {
|
|
86
88
|
silentRefresh: true,
|
|
87
89
|
parentFeed: callableFeedUrl,
|
|
88
90
|
riverId,
|
|
@@ -98,7 +100,7 @@ export const useFeedLoader = ({
|
|
|
98
100
|
) {
|
|
99
101
|
if (callableFeedUrl && !pipesOptions.skipLoading) {
|
|
100
102
|
dispatch(
|
|
101
|
-
loadPipesData(callableFeedUrl, {
|
|
103
|
+
ZappPipes.loadPipesData(callableFeedUrl, {
|
|
102
104
|
...pipesOptions,
|
|
103
105
|
clearCache: true,
|
|
104
106
|
riverId,
|
|
@@ -131,7 +133,9 @@ export const useFeedLoader = ({
|
|
|
131
133
|
// Reload feed when feedUrl changes, unless skipLoading is true
|
|
132
134
|
useEffect(() => {
|
|
133
135
|
if (!isInitialRender && callableFeedUrl && !pipesOptions.skipLoading) {
|
|
134
|
-
dispatch(
|
|
136
|
+
dispatch(
|
|
137
|
+
ZappPipes.loadPipesData(callableFeedUrl, { ...pipesOptions, riverId })
|
|
138
|
+
);
|
|
135
139
|
}
|
|
136
140
|
}, [callableFeedUrl]);
|
|
137
141
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { useDispatch } from "react-redux";
|
|
3
2
|
|
|
4
3
|
import { getDatasourceUrl } from "@applicaster/zapp-react-native-ui-components/Decorators/RiverFeedLoader/utils/getDatasourceUrl";
|
|
5
4
|
import { usePipesContexts } from "@applicaster/zapp-react-native-ui-components/Decorators/RiverFeedLoader/utils/usePipesContexts";
|
|
6
5
|
import { clearPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
7
6
|
|
|
8
|
-
import { useRoute } from "../navigation
|
|
7
|
+
import { useRoute } from "../navigation";
|
|
8
|
+
import { useAppDispatch } from "@applicaster/zapp-react-native-redux";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* reset river components cache when screen is unmounted
|
|
@@ -13,7 +13,7 @@ import { useRoute } from "../navigation/useRoute";
|
|
|
13
13
|
* @param {Array} riverComponents list of UI components
|
|
14
14
|
*/
|
|
15
15
|
export const usePipesCacheReset = (riverId, riverComponents) => {
|
|
16
|
-
const dispatch =
|
|
16
|
+
const dispatch = useAppDispatch();
|
|
17
17
|
const { screenData, pathname } = useRoute();
|
|
18
18
|
const pipesContexts = usePipesContexts(riverId, pathname);
|
|
19
19
|
|
|
@@ -42,15 +42,17 @@ jest.mock("react-native-safe-area-context", () => ({
|
|
|
42
42
|
}));
|
|
43
43
|
|
|
44
44
|
jest.mock("../../../reactUtils", () => ({
|
|
45
|
+
...jest.requireActual("../../../reactUtils"),
|
|
45
46
|
platformSelect: jest.fn((specs) => specs[platform] || specs.default),
|
|
46
47
|
isTV: jest.fn(() => mock_tv_flag),
|
|
47
48
|
}));
|
|
48
49
|
|
|
49
50
|
jest.mock("../../navigation", () => ({
|
|
50
|
-
useNavigation: () => null,
|
|
51
51
|
useIsScreenActive: () => true,
|
|
52
52
|
}));
|
|
53
53
|
|
|
54
|
+
jest.mock("../../navigation/useNavigation");
|
|
55
|
+
|
|
54
56
|
const { Dimensions } = require("react-native");
|
|
55
57
|
const { useDimensions } = require("..");
|
|
56
58
|
|
|
@@ -6,7 +6,10 @@ import { NativeModules, Platform } from "react-native";
|
|
|
6
6
|
* @param {String} orientation - Orientation enum passed to the function
|
|
7
7
|
* @returns {Boolean} isTablet - returns whether the given device is a tablet
|
|
8
8
|
*/
|
|
9
|
-
export const isTablet = (
|
|
9
|
+
export const isTablet = (
|
|
10
|
+
dimensions?: { width: number; height: number },
|
|
11
|
+
orientation?: string
|
|
12
|
+
) => {
|
|
10
13
|
if (Platform?.OS === "ios") {
|
|
11
14
|
return Platform?.isPad;
|
|
12
15
|
} else if (Platform?.OS === "android") {
|
|
@@ -15,7 +18,7 @@ export const isTablet = (dimensions, orientation) => {
|
|
|
15
18
|
return initialProps?.is_tablet;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
const { width } = dimensions;
|
|
21
|
+
const { width } = dimensions || {};
|
|
19
22
|
|
|
20
23
|
if (width < 600) return false;
|
|
21
24
|
if (width >= 600 && width < 840) return orientation === "portrait";
|