@applicaster/zapp-react-native-utils 13.0.0-alpha.8865907528 → 13.0.0-alpha.9053464934
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 +1 -2
- package/analyticsUtils/index.tsx +4 -3
- package/analyticsUtils/manager.ts +1 -1
- package/appUtils/orientationHelper.ts +11 -12
- package/appUtils/playerManager/player.ts +24 -12
- package/appUtils/playerManager/playerNative.ts +18 -3
- package/focusManager/index.ts +9 -1
- package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
- package/package.json +2 -3
- package/playerUtils/configurationGenerator.ts +8 -0
- package/reactHooks/app/useAppState.ts +2 -2
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +88 -39
- package/reactHooks/navigation/index.ts +7 -5
- package/services/js2native.ts +673 -0
- package/testUtils/index.tsx +8 -7
- package/time/BackgroundTimer.ts +55 -0
- package/time/Timer.ts +6 -6
|
@@ -4,7 +4,7 @@ import { postAnalyticEvent } from "../manager";
|
|
|
4
4
|
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
5
5
|
|
|
6
6
|
type SendHeaderClickEventProps = {
|
|
7
|
-
extraProps:
|
|
7
|
+
extraProps: ExtraProps;
|
|
8
8
|
component?: ZappUIComponent;
|
|
9
9
|
zappPipesData?: ZappPipesData;
|
|
10
10
|
item?: ZappEntry;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/// <reference types="../../" />
|
|
2
1
|
import { log_error, log_debug } from "../logger";
|
|
3
2
|
import { replaceAnalyticsPropsNils } from "./helper";
|
|
4
3
|
import { postAnalyticEvent } from "../manager";
|
|
5
4
|
|
|
6
5
|
import { ANALYTICS_CORE_EVENTS } from "../events";
|
|
7
6
|
|
|
8
|
-
type AnalyticsDefaultHelperProperties = {
|
|
7
|
+
declare type AnalyticsDefaultHelperProperties = {
|
|
9
8
|
analyticsScreenData: AnalyticsScreenProperties;
|
|
10
9
|
extraProps: any;
|
|
11
10
|
props;
|
package/analyticsUtils/index.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="@applicaster/zapp-react-native-utils" />
|
|
1
2
|
import * as R from "ramda";
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
@@ -30,7 +31,7 @@ import { ANALYTICS_CORE_EVENTS } from "./events";
|
|
|
30
31
|
import { noop } from "../functionUtils";
|
|
31
32
|
|
|
32
33
|
type ComponentWithChildrenProps = {
|
|
33
|
-
children: React.
|
|
34
|
+
children: React.ReactChildren;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
export function sendSelectCellEvent(item, component, headerTitle, itemIndex) {
|
|
@@ -119,11 +120,11 @@ export function getAnalyticsFunctions({
|
|
|
119
120
|
export const AnalyticsContext =
|
|
120
121
|
React.createContext<GetAnalyticsFunctions>(noop);
|
|
121
122
|
|
|
122
|
-
export function AnalyticsProvider(
|
|
123
|
+
export function AnalyticsProvider(props: ComponentWithChildrenProps) {
|
|
123
124
|
return (
|
|
124
125
|
// @ts-ignore - this is a valid context provider
|
|
125
126
|
<AnalyticsContext.Provider value={getAnalyticsFunctions}>
|
|
126
|
-
{children}
|
|
127
|
+
{props?.children}
|
|
127
128
|
</AnalyticsContext.Provider>
|
|
128
129
|
);
|
|
129
130
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import { NativeModules } from "react-native";
|
|
4
|
-
import { ANALYTICS_CORE_EVENTS } from "
|
|
4
|
+
import { ANALYTICS_CORE_EVENTS } from "@applicaster/zapp-react-native-utils/analyticsUtils/events";
|
|
5
5
|
|
|
6
6
|
import { analyticsUtilsLogger } from "./logger";
|
|
7
7
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as ReactNative from "react-native";
|
|
2
|
-
import { isTV, platformSelect } from "../reactUtils";
|
|
3
2
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
import { isTV, platformSelect } from "../reactUtils";
|
|
5
|
+
import { useIsTablet } from "../reactHooks";
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
QUICK_BRICK_EVENTS,
|
|
@@ -120,8 +121,15 @@ export const removeOrientationChangeListener = (listener: any): void => {
|
|
|
120
121
|
*/
|
|
121
122
|
export const isOrientationCompatible = ({
|
|
122
123
|
orientation,
|
|
123
|
-
layoutData: { width, height },
|
|
124
|
+
layoutData: { width, height, isTablet, isTabletPortrait },
|
|
124
125
|
}) => {
|
|
126
|
+
// We count portrait as compatible, because if default in zapp for mobile layout
|
|
127
|
+
// We count landscape as compatible, because if isTabletPortrait is false,
|
|
128
|
+
// it defaults for device
|
|
129
|
+
if (isTablet && !isTabletPortrait) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
125
133
|
const isLandscape = width > height;
|
|
126
134
|
|
|
127
135
|
if (
|
|
@@ -145,15 +153,6 @@ export const isOrientationCompatible = ({
|
|
|
145
153
|
return true;
|
|
146
154
|
};
|
|
147
155
|
|
|
148
|
-
export const useIsOrientationCompatible = (orientation) => {
|
|
149
|
-
const { height, width } = ReactNative.useWindowDimensions();
|
|
150
|
-
|
|
151
|
-
return isOrientationCompatible({
|
|
152
|
-
orientation,
|
|
153
|
-
layoutData: { width, height },
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
|
|
157
156
|
/**
|
|
158
157
|
* Determine final screen orientation based on device type,
|
|
159
158
|
* settings and orientation value provided by screen data settings
|
|
@@ -97,7 +97,7 @@ export class Player {
|
|
|
97
97
|
this.onVideoLoad = this.onVideoLoad.bind(this);
|
|
98
98
|
this.isFullScreenSupported = this.isFullScreenSupported.bind(this);
|
|
99
99
|
this.onPlayerSeekComplete = this.onPlayerSeekComplete.bind(this);
|
|
100
|
-
|
|
100
|
+
this.onAdBreakEnd = this.onAdBreakEnd.bind(this);
|
|
101
101
|
this.entryObservable = null;
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -201,17 +201,25 @@ export class Player {
|
|
|
201
201
|
adPosition: currentTime,
|
|
202
202
|
};
|
|
203
203
|
} else {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
this.updateContentDuration({ seekableDuration, duration, currentTime });
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
207
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
protected updateContentDuration = ({
|
|
209
|
+
seekableDuration = null,
|
|
210
|
+
duration = null,
|
|
211
|
+
currentTime = null,
|
|
212
|
+
}) => {
|
|
213
|
+
if (!isEmptyOrNil(seekableDuration) && seekableDuration >= 0) {
|
|
214
|
+
this.playerState.seekableDuration = seekableDuration;
|
|
215
|
+
}
|
|
211
216
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
217
|
+
if (!isEmptyOrNil(duration) && duration >= 0) {
|
|
218
|
+
this.playerState.contentDuration = duration;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!isEmptyOrNil(currentTime) && currentTime >= 0) {
|
|
222
|
+
this.playerState.contentPosition = currentTime;
|
|
215
223
|
}
|
|
216
224
|
};
|
|
217
225
|
|
|
@@ -559,7 +567,7 @@ export class Player {
|
|
|
559
567
|
});
|
|
560
568
|
};
|
|
561
569
|
|
|
562
|
-
onAdBreakEnd
|
|
570
|
+
onAdBreakEnd(event) {
|
|
563
571
|
this.playerState.adState = null;
|
|
564
572
|
this.playerState.isInAdBreak = false;
|
|
565
573
|
|
|
@@ -567,7 +575,7 @@ export class Player {
|
|
|
567
575
|
callbackName: SharedPlayerCallBacksKeys.OnAdBreakEnd,
|
|
568
576
|
event,
|
|
569
577
|
});
|
|
570
|
-
}
|
|
578
|
+
}
|
|
571
579
|
|
|
572
580
|
onAdEnd = (event) => {
|
|
573
581
|
this.playerState.adState = null;
|
|
@@ -736,6 +744,10 @@ export class Player {
|
|
|
736
744
|
return null;
|
|
737
745
|
};
|
|
738
746
|
|
|
747
|
+
public hasResumePosition() {
|
|
748
|
+
return false;
|
|
749
|
+
}
|
|
750
|
+
|
|
739
751
|
public getConfig = () => this.config;
|
|
740
752
|
|
|
741
753
|
// TODO: replace with enum of supported orientations
|
|
@@ -54,6 +54,10 @@ export class PlayerNative extends Player {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
public hasResumePosition() {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
57
61
|
getContentPosition = () => {
|
|
58
62
|
return this.playerState.contentPosition;
|
|
59
63
|
};
|
|
@@ -221,11 +225,13 @@ export class PlayerNative extends Player {
|
|
|
221
225
|
};
|
|
222
226
|
|
|
223
227
|
onVideoLoad = (event) => {
|
|
224
|
-
|
|
225
|
-
this.seekTo(this.startPosition);
|
|
226
|
-
this.startPosition = null;
|
|
228
|
+
this.updateContentDuration(event);
|
|
227
229
|
|
|
230
|
+
if (this.startPosition && !this.playerState.isInAdBreak) {
|
|
228
231
|
super.onVideoLoad({ ...event, ignoreContinueWatching: true });
|
|
232
|
+
|
|
233
|
+
this.seekTo(this.startPosition);
|
|
234
|
+
this.startPosition = null;
|
|
229
235
|
} else {
|
|
230
236
|
super.onVideoLoad(event);
|
|
231
237
|
}
|
|
@@ -249,6 +255,15 @@ export class PlayerNative extends Player {
|
|
|
249
255
|
}
|
|
250
256
|
};
|
|
251
257
|
|
|
258
|
+
onAdBreakEnd = (event) => {
|
|
259
|
+
super.onAdBreakEnd(event);
|
|
260
|
+
|
|
261
|
+
if (this.startPosition) {
|
|
262
|
+
this.seekTo(this.startPosition);
|
|
263
|
+
this.startPosition = null;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
252
267
|
// This function is called when native player used directly without wrapped component,
|
|
253
268
|
// Since event from native comes with wrapped in NativeEvent property
|
|
254
269
|
getNativeViewListener = (): QuickBrickPlayer.SharedPlayerCallBacks => {
|
package/focusManager/index.ts
CHANGED
|
@@ -117,17 +117,25 @@ export const useIsFocusable = (props: Props): void => {
|
|
|
117
117
|
isNilOrEmpty(zappPipesData?.data) ||
|
|
118
118
|
isNilOrEmpty(zappPipesData?.data?.entry);
|
|
119
119
|
|
|
120
|
+
const hasNoUIComponents = isNilOrEmpty(component?.ui_components);
|
|
121
|
+
|
|
120
122
|
const hasDataError = !!zappPipesData?.error;
|
|
121
123
|
|
|
122
124
|
const hasEmptyGroup = shouldShowEmptyGroup(component);
|
|
123
125
|
|
|
124
126
|
const isGallery = component?.component_type === "gallery-qb";
|
|
125
127
|
|
|
128
|
+
const isGroup = component?.component_type === "group-qb";
|
|
129
|
+
|
|
126
130
|
const isHiddenDueToEmptyData =
|
|
127
131
|
!isLoadingData && hasNoData && hideIfDataEmpty && !hasEmptyGroup;
|
|
128
132
|
|
|
133
|
+
const isEmptyGroup = isGroup && hasNoUIComponents;
|
|
134
|
+
|
|
129
135
|
const defaultFocusableLogic =
|
|
130
|
-
componentCellsFocusable &&
|
|
136
|
+
componentCellsFocusable &&
|
|
137
|
+
(!hasNoData || !hideIfDataEmpty) &&
|
|
138
|
+
!isEmptyGroup;
|
|
131
139
|
|
|
132
140
|
React.useEffect(() => {
|
|
133
141
|
if (isAndroidTVPlatform()) {
|
|
@@ -50,6 +50,14 @@ function getPlayerConfiguration({ platform }) {
|
|
|
50
50
|
label_tooltip:
|
|
51
51
|
"Set the query params which control the size of the image e.g width, height. This will help to optimize the loading time, when magic background is enabled.",
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
key: "audio_player_background_image_default_color",
|
|
55
|
+
label: "Audio Player Background Image Default Color",
|
|
56
|
+
initial_value: "",
|
|
57
|
+
type: "text_input",
|
|
58
|
+
label_tooltip:
|
|
59
|
+
"Set the default color for the audio player background image if not image or set of gradient colors are not provided.",
|
|
60
|
+
},
|
|
53
61
|
],
|
|
54
62
|
};
|
|
55
63
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "13.0.0-alpha.
|
|
3
|
+
"version": "13.0.0-alpha.9053464934",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "jest -w=2",
|
|
9
8
|
"build": "echo skipping hybrid ts build in main packages for now"
|
|
10
9
|
},
|
|
11
10
|
"publishConfig": {
|
|
@@ -28,7 +27,7 @@
|
|
|
28
27
|
},
|
|
29
28
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
29
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "13.0.0-alpha.
|
|
30
|
+
"@applicaster/applicaster-types": "13.0.0-alpha.9053464934",
|
|
32
31
|
"buffer": "^5.2.1",
|
|
33
32
|
"camelize": "^1.0.0",
|
|
34
33
|
"dayjs": "^1.11.10",
|
|
@@ -55,6 +55,14 @@ function getPlayerConfiguration({ platform }) {
|
|
|
55
55
|
label_tooltip:
|
|
56
56
|
"Set the query params which control the size of the image e.g width, height. This will help to optimize the loading time, when magic background is enabled.",
|
|
57
57
|
},
|
|
58
|
+
{
|
|
59
|
+
key: "audio_player_background_image_default_color",
|
|
60
|
+
label: "Audio Player Background Image Default Color",
|
|
61
|
+
initial_value: "",
|
|
62
|
+
type: "text_input",
|
|
63
|
+
label_tooltip:
|
|
64
|
+
"Set the default color for the audio player background image if not image or set of gradient colors are not provided.",
|
|
65
|
+
},
|
|
58
66
|
],
|
|
59
67
|
};
|
|
60
68
|
|
|
@@ -14,10 +14,10 @@ export function useAppState(returnIsActive) {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
React.useEffect(() => {
|
|
17
|
-
|
|
17
|
+
AppState.addEventListener("change", setAppState);
|
|
18
18
|
|
|
19
19
|
return () => {
|
|
20
|
-
|
|
20
|
+
AppState.removeEventListener("change", setAppState);
|
|
21
21
|
};
|
|
22
22
|
}, []);
|
|
23
23
|
|
|
@@ -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(
|
|
@@ -108,9 +108,11 @@ export function isNavBarVisible(
|
|
|
108
108
|
return false;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const showSecondaryLevel =
|
|
112
|
-
(
|
|
113
|
-
|
|
111
|
+
const showSecondaryLevel =
|
|
112
|
+
!isTV() ||
|
|
113
|
+
screenData?.navigations?.some(
|
|
114
|
+
(navigation) => navigation.styles?.show_secondary_level_menu
|
|
115
|
+
);
|
|
114
116
|
|
|
115
117
|
if (canGoBack && !showSecondaryLevel) {
|
|
116
118
|
return false;
|
|
@@ -125,10 +127,10 @@ export function isNavBarVisible(
|
|
|
125
127
|
|
|
126
128
|
export const useBackHandler = (cb: () => boolean) => {
|
|
127
129
|
useEffect(() => {
|
|
128
|
-
|
|
130
|
+
BackHandler.addEventListener("hardwareBackPress", cb);
|
|
129
131
|
|
|
130
132
|
return () => {
|
|
131
|
-
|
|
133
|
+
BackHandler.removeEventListener("hardwareBackPress", cb);
|
|
132
134
|
};
|
|
133
135
|
}, [cb]);
|
|
134
136
|
};
|