@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4462655310 → 12.0.0-alpha.4484269996
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 +2 -2
- package/Components/Cell/Cell.tsx +26 -5
- 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/FreezeWithCallback/Freeze.tsx +31 -0
- package/Components/FreezeWithCallback/LICENSE +21 -0
- package/Components/FreezeWithCallback/Suspender.tsx +17 -0
- package/Components/FreezeWithCallback/__tests__/index.test.tsx +170 -0
- package/Components/FreezeWithCallback/index.tsx +3 -0
- 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__/index.test.tsx +2 -1
- package/Components/Layout/TV/index.tsx +11 -65
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +1 -7
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +71 -0
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +20 -0
- package/Components/MasterCell/DefaultComponents/index.ts +2 -0
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +6 -1
- package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +7 -1
- package/Components/MasterCell/dataAdapter.ts +21 -7
- package/Components/MasterCell/index.tsx +5 -3
- package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
- package/Components/Navigator/StackNavigator.tsx +14 -5
- package/Components/PlayerContainer/PlayerContainer.tsx +2 -5
- package/Components/Screen/TV/hooks/index.ts +0 -2
- package/Components/Screen/TV/index.web.tsx +40 -41
- package/Components/Screen/__tests__/Screen.test.tsx +0 -49
- package/Components/Screen/index.tsx +28 -77
- package/Components/Screen/navigationHandler.ts +6 -3
- package/Components/Screen/orientationHandler.ts +18 -7
- package/Components/Screen/utils.ts +16 -0
- package/Components/ScreenResolver/index.tsx +6 -11
- package/Components/Transitioner/Scene.tsx +20 -12
- package/Components/Transitioner/Transitioner.tsx +26 -21
- package/Components/Transitioner/__tests__/Scene.test.js +7 -0
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +8 -4
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +10 -0
- 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 +31 -7
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +9 -2
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +27 -15
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +32 -4
- package/Components/VideoModal/ModalAnimation/utils.ts +7 -4
- package/Components/VideoModal/PlayerWrapper.tsx +2 -2
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +80 -14
- package/Components/VideoModal/hooks/useModalSize.ts +10 -12
- package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -3
- 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/package.json +5 -5
- package/Components/Screen/TV/hooks/useRestoreFocus.ts +0 -22
- /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
- /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { last
|
|
3
|
-
import {
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { last } from "ramda";
|
|
3
|
+
import { StyleSheet, View } 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
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
useIsScreenActive,
|
|
11
|
+
useNavigation,
|
|
12
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
10
13
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
11
14
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
12
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
useNavbarState,
|
|
17
|
+
useScreenBackgroundColor,
|
|
18
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks/screen";
|
|
13
19
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
14
20
|
|
|
15
21
|
import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
|
|
16
22
|
import { ScreenResolver } from "../../ScreenResolver";
|
|
17
|
-
import { useInitialFocus
|
|
23
|
+
import { useInitialFocus } from "./hooks";
|
|
24
|
+
import { isPlayerPlugin } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
25
|
+
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
26
|
+
import { FreezeWithCallback } from "../../FreezeWithCallback";
|
|
18
27
|
|
|
19
28
|
const styles = StyleSheet.create({
|
|
20
29
|
container: {
|
|
@@ -36,18 +45,6 @@ type Props = {
|
|
|
36
45
|
Components: Components;
|
|
37
46
|
};
|
|
38
47
|
|
|
39
|
-
const getPluginType = pathOr("unknown_plugin_type", [
|
|
40
|
-
"state",
|
|
41
|
-
"screen",
|
|
42
|
-
"plugin_type",
|
|
43
|
-
]);
|
|
44
|
-
|
|
45
|
-
const isPlayerPlugin = (routeState): boolean =>
|
|
46
|
-
getPluginType(routeState) === "player";
|
|
47
|
-
|
|
48
|
-
const isLoginPlugin = (routeState): boolean =>
|
|
49
|
-
getPluginType(routeState) === "login";
|
|
50
|
-
|
|
51
48
|
const getActiveRiver = ({
|
|
52
49
|
screenId,
|
|
53
50
|
screenType,
|
|
@@ -111,7 +108,6 @@ export const Screen = ({ route, Components }: Props) => {
|
|
|
111
108
|
const backgroundColor = useScreenBackgroundColor(screenId);
|
|
112
109
|
|
|
113
110
|
useInitialFocus();
|
|
114
|
-
useRestoreFocus();
|
|
115
111
|
|
|
116
112
|
const activeRiver = getActiveRiver({
|
|
117
113
|
screenId,
|
|
@@ -139,41 +135,44 @@ export const Screen = ({ route, Components }: Props) => {
|
|
|
139
135
|
fallbackNavigations: navigator.activeRiver.navigations,
|
|
140
136
|
});
|
|
141
137
|
|
|
142
|
-
const menuPlugin =
|
|
143
|
-
category: "menu",
|
|
144
|
-
navigations,
|
|
145
|
-
plugins,
|
|
146
|
-
}) as QuickBrickPlugin;
|
|
138
|
+
const menuPlugin = findMenuPlugin(navigations, plugins);
|
|
147
139
|
|
|
148
140
|
const NavBar = (Components.NavBar ||
|
|
149
141
|
menuPlugin.module) as React.ComponentType<any>;
|
|
150
142
|
|
|
151
143
|
const isPlayer = isPlayerPlugin(routeState);
|
|
152
|
-
const isLogin = isLoginPlugin(routeState);
|
|
153
144
|
|
|
154
|
-
const isNavBarVisible =
|
|
145
|
+
const { visible: isNavBarVisible } = useNavbarState();
|
|
155
146
|
|
|
156
147
|
const screenData =
|
|
157
148
|
screenType === "hooks" || isPlayer
|
|
158
149
|
? routeState?.state?.entry
|
|
159
150
|
: routeState?.state?.screen;
|
|
160
151
|
|
|
152
|
+
const isScreenActive = useIsScreenActive();
|
|
153
|
+
|
|
161
154
|
return (
|
|
162
|
-
<
|
|
163
|
-
|
|
164
|
-
|
|
155
|
+
<FreezeWithCallback
|
|
156
|
+
freeze={!isScreenActive}
|
|
157
|
+
onRelease={() => {
|
|
158
|
+
focusManager.setInitialFocus();
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<View style={[styles.container, { backgroundColor }]}>
|
|
162
|
+
<NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
|
|
163
|
+
<NavBar
|
|
164
|
+
isVisible={isNavBarVisible}
|
|
165
|
+
menuPlugin={menuPlugin}
|
|
166
|
+
navigationProps={navigationProps}
|
|
167
|
+
/>
|
|
168
|
+
</NavBarContainer>
|
|
169
|
+
<ScreenResolver
|
|
170
|
+
screenType={screenType}
|
|
171
|
+
screenId={screenId}
|
|
172
|
+
screenData={screenData}
|
|
165
173
|
groupId={route}
|
|
166
|
-
isVisible={isNavBarVisible}
|
|
167
|
-
menuPlugin={menuPlugin}
|
|
168
|
-
navigationProps={navigationProps}
|
|
169
174
|
/>
|
|
170
|
-
</
|
|
171
|
-
|
|
172
|
-
screenType={screenType}
|
|
173
|
-
screenId={screenId}
|
|
174
|
-
screenData={screenData}
|
|
175
|
-
groupId={route}
|
|
176
|
-
/>
|
|
177
|
-
</View>
|
|
175
|
+
</View>
|
|
176
|
+
</FreezeWithCallback>
|
|
178
177
|
);
|
|
179
178
|
};
|
|
@@ -99,14 +99,6 @@ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
|
|
|
99
99
|
}),
|
|
100
100
|
}));
|
|
101
101
|
|
|
102
|
-
const {
|
|
103
|
-
ORIENTATIONS,
|
|
104
|
-
} = require("@applicaster/zapp-react-native-utils/appUtils/orientationHelper");
|
|
105
|
-
|
|
106
|
-
const {
|
|
107
|
-
useCurrentScreenData,
|
|
108
|
-
} = require("@applicaster/zapp-react-native-utils/reactHooks/screen");
|
|
109
|
-
|
|
110
102
|
const {
|
|
111
103
|
allowedOrientationsForScreen,
|
|
112
104
|
getOrientation,
|
|
@@ -158,45 +150,4 @@ describe("<Screen Component />", () => {
|
|
|
158
150
|
expect(wrapper.toJSON()).toMatchSnapshot();
|
|
159
151
|
});
|
|
160
152
|
});
|
|
161
|
-
|
|
162
|
-
it("invokes the orientation hook when the route changes", () => {
|
|
163
|
-
act(() => {
|
|
164
|
-
wrapper = create(<Screen {...screenProps} />);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// @ts-ignore
|
|
168
|
-
useCurrentScreenData.mockReturnValue({
|
|
169
|
-
id: "player-testId",
|
|
170
|
-
general: { screen_orientation: ORIENTATIONS.landscapeSensor },
|
|
171
|
-
plugin_type: "player",
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
act(() => {
|
|
175
|
-
wrapper.update(
|
|
176
|
-
<Screen
|
|
177
|
-
{...screenProps}
|
|
178
|
-
pathname="/playable"
|
|
179
|
-
screenData={{
|
|
180
|
-
id: "player-testId",
|
|
181
|
-
general: { screen_orientation: ORIENTATIONS.landscapeSensor },
|
|
182
|
-
plugin_type: "player",
|
|
183
|
-
}}
|
|
184
|
-
/>
|
|
185
|
-
);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
useCurrentScreenData.mockReturnValue({
|
|
189
|
-
id: "player-testId",
|
|
190
|
-
general: { screen_orientation: ORIENTATIONS.landscapeSensor },
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
act(() => {
|
|
194
|
-
wrapper.update(<Screen {...screenProps} />);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
expect(allowedOrientationsForScreen).toHaveBeenNthCalledWith(
|
|
198
|
-
1,
|
|
199
|
-
ORIENTATIONS.landscapeSensor
|
|
200
|
-
);
|
|
201
|
-
});
|
|
202
153
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
import React from "react";
|
|
3
|
-
import * as R from "ramda";
|
|
4
3
|
import { View } from "react-native";
|
|
5
4
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
6
5
|
import {
|
|
@@ -11,10 +10,10 @@ import {
|
|
|
11
10
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
12
11
|
import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
13
12
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
shouldNavBarDisplayMenu,
|
|
14
|
+
getNavBarProps,
|
|
15
|
+
getScreenId,
|
|
16
16
|
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
17
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
18
17
|
import {
|
|
19
18
|
useDimensions,
|
|
20
19
|
useRoute,
|
|
@@ -25,39 +24,18 @@ import {
|
|
|
25
24
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
26
25
|
import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
|
|
27
26
|
|
|
28
|
-
import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
29
27
|
import { RouteManager } from "../RouteManager";
|
|
30
28
|
import { useScreenConfiguration } from "../River/useScreenConfiguration";
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
: "screen_id" in screenData
|
|
40
|
-
? screenData.screen_id
|
|
41
|
-
: fallbackRiver.id;
|
|
29
|
+
import { isValidColor } from "./utils";
|
|
30
|
+
|
|
31
|
+
const screenStyles = {
|
|
32
|
+
flex: 1,
|
|
33
|
+
paddingTop: 0,
|
|
34
|
+
// paddingBottom: insets.bottom, // Should be applied directly by UI plugin
|
|
35
|
+
// paddingLeft: insets.left, // Should be applied directly by UI plugin
|
|
36
|
+
// paddingRight: insets.right, // Should be applied directly by UI plugin
|
|
42
37
|
};
|
|
43
38
|
|
|
44
|
-
function colorIsNotTransparent(color) {
|
|
45
|
-
const layers = R.compose(
|
|
46
|
-
R.map(R.trim),
|
|
47
|
-
R.split(","),
|
|
48
|
-
R.replace(")", ""),
|
|
49
|
-
R.replace("rgba(", "")
|
|
50
|
-
)(color);
|
|
51
|
-
|
|
52
|
-
const alpha = Number(layers?.[3]);
|
|
53
|
-
|
|
54
|
-
return alpha > 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function isValidColor(string) {
|
|
58
|
-
return string && string !== "transparent" && colorIsNotTransparent(string);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
39
|
type Props = {
|
|
62
40
|
pathname: unknown;
|
|
63
41
|
screenData: unknown;
|
|
@@ -71,7 +49,6 @@ export function Screen(_props: Props) {
|
|
|
71
49
|
// Gets the data for the current screen configuration
|
|
72
50
|
const currentScreenData = useCurrentScreenData();
|
|
73
51
|
const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
|
|
74
|
-
const insets = useSafeAreaInsets();
|
|
75
52
|
|
|
76
53
|
const {
|
|
77
54
|
width: screenWidth,
|
|
@@ -96,30 +73,12 @@ export function Screen(_props: Props) {
|
|
|
96
73
|
|
|
97
74
|
const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
|
|
98
75
|
|
|
99
|
-
const hasMenu =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
|
|
107
|
-
const props = getNavigationPropsV2({
|
|
108
|
-
currentRiver,
|
|
109
|
-
title,
|
|
110
|
-
category: "nav_bar",
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
if (props) {
|
|
114
|
-
return {
|
|
115
|
-
...props,
|
|
116
|
-
id: pathname,
|
|
117
|
-
pathname: pathname,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return null;
|
|
122
|
-
}, [currentRiver, pathname]);
|
|
76
|
+
const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
|
|
77
|
+
|
|
78
|
+
const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
|
|
79
|
+
getNavBarProps(currentRiver, pathname, title),
|
|
80
|
+
[currentRiver, pathname]
|
|
81
|
+
);
|
|
123
82
|
|
|
124
83
|
const NavBar = React.useMemo(
|
|
125
84
|
() =>
|
|
@@ -141,23 +100,17 @@ export function Screen(_props: Props) {
|
|
|
141
100
|
|
|
142
101
|
const style = React.useMemo(
|
|
143
102
|
() => ({
|
|
144
|
-
|
|
103
|
+
...screenStyles,
|
|
145
104
|
backgroundColor: isValidColor(backgroundColor)
|
|
146
105
|
? backgroundColor
|
|
147
106
|
: theme.app_background_color,
|
|
148
|
-
paddingTop: 0,
|
|
149
|
-
// paddingBottom: insets.bottom, // Should be applied directly by UI plugin
|
|
150
|
-
// paddingLeft: insets.left, // Should be applied directly by UI plugin
|
|
151
|
-
// paddingRight: insets.right, // Should be applied directly by UI plugin
|
|
152
107
|
}),
|
|
153
|
-
[
|
|
108
|
+
[theme.app_background_color, backgroundColor]
|
|
154
109
|
);
|
|
155
110
|
|
|
156
111
|
const targetScreenData =
|
|
157
112
|
currentScreenData || (screenData as any)?.targetScreen || screenData;
|
|
158
113
|
|
|
159
|
-
useScreenOrientationHandler({ screenData: targetScreenData });
|
|
160
|
-
|
|
161
114
|
const orientation = useGetScreenOrientation(targetScreenData);
|
|
162
115
|
|
|
163
116
|
// We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
|
|
@@ -168,19 +121,17 @@ export function Screen(_props: Props) {
|
|
|
168
121
|
layoutData,
|
|
169
122
|
})
|
|
170
123
|
) {
|
|
171
|
-
return
|
|
124
|
+
return <View style={style} />;
|
|
172
125
|
}
|
|
173
126
|
|
|
174
127
|
return (
|
|
175
|
-
<
|
|
176
|
-
<
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
</View>
|
|
184
|
-
</ScreenContextProvider>
|
|
128
|
+
<View style={style}>
|
|
129
|
+
{navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
|
|
130
|
+
|
|
131
|
+
<OfflineFallbackScreen screenData={targetScreenData}>
|
|
132
|
+
{/* @TODO RouteManager doesn't use props, can they be removed ? */}
|
|
133
|
+
<RouteManager pathname={pathname} screenData={screenData} />
|
|
134
|
+
</OfflineFallbackScreen>
|
|
135
|
+
</View>
|
|
185
136
|
);
|
|
186
137
|
}
|
|
@@ -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}
|
|
@@ -21,9 +26,7 @@ export function isMenuVisible(route, screenData) {
|
|
|
21
26
|
if (screenData?.hookPlugin) {
|
|
22
27
|
const hookPlugin = screenData?.hookPlugin?.module;
|
|
23
28
|
|
|
24
|
-
return
|
|
25
|
-
hookPlugin?.showNavBar || hookPlugin?.presentFullScreen !== true || false
|
|
26
|
-
);
|
|
29
|
+
return hookPlugin?.showNavBar || hookPlugin?.presentFullScreen !== true;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
if (
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import React, { useLayoutEffect } from "react";
|
|
2
|
+
|
|
2
3
|
import {
|
|
3
4
|
allowedOrientationsForScreen,
|
|
4
5
|
ORIENTATIONS,
|
|
5
6
|
getOrientation,
|
|
6
7
|
useGetScreenOrientation,
|
|
7
8
|
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
8
|
-
|
|
9
|
+
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
9
10
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
10
11
|
import { findPluginByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
11
12
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
13
|
+
|
|
12
14
|
import { ZappHookModalContext } from "../../Contexts";
|
|
13
15
|
import { HookModalContextT } from "../../Contexts/ZappHookModalContext";
|
|
14
16
|
|
|
@@ -79,14 +81,23 @@ export function useNewOrientationForScreenData({
|
|
|
79
81
|
screenOrientation;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
screenData
|
|
84
|
-
|
|
84
|
+
type Props = {
|
|
85
|
+
screenData: {
|
|
86
|
+
screen: {};
|
|
87
|
+
};
|
|
88
|
+
isActive: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
85
92
|
const { isHooksExecutionInProgress } = React.useContext<HookModalContextT>(
|
|
86
93
|
ZappHookModalContext.ReactContext
|
|
87
94
|
);
|
|
88
95
|
|
|
89
|
-
const
|
|
96
|
+
const prevIsActive = usePrevious(isActive);
|
|
97
|
+
|
|
98
|
+
const newOrientation = useNewOrientationForScreenData({
|
|
99
|
+
screenData: screenData.screen,
|
|
100
|
+
});
|
|
90
101
|
|
|
91
102
|
useLayoutEffect(() => {
|
|
92
103
|
// Null means screen does not have orientation preference, so we can skip rotate
|
|
@@ -100,12 +111,12 @@ export function useScreenOrientationHandler({
|
|
|
100
111
|
return;
|
|
101
112
|
}
|
|
102
113
|
|
|
103
|
-
if (newOrientation !== current) {
|
|
114
|
+
if (!prevIsActive && isActive && newOrientation !== current) {
|
|
104
115
|
current = newOrientation;
|
|
105
116
|
|
|
106
117
|
setOrientation(newOrientation);
|
|
107
118
|
}
|
|
108
|
-
}, [newOrientation, isHooksExecutionInProgress]);
|
|
119
|
+
}, [newOrientation, isHooksExecutionInProgress, prevIsActive, isActive]);
|
|
109
120
|
}
|
|
110
121
|
|
|
111
122
|
export function useOrientationHandler({ screenData }: OrientationHookArgs) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { map, split, replace, compose, trim } from "ramda";
|
|
2
|
+
|
|
3
|
+
function colorIsNotTransparent(color) {
|
|
4
|
+
const layers = compose(
|
|
5
|
+
map(trim),
|
|
6
|
+
split(","),
|
|
7
|
+
replace(")", ""),
|
|
8
|
+
replace("rgba(", "")
|
|
9
|
+
)(color);
|
|
10
|
+
|
|
11
|
+
return Number(layers?.[3]) > 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isValidColor(string) {
|
|
15
|
+
return string && string !== "transparent" && colorIsNotTransparent(string);
|
|
16
|
+
}
|
|
@@ -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,13 +1,12 @@
|
|
|
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";
|
|
4
|
+
|
|
5
|
+
import { useScreenOrientationHandler } from "@applicaster/zapp-react-native-ui-components/Components/Screen/orientationHandler";
|
|
6
|
+
|
|
9
7
|
import { PathnameContext } from "../../Contexts/PathnameContext";
|
|
10
8
|
import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
|
|
9
|
+
import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
11
10
|
|
|
12
11
|
type Props = {
|
|
13
12
|
children: any;
|
|
@@ -46,6 +45,11 @@ export function Scene({
|
|
|
46
45
|
}: Props) {
|
|
47
46
|
const [initialScreenData, setInitialScreenData] = React.useState(screenData);
|
|
48
47
|
|
|
48
|
+
useScreenOrientationHandler({
|
|
49
|
+
screenData,
|
|
50
|
+
isActive,
|
|
51
|
+
});
|
|
52
|
+
|
|
49
53
|
React.useLayoutEffect(() => {
|
|
50
54
|
if (isActive) {
|
|
51
55
|
setInitialScreenData(screenData);
|
|
@@ -53,12 +57,14 @@ export function Scene({
|
|
|
53
57
|
}, [screenData, isActive]);
|
|
54
58
|
|
|
55
59
|
const frame = useSafeAreaFrame();
|
|
56
|
-
const { height, width } = useWindowDimensions();
|
|
57
|
-
|
|
58
|
-
// Safe frame takes too long to update,
|
|
59
|
-
// so we can not rely on it there, and use height and width instead.
|
|
60
60
|
const isAnimating = animating && overlayStyle;
|
|
61
|
-
|
|
61
|
+
|
|
62
|
+
const dimensions = isAnimating
|
|
63
|
+
? {
|
|
64
|
+
width: "100%",
|
|
65
|
+
height: "100%",
|
|
66
|
+
}
|
|
67
|
+
: frame;
|
|
62
68
|
|
|
63
69
|
return (
|
|
64
70
|
<Animated.View
|
|
@@ -67,7 +73,9 @@ export function Scene({
|
|
|
67
73
|
>
|
|
68
74
|
<ScreenDataContext.Provider value={initialScreenData}>
|
|
69
75
|
<PathnameContext.Provider value={pathname}>
|
|
70
|
-
{
|
|
76
|
+
<ScreenContextProvider pathname={pathname}>
|
|
77
|
+
{children}
|
|
78
|
+
</ScreenContextProvider>
|
|
71
79
|
</PathnameContext.Provider>
|
|
72
80
|
</ScreenDataContext.Provider>
|
|
73
81
|
{isAnimating && <Animated.View style={overlayStyle} />}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import
|
|
3
|
+
import { update, compose, tail, append, take, identity } from "ramda";
|
|
4
4
|
|
|
5
5
|
import { AnimationManager } from "./AnimationManager";
|
|
6
6
|
import { Scene } from "./Scene";
|
|
@@ -46,7 +46,7 @@ function prepareScene(children) {
|
|
|
46
46
|
*/
|
|
47
47
|
function scenesForBackTransition(props: SceneProps, { scenes }) {
|
|
48
48
|
return scenes.length > 1
|
|
49
|
-
?
|
|
49
|
+
? identity(scenes)
|
|
50
50
|
: [prepareScene(props.children), scenes[0]];
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -110,7 +110,7 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
110
110
|
pushTransitionStart() {
|
|
111
111
|
this.setState(
|
|
112
112
|
{
|
|
113
|
-
scenes:
|
|
113
|
+
scenes: append(prepareScene(this.props.children), this.state.scenes),
|
|
114
114
|
...this.animationManager.stateForAction(this.state, NAV_ACTION_PUSH),
|
|
115
115
|
},
|
|
116
116
|
() => {
|
|
@@ -166,21 +166,23 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
166
166
|
|
|
167
167
|
transitionWithoutAnimation(resetState) {
|
|
168
168
|
const { scenes } = this.state;
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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: update(scenes.length - 1, newScene, scenes) };
|
|
181
|
+
} else {
|
|
182
|
+
newState = {
|
|
183
|
+
scenes: compose(tail, append(newScene))(scenes),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
184
186
|
|
|
185
187
|
this.setState(newState);
|
|
186
188
|
}
|
|
@@ -223,7 +225,10 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
223
225
|
this.shouldSkipAnimationForRoute(previousRoute) ||
|
|
224
226
|
this.shouldSkipAnimationForRoute(currentRoute)
|
|
225
227
|
) {
|
|
226
|
-
|
|
228
|
+
// we are going back, in this case we need to have only one scene using resetState
|
|
229
|
+
const resetState = isGoingBack ? true : undefined;
|
|
230
|
+
|
|
231
|
+
return this.transitionWithoutAnimation(resetState);
|
|
227
232
|
}
|
|
228
233
|
|
|
229
234
|
switch (this.props.navigator.previousAction) {
|
|
@@ -266,7 +271,7 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
266
271
|
backTransitionEnd(stepsBack) {
|
|
267
272
|
this.setState({
|
|
268
273
|
animating: false,
|
|
269
|
-
scenes:
|
|
274
|
+
scenes: take(this.state.scenes.length - stepsBack, this.state.scenes),
|
|
270
275
|
});
|
|
271
276
|
}
|
|
272
277
|
|
|
@@ -282,7 +287,7 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
282
287
|
<View style={styles.container}>
|
|
283
288
|
{scenes[to.index] && (
|
|
284
289
|
<Scene
|
|
285
|
-
{...{ style: to
|
|
290
|
+
{...{ style: to?.style || {} }}
|
|
286
291
|
pathname={pathname}
|
|
287
292
|
isActive={pathname === this.props.navigator.currentRoute}
|
|
288
293
|
contentStyle={contentStyle}
|
|
@@ -16,6 +16,13 @@ jest.mock("react-native-safe-area-context", () => ({
|
|
|
16
16
|
})),
|
|
17
17
|
}));
|
|
18
18
|
|
|
19
|
+
jest.mock(
|
|
20
|
+
"@applicaster/zapp-react-native-ui-components/Components/Screen/orientationHandler",
|
|
21
|
+
() => ({
|
|
22
|
+
useScreenOrientationHandler: jest.fn(),
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
|
|
19
26
|
const { Scene } = require("../Scene");
|
|
20
27
|
|
|
21
28
|
const wrapper = shallow(
|