@applicaster/zapp-react-native-utils 12.0.0-alpha.7725319213 → 12.0.0-alpha.7855034103
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 +16 -8
- package/analyticsUtils/AnalyticsEvents/index.ts +6 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/__tests__/analyticsManager.test.js +75 -73
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +6 -0
- package/analyticsUtils/helpers/hooks.ts +1 -1
- package/analyticsUtils/index.tsx +6 -0
- package/appUtils/HooksManager/index.js +3 -1
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +12 -3
- package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +1 -1
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +80 -85
- package/appUtils/keyCodes/keys.web.js +1 -0
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +53 -0
- package/appUtils/playerManager/conts.ts +5 -0
- package/appUtils/playerManager/index.ts +1 -0
- package/appUtils/playerManager/player.ts +47 -6
- package/appUtils/playerManager/playerFactory.ts +12 -10
- package/appUtils/playerManager/playerNative.ts +32 -0
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +6 -1
- package/appUtils/playerManager/usePlayerState.tsx +13 -1
- package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +50 -0
- package/cellUtils/__tests__/cellUtils.test.ts +48 -0
- package/cellUtils/__tests__/fixtures.ts +13 -0
- package/cellUtils/index.ts +27 -2
- package/dateUtils/index.ts +11 -0
- package/focusManager/index.ts +1 -1
- package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +2 -2
- package/functionUtils/__tests__/functionUtils.test.js +244 -248
- package/headersUtils/index.ts +1 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/localizationUtils/__tests__/localizationUtils.test.ts +78 -55
- package/localizationUtils/index.ts +13 -19
- package/logger/index.ts +1 -1
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +10 -1
- package/manifestUtils/index.js +5 -1
- package/manifestUtils/secondaryImage/index.js +18 -15
- package/modalState/index.ts +57 -0
- package/navigationUtils/index.ts +56 -7
- package/numberUtils/index.ts +4 -0
- package/package.json +3 -2
- package/playerUtils/configurationGenerator.ts +11 -1
- package/pluginUtils/index.ts +2 -2
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +2 -0
- package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +18 -1
- package/reactHooks/cell-click/__tests__/index.test.js +5 -0
- package/reactHooks/cell-click/index.ts +2 -2
- package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
- package/reactHooks/feed/useInflatedUrl.ts +44 -15
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -9
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +66 -59
- package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
- package/reactHooks/layout/types/index.ts +2 -0
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +11 -16
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +12 -14
- package/reactHooks/layout/useDimensions/useDimensions.ts +13 -7
- package/reactHooks/navigation/__mocks__/index.ts +15 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +7 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +240 -81
- package/reactHooks/navigation/index.ts +208 -86
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +3 -1
- package/reactHooks/screen/__mocks__/useScreenContext.ts +3 -1
- package/reactHooks/screen/index.ts +2 -0
- package/reactHooks/screen/useScreenContext.ts +5 -4
- package/reactHooks/screen/useScreenData.ts +1 -1
- package/reactHooks/state/useRivers.ts +3 -1
- package/reactHooks/useListenEventBusEvent.ts +1 -4
- package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +10 -9
- package/riverComponetsMeasurementProvider/index.tsx +2 -2
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +38 -23
- package/types.ts +4 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { useContext } from "react";
|
|
4
5
|
import * as R from "ramda";
|
|
5
6
|
import { handleActionSchemeUrl } from "@applicaster/quick-brick-core/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/useUrlSchemeHandler";
|
|
6
7
|
import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
|
|
@@ -12,7 +13,6 @@ import {
|
|
|
12
13
|
import { ZappPipesEntryContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
13
14
|
import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
14
15
|
import { noop } from "../../functionUtils";
|
|
15
|
-
import { useContext } from "react";
|
|
16
16
|
import { ActionExecutorContext } from "../../actionsExecutor/ActionExecutorContext";
|
|
17
17
|
import { useSendAnalyticsOnPress } from "../analytics";
|
|
18
18
|
import { logOnPress, warnEmptyContentType } from "./helpers";
|
|
@@ -83,7 +83,7 @@ export const useCellClick = (props: Props) => {
|
|
|
83
83
|
if (typeof onCellTap === "function") {
|
|
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(
|
|
@@ -12,9 +12,21 @@ const {
|
|
|
12
12
|
|
|
13
13
|
const { reactHooksLogger } = require("../../logger");
|
|
14
14
|
|
|
15
|
+
let mockStore;
|
|
16
|
+
|
|
15
17
|
describe("getInflatedDataSourceUrl", () => {
|
|
16
18
|
beforeEach(() => {
|
|
17
19
|
reactHooksLogger.warning.mockClear();
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
appStore,
|
|
23
|
+
} = require("@applicaster/zapp-react-native-redux/AppStore");
|
|
24
|
+
|
|
25
|
+
mockStore = {
|
|
26
|
+
getState: jest.fn().mockReturnValue({ pipesEndpoints: {} }),
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
appStore.set(mockStore);
|
|
18
30
|
});
|
|
19
31
|
|
|
20
32
|
it("returns the url inflated with the right params", () => {
|
|
@@ -72,7 +84,8 @@ describe("getInflatedDataSourceUrl", () => {
|
|
|
72
84
|
expect(reactHooksLogger.warning).toHaveBeenCalledTimes(1);
|
|
73
85
|
|
|
74
86
|
expect(reactHooksLogger.warning).toHaveBeenCalledWith({
|
|
75
|
-
message:
|
|
87
|
+
message:
|
|
88
|
+
"Not enough data to fully inflate url: {{entry.id}} source: http://foo.com/show/seriesId={{seriesId}}",
|
|
76
89
|
data: { source, contexts, mapping },
|
|
77
90
|
});
|
|
78
91
|
});
|
|
@@ -107,7 +120,8 @@ describe("getInflatedDataSourceUrl", () => {
|
|
|
107
120
|
expect(reactHooksLogger.warning).toHaveBeenCalledTimes(1);
|
|
108
121
|
|
|
109
122
|
expect(reactHooksLogger.warning).toHaveBeenCalledWith({
|
|
110
|
-
message:
|
|
123
|
+
message:
|
|
124
|
+
"Not enough data to fully inflate url: {{entry.extensions.groupName}} source: https://zapp-1689-emmys.web.app/emmys/group-categories/{{groupName}}",
|
|
111
125
|
data: { source, contexts, mapping },
|
|
112
126
|
});
|
|
113
127
|
});
|
|
@@ -148,7 +162,8 @@ describe("getInflatedDataSourceUrl", () => {
|
|
|
148
162
|
expect(reactHooksLogger.warning).toHaveBeenCalledTimes(1);
|
|
149
163
|
|
|
150
164
|
expect(reactHooksLogger.warning).toHaveBeenCalledWith({
|
|
151
|
-
message:
|
|
165
|
+
message:
|
|
166
|
+
"Not enough data to fully inflate url: {{entry.extensions.groupName2}} source: https://zapp-1689-emmys.web.app/emmys/group-categories/{{groupName1}}?test={{groupName2}}",
|
|
152
167
|
data: { source, contexts, mapping },
|
|
153
168
|
});
|
|
154
169
|
});
|
|
@@ -9,9 +9,15 @@ import {
|
|
|
9
9
|
|
|
10
10
|
import { inflateString } from "../../stringUtils";
|
|
11
11
|
import { useRoute } from "../navigation";
|
|
12
|
-
import {
|
|
12
|
+
import { getMissingValues } from "../../inflatedUrlUtils";
|
|
13
13
|
import { reactHooksLogger as logger } from "../logger";
|
|
14
14
|
import { isTV } from "../../reactUtils";
|
|
15
|
+
import {
|
|
16
|
+
findEndpointForURL,
|
|
17
|
+
HTTP_METHODS,
|
|
18
|
+
} from "@applicaster/zapp-pipes-v2-client";
|
|
19
|
+
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
20
|
+
import { ENDPOINT_TAGS } from "../../types";
|
|
15
21
|
|
|
16
22
|
/**
|
|
17
23
|
* will match any occurrence in a string of one or more word characters
|
|
@@ -105,24 +111,47 @@ export const getInflatedDataSourceUrl: GetInflatedDataSourceUrl = ({
|
|
|
105
111
|
R.keys(mapping)
|
|
106
112
|
);
|
|
107
113
|
|
|
108
|
-
|
|
109
|
-
const message = "Not enough data to fully inflate url";
|
|
114
|
+
const missingValues = getMissingValues(contexts, string);
|
|
110
115
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
if (missingValues && missingValues.length > 0) {
|
|
117
|
+
const pipesEndpoints = appStore.get("pipesEndpoints");
|
|
118
|
+
|
|
119
|
+
const endpointURL = findEndpointForURL(
|
|
120
|
+
source,
|
|
121
|
+
pipesEndpoints,
|
|
122
|
+
HTTP_METHODS.GET
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const tags = pipesEndpoints?.[endpointURL]?.tags;
|
|
126
|
+
const allowMissingKeys = tags?.includes(ENDPOINT_TAGS.allow_missing_keys);
|
|
127
|
+
|
|
128
|
+
if (!allowMissingKeys) {
|
|
129
|
+
const message = `Not enough data to fully inflate url: ${missingValues.join(
|
|
130
|
+
","
|
|
131
|
+
)} source: ${source}`;
|
|
132
|
+
|
|
133
|
+
// todo: add js only payload instead
|
|
134
|
+
if (__DEV__) {
|
|
135
|
+
logger.warning({
|
|
136
|
+
message,
|
|
137
|
+
data: { source, contexts, mapping },
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
// todo: log values we've failed to resolve
|
|
141
|
+
logger.warning({
|
|
142
|
+
message,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// return null in order to prevent start fetching data with invalid url
|
|
147
|
+
return null;
|
|
117
148
|
} else {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
149
|
+
logger.debug({
|
|
150
|
+
message: `Ignoring missing values in url because ${
|
|
151
|
+
ENDPOINT_TAGS.allow_missing_keys
|
|
152
|
+
} endpoint tag, keys: ${missingValues.join(",")}`,
|
|
121
153
|
});
|
|
122
154
|
}
|
|
123
|
-
|
|
124
|
-
// return null in order to prevent start fetching data with invalid url
|
|
125
|
-
return null;
|
|
126
155
|
}
|
|
127
156
|
|
|
128
157
|
return inflateString({ string, data: contexts });
|
|
@@ -5,27 +5,34 @@ type Return = (index: number) => void;
|
|
|
5
5
|
|
|
6
6
|
type Predicate = (
|
|
7
7
|
entry: ZappUIComponentProps["zappPipesData"]["data"]["entry"],
|
|
8
|
-
index: number
|
|
8
|
+
index: number,
|
|
9
|
+
numberOfColumns: number
|
|
9
10
|
) => boolean;
|
|
10
11
|
|
|
11
12
|
type Props = {
|
|
12
13
|
ifNeeded: Predicate;
|
|
13
14
|
loadNextData: () => void;
|
|
14
15
|
entry: ZappUIComponentProps["zappPipesData"]["data"]["entry"];
|
|
16
|
+
numberOfColumns?: number;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
const handleLoadNextPage =
|
|
18
20
|
(
|
|
19
|
-
ifNeeded: (
|
|
21
|
+
ifNeeded: (
|
|
22
|
+
entry: ZappEntry[],
|
|
23
|
+
index: number,
|
|
24
|
+
numberOfColumns?: number
|
|
25
|
+
) => boolean,
|
|
20
26
|
loadNextData: () => void,
|
|
21
|
-
entry: ZappEntry[]
|
|
27
|
+
entry: ZappEntry[],
|
|
28
|
+
numberOfColumns
|
|
22
29
|
) =>
|
|
23
30
|
(index: number) => {
|
|
24
31
|
/**
|
|
25
32
|
* Lazy-Loading, invoke nextLoadData if we reach the end of the List
|
|
26
33
|
*/
|
|
27
34
|
|
|
28
|
-
if (ifNeeded(entry, index)) {
|
|
35
|
+
if (ifNeeded(entry, index, numberOfColumns)) {
|
|
29
36
|
loadNextData();
|
|
30
37
|
}
|
|
31
38
|
};
|
|
@@ -34,10 +41,10 @@ export const useLoadNextPageIfNeeded = ({
|
|
|
34
41
|
ifNeeded,
|
|
35
42
|
loadNextData = noop,
|
|
36
43
|
entry,
|
|
44
|
+
numberOfColumns = 0,
|
|
37
45
|
}: Props): Return => {
|
|
38
|
-
return React.useCallback(
|
|
39
|
-
ifNeeded,
|
|
40
|
-
loadNextData,
|
|
41
|
-
|
|
42
|
-
]);
|
|
46
|
+
return React.useCallback(
|
|
47
|
+
handleLoadNextPage(ifNeeded, loadNextData, entry, numberOfColumns),
|
|
48
|
+
[ifNeeded, loadNextData, entry, numberOfColumns]
|
|
49
|
+
);
|
|
43
50
|
};
|
package/reactHooks/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
1
3
|
import { cleanup, renderHook } from "@testing-library/react-hooks";
|
|
4
|
+
import { Provider } from "react-redux";
|
|
5
|
+
import configureStore from "redux-mock-store";
|
|
6
|
+
|
|
7
|
+
import * as ReactNative from "react-native";
|
|
2
8
|
|
|
3
9
|
const mocked_return_value = (tv) => ({
|
|
4
10
|
screen: tv
|
|
@@ -10,41 +16,31 @@ const mocked_return_value = (tv) => ({
|
|
|
10
16
|
const platform = "android";
|
|
11
17
|
let tv_flag = false;
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
ReactNative.Dimensions.get = jest.fn(
|
|
20
|
+
(context) => mocked_return_value(tv_flag)[context]
|
|
21
|
+
);
|
|
16
22
|
|
|
17
23
|
const mockRemoveFn = jest.fn();
|
|
18
24
|
|
|
19
|
-
jest.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const Dims = {
|
|
23
|
-
get: jest.fn((context) => mocked_return_value(tv_flag)[context]),
|
|
24
|
-
addEventListener: jest.fn().mockReturnValue({
|
|
25
|
-
remove: mockRemoveFn,
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const QuickBrickCommunicationModule = {
|
|
30
|
-
initialProps: {
|
|
31
|
-
is_tablet: false,
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
...RNMock,
|
|
37
|
-
Dimensions: Dims,
|
|
38
|
-
Platform: {
|
|
39
|
-
OS: platform,
|
|
40
|
-
},
|
|
41
|
-
NativeModules: {
|
|
42
|
-
...RNMock.NativeModules,
|
|
43
|
-
QuickBrickCommunicationModule,
|
|
44
|
-
},
|
|
45
|
-
};
|
|
25
|
+
ReactNative.Dimensions.addEventListener = jest.fn().mockReturnValue({
|
|
26
|
+
remove: mockRemoveFn,
|
|
46
27
|
});
|
|
47
28
|
|
|
29
|
+
ReactNative.Platform.OS = platform;
|
|
30
|
+
|
|
31
|
+
const QuickBrickCommunicationModule = {
|
|
32
|
+
initialProps: {
|
|
33
|
+
is_tablet: false,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
ReactNative.NativeModules.QuickBrickCommunicationModule =
|
|
38
|
+
QuickBrickCommunicationModule;
|
|
39
|
+
|
|
40
|
+
jest.mock("react-native-safe-area-context", () => ({
|
|
41
|
+
useSafeAreaInsets: () => ({ top: 50 }),
|
|
42
|
+
}));
|
|
43
|
+
|
|
48
44
|
jest.mock("../../../reactUtils", () => ({
|
|
49
45
|
platformSelect: jest.fn((specs) => specs[platform] || specs.default),
|
|
50
46
|
isTV: jest.fn(() => tv_flag),
|
|
@@ -52,22 +48,47 @@ jest.mock("../../../reactUtils", () => ({
|
|
|
52
48
|
|
|
53
49
|
jest.mock("../../navigation", () => ({
|
|
54
50
|
useNavigation: () => null,
|
|
51
|
+
useIsScreenActive: () => true,
|
|
55
52
|
}));
|
|
56
53
|
|
|
57
54
|
const { Dimensions } = require("react-native");
|
|
58
|
-
const { useDimensions } = require("
|
|
55
|
+
const { useDimensions } = require("..");
|
|
56
|
+
|
|
57
|
+
const mockStore = configureStore();
|
|
58
|
+
|
|
59
|
+
const getWrapper = () => {
|
|
60
|
+
const store = mockStore({ appData: {} });
|
|
61
|
+
|
|
62
|
+
const Wrapper = ({ children }: { children: React.ReactChild }) => (
|
|
63
|
+
/* @ts-ignore */
|
|
64
|
+
<Provider store={store}>{children}</Provider>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return Wrapper;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const testHook = (context, params?) => {
|
|
71
|
+
const wrapper = getWrapper();
|
|
72
|
+
|
|
73
|
+
const {
|
|
74
|
+
result,
|
|
75
|
+
result: { current: dimensions },
|
|
76
|
+
} = renderHook(() => useDimensions(context, params), {
|
|
77
|
+
wrapper,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return { result, dimensions };
|
|
81
|
+
};
|
|
59
82
|
|
|
60
83
|
describe("useDimensions", () => {
|
|
61
84
|
it("renders", () => {
|
|
62
|
-
const { result } =
|
|
63
|
-
useDimensions("window", { fullDimensions: true })
|
|
64
|
-
);
|
|
85
|
+
const { result } = testHook("window", { fullDimensions: true });
|
|
65
86
|
|
|
66
87
|
expect(result).toBeDefined();
|
|
67
88
|
});
|
|
68
89
|
|
|
69
90
|
it("sets event listener", () => {
|
|
70
|
-
|
|
91
|
+
testHook("window", { fullDimensions: true });
|
|
71
92
|
|
|
72
93
|
expect(Dimensions.addEventListener).toBeCalledWith(
|
|
73
94
|
"change",
|
|
@@ -76,16 +97,14 @@ describe("useDimensions", () => {
|
|
|
76
97
|
});
|
|
77
98
|
|
|
78
99
|
it("removes event listener", () => {
|
|
79
|
-
|
|
100
|
+
testHook("window", { fullDimensions: true });
|
|
80
101
|
cleanup();
|
|
81
102
|
|
|
82
103
|
expect(mockRemoveFn).toBeCalled();
|
|
83
104
|
});
|
|
84
105
|
|
|
85
106
|
it("Returns full dimensions object", () => {
|
|
86
|
-
const {
|
|
87
|
-
result: { current: dimensions },
|
|
88
|
-
} = renderHook(() => useDimensions("window", { fullDimensions: true }));
|
|
107
|
+
const { dimensions } = testHook("window", { fullDimensions: true });
|
|
89
108
|
|
|
90
109
|
expect(dimensions).toHaveProperty("height");
|
|
91
110
|
expect(dimensions).toHaveProperty("width");
|
|
@@ -94,20 +113,17 @@ describe("useDimensions", () => {
|
|
|
94
113
|
});
|
|
95
114
|
|
|
96
115
|
it("Returns shorthand dimensions object", () => {
|
|
97
|
-
const {
|
|
98
|
-
result: { current: dimensions },
|
|
99
|
-
} = renderHook(() => useDimensions("window"));
|
|
116
|
+
const { dimensions } = testHook("window");
|
|
100
117
|
|
|
101
118
|
expect(dimensions).toHaveProperty("height");
|
|
102
119
|
expect(dimensions).toHaveProperty("width");
|
|
103
120
|
});
|
|
104
121
|
|
|
105
122
|
it("Returns the device info object", () => {
|
|
106
|
-
const {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
);
|
|
123
|
+
const { dimensions } = testHook("window", {
|
|
124
|
+
fullDimensions: true,
|
|
125
|
+
deviceInfo: true,
|
|
126
|
+
});
|
|
111
127
|
|
|
112
128
|
expect(dimensions).toHaveProperty("height");
|
|
113
129
|
expect(dimensions).toHaveProperty("width");
|
|
@@ -120,10 +136,7 @@ describe("useDimensions", () => {
|
|
|
120
136
|
it("applies the scale on TV, and screen context", () => {
|
|
121
137
|
tv_flag = true;
|
|
122
138
|
const { screen } = mocked_return_value(tv_flag);
|
|
123
|
-
|
|
124
|
-
const {
|
|
125
|
-
result: { current: dimensions },
|
|
126
|
-
} = renderHook(() => useDimensions("screen"));
|
|
139
|
+
const { dimensions } = testHook("screen");
|
|
127
140
|
|
|
128
141
|
expect(dimensions).toHaveProperty("height", screen.height * screen.scale);
|
|
129
142
|
expect(dimensions).toHaveProperty("width", screen.width * screen.scale);
|
|
@@ -135,10 +148,7 @@ describe("useDimensions", () => {
|
|
|
135
148
|
it("doesn't apply the scale on mobile with screen context", () => {
|
|
136
149
|
tv_flag = false;
|
|
137
150
|
const { screen } = mocked_return_value(tv_flag);
|
|
138
|
-
|
|
139
|
-
const {
|
|
140
|
-
result: { current: dimensions },
|
|
141
|
-
} = renderHook(() => useDimensions("screen"));
|
|
151
|
+
const { dimensions } = testHook("screen");
|
|
142
152
|
|
|
143
153
|
expect(dimensions).toHaveProperty("height", screen.height);
|
|
144
154
|
expect(dimensions).toHaveProperty("width", screen.width);
|
|
@@ -148,10 +158,7 @@ describe("useDimensions", () => {
|
|
|
148
158
|
it("doesn't apply the scale on TV with window context", () => {
|
|
149
159
|
tv_flag = true;
|
|
150
160
|
const { window } = mocked_return_value(tv_flag);
|
|
151
|
-
|
|
152
|
-
const {
|
|
153
|
-
result: { current: dimensions },
|
|
154
|
-
} = renderHook(() => useDimensions("window"));
|
|
161
|
+
const { dimensions } = testHook("window");
|
|
155
162
|
|
|
156
163
|
expect(dimensions).toHaveProperty("height", window.height);
|
|
157
164
|
expect(dimensions).toHaveProperty("width", window.width);
|
|
@@ -3,13 +3,15 @@ import { isTablet } from "../isTablet";
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns an object with additional device info that can be used to determine if tablet
|
|
5
5
|
* @param {Number} dimensions - Dimensions object passed to the function
|
|
6
|
+
* @param {Object} appData - application data object passed to the function
|
|
6
7
|
* @returns {DeviceInfo} deviceInfo - returns an object with scale, isTablet, and orientation
|
|
7
8
|
*/
|
|
8
|
-
export const getDeviceInfo = (dimensions) => {
|
|
9
|
+
export const getDeviceInfo = (dimensions, appData) => {
|
|
9
10
|
const scale = dimensions?.scale;
|
|
10
11
|
const isLandscape = dimensions?.width > dimensions?.height;
|
|
11
12
|
const orientation = isLandscape ? "landscape" : "portrait";
|
|
12
13
|
const tablet = isTablet(dimensions, orientation) || false;
|
|
14
|
+
const isTabletLandscape = tablet && !appData?.isTabletPortrait;
|
|
13
15
|
|
|
14
|
-
return { scale, isTablet: tablet, orientation };
|
|
16
|
+
return { scale, isTablet: tablet, orientation, isTabletLandscape };
|
|
15
17
|
};
|
|
@@ -2,6 +2,7 @@ type DeviceInfo = {
|
|
|
2
2
|
isTablet: boolean;
|
|
3
3
|
scale: number;
|
|
4
4
|
orientation: string;
|
|
5
|
+
isTabletLandscape: boolean;
|
|
5
6
|
};
|
|
6
7
|
|
|
7
8
|
type RNDimensions = {
|
|
@@ -20,6 +21,7 @@ export type Options = {
|
|
|
20
21
|
excludeStatusBar?: boolean;
|
|
21
22
|
rounded?: boolean;
|
|
22
23
|
deviceInfo?: boolean;
|
|
24
|
+
updateForInactiveScreens?: boolean;
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
export type Context = "window" | "screen";
|
package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import * as ReactNative from "react-native";
|
|
2
2
|
|
|
3
|
-
jest.
|
|
4
|
-
|
|
5
|
-
(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
);
|
|
3
|
+
const mockDimensionsGet = jest.fn(
|
|
4
|
+
(type) =>
|
|
5
|
+
({
|
|
6
|
+
window: { width: 1, height: 1 },
|
|
7
|
+
screen: { width: 360, height: 540 },
|
|
8
|
+
}[type])
|
|
9
|
+
);
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
Platform: jest.fn(() => ({ OS: mockPlatformOS })),
|
|
14
|
-
Dimensions: { get: mockDimensionsGet },
|
|
15
|
-
};
|
|
16
|
-
});
|
|
11
|
+
ReactNative.Dimensions.get = mockDimensionsGet;
|
|
17
12
|
|
|
18
13
|
const mockGetConstants = jest.fn().mockReturnValue({
|
|
19
14
|
Dimensions: {
|
|
@@ -26,9 +21,10 @@ jest.mock("react-native/Libraries/Utilities/NativeDeviceInfo", () => ({
|
|
|
26
21
|
getConstants: mockGetConstants,
|
|
27
22
|
}));
|
|
28
23
|
|
|
29
|
-
const { Platform, Dimensions } =
|
|
24
|
+
const { Platform, Dimensions } = ReactNative;
|
|
30
25
|
|
|
31
26
|
Platform.OS = "android";
|
|
27
|
+
|
|
32
28
|
const { getInitialDimensions } = require("../getInitialDimensions.native.ts");
|
|
33
29
|
|
|
34
30
|
describe("useDimensions > helpers ( native )", () => {
|
|
@@ -48,7 +44,6 @@ describe("useDimensions > helpers ( native )", () => {
|
|
|
48
44
|
|
|
49
45
|
it("should call NativeDeviceInfo.getConstants for ios when width === height", () => {
|
|
50
46
|
Platform.OS = "ios";
|
|
51
|
-
mockPlatformOS = "ios";
|
|
52
47
|
|
|
53
48
|
jest.fn().mockReturnValue({
|
|
54
49
|
Dimensions: {
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
const mockDimensionsGet = jest.fn(
|
|
3
|
-
(type) =>
|
|
4
|
-
({
|
|
5
|
-
window: { width: 1, height: 1 },
|
|
6
|
-
screen: { width: 360, height: 540 },
|
|
7
|
-
}[type])
|
|
8
|
-
);
|
|
1
|
+
import * as ReactNative from "react-native";
|
|
9
2
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
3
|
+
const mockDimensionsGet = jest.fn(
|
|
4
|
+
(type) =>
|
|
5
|
+
({
|
|
6
|
+
window: { width: 1, height: 1 },
|
|
7
|
+
screen: { width: 360, height: 540 },
|
|
8
|
+
}[type])
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
ReactNative.Dimensions.get = mockDimensionsGet;
|
|
15
12
|
|
|
16
|
-
const { Platform, Dimensions } =
|
|
13
|
+
const { Platform, Dimensions } = ReactNative;
|
|
17
14
|
|
|
18
15
|
Platform.OS = "web";
|
|
16
|
+
|
|
19
17
|
const { getInitialDimensions } = require("../getInitialDimensions.ts");
|
|
20
18
|
|
|
21
19
|
describe("useDimensions > helpers (web)", () => {
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import * as R from "ramda";
|
|
4
4
|
|
|
5
5
|
import { Dimensions, Platform, StatusBar } from "react-native";
|
|
6
|
+
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
7
|
+
|
|
6
8
|
import { isTV } from "../../../reactUtils";
|
|
7
9
|
|
|
8
10
|
import { Options, UseDimensions } from "../types";
|
|
9
11
|
import { getDeviceInfo } from "../getDeviceInfo";
|
|
10
12
|
import { getInitialDimensions } from "./helpers";
|
|
13
|
+
import { useIsScreenActive } from "../../navigation";
|
|
11
14
|
|
|
12
15
|
function compensateForScaleIfNeeded(context) {
|
|
13
16
|
return function () {
|
|
@@ -32,8 +35,11 @@ const statusBarHeight = StatusBar?.currentHeight;
|
|
|
32
35
|
*/
|
|
33
36
|
export const useDimensions: UseDimensions = (
|
|
34
37
|
context = "window",
|
|
35
|
-
fullDimensions = { fullDimensions: false }
|
|
38
|
+
fullDimensions = { fullDimensions: false, updateForInactiveScreens: true }
|
|
36
39
|
) => {
|
|
40
|
+
const isActive = useIsScreenActive();
|
|
41
|
+
const { appData } = usePickFromState(["appData"]);
|
|
42
|
+
|
|
37
43
|
if (typeof fullDimensions === "boolean") {
|
|
38
44
|
// eslint-disable-next-line no-console
|
|
39
45
|
console.warn(
|
|
@@ -47,7 +53,7 @@ export const useDimensions: UseDimensions = (
|
|
|
47
53
|
: { ...fullDimensions };
|
|
48
54
|
|
|
49
55
|
const [dimensions, setDimensions] = useState(getInitialDimensions(context));
|
|
50
|
-
const deviceInfo = useRef(getDeviceInfo(dimensions));
|
|
56
|
+
const deviceInfo = useRef(getDeviceInfo(dimensions, appData));
|
|
51
57
|
|
|
52
58
|
const applyOptions = R.compose(
|
|
53
59
|
R.when(() => options.deviceInfo, R.assoc("deviceInfo", deviceInfo.current)),
|
|
@@ -73,7 +79,7 @@ export const useDimensions: UseDimensions = (
|
|
|
73
79
|
|
|
74
80
|
if (newDimensions.width === newDimensions.height) {
|
|
75
81
|
/**
|
|
76
|
-
* Ignoring case
|
|
82
|
+
* Ignoring case occurred on iOS when Dimensions.get sometimes returning
|
|
77
83
|
* wrong `window` sizes
|
|
78
84
|
* when switch background -> foreground state.
|
|
79
85
|
* ( TODO fix when 1:1 aspect ratio will be used )
|
|
@@ -81,8 +87,8 @@ export const useDimensions: UseDimensions = (
|
|
|
81
87
|
|
|
82
88
|
// eslint-disable-next-line no-console
|
|
83
89
|
console.log("change: wrong values - width equal to height, ignoring");
|
|
84
|
-
} else {
|
|
85
|
-
deviceInfo.current = getDeviceInfo(newDimensions);
|
|
90
|
+
} else if (isActive || options.updateForInactiveScreens) {
|
|
91
|
+
deviceInfo.current = getDeviceInfo(newDimensions, appData);
|
|
86
92
|
setDimensions(newDimensions);
|
|
87
93
|
}
|
|
88
94
|
};
|
|
@@ -92,7 +98,7 @@ export const useDimensions: UseDimensions = (
|
|
|
92
98
|
return () => {
|
|
93
99
|
activeSubscription.remove();
|
|
94
100
|
};
|
|
95
|
-
}, []);
|
|
101
|
+
}, [isActive]);
|
|
96
102
|
|
|
97
103
|
const memoizedDimensions = useMemo(() => {
|
|
98
104
|
return { ...applyOptions(dimensions), statusBarHeight };
|
|
@@ -15,11 +15,26 @@ export const mockMenu: ZappNavigation = {
|
|
|
15
15
|
// preset_id?: null | unknown;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
export const useRoute = jest.fn(() => ({
|
|
19
|
+
screenData: {
|
|
20
|
+
name: "someName",
|
|
21
|
+
},
|
|
22
|
+
pathname: "someRoute",
|
|
23
|
+
}));
|
|
24
|
+
|
|
18
25
|
export const useNavigation = jest.fn(() => ({
|
|
19
26
|
data: {},
|
|
27
|
+
screenData: {
|
|
28
|
+
name: "someName",
|
|
29
|
+
},
|
|
30
|
+
activeRiver: {
|
|
31
|
+
id: "someId",
|
|
32
|
+
},
|
|
20
33
|
currentRoute: "someRoute",
|
|
21
34
|
}));
|
|
22
35
|
|
|
23
36
|
export const useNavigationPluginData = jest.fn().mockReturnValue(mockMenu);
|
|
24
37
|
|
|
25
38
|
export const useIsNavBarVisible = jest.fn().mockReturnValue(true);
|
|
39
|
+
|
|
40
|
+
export const useIsScreenActive = jest.fn().mockReturnValue(true);
|