@applicaster/zapp-react-native-ui-components 14.0.0-alpha.2385258459 → 14.0.0-alpha.2482261241
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/Components/BaseFocusable/index.tsx +23 -12
- package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
- package/Components/FeedLoader/FeedLoader.tsx +6 -15
- package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
- package/Components/FeedLoader/index.js +2 -8
- package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +5 -6
- package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
- package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
- package/Components/MasterCell/utils/index.ts +11 -5
- package/Components/OfflineHandler/__tests__/index.test.tsx +6 -13
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +0 -1
- package/Components/River/RefreshControl.tsx +11 -19
- package/Components/River/__tests__/river.test.js +12 -26
- package/Components/Screen/__tests__/Screen.test.tsx +5 -17
- package/Components/Tabs/Tabs.tsx +2 -3
- package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
- package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
- package/Contexts/ScreenContext/index.tsx +46 -6
- package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
- package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
- package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
- package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
- package/Decorators/RiverFeedLoader/index.tsx +22 -4
- package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +27 -27
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +35 -10
- package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
- package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
- package/events/index.ts +1 -0
- package/package.json +5 -5
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
|
@@ -1,28 +1,58 @@
|
|
|
1
1
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
2
|
-
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-
|
|
2
|
+
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/StorageSingleSelectProvider";
|
|
3
3
|
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
|
|
4
|
-
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-
|
|
4
|
+
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/StorageMultiSelectProvider";
|
|
5
5
|
import React, { useEffect } from "react";
|
|
6
6
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
7
7
|
import { BehaviorSubject } from "rxjs";
|
|
8
8
|
import { masterCellLogger } from "../logger";
|
|
9
9
|
import get from "lodash/get";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
import { ScreenMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenStateMultiSelectProvider";
|
|
11
|
+
import { ScreenSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenSingleValueProvider";
|
|
12
|
+
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
13
|
+
import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
|
|
14
|
+
|
|
15
|
+
const parseContextKey = (
|
|
16
|
+
key: string,
|
|
17
|
+
context: string = "ctx"
|
|
18
|
+
): string | null => {
|
|
19
|
+
if (!key?.startsWith(`@{${context}/`)) return null;
|
|
20
|
+
|
|
21
|
+
return key.substring(`@{${context}/`.length, key.length - 1);
|
|
15
22
|
};
|
|
16
23
|
|
|
17
24
|
const getDataSourceProvider = (
|
|
18
|
-
behavior: Behavior
|
|
25
|
+
behavior: Behavior,
|
|
26
|
+
screenRoute: string,
|
|
27
|
+
screenStateStore: ReturnType<typeof useScreenStateStore>
|
|
19
28
|
): BehaviorSubject<string[] | string> | null => {
|
|
20
29
|
if (!behavior) return null;
|
|
21
30
|
|
|
22
31
|
const selection = String(behavior.current_selection);
|
|
32
|
+
const screenKey = parseContextKey(selection, "screen");
|
|
33
|
+
|
|
34
|
+
if (screenKey) {
|
|
35
|
+
if (behavior.select_mode === "multi") {
|
|
36
|
+
return ScreenMultiSelectProvider.getProvider(
|
|
37
|
+
screenKey,
|
|
38
|
+
screenRoute,
|
|
39
|
+
screenStateStore
|
|
40
|
+
).getObservable();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (behavior.select_mode === "single") {
|
|
44
|
+
return ScreenSingleValueProvider.getProvider(
|
|
45
|
+
screenKey,
|
|
46
|
+
screenRoute,
|
|
47
|
+
screenStateStore
|
|
48
|
+
).getObservable();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
23
52
|
const contextKey = parseContextKey(selection);
|
|
24
53
|
|
|
25
54
|
if (contextKey) {
|
|
55
|
+
// TODO: Add storage scope to behavior
|
|
26
56
|
if (behavior.select_mode === "multi") {
|
|
27
57
|
return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
|
|
28
58
|
}
|
|
@@ -41,6 +71,8 @@ const getDataSourceProvider = (
|
|
|
41
71
|
|
|
42
72
|
export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
43
73
|
const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
|
|
74
|
+
const screenRoute = useRoute()?.pathname || "";
|
|
75
|
+
const screenStateStore = useScreenStateStore();
|
|
44
76
|
const player = usePlayer();
|
|
45
77
|
|
|
46
78
|
const triggerUpdate = () => setLastUpdate(Date.now());
|
|
@@ -48,7 +80,11 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
48
80
|
useEffect(() => {
|
|
49
81
|
if (!behavior) return;
|
|
50
82
|
|
|
51
|
-
const dataSource = getDataSourceProvider(
|
|
83
|
+
const dataSource = getDataSourceProvider(
|
|
84
|
+
behavior,
|
|
85
|
+
screenRoute,
|
|
86
|
+
screenStateStore
|
|
87
|
+
);
|
|
52
88
|
|
|
53
89
|
if (dataSource) {
|
|
54
90
|
const subscription = dataSource.subscribe(triggerUpdate);
|
|
@@ -72,10 +108,17 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
72
108
|
|
|
73
109
|
// We cant use async in this function (its inside render),
|
|
74
110
|
// so we rely on useBehaviorUpdate to update current value and trigger re-render
|
|
75
|
-
export const isCellSelected = (
|
|
76
|
-
item
|
|
77
|
-
|
|
78
|
-
|
|
111
|
+
export const isCellSelected = ({
|
|
112
|
+
item,
|
|
113
|
+
screenRoute,
|
|
114
|
+
screenStateStore,
|
|
115
|
+
behavior,
|
|
116
|
+
}: {
|
|
117
|
+
item: ZappEntry;
|
|
118
|
+
screenRoute: string;
|
|
119
|
+
screenStateStore: ReturnType<typeof useScreenStateStore>;
|
|
120
|
+
behavior?: Behavior;
|
|
121
|
+
}): boolean => {
|
|
79
122
|
if (!behavior) return false;
|
|
80
123
|
|
|
81
124
|
const id = behavior.selector ? get(item, behavior.selector) : item.id;
|
|
@@ -99,7 +142,32 @@ export const isCellSelected = (
|
|
|
99
142
|
}
|
|
100
143
|
|
|
101
144
|
const selection = String(behavior.current_selection);
|
|
102
|
-
|
|
145
|
+
|
|
146
|
+
const screenKey = parseContextKey(selection, "screen");
|
|
147
|
+
|
|
148
|
+
if (screenKey) {
|
|
149
|
+
if (behavior.select_mode === "single") {
|
|
150
|
+
const selectedItem = ScreenSingleValueProvider.getProvider(
|
|
151
|
+
screenKey,
|
|
152
|
+
screenRoute,
|
|
153
|
+
screenStateStore
|
|
154
|
+
).getValue();
|
|
155
|
+
|
|
156
|
+
return selectedItem === String(id);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (behavior.select_mode === "multi") {
|
|
160
|
+
const selectedItems = ScreenMultiSelectProvider.getProvider(
|
|
161
|
+
screenKey,
|
|
162
|
+
screenRoute,
|
|
163
|
+
screenStateStore
|
|
164
|
+
).getSelectedItems();
|
|
165
|
+
|
|
166
|
+
return selectedItems?.includes(String(id));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const contextKey = parseContextKey(selection, "ctx");
|
|
103
171
|
|
|
104
172
|
if (contextKey) {
|
|
105
173
|
if (behavior.select_mode === "single") {
|
|
@@ -8,6 +8,8 @@ import { masterCellLogger } from "../logger";
|
|
|
8
8
|
import { getCellState } from "../../Cell/utils";
|
|
9
9
|
import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
10
10
|
import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
|
|
11
|
+
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
|
+
import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
|
|
11
13
|
|
|
12
14
|
const hasElementSpecificViewType = (viewType) => (element) => {
|
|
13
15
|
if (R.isNil(element)) {
|
|
@@ -190,10 +192,6 @@ export const getFocusedButtonId = (focusable) => {
|
|
|
190
192
|
});
|
|
191
193
|
};
|
|
192
194
|
|
|
193
|
-
export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
|
|
194
|
-
return isCellSelected(item, behavior);
|
|
195
|
-
};
|
|
196
|
-
|
|
197
195
|
export const useCellState = ({
|
|
198
196
|
item,
|
|
199
197
|
behavior,
|
|
@@ -204,9 +202,17 @@ export const useCellState = ({
|
|
|
204
202
|
focused: boolean;
|
|
205
203
|
}): CellState => {
|
|
206
204
|
const lastUpdate = useBehaviorUpdate(behavior);
|
|
205
|
+
const router = useRoute();
|
|
206
|
+
const screenStateStore = useScreenStateStore();
|
|
207
207
|
|
|
208
208
|
const _isSelected = useMemo(
|
|
209
|
-
() =>
|
|
209
|
+
() =>
|
|
210
|
+
isCellSelected({
|
|
211
|
+
item,
|
|
212
|
+
screenRoute: router?.pathname,
|
|
213
|
+
screenStateStore,
|
|
214
|
+
behavior,
|
|
215
|
+
}),
|
|
210
216
|
[behavior, item, lastUpdate]
|
|
211
217
|
);
|
|
212
218
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
3
|
-
import renderer, { act } from "react-test-renderer";
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
4
3
|
|
|
5
4
|
jest.useFakeTimers({ legacyFakeTimers: true });
|
|
6
5
|
|
|
@@ -49,24 +48,18 @@ describe("OfflineHandler", () => {
|
|
|
49
48
|
const { OfflineHandler, NotificationView } = require("../");
|
|
50
49
|
|
|
51
50
|
it("renders", () => {
|
|
52
|
-
const
|
|
53
|
-
expect(
|
|
51
|
+
const { toJSON } = render(<OfflineHandler />);
|
|
52
|
+
expect(toJSON()).toMatchSnapshot();
|
|
54
53
|
});
|
|
55
54
|
|
|
56
55
|
it("renders Notification mode if component was rendered while online", () => {
|
|
57
56
|
mockConnectionStatus = true;
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
act(() => {
|
|
62
|
-
instance = renderer.create(<OfflineHandler />);
|
|
63
|
-
});
|
|
58
|
+
const { rerender, UNSAFE_getByType } = render(<OfflineHandler />);
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
instance.update(<OfflineHandler />);
|
|
67
|
-
});
|
|
60
|
+
rerender(<OfflineHandler />);
|
|
68
61
|
|
|
69
|
-
const notificationsView =
|
|
62
|
+
const notificationsView = UNSAFE_getByType(NotificationView);
|
|
70
63
|
expect(notificationsView).toBeDefined();
|
|
71
64
|
});
|
|
72
65
|
});
|
|
@@ -2,7 +2,6 @@ import { renderHook, act } from "@testing-library/react-hooks";
|
|
|
2
2
|
import { BehaviorSubject } from "rxjs";
|
|
3
3
|
import { useLoadingState } from "../useLoadingState";
|
|
4
4
|
|
|
5
|
-
// Mock the useRefWithInitialValue hook
|
|
6
5
|
jest.mock(
|
|
7
6
|
"@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue",
|
|
8
7
|
() => ({
|
|
@@ -13,10 +13,7 @@ import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/react
|
|
|
13
13
|
import { useShallow } from "zustand/react/shallow";
|
|
14
14
|
import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
15
15
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
16
|
-
import {
|
|
17
|
-
ZappPipes,
|
|
18
|
-
useAppDispatch,
|
|
19
|
-
} from "@applicaster/zapp-react-native-redux";
|
|
16
|
+
import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
20
17
|
|
|
21
18
|
const BRIGHTNESS_THRESHOLD = 160;
|
|
22
19
|
const ABOVE_DEFAULT_COLOR = "gray";
|
|
@@ -63,38 +60,33 @@ export const usePullToRefresh = (
|
|
|
63
60
|
) => {
|
|
64
61
|
const isPipesV1 = !!pullToRefreshPipesV1RefreshingStateUpdater;
|
|
65
62
|
|
|
66
|
-
const dispatch = useAppDispatch();
|
|
67
|
-
|
|
68
63
|
const [refreshing, setRefreshing] = React.useState(false);
|
|
69
64
|
|
|
70
65
|
const feeds: string[] =
|
|
71
66
|
riverComponents?.map(R.path(["data", "source"])).filter((feed) => !!feed) ??
|
|
72
67
|
[];
|
|
73
68
|
|
|
74
|
-
const screenData = useCurrentScreenData();
|
|
75
|
-
|
|
76
69
|
const feedsLength = feeds.length;
|
|
77
70
|
|
|
78
71
|
const [requestsCompletedCounter, setRequestsCompletedCounter] =
|
|
79
72
|
React.useState(0);
|
|
80
73
|
|
|
74
|
+
const loadPipesDataDispatcher = useLoadPipesDataDispatch();
|
|
75
|
+
|
|
81
76
|
React.useEffect(() => {
|
|
82
77
|
// will not work for pipes v1 on 1st level screens
|
|
83
78
|
if (refreshing && !isPipesV1) {
|
|
84
79
|
feeds.forEach((feed) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
riverId: screenData.id,
|
|
93
|
-
})
|
|
94
|
-
);
|
|
80
|
+
loadPipesDataDispatcher(feed, {
|
|
81
|
+
silentRefresh: true,
|
|
82
|
+
clearCache: true,
|
|
83
|
+
callback: () => {
|
|
84
|
+
setRequestsCompletedCounter(R.inc);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
95
87
|
});
|
|
96
88
|
}
|
|
97
|
-
}, [refreshing, isPipesV1]);
|
|
89
|
+
}, [refreshing, isPipesV1, feeds, loadPipesDataDispatcher]);
|
|
98
90
|
|
|
99
91
|
React.useEffect(() => {
|
|
100
92
|
if (requestsCompletedCounter === feedsLength) {
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import configureStore from "redux-mock-store";
|
|
2
|
+
import { screen } from "@testing-library/react-native";
|
|
4
3
|
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
5
|
-
import { Provider } from "react-redux";
|
|
6
4
|
|
|
7
|
-
import { River } from "../";
|
|
8
5
|
import { ScreenResolver } from "../../ScreenResolver";
|
|
9
6
|
import { RiverComponent } from "../River";
|
|
10
7
|
|
|
11
|
-
jest.mock(
|
|
12
|
-
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
|
|
13
|
-
() => ({
|
|
14
|
-
useIsScreenActive: jest.fn(() => true),
|
|
15
|
-
})
|
|
16
|
-
);
|
|
17
|
-
|
|
18
8
|
jest.mock(
|
|
19
9
|
"@applicaster/zapp-react-native-ui-components/Components/GeneralContentScreen",
|
|
20
10
|
() => {
|
|
@@ -46,6 +36,13 @@ jest.mock(
|
|
|
46
36
|
})
|
|
47
37
|
);
|
|
48
38
|
|
|
39
|
+
jest.mock(
|
|
40
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
|
|
41
|
+
() => ({
|
|
42
|
+
useIsScreenActive: jest.fn(() => true),
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
|
|
49
46
|
const river = {
|
|
50
47
|
home: true,
|
|
51
48
|
id: "A1234",
|
|
@@ -89,28 +86,17 @@ const riverProps = {
|
|
|
89
86
|
|
|
90
87
|
const appData = { layoutVersion: "v1" };
|
|
91
88
|
|
|
92
|
-
const store =
|
|
89
|
+
const store = { rivers, appData };
|
|
93
90
|
|
|
94
91
|
describe("When River has a general_content type", () => {
|
|
95
92
|
it("renders GeneralContentScreen correctly", () => {
|
|
96
|
-
const { getByTestId } =
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
</Provider>
|
|
93
|
+
const { getByTestId } = renderWithProviders(
|
|
94
|
+
<RiverComponent {...riverProps} />,
|
|
95
|
+
store
|
|
100
96
|
);
|
|
101
97
|
|
|
102
98
|
expect(getByTestId("general-content-screen")).toBeTruthy();
|
|
103
99
|
});
|
|
104
|
-
|
|
105
|
-
it("renders River component correctly", () => {
|
|
106
|
-
const wrapper = render(
|
|
107
|
-
<Provider store={store}>
|
|
108
|
-
<River screenId="A1234" />
|
|
109
|
-
</Provider>
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
113
|
-
});
|
|
114
100
|
});
|
|
115
101
|
|
|
116
102
|
describe("When River has any other type other than general_content", () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
4
|
|
|
5
5
|
const Mocked_RouteManager = jest.fn((props) => (
|
|
6
6
|
<View testID="routeManager" {...props} />
|
|
@@ -152,8 +152,6 @@ const screenProps = {
|
|
|
152
152
|
const { Screen } = require("..");
|
|
153
153
|
|
|
154
154
|
describe("<Screen Component />", () => {
|
|
155
|
-
let wrapper;
|
|
156
|
-
|
|
157
155
|
beforeEach(() => {
|
|
158
156
|
allowedOrientationsForScreen.mockClear();
|
|
159
157
|
getOrientation.mockClear();
|
|
@@ -161,26 +159,16 @@ describe("<Screen Component />", () => {
|
|
|
161
159
|
});
|
|
162
160
|
|
|
163
161
|
describe("when the navbar should show", () => {
|
|
164
|
-
act(() => {
|
|
165
|
-
wrapper = create(<Screen {...screenProps} />);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
162
|
it("renders correctly", () => {
|
|
169
|
-
|
|
163
|
+
const { toJSON } = render(<Screen {...screenProps} />);
|
|
164
|
+
expect(toJSON()).toMatchSnapshot();
|
|
170
165
|
});
|
|
171
166
|
});
|
|
172
167
|
|
|
173
168
|
describe("when the navbar should be hidden", () => {
|
|
174
|
-
beforeEach(() => {
|
|
175
|
-
wrapper = create(<Screen {...screenProps} />);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
169
|
it("renders correctly", () => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
170
|
+
const { toJSON } = render(<Screen {...screenProps} />);
|
|
171
|
+
expect(toJSON()).toMatchSnapshot();
|
|
184
172
|
});
|
|
185
173
|
});
|
|
186
174
|
});
|
package/Components/Tabs/Tabs.tsx
CHANGED
|
@@ -158,12 +158,11 @@ const TabsComponent = ({
|
|
|
158
158
|
|
|
159
159
|
const renderItem = React.useCallback(
|
|
160
160
|
({ item, index, item: { id } }: RenderItemProps) => (
|
|
161
|
-
|
|
161
|
+
<React.Fragment key={id}>
|
|
162
162
|
<Tab
|
|
163
163
|
ref={(ref) => {
|
|
164
164
|
tabRefs.current[index] = ref;
|
|
165
165
|
}}
|
|
166
|
-
key={id}
|
|
167
166
|
{...{
|
|
168
167
|
title: getTitle(item),
|
|
169
168
|
id,
|
|
@@ -177,7 +176,7 @@ const TabsComponent = ({
|
|
|
177
176
|
{display_mode === "fractional" &&
|
|
178
177
|
index !== tabs?.length - 1 &&
|
|
179
178
|
renderGutter()}
|
|
180
|
-
|
|
179
|
+
</React.Fragment>
|
|
181
180
|
),
|
|
182
181
|
[tabs, display_mode, configuration, onTabPress, getTitle, getSelectedItem]
|
|
183
182
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View, TouchableOpacity } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
4
4
|
|
|
5
5
|
import { Touchable } from "..";
|
|
6
6
|
|
|
@@ -23,38 +23,31 @@ describe("<Touchable />", () => {
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
it("has accessible flag set to false", () => {
|
|
26
|
-
|
|
26
|
+
const { toJSON, UNSAFE_getByType } = render(<Touchable {...props} />);
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const touchableWrapper = wrapper.root.findByType(TouchableOpacity);
|
|
33
|
-
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
28
|
+
const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
|
|
29
|
+
expect(toJSON()).toMatchSnapshot();
|
|
34
30
|
expect(touchableWrapper.props).toHaveProperty("accessible", false);
|
|
35
31
|
});
|
|
36
32
|
});
|
|
37
33
|
|
|
38
34
|
describe("when not running in automated tests environment", () => {
|
|
39
|
-
let wrapper;
|
|
40
|
-
|
|
41
|
-
act(() => {
|
|
42
|
-
wrapper = create(<Touchable {...props} />);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const touchableWrapper = wrapper.root.findByType(TouchableOpacity);
|
|
46
|
-
|
|
47
35
|
beforeEach(props.onPress.mockClear);
|
|
48
36
|
|
|
49
37
|
it("renders correctly", () => {
|
|
50
|
-
|
|
38
|
+
const { toJSON } = render(<Touchable {...props} />);
|
|
39
|
+
expect(toJSON()).toMatchSnapshot();
|
|
51
40
|
});
|
|
52
41
|
|
|
53
42
|
it("has accessible flag set to true", () => {
|
|
43
|
+
const { UNSAFE_getByType } = render(<Touchable {...props} />);
|
|
44
|
+
const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
|
|
54
45
|
expect(touchableWrapper.props).toHaveProperty("accessible", true);
|
|
55
46
|
});
|
|
56
47
|
|
|
57
48
|
it("assigns testID and accessibilityLabel props correctly", () => {
|
|
49
|
+
const { UNSAFE_getByType } = render(<Touchable {...props} />);
|
|
50
|
+
const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
|
|
58
51
|
expect(touchableWrapper.props).toHaveProperty("testID", props.testID);
|
|
59
52
|
|
|
60
53
|
expect(touchableWrapper.props).toHaveProperty(
|
|
@@ -64,6 +57,8 @@ describe("<Touchable />", () => {
|
|
|
64
57
|
});
|
|
65
58
|
|
|
66
59
|
it("calls the onPress event when it is pressed", () => {
|
|
60
|
+
const { UNSAFE_getByType } = render(<Touchable {...props} />);
|
|
61
|
+
const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
|
|
67
62
|
touchableWrapper.props.onPress();
|
|
68
63
|
expect(props.onPress).toHaveBeenCalledTimes(1);
|
|
69
64
|
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Animated,
|
|
2
|
+
import { Animated, StyleSheet, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
5
|
import {
|
|
6
|
-
GestureHandlerRootView,
|
|
7
6
|
NativeViewGestureHandler,
|
|
8
7
|
PanGestureHandler,
|
|
9
8
|
State,
|
|
@@ -357,15 +356,10 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
|
|
|
357
356
|
};
|
|
358
357
|
}, [playerAnimationState, isAudioItem, isMinimizedModal]);
|
|
359
358
|
|
|
360
|
-
const Wrapper = React.useMemo(
|
|
361
|
-
() => (Platform.OS === "android" ? GestureHandlerRootView : View),
|
|
362
|
-
[]
|
|
363
|
-
);
|
|
364
|
-
|
|
365
359
|
const scrollEnabled = isMaximizedModal && isNotMinimizeMaximazeAnimation;
|
|
366
360
|
|
|
367
361
|
return (
|
|
368
|
-
<
|
|
362
|
+
<View style={generalStyles.container}>
|
|
369
363
|
<TapGestureHandler
|
|
370
364
|
maxDurationMs={100000}
|
|
371
365
|
ref={tapHandlerRef}
|
|
@@ -405,7 +399,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
|
|
|
405
399
|
</PanGestureHandler>
|
|
406
400
|
</View>
|
|
407
401
|
</TapGestureHandler>
|
|
408
|
-
</
|
|
402
|
+
</View>
|
|
409
403
|
);
|
|
410
404
|
};
|
|
411
405
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
3
3
|
|
|
4
4
|
const props = {
|
|
5
5
|
entry: {},
|
|
@@ -42,16 +42,16 @@ const { PlayerDetails } = require("../PlayerDetails");
|
|
|
42
42
|
|
|
43
43
|
describe("PlayerDetails", () => {
|
|
44
44
|
it("renders properly", () => {
|
|
45
|
-
const
|
|
45
|
+
const { toJSON } = render(<PlayerDetails {...props} />);
|
|
46
46
|
|
|
47
|
-
expect(
|
|
47
|
+
expect(toJSON()).toMatchSnapshot();
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it("renders properly on tablet in landscape orientation", () => {
|
|
51
|
-
const
|
|
51
|
+
const { toJSON } = render(
|
|
52
52
|
<PlayerDetails {...props} isTabletLandscape={true} />
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
-
expect(
|
|
55
|
+
expect(toJSON()).toMatchSnapshot();
|
|
56
56
|
});
|
|
57
57
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
3
3
|
import { View } from "react-native";
|
|
4
4
|
import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
|
|
5
5
|
|
|
@@ -14,12 +14,12 @@ describe("withConfigurationProvider", () => {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
it("provides configuration to children", () => {
|
|
17
|
-
const
|
|
17
|
+
const { toJSON } = render(
|
|
18
18
|
<ConfigurationProvider configuration={{ target: "foobar" }}>
|
|
19
19
|
<TestComponent />
|
|
20
20
|
</ConfigurationProvider>
|
|
21
21
|
);
|
|
22
22
|
|
|
23
|
-
expect(
|
|
23
|
+
expect(toJSON()).toMatchSnapshot();
|
|
24
24
|
});
|
|
25
25
|
});
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
14
14
|
import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
|
|
15
15
|
import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
|
|
16
|
-
import { create
|
|
16
|
+
import { create } from "zustand";
|
|
17
|
+
import { subscribeWithSelector } from "zustand/middleware";
|
|
17
18
|
import { useShallow } from "zustand/react/shallow";
|
|
18
19
|
import { Animated } from "react-native";
|
|
19
20
|
|
|
@@ -39,11 +40,26 @@ interface NavBarState {
|
|
|
39
40
|
setSummary: (subtitle: string) => void;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const createStateStore = () =>
|
|
44
|
+
create(
|
|
45
|
+
subscribeWithSelector<ScreenStateStore>((set) => ({
|
|
46
|
+
data: {},
|
|
47
|
+
setValue: (key, value) =>
|
|
48
|
+
set((state) => ({
|
|
49
|
+
data: {
|
|
50
|
+
...state.data,
|
|
51
|
+
[key]: value,
|
|
52
|
+
},
|
|
53
|
+
})),
|
|
54
|
+
removeValue: (key) =>
|
|
55
|
+
set((state) => {
|
|
56
|
+
const newData = { ...state.data };
|
|
57
|
+
delete newData[key];
|
|
58
|
+
|
|
59
|
+
return { data: newData };
|
|
60
|
+
}),
|
|
61
|
+
}))
|
|
62
|
+
);
|
|
47
63
|
|
|
48
64
|
const createStore = () =>
|
|
49
65
|
create<NavBarStoreState>((set) => ({
|
|
@@ -65,7 +81,15 @@ const createStore = () =>
|
|
|
65
81
|
},
|
|
66
82
|
}));
|
|
67
83
|
|
|
84
|
+
type ScreenContextType = {
|
|
85
|
+
_navBarStore: ReturnType<typeof createStore>;
|
|
86
|
+
_stateStore: ReturnType<typeof createStateStore>;
|
|
87
|
+
navBar: NavBarState;
|
|
88
|
+
legacyFormatScreenData: LegacyNavigationScreenData | null;
|
|
89
|
+
};
|
|
90
|
+
|
|
68
91
|
export const ScreenContext = createContext<ScreenContextType>({
|
|
92
|
+
_stateStore: createStateStore(),
|
|
69
93
|
_navBarStore: createStore(),
|
|
70
94
|
navBar: {
|
|
71
95
|
visible: true,
|
|
@@ -103,6 +127,21 @@ export function ScreenContextProvider({
|
|
|
103
127
|
null
|
|
104
128
|
);
|
|
105
129
|
|
|
130
|
+
const screenStateRef = useRef<null | ReturnType<typeof createStateStore>>(
|
|
131
|
+
null
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const getScreenState = useCallback(() => {
|
|
135
|
+
if (screenStateRef.current !== null) {
|
|
136
|
+
return screenStateRef.current;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const stateStore = createStateStore();
|
|
140
|
+
screenStateRef.current = stateStore;
|
|
141
|
+
|
|
142
|
+
return stateStore;
|
|
143
|
+
}, []);
|
|
144
|
+
|
|
106
145
|
const getScreenNavBarState = useCallback(() => {
|
|
107
146
|
if (screenNavBarStateRef.current !== null) {
|
|
108
147
|
return screenNavBarStateRef.current;
|
|
@@ -163,6 +202,7 @@ export function ScreenContextProvider({
|
|
|
163
202
|
value={useMemo(
|
|
164
203
|
() => ({
|
|
165
204
|
_navBarStore: getScreenNavBarState(),
|
|
205
|
+
_stateStore: getScreenState(),
|
|
166
206
|
navBar: navBarState,
|
|
167
207
|
legacyFormatScreenData: routeScreenData,
|
|
168
208
|
}),
|