@applicaster/zapp-react-native-ui-components 12.0.0-alpha.9233494544 → 12.0.0-alpha.9241554284

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.
Files changed (88) hide show
  1. package/Components/BaseFocusable/index.tsx +3 -3
  2. package/Components/Cell/Cell.tsx +30 -13
  3. package/Components/Cell/CellWithFocusable.tsx +6 -4
  4. package/Components/Cell/TvOSCellComponent.tsx +3 -7
  5. package/Components/Focusable/Focusable.tsx +6 -1
  6. package/Components/FocusableGroup/index.tsx +10 -2
  7. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  8. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  9. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  10. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  11. package/Components/Layout/TV/__tests__/index.test.tsx +20 -75
  12. package/Components/Layout/TV/index.tsx +29 -181
  13. package/Components/Layout/TV/index.web.tsx +33 -0
  14. package/Components/Layout/index.tsx +15 -11
  15. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +4 -1
  16. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +86 -116
  17. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  18. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  19. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/index.ts +57 -0
  20. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  21. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +20 -0
  22. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  23. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  24. package/Components/MasterCell/DefaultComponents/index.ts +2 -0
  25. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  26. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
  27. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  28. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +7 -1
  29. package/Components/MasterCell/dataAdapter.ts +21 -7
  30. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  31. package/Components/MasterCell/index.tsx +5 -3
  32. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  33. package/Components/MasterCell/utils/index.ts +17 -30
  34. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  35. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  36. package/Components/Navigator/StackNavigator.tsx +57 -0
  37. package/Components/Navigator/index.ts +1 -0
  38. package/Components/PlayerContainer/PlayerContainer.tsx +3 -0
  39. package/Components/River/ComponentsMap/ComponentsMap.tsx +24 -17
  40. package/Components/River/RefreshControl.tsx +55 -1
  41. package/Components/River/TV/River.tsx +0 -22
  42. package/Components/RouteManager/index.tsx +2 -2
  43. package/Components/Screen/TV/hooks/index.ts +3 -0
  44. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  45. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  46. package/Components/Screen/TV/index.web.tsx +40 -44
  47. package/Components/Screen/__tests__/Screen.test.tsx +3 -49
  48. package/Components/Screen/index.tsx +55 -76
  49. package/Components/Screen/navigationHandler.ts +5 -0
  50. package/Components/Screen/orientationHandler.ts +18 -7
  51. package/Components/Screen/utils.ts +16 -0
  52. package/Components/ScreenResolver/index.tsx +6 -11
  53. package/Components/Transitioner/Scene.tsx +40 -26
  54. package/Components/Transitioner/Transitioner.tsx +46 -48
  55. package/Components/Transitioner/__tests__/Scene.test.js +7 -0
  56. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
  57. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -0
  58. package/Components/VideoLive/LiveImageManager.ts +28 -1
  59. package/Components/VideoLive/PlayerLiveImageComponent.tsx +52 -24
  60. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +26 -24
  61. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +2 -14
  62. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +79 -45
  63. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +47 -33
  64. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +121 -86
  65. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +44 -5
  66. package/Components/VideoModal/ModalAnimation/utils.ts +7 -4
  67. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  68. package/Components/VideoModal/PlayerWrapper.tsx +67 -60
  69. package/Components/VideoModal/VideoModal.tsx +17 -17
  70. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
  71. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +80 -14
  72. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  73. package/Components/VideoModal/utils.ts +5 -2
  74. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  75. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +4 -4
  76. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  77. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  78. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  79. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  80. package/Contexts/FocusableGroupContext/index.ts +7 -0
  81. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  82. package/Contexts/ScreenContext/index.tsx +2 -2
  83. package/Contexts/ScreenDataContext/index.tsx +20 -0
  84. package/events/index.ts +1 -0
  85. package/package.json +5 -5
  86. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  87. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  88. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
@@ -1,20 +1,34 @@
1
1
  import * as React from "react";
2
- import { last, pathOr } from "ramda";
3
- import { ScreenResolver } from "../../ScreenResolver";
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";
13
-
14
12
  import {
15
- useInitialFocus,
16
- useRestoreFocus,
17
- } from "@applicaster/zapp-react-dom-ui-components/Components/River/hooks";
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
+ });
18
32
 
19
33
  type Components = {
20
34
  NavBar: React.ComponentType<any>;
@@ -26,16 +40,6 @@ type Props = {
26
40
  Components: Components;
27
41
  };
28
42
 
29
- const isPlayer = (routeState): boolean => {
30
- const pluginType = pathOr(
31
- "unknown_plugin_type",
32
- ["state", "screen", "plugin_type"],
33
- routeState
34
- );
35
-
36
- return pluginType === "player";
37
- };
38
-
39
43
  const getActiveRiver = ({
40
44
  screenId,
41
45
  screenType,
@@ -46,6 +50,7 @@ const getActiveRiver = ({
46
50
  if (rivers[screenId]) {
47
51
  if (screenType === "hooks") {
48
52
  const navigations = routeState?.state?.entry?.payload?.navigations;
53
+
49
54
  if (navigations) {
50
55
  return routeState.state.entry.payload;
51
56
  }
@@ -69,6 +74,7 @@ const getNavigations = ({
69
74
  // river presents
70
75
  if (screenType === "hooks") {
71
76
  const navigations = routeState?.state?.entry?.payload?.navigations;
77
+
72
78
  if (navigations) {
73
79
  return navigations;
74
80
  }
@@ -81,19 +87,21 @@ const getNavigations = ({
81
87
  return fallbackNavigations;
82
88
  };
83
89
 
84
- export const Screen = (props: Props) => {
85
- if (!props.route) {
86
- throw new Error("Required props route is missing");
90
+ export const Screen = ({ route, Components }: Props) => {
91
+ if (isNilOrEmpty(route)) {
92
+ throw Error("Required props: route is missing");
87
93
  }
88
94
 
89
95
  const navigator = useNavigation();
90
96
  const { plugins = [], rivers = [] } = usePickFromState(["plugins", "rivers"]);
91
97
 
92
- const pathAttributes = getPathAttributes({ pathname: props.route });
93
- const routeState = navigator.getStackForPathname(props.route);
98
+ const pathAttributes = getPathAttributes({ pathname: route });
99
+ const routeState = navigator.getStackForPathname(route);
94
100
 
95
101
  const { screenType, screenId } = last(pathAttributes);
96
102
 
103
+ const backgroundColor = useScreenBackgroundColor(screenId);
104
+
97
105
  useInitialFocus();
98
106
  useRestoreFocus();
99
107
 
@@ -105,14 +113,6 @@ export const Screen = (props: Props) => {
105
113
  fallbackActiveRiver: navigator.activeRiver,
106
114
  });
107
115
 
108
- console.log("debug_2", "Screen", {
109
- screenType,
110
- routeState,
111
- route: props.route,
112
- navigator,
113
- activeRiver,
114
- });
115
-
116
116
  const navigationProps = getNavigationProps({
117
117
  navigator: {
118
118
  // @ts-ignore
@@ -131,39 +131,35 @@ export const Screen = (props: Props) => {
131
131
  fallbackNavigations: navigator.activeRiver.navigations,
132
132
  });
133
133
 
134
- const menuPlugin = resolveNavigationPlugin({
135
- category: "menu",
136
- navigations,
137
- plugins,
138
- }) as QuickBrickPlugin;
134
+ const menuPlugin = findMenuPlugin(navigations, plugins);
139
135
 
140
- const NavBar = (props.Components.NavBar ||
136
+ const NavBar = (Components.NavBar ||
141
137
  menuPlugin.module) as React.ComponentType<any>;
142
138
 
143
- const isNavBarVisible = !isPlayer(routeState);
139
+ const isPlayer = isPlayerPlugin(routeState);
140
+
141
+ const { visible: isNavBarVisible } = useNavbarState();
144
142
 
145
143
  const screenData =
146
- screenType === "hooks"
144
+ screenType === "hooks" || isPlayer
147
145
  ? routeState?.state?.entry
148
146
  : routeState?.state?.screen;
149
147
 
150
148
  return (
151
- <>
149
+ <View style={[styles.container, { backgroundColor }]}>
152
150
  <NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
153
151
  <NavBar
154
- groupId={props.route}
155
152
  isVisible={isNavBarVisible}
156
153
  menuPlugin={menuPlugin}
157
154
  navigationProps={navigationProps}
158
- // Maybe activeRiver?
159
155
  />
160
156
  </NavBarContainer>
161
157
  <ScreenResolver
162
158
  screenType={screenType}
163
159
  screenId={screenId}
164
160
  screenData={screenData}
165
- groupId={props.route}
161
+ groupId={route}
166
162
  />
167
- </>
163
+ </View>
168
164
  );
169
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(),
@@ -96,14 +99,6 @@ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
96
99
  }),
97
100
  }));
98
101
 
99
- const {
100
- ORIENTATIONS,
101
- } = require("@applicaster/zapp-react-native-utils/appUtils/orientationHelper");
102
-
103
- const {
104
- useCurrentScreenData,
105
- } = require("@applicaster/zapp-react-native-utils/reactHooks/screen");
106
-
107
102
  const {
108
103
  allowedOrientationsForScreen,
109
104
  getOrientation,
@@ -155,45 +150,4 @@ describe("<Screen Component />", () => {
155
150
  expect(wrapper.toJSON()).toMatchSnapshot();
156
151
  });
157
152
  });
158
-
159
- it("invokes the orientation hook when the route changes", () => {
160
- act(() => {
161
- wrapper = create(<Screen {...screenProps} />);
162
- });
163
-
164
- // @ts-ignore
165
- useCurrentScreenData.mockReturnValue({
166
- id: "player-testId",
167
- general: { screen_orientation: ORIENTATIONS.landscapeSensor },
168
- plugin_type: "player",
169
- });
170
-
171
- act(() => {
172
- wrapper.update(
173
- <Screen
174
- {...screenProps}
175
- pathname="/playable"
176
- screenData={{
177
- id: "player-testId",
178
- general: { screen_orientation: ORIENTATIONS.landscapeSensor },
179
- plugin_type: "player",
180
- }}
181
- />
182
- );
183
- });
184
-
185
- useCurrentScreenData.mockReturnValue({
186
- id: "player-testId",
187
- general: { screen_orientation: ORIENTATIONS.landscapeSensor },
188
- });
189
-
190
- act(() => {
191
- wrapper.update(<Screen {...screenProps} />);
192
- });
193
-
194
- expect(allowedOrientationsForScreen).toHaveBeenNthCalledWith(
195
- 1,
196
- ORIENTATIONS.landscapeSensor
197
- );
198
- });
199
153
  });
@@ -1,16 +1,19 @@
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";
5
+ import {
6
+ isOrientationCompatible,
7
+ useGetScreenOrientation,
8
+ } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
6
9
 
7
10
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
8
11
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
9
12
  import {
10
- getNavigationPropsV2,
11
- resolveNavigationPlugin,
13
+ shouldNavBarDisplayMenu,
14
+ getNavBarProps,
15
+ getScreenId,
12
16
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
13
- import { useSafeAreaInsets } from "react-native-safe-area-context";
14
17
  import {
15
18
  useDimensions,
16
19
  useRoute,
@@ -21,39 +24,18 @@ import {
21
24
  } from "@applicaster/zapp-react-native-utils/reactHooks";
22
25
  import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
23
26
 
24
- import { ScreenContextProvider } from "../../Contexts/ScreenContext";
25
27
  import { RouteManager } from "../RouteManager";
26
28
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
27
- import { useScreenOrientationHandler } from "./orientationHandler";
28
-
29
- const getScreenId = (
30
- screenData: LegacyNavigationScreenData,
31
- fallbackRiver: ZappRiver
32
- ) => {
33
- return screenData?.targetScreen
34
- ? screenData?.targetScreen?.id ?? fallbackRiver.id
35
- : "screen_id" in screenData
36
- ? screenData.screen_id
37
- : 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
38
37
  };
39
38
 
40
- function colorIsNotTransparent(color) {
41
- const layers = R.compose(
42
- R.map(R.trim),
43
- R.split(","),
44
- R.replace(")", ""),
45
- R.replace("rgba(", "")
46
- )(color);
47
-
48
- const alpha = Number(layers?.[3]);
49
-
50
- return alpha > 0;
51
- }
52
-
53
- function isValidColor(string) {
54
- return string && string !== "transparent" && colorIsNotTransparent(string);
55
- }
56
-
57
39
  type Props = {
58
40
  pathname: unknown;
59
41
  screenData: unknown;
@@ -67,9 +49,12 @@ export function Screen(_props: Props) {
67
49
  // Gets the data for the current screen configuration
68
50
  const currentScreenData = useCurrentScreenData();
69
51
  const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
70
- const insets = useSafeAreaInsets();
71
52
 
72
- const { width: screenWidth } = useDimensions("screen", {
53
+ const {
54
+ width: screenWidth,
55
+ height,
56
+ deviceInfo,
57
+ } = useDimensions("screen", {
73
58
  fullDimensions: true,
74
59
  });
75
60
 
@@ -81,30 +66,19 @@ export function Screen(_props: Props) {
81
66
 
82
67
  const { title } = useNavbarState();
83
68
 
84
- const hasMenu =
85
- resolveNavigationPlugin({
86
- category: "menu",
87
- navigations: currentRiver.navigations,
88
- plugins,
89
- })?.identifier === "quick_brick_side_menu";
90
-
91
- const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
92
- const props = getNavigationPropsV2({
93
- currentRiver,
94
- title,
95
- category: "nav_bar",
96
- });
97
-
98
- if (props) {
99
- return {
100
- ...props,
101
- id: pathname,
102
- pathname: pathname,
103
- };
104
- }
105
-
106
- return null;
107
- }, [currentRiver, pathname]);
69
+ const isTablet = deviceInfo?.isTablet;
70
+
71
+ const { appData } = usePickFromState(["appData"]);
72
+ const isTabletPortrait = appData?.isTabletPortrait;
73
+
74
+ const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
75
+
76
+ const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
77
+
78
+ const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
79
+ getNavBarProps(currentRiver, pathname, title),
80
+ [currentRiver, pathname]
81
+ );
108
82
 
109
83
  const NavBar = React.useMemo(
110
84
  () =>
@@ -126,33 +100,38 @@ export function Screen(_props: Props) {
126
100
 
127
101
  const style = React.useMemo(
128
102
  () => ({
129
- flex: 1,
103
+ ...screenStyles,
130
104
  backgroundColor: isValidColor(backgroundColor)
131
105
  ? backgroundColor
132
106
  : 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
107
  }),
138
- [insets, screenWidth, theme.app_background_color, backgroundColor]
108
+ [theme.app_background_color, backgroundColor]
139
109
  );
140
110
 
141
111
  const targetScreenData =
142
112
  currentScreenData || (screenData as any)?.targetScreen || screenData;
143
113
 
144
- useScreenOrientationHandler({ screenData: targetScreenData });
114
+ const orientation = useGetScreenOrientation(targetScreenData);
115
+
116
+ // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
117
+ // This saves unnecessary re-renders and user will not see distorted aspect screen.
118
+ if (
119
+ !isOrientationCompatible({
120
+ orientation,
121
+ layoutData,
122
+ })
123
+ ) {
124
+ return <View style={style} />;
125
+ }
145
126
 
146
127
  return (
147
- <ScreenContextProvider pathname={pathname}>
148
- <View style={style}>
149
- {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
150
-
151
- <OfflineFallbackScreen screenData={targetScreenData}>
152
- {/* @TODO RouteManager doesn't use props, can they be removed ? */}
153
- <RouteManager pathname={pathname} screenData={screenData} />
154
- </OfflineFallbackScreen>
155
- </View>
156
- </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>
157
136
  );
158
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}
@@ -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
- export function useScreenOrientationHandler({
83
- screenData,
84
- }: OrientationHookArgs) {
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 newOrientation = useNewOrientationForScreenData({ screenData });
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 * as R from "ramda";
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
- R.path(["module", "Component"], ScreenPlugin) ||
104
- R.prop("module", ScreenPlugin) ||
105
- R.prop("Component", ScreenPlugin) ||
98
+ path(["module", "Component"], ScreenPlugin) ||
99
+ prop("module", ScreenPlugin) ||
100
+ prop("Component", ScreenPlugin) ||
106
101
  ScreenPlugin;
107
102
 
108
103
  const configuration =
109
- R.prop("configuration", ScreenPlugin) ||
110
- R.prop("__plugin_configuration", ScreenComponent);
104
+ prop("configuration", ScreenPlugin) ||
105
+ prop("__plugin_configuration", ScreenComponent);
111
106
 
112
107
  if (ScreenComponent) {
113
108
  return (
@@ -1,12 +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";
8
+ import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
9
+ import { ScreenContextProvider } from "../../Contexts/ScreenContext";
10
10
 
11
11
  type Props = {
12
12
  children: any;
@@ -16,6 +16,8 @@ type Props = {
16
16
  animating: boolean;
17
17
  contentStyle: ViewStyle;
18
18
  pathname: string;
19
+ isActive: boolean;
20
+ screenData: NavigationScreenData;
19
21
  };
20
22
 
21
23
  /**
@@ -38,34 +40,46 @@ export function Scene({
38
40
  animating,
39
41
  contentStyle,
40
42
  pathname,
43
+ isActive = false,
44
+ screenData,
41
45
  }: Props) {
46
+ const [initialScreenData, setInitialScreenData] = React.useState(screenData);
47
+
48
+ useScreenOrientationHandler({
49
+ screenData,
50
+ isActive,
51
+ });
52
+
53
+ React.useLayoutEffect(() => {
54
+ if (isActive) {
55
+ setInitialScreenData(screenData);
56
+ }
57
+ }, [screenData, isActive]);
58
+
42
59
  const frame = useSafeAreaFrame();
43
- const { height, width } = useWindowDimensions();
44
60
 
45
- if (overlayStyle && animating) {
46
- // Safe frame takes too long to update,
47
- // so we can not rely on it there, and use height and width instead.
48
- return (
49
- <Animated.View
50
- pointerEvents={pointerEvents}
51
- style={[style, contentStyle, { height, width }]}
52
- >
53
- <PathnameContext.Provider value={pathname}>
54
- {children}
55
- </PathnameContext.Provider>
56
- <Animated.View style={overlayStyle} />
57
- </Animated.View>
58
- );
59
- }
61
+ const isAnimating = animating && overlayStyle;
62
+
63
+ const dimensions = isAnimating
64
+ ? {
65
+ height: "100%",
66
+ width: "100%",
67
+ }
68
+ : frame;
60
69
 
61
70
  return (
62
71
  <Animated.View
63
72
  pointerEvents={pointerEvents}
64
- style={[style, contentStyle, frame]}
73
+ style={[style, contentStyle, dimensions]}
65
74
  >
66
- <PathnameContext.Provider value={pathname}>
67
- {children}
68
- </PathnameContext.Provider>
75
+ <ScreenDataContext.Provider value={initialScreenData}>
76
+ <PathnameContext.Provider value={pathname}>
77
+ <ScreenContextProvider pathname={pathname}>
78
+ {children}
79
+ </ScreenContextProvider>
80
+ </PathnameContext.Provider>
81
+ </ScreenDataContext.Provider>
82
+ {isAnimating && <Animated.View style={overlayStyle} />}
69
83
  </Animated.View>
70
84
  );
71
85
  }