@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4837064762 → 12.0.0-alpha.4885205607
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 +3 -3
- package/Components/Cell/Cell.tsx +30 -13
- package/Components/Cell/CellWithFocusable.tsx +6 -4
- package/Components/Cell/TvOSCellComponent.tsx +3 -7
- package/Components/Focusable/Focusable.tsx +6 -1
- package/Components/FocusableGroup/index.tsx +10 -2
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/Layout/TV/ScreenContainer.tsx +79 -5
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
- package/Components/Layout/TV/__tests__/index.test.tsx +20 -75
- package/Components/Layout/TV/index.tsx +29 -181
- package/Components/Layout/TV/index.web.tsx +33 -0
- package/Components/Layout/index.tsx +15 -11
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +88 -112
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +20 -0
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
- package/Components/MasterCell/dataAdapter.ts +21 -7
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/index.tsx +5 -3
- package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
- package/Components/MasterCell/utils/index.ts +32 -29
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/Navigator/StackNavigator.tsx +57 -0
- package/Components/Navigator/index.ts +1 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +3 -0
- package/Components/River/ComponentsMap/ComponentsMap.tsx +24 -17
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/TV/River.tsx +0 -23
- package/Components/RouteManager/index.tsx +2 -2
- package/Components/Screen/TV/hooks/index.ts +3 -0
- package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
- package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
- package/Components/Screen/TV/index.web.tsx +59 -45
- package/Components/Screen/__tests__/Screen.test.tsx +3 -0
- package/Components/Screen/index.tsx +55 -58
- package/Components/Screen/navigationHandler.ts +5 -0
- package/Components/ScreenResolver/index.tsx +6 -11
- package/Components/Transitioner/Scene.tsx +32 -26
- package/Components/Transitioner/Transitioner.tsx +38 -43
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +28 -1
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +26 -24
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +2 -14
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +56 -43
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +42 -32
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +104 -86
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +44 -5
- package/Components/VideoModal/ModalAnimation/utils.ts +7 -4
- package/Components/VideoModal/PlayerDetails.tsx +3 -3
- package/Components/VideoModal/PlayerWrapper.tsx +67 -60
- package/Components/VideoModal/VideoModal.tsx +17 -17
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +32 -12
- package/Components/VideoModal/hooks/useModalSize.ts +10 -12
- package/Components/VideoModal/utils.ts +5 -2
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
- package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
- package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
- package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
- package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
- package/Contexts/FocusableGroupContext/index.ts +7 -0
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
- package/Contexts/ScreenContext/index.tsx +2 -2
- package/Contexts/ScreenDataContext/index.tsx +20 -0
- package/events/index.ts +1 -0
- package/package.json +5 -5
- package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
- /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
- /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { last
|
|
3
|
-
import {
|
|
2
|
+
import { last } from "ramda";
|
|
3
|
+
import { View, StyleSheet } from "react-native";
|
|
4
4
|
import {
|
|
5
|
+
findMenuPlugin,
|
|
5
6
|
getNavigationProps,
|
|
6
7
|
getPathAttributes,
|
|
7
|
-
resolveNavigationPlugin,
|
|
8
8
|
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
9
9
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
10
|
-
import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
|
|
11
10
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
12
11
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
12
|
+
import {
|
|
13
|
+
useNavbarState,
|
|
14
|
+
useScreenBackgroundColor,
|
|
15
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks/screen";
|
|
16
|
+
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
17
|
+
|
|
18
|
+
import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
|
|
19
|
+
import { ScreenResolver } from "../../ScreenResolver";
|
|
20
|
+
import { useInitialFocus, useRestoreFocus } from "./hooks";
|
|
21
|
+
import { isPlayerPlugin } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
22
|
+
|
|
23
|
+
const styles = StyleSheet.create({
|
|
24
|
+
container: {
|
|
25
|
+
position: "absolute",
|
|
26
|
+
top: 0,
|
|
27
|
+
left: 0,
|
|
28
|
+
right: 0,
|
|
29
|
+
bottom: 0,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
13
32
|
|
|
14
33
|
type Components = {
|
|
15
34
|
NavBar: React.ComponentType<any>;
|
|
@@ -21,16 +40,6 @@ type Props = {
|
|
|
21
40
|
Components: Components;
|
|
22
41
|
};
|
|
23
42
|
|
|
24
|
-
const isPlayer = (routeState): boolean => {
|
|
25
|
-
const pluginType = pathOr(
|
|
26
|
-
"unknown_plugin_type",
|
|
27
|
-
["state", "screen", "plugin_type"],
|
|
28
|
-
routeState
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
return pluginType === "player";
|
|
32
|
-
};
|
|
33
|
-
|
|
34
43
|
const getActiveRiver = ({
|
|
35
44
|
screenId,
|
|
36
45
|
screenType,
|
|
@@ -39,10 +48,15 @@ const getActiveRiver = ({
|
|
|
39
48
|
fallbackActiveRiver,
|
|
40
49
|
}) => {
|
|
41
50
|
if (rivers[screenId]) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
if (screenType === "hooks") {
|
|
52
|
+
const navigations = routeState?.state?.entry?.payload?.navigations;
|
|
53
|
+
|
|
54
|
+
if (navigations) {
|
|
55
|
+
return routeState.state.entry.payload;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return routeState?.state?.screen;
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
// screenId is not presented into rivers, use fallback instead
|
|
@@ -58,34 +72,38 @@ const getNavigations = ({
|
|
|
58
72
|
}) => {
|
|
59
73
|
if (rivers[screenId]) {
|
|
60
74
|
// river presents
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
if (screenType === "hooks") {
|
|
76
|
+
const navigations = routeState?.state?.entry?.payload?.navigations;
|
|
77
|
+
|
|
78
|
+
if (navigations) {
|
|
79
|
+
return navigations;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return routeState?.state?.screen?.navigations;
|
|
64
84
|
}
|
|
65
85
|
|
|
66
86
|
// screenId is not presented into rivers, use fallback instead
|
|
67
87
|
return fallbackNavigations;
|
|
68
88
|
};
|
|
69
89
|
|
|
70
|
-
export const Screen = (
|
|
71
|
-
if (
|
|
72
|
-
throw
|
|
90
|
+
export const Screen = ({ route, Components }: Props) => {
|
|
91
|
+
if (isNilOrEmpty(route)) {
|
|
92
|
+
throw Error("Required props: route is missing");
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
const navigator = useNavigation();
|
|
76
96
|
const { plugins = [], rivers = [] } = usePickFromState(["plugins", "rivers"]);
|
|
77
97
|
|
|
78
|
-
const pathAttributes = getPathAttributes({ pathname:
|
|
79
|
-
const routeState = navigator.getStackForPathname(
|
|
98
|
+
const pathAttributes = getPathAttributes({ pathname: route });
|
|
99
|
+
const routeState = navigator.getStackForPathname(route);
|
|
80
100
|
|
|
81
101
|
const { screenType, screenId } = last(pathAttributes);
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// navigator,
|
|
88
|
-
// });
|
|
103
|
+
const backgroundColor = useScreenBackgroundColor(screenId);
|
|
104
|
+
|
|
105
|
+
useInitialFocus();
|
|
106
|
+
useRestoreFocus();
|
|
89
107
|
|
|
90
108
|
const activeRiver = getActiveRiver({
|
|
91
109
|
screenId,
|
|
@@ -113,39 +131,35 @@ export const Screen = (props: Props) => {
|
|
|
113
131
|
fallbackNavigations: navigator.activeRiver.navigations,
|
|
114
132
|
});
|
|
115
133
|
|
|
116
|
-
const menuPlugin =
|
|
117
|
-
category: "menu",
|
|
118
|
-
navigations,
|
|
119
|
-
plugins,
|
|
120
|
-
}) as QuickBrickPlugin;
|
|
134
|
+
const menuPlugin = findMenuPlugin(navigations, plugins);
|
|
121
135
|
|
|
122
|
-
const NavBar = (
|
|
136
|
+
const NavBar = (Components.NavBar ||
|
|
123
137
|
menuPlugin.module) as React.ComponentType<any>;
|
|
124
138
|
|
|
125
|
-
const
|
|
139
|
+
const isPlayer = isPlayerPlugin(routeState);
|
|
140
|
+
|
|
141
|
+
const { visible: isNavBarVisible } = useNavbarState();
|
|
126
142
|
|
|
127
143
|
const screenData =
|
|
128
|
-
screenType === "hooks"
|
|
144
|
+
screenType === "hooks" || isPlayer
|
|
129
145
|
? routeState?.state?.entry
|
|
130
146
|
: routeState?.state?.screen;
|
|
131
147
|
|
|
132
148
|
return (
|
|
133
|
-
|
|
149
|
+
<View style={[styles.container, { backgroundColor }]}>
|
|
134
150
|
<NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
|
|
135
151
|
<NavBar
|
|
136
|
-
groupId={props.route}
|
|
137
152
|
isVisible={isNavBarVisible}
|
|
138
153
|
menuPlugin={menuPlugin}
|
|
139
154
|
navigationProps={navigationProps}
|
|
140
|
-
// Maybe activeRiver?
|
|
141
155
|
/>
|
|
142
156
|
</NavBarContainer>
|
|
143
157
|
<ScreenResolver
|
|
144
158
|
screenType={screenType}
|
|
145
159
|
screenId={screenId}
|
|
146
160
|
screenData={screenData}
|
|
147
|
-
groupId={
|
|
161
|
+
groupId={route}
|
|
148
162
|
/>
|
|
149
|
-
|
|
163
|
+
</View>
|
|
150
164
|
);
|
|
151
165
|
};
|
|
@@ -10,6 +10,8 @@ const mock_navBarVisibleFlag = true;
|
|
|
10
10
|
|
|
11
11
|
const mockIsNavBarVisible = jest.fn(() => mock_navBarVisibleFlag);
|
|
12
12
|
|
|
13
|
+
const mockIsOrientationCompatible = jest.fn(() => true);
|
|
14
|
+
|
|
13
15
|
jest.mock("react-native-safe-area-context", () => ({
|
|
14
16
|
useSafeAreaInsets: () => ({ top: 44 }),
|
|
15
17
|
}));
|
|
@@ -21,6 +23,7 @@ jest.mock("../../RouteManager", () => ({
|
|
|
21
23
|
jest.mock(
|
|
22
24
|
"@applicaster/zapp-react-native-utils/appUtils/orientationHelper",
|
|
23
25
|
() => ({
|
|
26
|
+
isOrientationCompatible: mockIsOrientationCompatible,
|
|
24
27
|
allowedOrientationsForScreen: jest.fn(),
|
|
25
28
|
getOrientation: jest.fn(),
|
|
26
29
|
getScreenOrientation: jest.fn(),
|
|
@@ -3,14 +3,18 @@ import React from "react";
|
|
|
3
3
|
import * as R from "ramda";
|
|
4
4
|
import { View } from "react-native";
|
|
5
5
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
6
|
+
import {
|
|
7
|
+
isOrientationCompatible,
|
|
8
|
+
useGetScreenOrientation,
|
|
9
|
+
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
6
10
|
|
|
7
11
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
8
12
|
import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
9
13
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
shouldNavBarDisplayMenu,
|
|
15
|
+
getNavBarProps,
|
|
16
|
+
getScreenId,
|
|
12
17
|
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
13
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
14
18
|
import {
|
|
15
19
|
useDimensions,
|
|
16
20
|
useRoute,
|
|
@@ -21,20 +25,16 @@ import {
|
|
|
21
25
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
22
26
|
import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
|
|
23
27
|
|
|
24
|
-
import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
25
28
|
import { RouteManager } from "../RouteManager";
|
|
26
29
|
import { useScreenConfiguration } from "../River/useScreenConfiguration";
|
|
27
30
|
import { useScreenOrientationHandler } from "./orientationHandler";
|
|
28
31
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: "screen_id" in screenData
|
|
36
|
-
? screenData.screen_id
|
|
37
|
-
: fallbackRiver.id;
|
|
32
|
+
const screenStyles = {
|
|
33
|
+
flex: 1,
|
|
34
|
+
paddingTop: 0,
|
|
35
|
+
// paddingBottom: insets.bottom, // Should be applied directly by UI plugin
|
|
36
|
+
// paddingLeft: insets.left, // Should be applied directly by UI plugin
|
|
37
|
+
// paddingRight: insets.right, // Should be applied directly by UI plugin
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
function colorIsNotTransparent(color) {
|
|
@@ -45,9 +45,7 @@ function colorIsNotTransparent(color) {
|
|
|
45
45
|
R.replace("rgba(", "")
|
|
46
46
|
)(color);
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return alpha > 0;
|
|
48
|
+
return Number(layers?.[3]) > 0;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
function isValidColor(string) {
|
|
@@ -67,9 +65,12 @@ export function Screen(_props: Props) {
|
|
|
67
65
|
// Gets the data for the current screen configuration
|
|
68
66
|
const currentScreenData = useCurrentScreenData();
|
|
69
67
|
const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
|
|
70
|
-
const insets = useSafeAreaInsets();
|
|
71
68
|
|
|
72
|
-
const {
|
|
69
|
+
const {
|
|
70
|
+
width: screenWidth,
|
|
71
|
+
height,
|
|
72
|
+
deviceInfo,
|
|
73
|
+
} = useDimensions("screen", {
|
|
73
74
|
fullDimensions: true,
|
|
74
75
|
});
|
|
75
76
|
|
|
@@ -81,30 +82,19 @@ export function Screen(_props: Props) {
|
|
|
81
82
|
|
|
82
83
|
const { title } = useNavbarState();
|
|
83
84
|
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (props) {
|
|
99
|
-
return {
|
|
100
|
-
...props,
|
|
101
|
-
id: pathname,
|
|
102
|
-
pathname: pathname,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return null;
|
|
107
|
-
}, [currentRiver, pathname]);
|
|
85
|
+
const isTablet = deviceInfo?.isTablet;
|
|
86
|
+
|
|
87
|
+
const { appData } = usePickFromState(["appData"]);
|
|
88
|
+
const isTabletPortrait = appData?.isTabletPortrait;
|
|
89
|
+
|
|
90
|
+
const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
|
|
91
|
+
|
|
92
|
+
const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
|
|
93
|
+
|
|
94
|
+
const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
|
|
95
|
+
getNavBarProps(currentRiver, pathname, title),
|
|
96
|
+
[currentRiver, pathname]
|
|
97
|
+
);
|
|
108
98
|
|
|
109
99
|
const NavBar = React.useMemo(
|
|
110
100
|
() =>
|
|
@@ -126,16 +116,12 @@ export function Screen(_props: Props) {
|
|
|
126
116
|
|
|
127
117
|
const style = React.useMemo(
|
|
128
118
|
() => ({
|
|
129
|
-
|
|
119
|
+
...screenStyles,
|
|
130
120
|
backgroundColor: isValidColor(backgroundColor)
|
|
131
121
|
? backgroundColor
|
|
132
122
|
: theme.app_background_color,
|
|
133
|
-
paddingTop: 0,
|
|
134
|
-
// paddingBottom: insets.bottom, // Should be applied directly by UI plugin
|
|
135
|
-
// paddingLeft: insets.left, // Should be applied directly by UI plugin
|
|
136
|
-
// paddingRight: insets.right, // Should be applied directly by UI plugin
|
|
137
123
|
}),
|
|
138
|
-
[
|
|
124
|
+
[theme.app_background_color, backgroundColor]
|
|
139
125
|
);
|
|
140
126
|
|
|
141
127
|
const targetScreenData =
|
|
@@ -143,16 +129,27 @@ export function Screen(_props: Props) {
|
|
|
143
129
|
|
|
144
130
|
useScreenOrientationHandler({ screenData: targetScreenData });
|
|
145
131
|
|
|
132
|
+
const orientation = useGetScreenOrientation(targetScreenData);
|
|
133
|
+
|
|
134
|
+
// We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
|
|
135
|
+
// This saves unnecessary re-renders and user will not see distorted aspect screen.
|
|
136
|
+
if (
|
|
137
|
+
!isOrientationCompatible({
|
|
138
|
+
orientation,
|
|
139
|
+
layoutData,
|
|
140
|
+
})
|
|
141
|
+
) {
|
|
142
|
+
return <View style={style} />;
|
|
143
|
+
}
|
|
144
|
+
|
|
146
145
|
return (
|
|
147
|
-
<
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
</View>
|
|
156
|
-
</ScreenContextProvider>
|
|
146
|
+
<View style={style}>
|
|
147
|
+
{navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
|
|
148
|
+
|
|
149
|
+
<OfflineFallbackScreen screenData={targetScreenData}>
|
|
150
|
+
{/* @TODO RouteManager doesn't use props, can they be removed ? */}
|
|
151
|
+
<RouteManager pathname={pathname} screenData={screenData} />
|
|
152
|
+
</OfflineFallbackScreen>
|
|
153
|
+
</View>
|
|
157
154
|
);
|
|
158
155
|
}
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* is similar to the navbar, except that it covers scenarios where only the navbar (and not)
|
|
6
6
|
* the menu, will be hidden
|
|
7
7
|
*
|
|
8
|
+
* - playable screens
|
|
9
|
+
* - qb_search_screen
|
|
10
|
+
* - screen hooks that specify showNavBar or presentFullScreen
|
|
11
|
+
* - screens or nested screens that have allow_screen_plugin_presentation set to true
|
|
12
|
+
*
|
|
8
13
|
* @param {String} route current route of the screen
|
|
9
14
|
* @param {Object} screenData payload associated with the currently presented screen
|
|
10
15
|
* @returns {Boolean}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
3
|
-
import { useDispatch } from "react-redux";
|
|
2
|
+
import { path, prop } from "ramda";
|
|
4
3
|
import {
|
|
5
4
|
findPluginByType,
|
|
6
5
|
findPluginByIdentifier,
|
|
@@ -15,7 +14,6 @@ import { componentsLogger } from "../../Helpers/logger";
|
|
|
15
14
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
16
15
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
17
16
|
import { useScreenAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks";
|
|
18
|
-
import { setAppStateHasFinishedTransitioning } from "@applicaster/zapp-react-native-redux/appState";
|
|
19
17
|
|
|
20
18
|
const logger = componentsLogger.addSubsystem("ScreenResolver");
|
|
21
19
|
|
|
@@ -54,11 +52,8 @@ export function ScreenResolverComponent(props: Props) {
|
|
|
54
52
|
|
|
55
53
|
const [, setScreenContext] = ZappPipesScreenContext.useZappPipesContext();
|
|
56
54
|
|
|
57
|
-
const dispatch = useDispatch();
|
|
58
|
-
|
|
59
55
|
React.useEffect(() => {
|
|
60
56
|
setScreenContext(rivers[screenId]);
|
|
61
|
-
dispatch(setAppStateHasFinishedTransitioning());
|
|
62
57
|
}, [screenId]);
|
|
63
58
|
|
|
64
59
|
const ScreenPlugin =
|
|
@@ -100,14 +95,14 @@ export function ScreenResolverComponent(props: Props) {
|
|
|
100
95
|
}
|
|
101
96
|
|
|
102
97
|
const ScreenComponent =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
path(["module", "Component"], ScreenPlugin) ||
|
|
99
|
+
prop("module", ScreenPlugin) ||
|
|
100
|
+
prop("Component", ScreenPlugin) ||
|
|
106
101
|
ScreenPlugin;
|
|
107
102
|
|
|
108
103
|
const configuration =
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
prop("configuration", ScreenPlugin) ||
|
|
105
|
+
prop("__plugin_configuration", ScreenComponent);
|
|
111
106
|
|
|
112
107
|
if (ScreenComponent) {
|
|
113
108
|
return (
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
Animated,
|
|
4
|
-
useWindowDimensions,
|
|
5
|
-
ViewProps,
|
|
6
|
-
ViewStyle,
|
|
7
|
-
} from "react-native";
|
|
2
|
+
import { Animated, ViewProps, ViewStyle } from "react-native";
|
|
8
3
|
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
9
4
|
import { PathnameContext } from "../../Contexts/PathnameContext";
|
|
5
|
+
import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
|
|
6
|
+
import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
10
7
|
|
|
11
8
|
type Props = {
|
|
12
9
|
children: any;
|
|
@@ -16,6 +13,8 @@ type Props = {
|
|
|
16
13
|
animating: boolean;
|
|
17
14
|
contentStyle: ViewStyle;
|
|
18
15
|
pathname: string;
|
|
16
|
+
isActive: boolean;
|
|
17
|
+
screenData: NavigationScreenData;
|
|
19
18
|
};
|
|
20
19
|
|
|
21
20
|
/**
|
|
@@ -38,34 +37,41 @@ export function Scene({
|
|
|
38
37
|
animating,
|
|
39
38
|
contentStyle,
|
|
40
39
|
pathname,
|
|
40
|
+
isActive = false,
|
|
41
|
+
screenData,
|
|
41
42
|
}: Props) {
|
|
43
|
+
const [initialScreenData, setInitialScreenData] = React.useState(screenData);
|
|
44
|
+
|
|
45
|
+
React.useLayoutEffect(() => {
|
|
46
|
+
if (isActive) {
|
|
47
|
+
setInitialScreenData(screenData);
|
|
48
|
+
}
|
|
49
|
+
}, [screenData, isActive]);
|
|
50
|
+
|
|
42
51
|
const frame = useSafeAreaFrame();
|
|
43
|
-
const { height, width } = useWindowDimensions();
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<PathnameContext.Provider value={pathname}>
|
|
54
|
-
{children}
|
|
55
|
-
</PathnameContext.Provider>
|
|
56
|
-
<Animated.View style={overlayStyle} />
|
|
57
|
-
</Animated.View>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
53
|
+
const isAnimating = animating && overlayStyle;
|
|
54
|
+
|
|
55
|
+
const dimensions = isAnimating
|
|
56
|
+
? {
|
|
57
|
+
height: "100%",
|
|
58
|
+
width: "100%",
|
|
59
|
+
}
|
|
60
|
+
: frame;
|
|
60
61
|
|
|
61
62
|
return (
|
|
62
63
|
<Animated.View
|
|
63
64
|
pointerEvents={pointerEvents}
|
|
64
|
-
style={[style, contentStyle,
|
|
65
|
+
style={[style, contentStyle, dimensions]}
|
|
65
66
|
>
|
|
66
|
-
<
|
|
67
|
-
{
|
|
68
|
-
|
|
67
|
+
<ScreenDataContext.Provider value={initialScreenData}>
|
|
68
|
+
<PathnameContext.Provider value={pathname}>
|
|
69
|
+
<ScreenContextProvider pathname={pathname}>
|
|
70
|
+
{children}
|
|
71
|
+
</ScreenContextProvider>
|
|
72
|
+
</PathnameContext.Provider>
|
|
73
|
+
</ScreenDataContext.Provider>
|
|
74
|
+
{isAnimating && <Animated.View style={overlayStyle} />}
|
|
69
75
|
</Animated.View>
|
|
70
76
|
);
|
|
71
77
|
}
|
|
@@ -4,10 +4,7 @@ import * as R from "ramda";
|
|
|
4
4
|
|
|
5
5
|
import { AnimationManager } from "./AnimationManager";
|
|
6
6
|
import { Scene } from "./Scene";
|
|
7
|
-
|
|
8
|
-
getScreenOrientation,
|
|
9
|
-
isOrientationCompatible,
|
|
10
|
-
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
7
|
+
|
|
11
8
|
import {
|
|
12
9
|
getSceneByRoute,
|
|
13
10
|
shouldSkipAnimationForPreviousWebViewScene,
|
|
@@ -169,21 +166,23 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
169
166
|
|
|
170
167
|
transitionWithoutAnimation(resetState) {
|
|
171
168
|
const { scenes } = this.state;
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
169
|
+
const newScene = prepareScene(this.props.children);
|
|
170
|
+
const isLastSceneHook = scenes[scenes.length - 1].key.startsWith("/hook");
|
|
171
|
+
|
|
172
|
+
let newState;
|
|
173
|
+
|
|
174
|
+
if (resetState) {
|
|
175
|
+
newState = {
|
|
176
|
+
scenes: [newScene],
|
|
177
|
+
to: { index: 0 },
|
|
178
|
+
};
|
|
179
|
+
} else if (isLastSceneHook || scenes.length === 1) {
|
|
180
|
+
newState = { scenes: R.update(scenes.length - 1, newScene, scenes) };
|
|
181
|
+
} else {
|
|
182
|
+
newState = {
|
|
183
|
+
scenes: R.compose(R.tail, R.append(newScene))(scenes),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
187
186
|
|
|
188
187
|
this.setState(newState);
|
|
189
188
|
}
|
|
@@ -277,33 +276,25 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
277
276
|
// so only a single scene should be rendered,
|
|
278
277
|
// instead of dangerous nulls or duplicates.
|
|
279
278
|
renderSingleScene({ scenes, to }) {
|
|
280
|
-
const { contentStyle
|
|
281
|
-
const screenData =
|
|
282
|
-
|
|
283
|
-
const orientation = getScreenOrientation({
|
|
284
|
-
screenData,
|
|
285
|
-
layoutData,
|
|
286
|
-
});
|
|
279
|
+
const { contentStyle } = this.props;
|
|
280
|
+
const screenData = this.props.children.props.screenData;
|
|
281
|
+
const pathname = scenes[to.index].key;
|
|
287
282
|
|
|
288
|
-
// We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
|
|
289
|
-
// This saves unnecessary re-renders and user will not see distorted aspect screen.
|
|
290
283
|
return (
|
|
291
284
|
<View style={styles.container}>
|
|
292
|
-
{scenes[to.index] &&
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
</Scene>
|
|
306
|
-
)}
|
|
285
|
+
{scenes[to.index] && (
|
|
286
|
+
<Scene
|
|
287
|
+
{...{ style: to.style }}
|
|
288
|
+
pathname={pathname}
|
|
289
|
+
isActive={pathname === this.props.navigator.currentRoute}
|
|
290
|
+
contentStyle={contentStyle}
|
|
291
|
+
key={scenes[to.index].key}
|
|
292
|
+
screenUniqueId={scenes[to.index].screenUniqueId}
|
|
293
|
+
screenData={screenData}
|
|
294
|
+
>
|
|
295
|
+
{scenes[to.index].children}
|
|
296
|
+
</Scene>
|
|
297
|
+
)}
|
|
307
298
|
</View>
|
|
308
299
|
);
|
|
309
300
|
}
|
|
@@ -319,12 +310,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
319
310
|
<Scene
|
|
320
311
|
key={scenes[from.index].key}
|
|
321
312
|
pathname={scenes[from.index].key}
|
|
313
|
+
isActive={scenes[from.index].key === this.props.navigator.currentRoute}
|
|
322
314
|
style={from.style}
|
|
323
315
|
pointerEvents="none"
|
|
324
316
|
overlayStyle={from.overlayStyle}
|
|
325
317
|
animating={this.state.animating}
|
|
326
318
|
contentStyle={contentStyle}
|
|
327
319
|
screenUniqueId={scenes[from.index].screenUniqueId}
|
|
320
|
+
screenData={scenes[from.index].children.props.screenData}
|
|
328
321
|
>
|
|
329
322
|
{scenes[from.index].children}
|
|
330
323
|
</Scene>
|
|
@@ -333,12 +326,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
333
326
|
const toScene = scenes[to.index] && (
|
|
334
327
|
<Scene
|
|
335
328
|
pathname={scenes[to.index].key}
|
|
329
|
+
isActive={scenes[to.index].key === this.props.navigator.currentRoute}
|
|
336
330
|
key={scenes[to.index].key}
|
|
337
331
|
style={to.style}
|
|
338
332
|
overlayStyle={to.overlayStyle}
|
|
339
333
|
animating={this.state.animating}
|
|
340
334
|
contentStyle={contentStyle}
|
|
341
335
|
screenUniqueId={scenes[to.index].screenUniqueId}
|
|
336
|
+
screenData={this.props.children.props.screenData}
|
|
342
337
|
>
|
|
343
338
|
{scenes[to.index].children}
|
|
344
339
|
</Scene>
|
|
@@ -21,7 +21,11 @@ exports[`<Scene /> renders correctly 1`] = `
|
|
|
21
21
|
]
|
|
22
22
|
}
|
|
23
23
|
>
|
|
24
|
-
<ContextProvider
|
|
24
|
+
<ContextProvider>
|
|
25
|
+
<ContextProvider>
|
|
26
|
+
<ScreenContextProvider />
|
|
27
|
+
</ContextProvider>
|
|
28
|
+
</ContextProvider>
|
|
25
29
|
</ForwardRef(AnimatedComponentWrapper)>
|
|
26
30
|
`;
|
|
27
31
|
|
|
@@ -37,13 +41,17 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
|
|
|
37
41
|
"paddingBottom": 49,
|
|
38
42
|
},
|
|
39
43
|
Object {
|
|
40
|
-
"height":
|
|
41
|
-
"width":
|
|
44
|
+
"height": "100%",
|
|
45
|
+
"width": "100%",
|
|
42
46
|
},
|
|
43
47
|
]
|
|
44
48
|
}
|
|
45
49
|
>
|
|
46
|
-
<ContextProvider
|
|
50
|
+
<ContextProvider>
|
|
51
|
+
<ContextProvider>
|
|
52
|
+
<ScreenContextProvider />
|
|
53
|
+
</ContextProvider>
|
|
54
|
+
</ContextProvider>
|
|
47
55
|
<ForwardRef(AnimatedComponentWrapper)
|
|
48
56
|
style={
|
|
49
57
|
Object {
|