@applicaster/zapp-react-native-utils 12.0.0-alpha.8433353116 → 12.0.0-alpha.8454200631
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/index.ts +6 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +6 -0
- package/analyticsUtils/index.tsx +6 -0
- package/appUtils/playerManager/player.ts +1 -0
- package/appUtils/playerManager/playerNative.ts +5 -0
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +6 -1
- package/cellUtils/__tests__/cellUtils.test.ts +9 -20
- package/cellUtils/index.ts +8 -12
- package/dateUtils/index.ts +11 -0
- package/headersUtils/index.ts +1 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/localizationUtils/__tests__/localizationUtils.test.ts +72 -53
- package/localizationUtils/index.ts +13 -22
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +2 -1
- package/numberUtils/index.ts +4 -0
- package/package.json +2 -2
- package/playerUtils/configurationGenerator.ts +3 -1
- package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +16 -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/layout/__tests__/{index.test.js → index.test.tsx} +43 -29
- package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
- package/reactHooks/layout/types/index.ts +1 -0
- package/reactHooks/layout/useDimensions/useDimensions.ts +5 -2
- package/reactHooks/navigation/__mocks__/index.ts +13 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
- package/reactHooks/navigation/index.ts +22 -61
- package/reactHooks/screen/useScreenContext.ts +4 -3
- package/screenState/index.ts +0 -8
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +24 -22
- package/types.ts +4 -0
package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx}
RENAMED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
1
3
|
import { act, renderHook } from "@testing-library/react-hooks";
|
|
4
|
+
import { Provider } from "react-redux";
|
|
5
|
+
import configureStore from "redux-mock-store";
|
|
2
6
|
|
|
3
7
|
const mockUpdateComponentsPositions = jest.fn();
|
|
4
8
|
|
|
@@ -19,11 +23,22 @@ jest.useFakeTimers();
|
|
|
19
23
|
|
|
20
24
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
|
|
21
25
|
|
|
26
|
+
const mockStore = configureStore();
|
|
27
|
+
|
|
28
|
+
const store = mockStore({ appData: {} });
|
|
29
|
+
|
|
30
|
+
const Wrapper = ({ children }: { children: React.ReactChild }) => (
|
|
31
|
+
/* @ts-ignore */
|
|
32
|
+
<Provider store={store}>{children}</Provider>
|
|
33
|
+
);
|
|
34
|
+
|
|
22
35
|
const { useTrackedView } = require("../useTrackedView");
|
|
23
36
|
|
|
24
37
|
describe("useTrackCurrentAutoScrollingElement", () => {
|
|
25
38
|
it("should update position for selected component", async () => {
|
|
26
|
-
const { result } = renderHook(() => useTrackedView("123")
|
|
39
|
+
const { result } = renderHook(() => useTrackedView("123"), {
|
|
40
|
+
wrapper: Wrapper,
|
|
41
|
+
});
|
|
27
42
|
|
|
28
43
|
// Fast-forward until all timers have been executed
|
|
29
44
|
jest.advanceTimersByTime(3000);
|
|
@@ -6,6 +6,7 @@ import { waitFor } from "@testing-library/react-native";
|
|
|
6
6
|
const navigator = {
|
|
7
7
|
getPathname: () => "pathnameMock",
|
|
8
8
|
push: jest.fn(),
|
|
9
|
+
data: {},
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
@@ -28,6 +29,10 @@ jest.mock("@applicaster/zapp-react-native-ui-components/Contexts", () => ({
|
|
|
28
29
|
},
|
|
29
30
|
}));
|
|
30
31
|
|
|
32
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
|
|
33
|
+
useScreenContext: jest.fn(() => navigator.data),
|
|
34
|
+
}));
|
|
35
|
+
|
|
31
36
|
const { useCellClick } = require("../");
|
|
32
37
|
|
|
33
38
|
const mockProps = {
|
|
@@ -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 });
|
|
@@ -1,4 +1,8 @@
|
|
|
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";
|
|
2
6
|
|
|
3
7
|
import * as ReactNative from "react-native";
|
|
4
8
|
|
|
@@ -48,19 +52,43 @@ jest.mock("../../navigation", () => ({
|
|
|
48
52
|
}));
|
|
49
53
|
|
|
50
54
|
const { Dimensions } = require("react-native");
|
|
51
|
-
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
|
+
};
|
|
52
82
|
|
|
53
83
|
describe("useDimensions", () => {
|
|
54
84
|
it("renders", () => {
|
|
55
|
-
const { result } =
|
|
56
|
-
useDimensions("window", { fullDimensions: true })
|
|
57
|
-
);
|
|
85
|
+
const { result } = testHook("window", { fullDimensions: true });
|
|
58
86
|
|
|
59
87
|
expect(result).toBeDefined();
|
|
60
88
|
});
|
|
61
89
|
|
|
62
90
|
it("sets event listener", () => {
|
|
63
|
-
|
|
91
|
+
testHook("window", { fullDimensions: true });
|
|
64
92
|
|
|
65
93
|
expect(Dimensions.addEventListener).toBeCalledWith(
|
|
66
94
|
"change",
|
|
@@ -69,16 +97,14 @@ describe("useDimensions", () => {
|
|
|
69
97
|
});
|
|
70
98
|
|
|
71
99
|
it("removes event listener", () => {
|
|
72
|
-
|
|
100
|
+
testHook("window", { fullDimensions: true });
|
|
73
101
|
cleanup();
|
|
74
102
|
|
|
75
103
|
expect(mockRemoveFn).toBeCalled();
|
|
76
104
|
});
|
|
77
105
|
|
|
78
106
|
it("Returns full dimensions object", () => {
|
|
79
|
-
const {
|
|
80
|
-
result: { current: dimensions },
|
|
81
|
-
} = renderHook(() => useDimensions("window", { fullDimensions: true }));
|
|
107
|
+
const { dimensions } = testHook("window", { fullDimensions: true });
|
|
82
108
|
|
|
83
109
|
expect(dimensions).toHaveProperty("height");
|
|
84
110
|
expect(dimensions).toHaveProperty("width");
|
|
@@ -87,20 +113,17 @@ describe("useDimensions", () => {
|
|
|
87
113
|
});
|
|
88
114
|
|
|
89
115
|
it("Returns shorthand dimensions object", () => {
|
|
90
|
-
const {
|
|
91
|
-
result: { current: dimensions },
|
|
92
|
-
} = renderHook(() => useDimensions("window"));
|
|
116
|
+
const { dimensions } = testHook("window");
|
|
93
117
|
|
|
94
118
|
expect(dimensions).toHaveProperty("height");
|
|
95
119
|
expect(dimensions).toHaveProperty("width");
|
|
96
120
|
});
|
|
97
121
|
|
|
98
122
|
it("Returns the device info object", () => {
|
|
99
|
-
const {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
);
|
|
123
|
+
const { dimensions } = testHook("window", {
|
|
124
|
+
fullDimensions: true,
|
|
125
|
+
deviceInfo: true,
|
|
126
|
+
});
|
|
104
127
|
|
|
105
128
|
expect(dimensions).toHaveProperty("height");
|
|
106
129
|
expect(dimensions).toHaveProperty("width");
|
|
@@ -113,10 +136,7 @@ describe("useDimensions", () => {
|
|
|
113
136
|
it("applies the scale on TV, and screen context", () => {
|
|
114
137
|
tv_flag = true;
|
|
115
138
|
const { screen } = mocked_return_value(tv_flag);
|
|
116
|
-
|
|
117
|
-
const {
|
|
118
|
-
result: { current: dimensions },
|
|
119
|
-
} = renderHook(() => useDimensions("screen"));
|
|
139
|
+
const { dimensions } = testHook("screen");
|
|
120
140
|
|
|
121
141
|
expect(dimensions).toHaveProperty("height", screen.height * screen.scale);
|
|
122
142
|
expect(dimensions).toHaveProperty("width", screen.width * screen.scale);
|
|
@@ -128,10 +148,7 @@ describe("useDimensions", () => {
|
|
|
128
148
|
it("doesn't apply the scale on mobile with screen context", () => {
|
|
129
149
|
tv_flag = false;
|
|
130
150
|
const { screen } = mocked_return_value(tv_flag);
|
|
131
|
-
|
|
132
|
-
const {
|
|
133
|
-
result: { current: dimensions },
|
|
134
|
-
} = renderHook(() => useDimensions("screen"));
|
|
151
|
+
const { dimensions } = testHook("screen");
|
|
135
152
|
|
|
136
153
|
expect(dimensions).toHaveProperty("height", screen.height);
|
|
137
154
|
expect(dimensions).toHaveProperty("width", screen.width);
|
|
@@ -141,10 +158,7 @@ describe("useDimensions", () => {
|
|
|
141
158
|
it("doesn't apply the scale on TV with window context", () => {
|
|
142
159
|
tv_flag = true;
|
|
143
160
|
const { window } = mocked_return_value(tv_flag);
|
|
144
|
-
|
|
145
|
-
const {
|
|
146
|
-
result: { current: dimensions },
|
|
147
|
-
} = renderHook(() => useDimensions("window"));
|
|
161
|
+
const { dimensions } = testHook("window");
|
|
148
162
|
|
|
149
163
|
expect(dimensions).toHaveProperty("height", window.height);
|
|
150
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
|
};
|
|
@@ -3,6 +3,8 @@ import { useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
|
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";
|
|
@@ -36,6 +38,7 @@ export const useDimensions: UseDimensions = (
|
|
|
36
38
|
fullDimensions = { fullDimensions: false, updateForInactiveScreens: true }
|
|
37
39
|
) => {
|
|
38
40
|
const isActive = useIsScreenActive();
|
|
41
|
+
const { appData } = usePickFromState(["appData"]);
|
|
39
42
|
|
|
40
43
|
if (typeof fullDimensions === "boolean") {
|
|
41
44
|
// eslint-disable-next-line no-console
|
|
@@ -50,7 +53,7 @@ export const useDimensions: UseDimensions = (
|
|
|
50
53
|
: { ...fullDimensions };
|
|
51
54
|
|
|
52
55
|
const [dimensions, setDimensions] = useState(getInitialDimensions(context));
|
|
53
|
-
const deviceInfo = useRef(getDeviceInfo(dimensions));
|
|
56
|
+
const deviceInfo = useRef(getDeviceInfo(dimensions, appData));
|
|
54
57
|
|
|
55
58
|
const applyOptions = R.compose(
|
|
56
59
|
R.when(() => options.deviceInfo, R.assoc("deviceInfo", deviceInfo.current)),
|
|
@@ -85,7 +88,7 @@ export const useDimensions: UseDimensions = (
|
|
|
85
88
|
// eslint-disable-next-line no-console
|
|
86
89
|
console.log("change: wrong values - width equal to height, ignoring");
|
|
87
90
|
} else if (isActive || options.updateForInactiveScreens) {
|
|
88
|
-
deviceInfo.current = getDeviceInfo(newDimensions);
|
|
91
|
+
deviceInfo.current = getDeviceInfo(newDimensions, appData);
|
|
89
92
|
setDimensions(newDimensions);
|
|
90
93
|
}
|
|
91
94
|
};
|
|
@@ -15,8 +15,21 @@ 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
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
|
|
3
3
|
import { renderHook } from "@testing-library/react-hooks";
|
|
4
|
-
import {
|
|
4
|
+
import { isNavBarVisible, useRoute } from "../";
|
|
5
5
|
import { Provider } from "react-redux";
|
|
6
6
|
import configureMockStore from "redux-mock-store";
|
|
7
7
|
import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
|
|
8
8
|
import { ZappHookModalContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
|
|
9
9
|
import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
|
|
10
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
10
11
|
|
|
11
12
|
const plugins = [];
|
|
12
13
|
|
|
@@ -100,13 +101,15 @@ const mainStackWrapper = ({
|
|
|
100
101
|
pathname = homeStack.route,
|
|
101
102
|
}) => (
|
|
102
103
|
<Provider store={store}>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
<ScreenDataContext.Provider value={homeStack.state}>
|
|
105
|
+
<NavigationContext.Provider
|
|
106
|
+
value={{ ...mainStackNavigator, ...navigator, currentRoute: pathname }}
|
|
107
|
+
>
|
|
108
|
+
<PathnameContext.Provider value={pathname}>
|
|
109
|
+
{children}
|
|
110
|
+
</PathnameContext.Provider>
|
|
111
|
+
</NavigationContext.Provider>
|
|
112
|
+
</ScreenDataContext.Provider>
|
|
110
113
|
</Provider>
|
|
111
114
|
);
|
|
112
115
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
/* eslint max-len: off */
|
|
3
3
|
|
|
4
|
-
import React, { useEffect, useMemo } from "react";
|
|
4
|
+
import React, { useContext, useEffect, useMemo } from "react";
|
|
5
5
|
import { BackHandler, InteractionManager, NativeModules } from "react-native";
|
|
6
6
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
7
|
+
import { isEmpty } from "ramda";
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
10
|
useContentTypes,
|
|
@@ -31,6 +32,7 @@ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
|
31
32
|
import { useNavbarState } from "../screen";
|
|
32
33
|
import { useNavigation } from "./useNavigation";
|
|
33
34
|
import { useModalStore } from "../../modalState";
|
|
35
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
34
36
|
|
|
35
37
|
export { useNavigation } from "./useNavigation";
|
|
36
38
|
|
|
@@ -146,16 +148,8 @@ export const useRoute = (): {
|
|
|
146
148
|
pathname: string;
|
|
147
149
|
} => {
|
|
148
150
|
const pathname = usePathname() || "";
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* compose `useRoute()` output data
|
|
152
|
-
*/
|
|
153
|
-
const composeRouteData = (screenData: VariousScreenData) => ({
|
|
154
|
-
screenData,
|
|
155
|
-
pathname,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
151
|
const navigator = useNavigation();
|
|
152
|
+
const screenDataContext = legacyScreenData(useContext(ScreenDataContext));
|
|
159
153
|
|
|
160
154
|
const { plugins, contentTypes, rivers } = usePickFromState([
|
|
161
155
|
"plugins",
|
|
@@ -163,10 +157,11 @@ export const useRoute = (): {
|
|
|
163
157
|
"contentTypes",
|
|
164
158
|
]);
|
|
165
159
|
|
|
166
|
-
const currentStack = navigator.getStackForPathname(pathname);
|
|
167
160
|
const { modalState } = useModalStore();
|
|
168
161
|
const hookModalState = useZappHooksModalState();
|
|
162
|
+
|
|
169
163
|
const modalScreenData = modalState.screen;
|
|
164
|
+
|
|
170
165
|
const hookModalScreenData = hookModalState.state.screenData?.payload;
|
|
171
166
|
|
|
172
167
|
const videoModalScreenData =
|
|
@@ -183,15 +178,6 @@ export const useRoute = (): {
|
|
|
183
178
|
plugins
|
|
184
179
|
);
|
|
185
180
|
|
|
186
|
-
const currentRouteScreenData = legacyScreenData(
|
|
187
|
-
{
|
|
188
|
-
screen: currentStack?.state?.screen ?? navigator.data?.screen ?? {},
|
|
189
|
-
entry: currentStack?.state?.entry ?? {},
|
|
190
|
-
} as NavigationScreenData,
|
|
191
|
-
|
|
192
|
-
plugins
|
|
193
|
-
);
|
|
194
|
-
|
|
195
181
|
// There are 4 route scenarios
|
|
196
182
|
// For regular screens take date from navigator stack.
|
|
197
183
|
// is path is model grab screenData from modal state
|
|
@@ -200,58 +186,33 @@ export const useRoute = (): {
|
|
|
200
186
|
// if path is hook grab screenData from screenData
|
|
201
187
|
|
|
202
188
|
if (isModalPathname(pathname)) {
|
|
203
|
-
|
|
189
|
+
const screenData = modalScreenData ?? ({} as ZappEntry);
|
|
190
|
+
|
|
191
|
+
return { screenData, pathname };
|
|
204
192
|
}
|
|
205
193
|
|
|
206
194
|
if (isVideoModalPathname(pathname)) {
|
|
207
|
-
|
|
195
|
+
const screenData = videoModalScreenData as LegacyNavigationScreenData;
|
|
196
|
+
|
|
197
|
+
return { screenData, pathname };
|
|
208
198
|
}
|
|
209
199
|
|
|
210
200
|
if (isHookModalPathname(pathname)) {
|
|
211
|
-
|
|
201
|
+
const screenData = hookModalScreenData;
|
|
202
|
+
|
|
203
|
+
return { screenData, pathname };
|
|
212
204
|
}
|
|
213
205
|
|
|
214
206
|
if (isHookPathname(pathname)) {
|
|
215
|
-
|
|
216
|
-
* HACK
|
|
217
|
-
*
|
|
218
|
-
* This condition relies on hacky approach to get the current hook screen data
|
|
219
|
-
* using navigator.screenData for some cases.
|
|
220
|
-
* This is used when hook is in sequence.
|
|
221
|
-
*/
|
|
222
|
-
|
|
223
|
-
// case 1: stack not yet updated in navigator context, but navigator.screenData is updated already.
|
|
224
|
-
if (!currentStack) {
|
|
225
|
-
return composeRouteData(navigator.screenData);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const isValidHookInCurrentRouteScreenData =
|
|
229
|
-
"hookPlugin" in currentRouteScreenData &&
|
|
230
|
-
!!currentRouteScreenData.hookPlugin?.module;
|
|
231
|
-
|
|
232
|
-
let screenData;
|
|
233
|
-
|
|
234
|
-
// case 2: stack has valid hook data
|
|
235
|
-
if (isValidHookInCurrentRouteScreenData) {
|
|
236
|
-
screenData = currentRouteScreenData;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const navigatorScreenData = navigator.screenData as NavigatorEntry;
|
|
240
|
-
|
|
241
|
-
// case 3: current hookPlugin is missing weight, but navigator.screenData has weight, use navigator.screenData
|
|
242
|
-
if (
|
|
243
|
-
screenData.hookPlugin.identifier ===
|
|
244
|
-
navigatorScreenData?.hookPlugin?.identifier &&
|
|
245
|
-
!screenData.hookPlugin?.weight &&
|
|
246
|
-
navigatorScreenData?.hookPlugin?.weight
|
|
247
|
-
) {
|
|
248
|
-
screenData = navigator.screenData;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return composeRouteData(screenData);
|
|
207
|
+
return { screenData: screenDataContext, pathname };
|
|
252
208
|
}
|
|
253
209
|
|
|
254
|
-
|
|
210
|
+
// Cover cases where screenContext is used before navigation is initialized
|
|
211
|
+
const screenData = isEmpty(screenDataContext)
|
|
212
|
+
? navigator.screenData
|
|
213
|
+
: screenDataContext;
|
|
214
|
+
|
|
215
|
+
return { screenData, pathname };
|
|
255
216
|
};
|
|
256
217
|
|
|
257
218
|
type Callbacks = Partial<{
|
|
@@ -5,8 +5,9 @@ import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-co
|
|
|
5
5
|
import { useNavigation } from "../navigation/useNavigation";
|
|
6
6
|
|
|
7
7
|
import { ScreenContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenContext";
|
|
8
|
+
import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
|
|
8
9
|
|
|
9
|
-
function useScreenContextV2() {
|
|
10
|
+
export function useScreenContextV2() {
|
|
10
11
|
return useContext(ScreenContext);
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -44,9 +45,9 @@ export function useSetNavbarState() {
|
|
|
44
45
|
|
|
45
46
|
export function useScreenContext(): NavigationScreenData {
|
|
46
47
|
const navigator = useNavigation();
|
|
48
|
+
// Cover cases where screenContext is used before navigation is initialized
|
|
49
|
+
const screenData = useContext(ScreenDataContext) || navigator.data;
|
|
47
50
|
|
|
48
|
-
const screenKey = useMemo(() => navigator?.key, [navigator]);
|
|
49
|
-
const screenData = useMemo(() => navigator?.data, [screenKey]);
|
|
50
51
|
const modalScreenData = navigator?.modalData;
|
|
51
52
|
|
|
52
53
|
const isModal = useModalNavigationContext();
|
package/screenState/index.ts
CHANGED
|
@@ -49,11 +49,3 @@ export function useScreenState(
|
|
|
49
49
|
setSelectedEntry: (entryId) => setSelectedEntry(screenId, entryId),
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
export const useScreenScrollStore = create<{
|
|
54
|
-
scrollPosition: number;
|
|
55
|
-
scrollingVelocity: number;
|
|
56
|
-
}>(() => ({
|
|
57
|
-
scrollPosition: 0,
|
|
58
|
-
scrollingVelocity: 0,
|
|
59
|
-
}));
|
package/stringUtils/index.ts
CHANGED
|
@@ -152,3 +152,8 @@ export function objectToCamelCase(obj) {
|
|
|
152
152
|
export function isString(value: unknown): value is string {
|
|
153
153
|
return typeof value === "string" || value instanceof String;
|
|
154
154
|
}
|
|
155
|
+
|
|
156
|
+
/** Checks if a value is a non-empty string */
|
|
157
|
+
export function isNotEmptyString(value: unknown): value is string {
|
|
158
|
+
return isString(value) && value.length > 0;
|
|
159
|
+
}
|