@applicaster/zapp-react-native-ui-components 15.0.0-rc.12 → 15.0.0-rc.121
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/AnimatedInOut/index.tsx +69 -26
- package/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/Cell.tsx +14 -3
- package/Components/Cell/CellWithFocusable.tsx +9 -0
- package/Components/Cell/FocusableWrapper.tsx +47 -0
- package/Components/Cell/TvOSCellComponent.tsx +106 -19
- package/Components/Focusable/Focusable.tsx +4 -2
- package/Components/Focusable/FocusableTvOS.tsx +18 -1
- package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
- package/Components/FocusableGroup/FocusableTvOS.tsx +32 -1
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +39 -28
- package/Components/GeneralContentScreen/__tests__/GeneralContentScreen.test.tsx +104 -0
- package/Components/GeneralContentScreen/utils/__tests__/getScreenDataSource.test.ts +19 -0
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
- package/Components/GeneralContentScreen/utils/getScreenDataSource.ts +9 -0
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -6
- package/Components/HandlePlayable/HandlePlayable.tsx +33 -94
- package/Components/HandlePlayable/const.ts +3 -0
- package/Components/HandlePlayable/utils.ts +105 -0
- package/Components/HookRenderer/HookRenderer.tsx +40 -10
- package/Components/HookRenderer/__tests__/HookRenderer.test.tsx +60 -0
- package/Components/Layout/TV/LayoutBackground.tsx +5 -2
- package/Components/Layout/TV/NavBarContainer.tsx +1 -10
- package/Components/Layout/TV/ScreenContainer.tsx +2 -6
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
- package/Components/Layout/TV/index.tsx +3 -4
- package/Components/Layout/TV/index.web.tsx +3 -4
- package/Components/LinkHandler/LinkHandler.tsx +2 -2
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +30 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
- package/Components/MasterCell/DefaultComponents/LiveImage/__tests__/prepareEntry.test.ts +352 -0
- package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +136 -0
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +43 -22
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +40 -39
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +95 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +86 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/index.test.ts +141 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/index.ts +1 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +8 -8
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -2
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +233 -11
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +19 -15
- package/Components/MasterCell/hoc/__tests__/withAsyncRender.test.tsx +219 -0
- package/Components/MasterCell/hoc/withAsyncRender.tsx +9 -7
- package/Components/MasterCell/index.tsx +2 -0
- package/Components/MasterCell/utils/__tests__/resolveColor.test.js +82 -3
- package/Components/MasterCell/utils/index.ts +61 -31
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +102 -87
- package/Components/MeasurmentsPortal/__tests__/MeasurementsPortal.test.tsx +355 -0
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +17 -9
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +16 -8
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
- package/Components/OfflineHandler/NotificationView/utils.ts +34 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
- package/Components/PlayerContainer/PlayerContainer.tsx +43 -64
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/PreloaderWrapper/__tests__/index.test.tsx +26 -0
- package/Components/PreloaderWrapper/index.tsx +15 -0
- package/Components/River/ComponentsMap/ComponentsMap.tsx +16 -0
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
- package/Components/River/RefreshControl.tsx +9 -3
- package/Components/River/RiverItem.tsx +26 -20
- package/Components/River/TV/River.tsx +31 -14
- package/Components/River/TV/index.tsx +8 -4
- package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
- package/Components/River/TV/utils/index.ts +4 -0
- package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/River/__tests__/componentsMap.test.js +38 -0
- package/Components/Screen/TV/index.web.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +66 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +75 -6
- package/Components/Screen/index.tsx +9 -4
- package/Components/Screen/navigationHandler.ts +49 -24
- package/Components/Screen/orientationHandler.ts +10 -13
- package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +46 -0
- package/Components/ScreenFeedLoader/__tests__/ScreenFeedLoader.test.tsx +94 -0
- package/Components/ScreenFeedLoader/index.ts +1 -0
- package/Components/ScreenResolver/__tests__/screenResolver.test.js +24 -0
- package/Components/ScreenResolver/hooks/index.ts +3 -0
- package/Components/ScreenResolver/hooks/useGetComponent.ts +15 -0
- package/Components/ScreenResolver/hooks/useScreenComponentResolver.tsx +90 -0
- package/Components/ScreenResolver/index.tsx +15 -111
- package/Components/ScreenResolver/utils/__tests__/getScreenTypeProps.test.ts +45 -0
- package/Components/ScreenResolver/utils/getScreenTypeProps.ts +43 -0
- package/Components/ScreenResolver/utils/index.ts +1 -0
- package/Components/ScreenResolver/withDefaultScreenContext.tsx +16 -0
- package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +25 -0
- package/Components/ScreenResolverFeedProvider/__tests__/ScreenResolverFeedProvider.test.tsx +44 -0
- package/Components/ScreenResolverFeedProvider/index.ts +1 -0
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +44 -26
- package/Components/Tabs/TV/Tabs.tsx +20 -3
- package/Components/Tabs/TabContent.tsx +7 -4
- package/Components/Transitioner/Scene.tsx +10 -3
- package/Components/Transitioner/index.js +3 -3
- package/Components/VideoLive/LiveImageManager.ts +199 -54
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -33
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +2 -17
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +118 -171
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerWrapper.tsx +14 -88
- package/Components/VideoModal/VideoModal.tsx +1 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
- package/Components/VideoModal/hooks/useModalSize.ts +10 -5
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +91 -0
- package/Components/VideoModal/utils.ts +19 -9
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
- package/Components/Viewport/ViewportAware/index.tsx +16 -7
- package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
- package/Components/ZappUIComponent/index.tsx +12 -6
- package/Components/index.js +1 -1
- package/Contexts/ScreenContext/__tests__/index.test.tsx +57 -0
- package/Contexts/ScreenContext/index.tsx +71 -19
- package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
- package/Contexts/ZappHookModalContext/index.tsx +37 -61
- package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
- package/Contexts/index.ts +0 -2
- package/Decorators/Analytics/index.tsx +6 -5
- package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
- package/Decorators/ConfigurationWrapper/const.ts +1 -0
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
- package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
- package/Helpers/DataSourceHelper/index.ts +19 -0
- package/events/index.ts +3 -0
- package/events/scrollEndReached.ts +15 -0
- package/index.d.ts +7 -0
- package/package.json +6 -5
- package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +0 -57
- package/Components/PlayerContainer/ErrorDisplay/index.ts +0 -9
- package/Components/River/TV/withTVEventHandler.tsx +0 -27
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
- package/Helpers/DataSourceHelper/index.js +0 -19
- /package/Components/HookRenderer/{index.tsx → index.ts} +0 -0
|
@@ -137,6 +137,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
137
137
|
keyExtractor={[Function]}
|
|
138
138
|
maxToRenderPerBatch={10}
|
|
139
139
|
onContentSizeChange={[Function]}
|
|
140
|
+
onEndReached={[Function]}
|
|
140
141
|
onLayout={[Function]}
|
|
141
142
|
onMomentumScrollBegin={[Function]}
|
|
142
143
|
onMomentumScrollEnd={[Function]}
|
|
@@ -154,6 +155,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
154
155
|
}
|
|
155
156
|
}
|
|
156
157
|
stickyHeaderIndices={[]}
|
|
158
|
+
testID="components-map-flat-list"
|
|
157
159
|
viewabilityConfigCallbackPairs={[]}
|
|
158
160
|
windowSize={12}
|
|
159
161
|
>
|
|
@@ -139,7 +139,13 @@ jest.mock(
|
|
|
139
139
|
})
|
|
140
140
|
);
|
|
141
141
|
|
|
142
|
+
jest.mock("@applicaster/zapp-react-native-ui-components/events", () => ({
|
|
143
|
+
...jest.requireActual("@applicaster/zapp-react-native-ui-components/events"),
|
|
144
|
+
emitScrollEndReached: jest.fn(),
|
|
145
|
+
}));
|
|
146
|
+
|
|
142
147
|
const { View } = require("react-native");
|
|
148
|
+
const events = require("@applicaster/zapp-react-native-ui-components/events");
|
|
143
149
|
const { ComponentsMap } = require("../ComponentsMap/ComponentsMap");
|
|
144
150
|
const theme = require("./theme-mock.json");
|
|
145
151
|
|
|
@@ -190,4 +196,36 @@ describe("componentsMap", () => {
|
|
|
190
196
|
|
|
191
197
|
expect(toJSON()).toMatchSnapshot();
|
|
192
198
|
});
|
|
199
|
+
|
|
200
|
+
it("calls emitScrollEndReached when onScroll was called and isScreenWrappedInContainer is false", () => {
|
|
201
|
+
themeSpy = jest
|
|
202
|
+
.spyOn(themeUtils, "useTheme")
|
|
203
|
+
.mockImplementation(() => () => theme);
|
|
204
|
+
|
|
205
|
+
events.emitScrollEndReached.mockClear();
|
|
206
|
+
|
|
207
|
+
const { getByTestId } = render(
|
|
208
|
+
<Provider store={store}>
|
|
209
|
+
<ComponentsMap
|
|
210
|
+
{...props}
|
|
211
|
+
isScreenWrappedInContainer={false}
|
|
212
|
+
feed={{ entry: [] }}
|
|
213
|
+
/>
|
|
214
|
+
</Provider>
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const flatList = getByTestId("components-map-flat-list");
|
|
218
|
+
|
|
219
|
+
flatList.props.onScroll({
|
|
220
|
+
nativeEvent: {
|
|
221
|
+
contentOffset: { y: 0 },
|
|
222
|
+
layoutMeasurement: { height: 100 },
|
|
223
|
+
contentSize: { height: 200 },
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
flatList.props.onEndReached();
|
|
228
|
+
|
|
229
|
+
expect(events.emitScrollEndReached).toHaveBeenCalledTimes(1);
|
|
230
|
+
});
|
|
193
231
|
});
|
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
useIsScreenActive,
|
|
11
11
|
useNavigation,
|
|
12
|
+
useRivers,
|
|
12
13
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
13
14
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
14
|
-
import {
|
|
15
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
|
|
15
16
|
import {
|
|
16
17
|
useNavbarState,
|
|
17
18
|
useScreenBackgroundColor,
|
|
@@ -102,7 +103,8 @@ export const Screen = ({ route, Components }: Props) => {
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
const navigator = useNavigation();
|
|
105
|
-
const
|
|
106
|
+
const plugins = usePlugins();
|
|
107
|
+
const rivers = useRivers();
|
|
106
108
|
|
|
107
109
|
const pathAttributes = getPathAttributes({ pathname: route });
|
|
108
110
|
const routeState = navigator.getStackForPathname(route);
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
4
4
|
|
|
5
5
|
const Mocked_RouteManager = jest.fn((props) => (
|
|
6
6
|
<View testID="routeManager" {...props} />
|
|
7
7
|
));
|
|
8
8
|
|
|
9
|
-
const mock_navBarVisibleFlag = true;
|
|
10
|
-
|
|
11
|
-
const mockIsNavBarVisible = jest.fn(() => mock_navBarVisibleFlag);
|
|
12
|
-
|
|
13
9
|
const mockIsOrientationCompatible = jest.fn(() => true);
|
|
14
10
|
|
|
15
11
|
jest.mock("react-native-safe-area-context", () => ({
|
|
12
|
+
...jest.requireActual("react-native-safe-area-context"),
|
|
16
13
|
useSafeAreaInsets: () => ({ top: 44 }),
|
|
14
|
+
useSafeAreaFrame: () => ({ x: 0, y: 0, width: 375, height: 812 }),
|
|
17
15
|
}));
|
|
18
16
|
|
|
19
17
|
jest.mock("../../RouteManager", () => ({
|
|
@@ -35,12 +33,14 @@ jest.mock(
|
|
|
35
33
|
);
|
|
36
34
|
|
|
37
35
|
jest.mock("@applicaster/zapp-react-native-utils/analyticsUtils", () => ({
|
|
36
|
+
...jest.requireActual("@applicaster/zapp-react-native-utils/analyticsUtils"),
|
|
38
37
|
useAnalytics: jest.fn(() => ({
|
|
39
38
|
sendScreenEvent: jest.fn(),
|
|
40
39
|
})),
|
|
41
40
|
}));
|
|
42
41
|
|
|
43
42
|
jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
|
|
43
|
+
...jest.requireActual("@applicaster/zapp-react-native-utils/theme"),
|
|
44
44
|
useTheme: jest.fn(() => ({
|
|
45
45
|
app_background_color: "blue",
|
|
46
46
|
})),
|
|
@@ -77,21 +77,44 @@ jest.mock(
|
|
|
77
77
|
})
|
|
78
78
|
);
|
|
79
79
|
|
|
80
|
-
jest.mock(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
})
|
|
94
|
-
|
|
80
|
+
jest.mock(
|
|
81
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation",
|
|
82
|
+
() => ({
|
|
83
|
+
...jest.requireActual(
|
|
84
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation"
|
|
85
|
+
),
|
|
86
|
+
useNavigation: jest.fn(() => ({
|
|
87
|
+
canGoBack: () => false,
|
|
88
|
+
currentRoute: "/river/testId",
|
|
89
|
+
activeRiver: { id: "testId" },
|
|
90
|
+
screenData: { id: "testId" },
|
|
91
|
+
data: { screen: { id: "testId" } },
|
|
92
|
+
})),
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
jest.mock(
|
|
97
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
|
|
98
|
+
() => ({
|
|
99
|
+
...jest.requireActual(
|
|
100
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive"
|
|
101
|
+
),
|
|
102
|
+
useIsScreenActive: jest.fn().mockReturnValue(true),
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
jest.mock(
|
|
107
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute",
|
|
108
|
+
() => ({
|
|
109
|
+
...jest.requireActual(
|
|
110
|
+
"@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute"
|
|
111
|
+
),
|
|
112
|
+
useRoute: jest.fn(() => ({
|
|
113
|
+
pathname: "/river/testId",
|
|
114
|
+
screenData: { id: "testId" },
|
|
115
|
+
})),
|
|
116
|
+
})
|
|
117
|
+
);
|
|
95
118
|
|
|
96
119
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
|
|
97
120
|
...jest.requireActual("@applicaster/zapp-react-native-utils/reactHooks"),
|
|
@@ -112,26 +135,6 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
|
|
|
112
135
|
useIsTablet: jest.fn(() => false),
|
|
113
136
|
}));
|
|
114
137
|
|
|
115
|
-
jest.mock("@applicaster/zapp-react-native-redux/hooks", () => {
|
|
116
|
-
const View = jest.requireActual("react-native").View;
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
|
|
120
|
-
usePickFromState: () => ({
|
|
121
|
-
plugins: [
|
|
122
|
-
{
|
|
123
|
-
name: "Offline Plugin",
|
|
124
|
-
identifier: "offline-experience",
|
|
125
|
-
type: "general",
|
|
126
|
-
module: {
|
|
127
|
-
OfflineFallbackScreen: ({ children }) => <View>{children}</View>, // eslint-disable-line
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
],
|
|
131
|
-
}),
|
|
132
|
-
};
|
|
133
|
-
});
|
|
134
|
-
|
|
135
138
|
const {
|
|
136
139
|
allowedOrientationsForScreen,
|
|
137
140
|
getOrientation,
|
|
@@ -151,6 +154,19 @@ const screenProps = {
|
|
|
151
154
|
|
|
152
155
|
const { Screen } = require("..");
|
|
153
156
|
|
|
157
|
+
const store = {
|
|
158
|
+
plugins: [
|
|
159
|
+
{
|
|
160
|
+
name: "Offline Plugin",
|
|
161
|
+
identifier: "offline-experience",
|
|
162
|
+
type: "general",
|
|
163
|
+
module: {
|
|
164
|
+
OfflineFallbackScreen: ({ children }) => <View>{children}</View>, // eslint-disable-line
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
|
|
154
170
|
describe("<Screen Component />", () => {
|
|
155
171
|
beforeEach(() => {
|
|
156
172
|
allowedOrientationsForScreen.mockClear();
|
|
@@ -160,14 +176,22 @@ describe("<Screen Component />", () => {
|
|
|
160
176
|
|
|
161
177
|
describe("when the navbar should show", () => {
|
|
162
178
|
it("renders correctly", () => {
|
|
163
|
-
const { toJSON } =
|
|
179
|
+
const { toJSON } = renderWithProviders(
|
|
180
|
+
<Screen {...screenProps} />,
|
|
181
|
+
store
|
|
182
|
+
);
|
|
183
|
+
|
|
164
184
|
expect(toJSON()).toMatchSnapshot();
|
|
165
185
|
});
|
|
166
186
|
});
|
|
167
187
|
|
|
168
188
|
describe("when the navbar should be hidden", () => {
|
|
169
189
|
it("renders correctly", () => {
|
|
170
|
-
const { toJSON } =
|
|
190
|
+
const { toJSON } = renderWithProviders(
|
|
191
|
+
<Screen {...screenProps} />,
|
|
192
|
+
store
|
|
193
|
+
);
|
|
194
|
+
|
|
171
195
|
expect(toJSON()).toMatchSnapshot();
|
|
172
196
|
});
|
|
173
197
|
});
|
|
@@ -1,67 +1,91 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<Screen Component /> when the navbar should be hidden renders correctly 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
4
|
+
<RNCSafeAreaProvider
|
|
5
|
+
onInsetsChange={[Function]}
|
|
6
6
|
style={
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
[
|
|
8
|
+
{
|
|
9
|
+
"flex": 1,
|
|
10
|
+
},
|
|
11
|
+
undefined,
|
|
12
|
+
]
|
|
12
13
|
}
|
|
13
14
|
>
|
|
14
15
|
<View
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
importantForAccessibility="yes"
|
|
17
|
+
style={
|
|
18
|
+
{
|
|
19
|
+
"backgroundColor": "blue",
|
|
20
|
+
"flex": 1,
|
|
21
|
+
"paddingTop": 0,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
>
|
|
23
25
|
<View
|
|
26
|
+
hasMenu={false}
|
|
27
|
+
id="/river/testId"
|
|
24
28
|
pathname="/river/testId"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
testID="routeManager"
|
|
29
|
+
selected="testId"
|
|
30
|
+
testID="navBar"
|
|
31
|
+
title="Test Title"
|
|
31
32
|
/>
|
|
33
|
+
<View>
|
|
34
|
+
<View
|
|
35
|
+
pathname="/river/testId"
|
|
36
|
+
screenData={
|
|
37
|
+
{
|
|
38
|
+
"id": "testId",
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
testID="routeManager"
|
|
42
|
+
/>
|
|
43
|
+
</View>
|
|
32
44
|
</View>
|
|
33
|
-
</
|
|
45
|
+
</RNCSafeAreaProvider>
|
|
34
46
|
`;
|
|
35
47
|
|
|
36
48
|
exports[`<Screen Component /> when the navbar should show renders correctly 1`] = `
|
|
37
|
-
<
|
|
38
|
-
|
|
49
|
+
<RNCSafeAreaProvider
|
|
50
|
+
onInsetsChange={[Function]}
|
|
39
51
|
style={
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
[
|
|
53
|
+
{
|
|
54
|
+
"flex": 1,
|
|
55
|
+
},
|
|
56
|
+
undefined,
|
|
57
|
+
]
|
|
45
58
|
}
|
|
46
59
|
>
|
|
47
60
|
<View
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
importantForAccessibility="yes"
|
|
62
|
+
style={
|
|
63
|
+
{
|
|
64
|
+
"backgroundColor": "blue",
|
|
65
|
+
"flex": 1,
|
|
66
|
+
"paddingTop": 0,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
>
|
|
56
70
|
<View
|
|
71
|
+
hasMenu={false}
|
|
72
|
+
id="/river/testId"
|
|
57
73
|
pathname="/river/testId"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
testID="routeManager"
|
|
74
|
+
selected="testId"
|
|
75
|
+
testID="navBar"
|
|
76
|
+
title="Test Title"
|
|
64
77
|
/>
|
|
78
|
+
<View>
|
|
79
|
+
<View
|
|
80
|
+
pathname="/river/testId"
|
|
81
|
+
screenData={
|
|
82
|
+
{
|
|
83
|
+
"id": "testId",
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
testID="routeManager"
|
|
87
|
+
/>
|
|
88
|
+
</View>
|
|
65
89
|
</View>
|
|
66
|
-
</
|
|
90
|
+
</RNCSafeAreaProvider>
|
|
67
91
|
`;
|
|
@@ -1,19 +1,89 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useAppData } from "@applicaster/zapp-react-native-redux/hooks";
|
|
2
2
|
import {
|
|
3
3
|
useGetScreenOrientation,
|
|
4
4
|
isOrientationCompatible,
|
|
5
5
|
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
6
6
|
import {
|
|
7
7
|
useCurrentScreenData,
|
|
8
|
-
useDimensions,
|
|
9
8
|
useRoute,
|
|
10
9
|
useIsTablet,
|
|
10
|
+
useIsScreenActive,
|
|
11
11
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
12
|
import { useMemo, useEffect, useState } from "react";
|
|
13
|
+
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
14
|
+
|
|
15
|
+
type MemoizedSafeAreaFrameWithActiveStateOptions = {
|
|
16
|
+
updateForInactiveScreens?: boolean;
|
|
17
|
+
isActive: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Base hook that wraps useSafeAreaFrame with memoization and inactive screen filtering.
|
|
22
|
+
* Requires isActive to be passed explicitly - use useMemoizedSafeAreaFrame for automatic detection.
|
|
23
|
+
*
|
|
24
|
+
* @param options.updateForInactiveScreens - If false, frame won't update when screen is inactive (default: true)
|
|
25
|
+
* @param options.isActive - Whether the screen is currently active
|
|
26
|
+
* @returns The memoized safe area frame { x, y, width, height }
|
|
27
|
+
*/
|
|
28
|
+
export const useMemoizedSafeAreaFrameWithActiveState = (
|
|
29
|
+
options: MemoizedSafeAreaFrameWithActiveStateOptions
|
|
30
|
+
) => {
|
|
31
|
+
const { updateForInactiveScreens = true, isActive } = options;
|
|
32
|
+
const frame = useSafeAreaFrame();
|
|
33
|
+
|
|
34
|
+
const [memoFrame, setMemoFrame] = useState(frame);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const shouldUpdate = isActive || updateForInactiveScreens;
|
|
38
|
+
|
|
39
|
+
const dimensionsChanged =
|
|
40
|
+
frame.width !== memoFrame.width || frame.height !== memoFrame.height;
|
|
41
|
+
|
|
42
|
+
if (shouldUpdate && dimensionsChanged) {
|
|
43
|
+
setMemoFrame(frame);
|
|
44
|
+
}
|
|
45
|
+
}, [
|
|
46
|
+
frame.width,
|
|
47
|
+
frame.height,
|
|
48
|
+
isActive,
|
|
49
|
+
updateForInactiveScreens,
|
|
50
|
+
frame,
|
|
51
|
+
memoFrame.width,
|
|
52
|
+
memoFrame.height,
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
return memoFrame;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
type MemoizedSafeAreaFrameOptions = {
|
|
59
|
+
updateForInactiveScreens?: boolean;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Hook that wraps useSafeAreaFrame with memoization and inactive screen filtering.
|
|
64
|
+
* Uses useIsScreenActive() internally to determine active state - use useMemoizedSafeAreaFrameWithActiveState
|
|
65
|
+
* if you need to pass isActive explicitly.
|
|
66
|
+
*
|
|
67
|
+
* @param options.updateForInactiveScreens - If false, frame won't update when screen is inactive (default: true)
|
|
68
|
+
* @returns The memoized safe area frame { x, y, width, height }
|
|
69
|
+
*/
|
|
70
|
+
export const useMemoizedSafeAreaFrame = (
|
|
71
|
+
options: MemoizedSafeAreaFrameOptions = {}
|
|
72
|
+
) => {
|
|
73
|
+
const { updateForInactiveScreens = true } = options;
|
|
74
|
+
const isActive = useIsScreenActive();
|
|
75
|
+
|
|
76
|
+
return useMemoizedSafeAreaFrameWithActiveState({
|
|
77
|
+
updateForInactiveScreens,
|
|
78
|
+
isActive,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
13
81
|
|
|
14
82
|
export const useWaitForValidOrientation = () => {
|
|
15
|
-
|
|
16
|
-
|
|
83
|
+
// Use memoized safe area frame to synchronize with Scene's dimension source
|
|
84
|
+
// This prevents race conditions where the orientation check passes before
|
|
85
|
+
// Scene's memoFrame has updated to the new dimensions
|
|
86
|
+
const { width: screenWidth, height } = useMemoizedSafeAreaFrame({
|
|
17
87
|
updateForInactiveScreens: false,
|
|
18
88
|
});
|
|
19
89
|
|
|
@@ -25,8 +95,7 @@ export const useWaitForValidOrientation = () => {
|
|
|
25
95
|
|
|
26
96
|
const isTablet = useIsTablet();
|
|
27
97
|
|
|
28
|
-
const {
|
|
29
|
-
const isTabletPortrait = appData?.isTabletPortrait;
|
|
98
|
+
const { isTabletPortrait } = useAppData();
|
|
30
99
|
|
|
31
100
|
const layoutData = useMemo(
|
|
32
101
|
() => ({ isTablet, isTabletPortrait, width: screenWidth, height }),
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { AccessibilityInfo, findNodeHandle, View } from "react-native";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
|
|
6
5
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
7
6
|
import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
8
7
|
import {
|
|
@@ -41,7 +40,7 @@ type Props = {
|
|
|
41
40
|
export function Screen(_props: Props) {
|
|
42
41
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
43
42
|
const navigation = useNavigation();
|
|
44
|
-
const
|
|
43
|
+
const plugins = usePlugins();
|
|
45
44
|
|
|
46
45
|
// Gets the data for the current screen configuration
|
|
47
46
|
const currentScreenData = useCurrentScreenData();
|
|
@@ -93,7 +92,13 @@ export function Screen(_props: Props) {
|
|
|
93
92
|
const isActive = useIsScreenActive();
|
|
94
93
|
|
|
95
94
|
const ref = React.useRef(null);
|
|
96
|
-
const
|
|
95
|
+
const isOrientationReady = useWaitForValidOrientation();
|
|
96
|
+
|
|
97
|
+
// Playable screens handle their own orientation via the native player plugin,
|
|
98
|
+
// so we skip the orientation wait gate to avoid a deadlock where the screen
|
|
99
|
+
// waits for landscape but blocks rendering that would trigger the rotation.
|
|
100
|
+
const isPlayableRoute = pathname?.includes("/playable");
|
|
101
|
+
const isReady = isOrientationReady || isPlayableRoute;
|
|
97
102
|
|
|
98
103
|
React.useEffect(() => {
|
|
99
104
|
if (ref.current && isActive && isReady) {
|
|
@@ -1,35 +1,19 @@
|
|
|
1
1
|
import { resolveNavigationPlugin } from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
* - playable screens
|
|
11
|
-
* - qb_search_screen
|
|
12
|
-
* - screen hooks that specify showNavBar or presentFullScreen
|
|
13
|
-
* - screens or nested screens that have allow_screen_plugin_presentation set to true
|
|
14
|
-
*
|
|
15
|
-
* @param {String} route current route of the screen
|
|
16
|
-
* @param {Object} screenData payload associated with the currently presented screen
|
|
17
|
-
* @returns {Boolean}
|
|
18
|
-
*/
|
|
19
|
-
export function isMenuVisible(route, screenData, plugins) {
|
|
20
|
-
const plugin = resolveNavigationPlugin({
|
|
3
|
+
export const BOTTOM_TABS_PLUGIN_ID = "quick-brick-bottom-tabs";
|
|
4
|
+
|
|
5
|
+
export const SIDE_MENU_PLUGIN_ID = "quick_brick_side_menu";
|
|
6
|
+
|
|
7
|
+
export function getMenuPlugin(screenData, plugins) {
|
|
8
|
+
return resolveNavigationPlugin({
|
|
21
9
|
category: "menu",
|
|
22
10
|
navigations:
|
|
23
11
|
screenData?.navigations || screenData?.targetScreen?.navigations,
|
|
24
12
|
plugins,
|
|
25
13
|
});
|
|
14
|
+
}
|
|
26
15
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!isBottomTabsPlugin) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
|
|
16
|
+
function shouldShowNavigation(route, screenData) {
|
|
33
17
|
if (route.includes("playable")) {
|
|
34
18
|
return false;
|
|
35
19
|
}
|
|
@@ -56,3 +40,44 @@ export function isMenuVisible(route, screenData, plugins) {
|
|
|
56
40
|
|
|
57
41
|
return true;
|
|
58
42
|
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* This function helps to decide whether the menu should be presented on the screen
|
|
46
|
+
* based on route and / or screen Data
|
|
47
|
+
*
|
|
48
|
+
* is similar to the navbar, except that it covers scenarios where only the navbar (and not)
|
|
49
|
+
* the menu will be hidden
|
|
50
|
+
*
|
|
51
|
+
* - playable screens
|
|
52
|
+
* - qb_search_screen
|
|
53
|
+
* - screen hooks that specify showNavBar or presentFullScreen
|
|
54
|
+
* - screens or nested screens that have allow_screen_plugin_presentation set to true
|
|
55
|
+
*
|
|
56
|
+
* @param {String} route current route of the screen
|
|
57
|
+
* @param {Object} screenData payload associated with the currently presented screen
|
|
58
|
+
* @returns {Boolean}
|
|
59
|
+
*/
|
|
60
|
+
export function isMenuVisible(route, screenData, plugins) {
|
|
61
|
+
const plugin = getMenuPlugin(screenData, plugins);
|
|
62
|
+
|
|
63
|
+
const isBottomTabsPlugin = plugin?.identifier === BOTTOM_TABS_PLUGIN_ID;
|
|
64
|
+
const isSideMenuPlugin = plugin?.identifier === SIDE_MENU_PLUGIN_ID;
|
|
65
|
+
|
|
66
|
+
if (!isBottomTabsPlugin && !isSideMenuPlugin) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return shouldShowNavigation(route, screenData);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isBottomTabVisible(route, screenData, plugins) {
|
|
74
|
+
const plugin = getMenuPlugin(screenData, plugins);
|
|
75
|
+
|
|
76
|
+
const isBottomTabsPlugin = plugin?.identifier === BOTTOM_TABS_PLUGIN_ID;
|
|
77
|
+
|
|
78
|
+
if (!isBottomTabsPlugin) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return shouldShowNavigation(route, screenData);
|
|
83
|
+
}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
allowedOrientationsForScreen,
|
|
5
|
-
ORIENTATIONS,
|
|
6
5
|
getOrientation,
|
|
6
|
+
ORIENTATIONS,
|
|
7
7
|
useGetScreenOrientation,
|
|
8
8
|
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
9
9
|
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
10
|
-
import {
|
|
10
|
+
import { usePlugins, useAppData } from "@applicaster/zapp-react-native-redux";
|
|
11
11
|
import { findPluginByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
12
12
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
13
|
-
|
|
14
|
-
import { ZappHookModalContext } from "../../Contexts";
|
|
15
|
-
import { HookModalContextT } from "../../Contexts/ZappHookModalContext";
|
|
13
|
+
import { zappHookModalStore } from "../../Contexts/ZappHookModalContext";
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* This function calls the native module needed to set orientation
|
|
@@ -65,8 +63,8 @@ export function useNewOrientationForScreenData({
|
|
|
65
63
|
}: OrientationHookArgs) {
|
|
66
64
|
const isTablet = useIsTablet();
|
|
67
65
|
|
|
68
|
-
const
|
|
69
|
-
const isTabletPortrait =
|
|
66
|
+
const plugins = usePlugins();
|
|
67
|
+
const { isTabletPortrait } = useAppData();
|
|
70
68
|
const isLandscapeTablet = isTablet && !isTabletPortrait;
|
|
71
69
|
|
|
72
70
|
const screenOrientation = useGetScreenOrientation(screenData);
|
|
@@ -89,10 +87,6 @@ type Props = {
|
|
|
89
87
|
};
|
|
90
88
|
|
|
91
89
|
export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
92
|
-
const { isHooksExecutionInProgress } = React.useContext<HookModalContextT>(
|
|
93
|
-
ZappHookModalContext.ReactContext
|
|
94
|
-
);
|
|
95
|
-
|
|
96
90
|
const prevIsActive = usePrevious(isActive);
|
|
97
91
|
|
|
98
92
|
const newOrientation = useNewOrientationForScreenData({
|
|
@@ -105,6 +99,9 @@ export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
|
105
99
|
return;
|
|
106
100
|
}
|
|
107
101
|
|
|
102
|
+
// TODO: make sure it can be static getter and subscription is not needed
|
|
103
|
+
const { isHooksExecutionInProgress } = zappHookModalStore.getState();
|
|
104
|
+
|
|
108
105
|
// If modal hook presented we need to skip
|
|
109
106
|
// Change orientation for presenter screen
|
|
110
107
|
if (isHooksExecutionInProgress) {
|
|
@@ -116,7 +113,7 @@ export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
|
116
113
|
|
|
117
114
|
setOrientation(newOrientation);
|
|
118
115
|
}
|
|
119
|
-
}, [newOrientation,
|
|
116
|
+
}, [newOrientation, prevIsActive, isActive]);
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
export function useOrientationHandler({ screenData }: OrientationHookArgs) {
|