@applicaster/zapp-react-native-ui-components 13.0.0-alpha.4700935119 → 13.0.0-alpha.4863201005

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 (50) hide show
  1. package/Components/BaseFocusable/index.ios.ts +1 -1
  2. package/Components/BaseFocusable/index.tsx +1 -1
  3. package/Components/Cell/Cell.tsx +7 -3
  4. package/Components/Focusable/Touchable.tsx +19 -20
  5. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  6. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  7. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -11
  8. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +31 -8
  9. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  10. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  11. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  12. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  13. package/Components/MasterCell/utils/index.ts +1 -1
  14. package/Components/ModalComponent/Header/index.tsx +3 -3
  15. package/Components/River/ComponentsMap/ComponentsMap.tsx +39 -65
  16. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  17. package/Components/River/RiverFooter.tsx +39 -9
  18. package/Components/River/RiverItem.tsx +37 -2
  19. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +100 -31
  20. package/Components/River/__tests__/componentsMap.test.js +17 -5
  21. package/Components/Screen/hooks.ts +56 -0
  22. package/Components/Screen/index.tsx +13 -39
  23. package/Components/Tabs/Tab.tsx +6 -6
  24. package/Components/TextInputTv/index.tsx +2 -2
  25. package/Components/Transitioner/AnimationManager.js +8 -8
  26. package/Components/Transitioner/Scene.tsx +52 -23
  27. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +59 -43
  28. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
  29. package/Components/Transitioner/index.js +8 -4
  30. package/Components/VideoLive/LiveImageManager.ts +27 -1
  31. package/Components/VideoLive/PlayerLiveImageComponent.tsx +29 -21
  32. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +51 -1
  33. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  34. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +7 -6
  35. package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
  36. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  37. package/Components/VideoModal/PlayerWrapper.tsx +16 -35
  38. package/Components/VideoModal/VideoModal.tsx +14 -23
  39. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -1
  40. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +0 -90
  41. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  42. package/Components/VideoModal/hooks/index.ts +7 -0
  43. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  44. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  45. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  46. package/Components/VideoModal/utils.ts +1 -1
  47. package/Contexts/ScreenContext/index.tsx +3 -2
  48. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  49. package/Decorators/ZappPipesDataConnector/index.tsx +31 -1
  50. package/package.json +5 -5
@@ -1,50 +1,86 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
3
-
4
- const allTrue = R.all(R.equals(true));
5
- const anyFalse = R.any(R.equals(false));
6
- const anyTrue = R.any(R.equals(true));
2
+ import { isNil, set, lensIndex, T, slice } from "ramda";
3
+ import { BehaviorSubject } from "rxjs";
4
+ import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
7
5
 
8
6
  const reducer = (state, { payload }) => {
9
- if (!R.isNil(payload) && !state[payload]) {
10
- return R.set(R.lensIndex(payload), true)(state);
7
+ if (!isNil(payload) && !state[payload]) {
8
+ return set(lensIndex(payload), true)(state);
11
9
  }
12
10
 
13
11
  return state;
14
12
  };
15
13
 
16
- type Return = {
17
- isAnyLoading: boolean;
18
- isAllLoaded: boolean;
14
+ type LoadingState = {
15
+ index: number;
16
+ done: boolean;
19
17
  waitForAllComponents: boolean;
18
+ };
19
+
20
+ type Return = {
21
+ loadingState: BehaviorSubject<LoadingState>;
20
22
  onLoadFinished: (index: number) => void;
21
23
  onLoadFailed: ({ error, index }: { error: Error; index: number }) => void;
22
24
  shouldShowLoadingError: boolean;
23
- isAnyLoaded: boolean;
24
25
  arePreviousComponentsLoaded: (index: number) => boolean;
25
26
  };
26
27
 
27
- type Action = { payload: { index: number } };
28
-
29
- type Loaded = true;
30
- type Loading = false;
31
-
32
- type LoadingState = Array<Loaded | Loading>;
33
-
34
28
  // TODO: Take this value from Zapp configuration, when feature is added to GeneralScreen
35
29
  const SHOULD_FAIL_ON_COMPONENT_LOADING = false;
36
30
 
37
- export const useLoadingState = (count: number): Return => {
31
+ const createLoadingStateObservable = () =>
32
+ new BehaviorSubject<LoadingState>({
33
+ index: -1,
34
+ done: false,
35
+ waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING,
36
+ });
37
+
38
+ export const useLoadingState = (
39
+ count: number,
40
+ onLoadDone: () => void
41
+ ): Return => {
42
+ const componentStateRef = React.useRef(new Array(count).fill(false));
38
43
  const [loadingError, setLoadingError] = React.useState(null);
39
44
 
40
- const [componentsState, dispatch] = React.useReducer<
41
- React.Reducer<LoadingState, Action>
42
- >(reducer, new Array(count).fill(false));
45
+ const loadingState = useRefWithInitialValue<BehaviorSubject<LoadingState>>(
46
+ createLoadingStateObservable
47
+ );
48
+
49
+ const arePreviousComponentsLoaded = React.useCallback((index) => {
50
+ if (index === 0) {
51
+ return true;
52
+ }
43
53
 
44
- const handleComponentLoaded = React.useCallback((index) => {
45
- dispatch({ payload: index });
54
+ const componentsBefore = slice(0, index, componentStateRef.current);
55
+
56
+ return componentsBefore.every(T);
46
57
  }, []);
47
58
 
59
+ const dispatch = React.useCallback(({ payload }) => {
60
+ const newState = reducer(componentStateRef.current, { payload });
61
+ componentStateRef.current = newState;
62
+ const isDone = arePreviousComponentsLoaded(count - 1);
63
+
64
+ const state = loadingState.current.getValue();
65
+
66
+ const newLoadingState = {
67
+ ...state,
68
+ index: state.index < payload ? payload : state.index,
69
+ done: isDone,
70
+ };
71
+
72
+ loadingState.current.next(newLoadingState);
73
+
74
+ if (isDone) {
75
+ onLoadDone();
76
+ }
77
+ }, []);
78
+
79
+ const handleComponentLoaded = React.useCallback(
80
+ (index) => dispatch({ payload: index }),
81
+ []
82
+ );
83
+
48
84
  const handleComponentLoadErrorWhenNeedToFail = React.useCallback(
49
85
  ({ error }) => {
50
86
  if (error !== loadingError) {
@@ -55,35 +91,26 @@ export const useLoadingState = (count: number): Return => {
55
91
  );
56
92
 
57
93
  const handleComponentLoadErrorWhenNoNeedToFail = React.useCallback(
58
- ({ index }) => {
59
- handleComponentLoaded(index);
60
- },
94
+ ({ index }) => handleComponentLoaded(index),
61
95
  []
62
96
  );
63
97
 
64
- const arePreviousComponentsLoaded = React.useCallback(
65
- (index) => {
66
- if (index === 0) {
67
- return true;
68
- }
69
-
70
- const componentsBefore = R.slice(0, index, componentsState);
71
-
72
- return allTrue(componentsBefore);
73
- },
74
- [componentsState]
98
+ return React.useMemo(
99
+ () => ({
100
+ loadingState: loadingState.current,
101
+ onLoadFinished: handleComponentLoaded,
102
+ onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
103
+ ? handleComponentLoadErrorWhenNeedToFail
104
+ : handleComponentLoadErrorWhenNoNeedToFail,
105
+ shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
106
+ arePreviousComponentsLoaded,
107
+ }),
108
+ [
109
+ loadingError,
110
+ handleComponentLoaded,
111
+ handleComponentLoadErrorWhenNeedToFail,
112
+ handleComponentLoadErrorWhenNoNeedToFail,
113
+ arePreviousComponentsLoaded,
114
+ ]
75
115
  );
76
-
77
- return {
78
- isAnyLoading: anyFalse(componentsState),
79
- isAllLoaded: allTrue(componentsState),
80
- onLoadFinished: handleComponentLoaded,
81
- onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
82
- ? handleComponentLoadErrorWhenNeedToFail
83
- : handleComponentLoadErrorWhenNoNeedToFail,
84
- shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
85
- isAnyLoaded: anyTrue(componentsState),
86
- waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING,
87
- arePreviousComponentsLoaded,
88
- };
89
116
  };
@@ -1,11 +1,23 @@
1
- import React from "react";
1
+ import React, { useCallback } from "react";
2
2
  import { StyleSheet, View } from "react-native";
3
3
  import { Spinner } from "@applicaster/zapp-react-native-ui-components/Components/Spinner";
4
+ import type { Subject } from "rxjs";
5
+ import { useStateFromSubscribe } from "@applicaster/zapp-react-native-utils/reactHooks/state/useStateFromSubscribe";
6
+
7
+ type LoadingState = {
8
+ waitForAllComponents: boolean;
9
+ index: number;
10
+ done: boolean;
11
+ };
12
+
13
+ type State = {
14
+ visible: boolean;
15
+ isAnyLoaded: boolean;
16
+ };
4
17
 
5
18
  type Props = {
6
- visible?: boolean;
7
19
  flatListHeight?: number;
8
- isAnyLoaded: boolean;
20
+ loadingState: Subject<LoadingState>;
9
21
  };
10
22
 
11
23
  const FOOTER_COMPONENT_HEIGHT = 200;
@@ -19,17 +31,35 @@ const footerStyles = StyleSheet.create({
19
31
  });
20
32
 
21
33
  function RiverFooterComponent(props: Props) {
22
- const { visible = true, flatListHeight, isAnyLoaded } = props;
34
+ const { flatListHeight, loadingState } = props;
35
+
36
+ const { visible, isAnyLoaded } = useStateFromSubscribe<LoadingState, State>(
37
+ loadingState,
38
+ useCallback(
39
+ ({ index, done, waitForAllComponents }, setState) =>
40
+ setState(() => ({
41
+ visible: !done,
42
+ isAnyLoaded: index >= 0 || waitForAllComponents,
43
+ })),
44
+ []
45
+ ),
46
+ {
47
+ visible: true,
48
+ isAnyLoaded: false,
49
+ }
50
+ );
23
51
 
24
52
  if (!visible) return null;
25
53
 
26
54
  return (
27
55
  <View
28
- renderToHardwareTextureAndroid={true}
29
- style={{
30
- ...footerStyles.container,
31
- height: isAnyLoaded ? FOOTER_COMPONENT_HEIGHT : flatListHeight,
32
- }}
56
+ renderToHardwareTextureAndroid
57
+ style={[
58
+ footerStyles.container,
59
+ {
60
+ height: isAnyLoaded ? FOOTER_COMPONENT_HEIGHT : flatListHeight,
61
+ },
62
+ ]}
33
63
  >
34
64
  <Spinner size={isAnyLoaded ? "small" : "large"} />
35
65
  </View>
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useEffect } from "react";
2
2
  import * as R from "ramda";
3
3
 
4
4
  import { applyDecorators } from "../../Decorators";
@@ -11,6 +11,7 @@ import {
11
11
  import { riverLogger } from "./logger";
12
12
  import { tvPluginsWithCellRenderer } from "../../const";
13
13
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
14
+ import type { BehaviorSubject } from "rxjs";
14
15
 
15
16
  export type RiverItemType = {
16
17
  item: ZappUIComponent;
@@ -24,6 +25,7 @@ export type RiverItemType = {
24
25
  getStaticComponentFeed: GeneralContentScreenProps["getStaticComponentFeed"];
25
26
  readyToBeDisplayed?: boolean;
26
27
  isLast: boolean;
28
+ loadingState: BehaviorSubject<{ index: number }>;
27
29
  };
28
30
 
29
31
  function getFeedUrl(feed: ZappFeed, index: number) {
@@ -36,6 +38,33 @@ function getFeedUrl(feed: ZappFeed, index: number) {
36
38
  }
37
39
  }
38
40
 
41
+ /**
42
+ * useLoadingState for RiverItemComponent
43
+ * takes currentIndex and loadingState as arguments
44
+ **/
45
+ const useLoadingState = (
46
+ currentIndex: number,
47
+ loadingState: RiverItemType["loadingState"]
48
+ ) => {
49
+ const [readyToBeDisplayed, setReadyToBeDisplayed] = React.useState(
50
+ loadingState.getValue().index + 1 === currentIndex
51
+ );
52
+
53
+ useEffect(() => {
54
+ const subscription = loadingState.subscribe(({ index }) => {
55
+ if (index + 1 === currentIndex) {
56
+ setReadyToBeDisplayed(true);
57
+ }
58
+ });
59
+
60
+ return () => {
61
+ subscription.unsubscribe();
62
+ };
63
+ }, [loadingState, currentIndex]);
64
+
65
+ return readyToBeDisplayed;
66
+ };
67
+
39
68
  function RiverItemComponent(props: RiverItemType) {
40
69
  const {
41
70
  item,
@@ -47,10 +76,12 @@ function RiverItemComponent(props: RiverItemType) {
47
76
  onLoadFinished,
48
77
  onLoadFailed,
49
78
  getStaticComponentFeed,
50
- readyToBeDisplayed,
51
79
  isLast,
80
+ loadingState,
52
81
  } = props;
53
82
 
83
+ const readyToBeDisplayed = useLoadingState(index, loadingState);
84
+
54
85
  const feedUrl = getFeedUrl(feed, index);
55
86
 
56
87
  const Component = useComponentResolver(
@@ -90,6 +121,10 @@ function RiverItemComponent(props: RiverItemType) {
90
121
  }
91
122
  }, []);
92
123
 
124
+ if (!readyToBeDisplayed) {
125
+ return null;
126
+ }
127
+
93
128
  if (Component === null || typeof Component === "undefined") {
94
129
  riverLogger.warning({
95
130
  message: `Component ${item.component_type} is null - skipping rendering`,
@@ -17,7 +17,90 @@ exports[`componentsMap renders renders components map correctly 1`] = `
17
17
  }
18
18
  >
19
19
  <RCTScrollView
20
- ListFooterComponent={[Function]}
20
+ ListFooterComponent={
21
+ <Memo(RiverFooterComponent)
22
+ flatListHeight={null}
23
+ loadingState={
24
+ BehaviorSubject {
25
+ "_value": {
26
+ "done": false,
27
+ "index": -1,
28
+ "waitForAllComponents": false,
29
+ },
30
+ "closed": false,
31
+ "currentObservers": null,
32
+ "hasError": false,
33
+ "isStopped": false,
34
+ "observers": [
35
+ SafeSubscriber {
36
+ "_finalizers": [
37
+ Subscription {
38
+ "_finalizers": null,
39
+ "_parentage": [Circular],
40
+ "closed": false,
41
+ "initialTeardown": [Function],
42
+ },
43
+ ],
44
+ "_parentage": null,
45
+ "closed": false,
46
+ "destination": ConsumerObserver {
47
+ "partialObserver": {
48
+ "complete": undefined,
49
+ "error": undefined,
50
+ "next": [Function],
51
+ },
52
+ },
53
+ "initialTeardown": undefined,
54
+ "isStopped": false,
55
+ },
56
+ SafeSubscriber {
57
+ "_finalizers": [
58
+ Subscription {
59
+ "_finalizers": null,
60
+ "_parentage": [Circular],
61
+ "closed": false,
62
+ "initialTeardown": [Function],
63
+ },
64
+ ],
65
+ "_parentage": null,
66
+ "closed": false,
67
+ "destination": ConsumerObserver {
68
+ "partialObserver": {
69
+ "complete": undefined,
70
+ "error": undefined,
71
+ "next": [Function],
72
+ },
73
+ },
74
+ "initialTeardown": undefined,
75
+ "isStopped": false,
76
+ },
77
+ SafeSubscriber {
78
+ "_finalizers": [
79
+ Subscription {
80
+ "_finalizers": null,
81
+ "_parentage": [Circular],
82
+ "closed": false,
83
+ "initialTeardown": [Function],
84
+ },
85
+ ],
86
+ "_parentage": null,
87
+ "closed": false,
88
+ "destination": ConsumerObserver {
89
+ "partialObserver": {
90
+ "complete": undefined,
91
+ "error": undefined,
92
+ "next": [Function],
93
+ },
94
+ },
95
+ "initialTeardown": undefined,
96
+ "isStopped": false,
97
+ },
98
+ ],
99
+ "thrownError": null,
100
+ }
101
+ }
102
+ />
103
+ }
21
104
  contentContainerStyle={
22
105
  {
23
106
  "paddingBottom": undefined,
@@ -80,22 +163,14 @@ exports[`componentsMap renders renders components map correctly 1`] = `
80
163
  style={null}
81
164
  >
82
165
  <View
166
+ onLayout={[Function]}
83
167
  style={
84
168
  {
85
- "display": "flex",
169
+ "flex": 1,
86
170
  }
87
171
  }
88
172
  >
89
- <View
90
- onLayout={[Function]}
91
- style={
92
- {
93
- "flex": 1,
94
- }
95
- }
96
- >
97
- <View />
98
- </View>
173
+ <View />
99
174
  </View>
100
175
  </View>
101
176
  <View
@@ -103,23 +178,13 @@ exports[`componentsMap renders renders components map correctly 1`] = `
103
178
  style={null}
104
179
  >
105
180
  <View
181
+ onLayout={[Function]}
106
182
  style={
107
183
  {
108
- "display": "none",
184
+ "flex": 1,
109
185
  }
110
186
  }
111
- >
112
- <View
113
- onLayout={[Function]}
114
- style={
115
- {
116
- "flex": 1,
117
- }
118
- }
119
- >
120
- <View />
121
- </View>
122
- </View>
187
+ />
123
188
  </View>
124
189
  <View
125
190
  onLayout={[Function]}
@@ -127,12 +192,16 @@ exports[`componentsMap renders renders components map correctly 1`] = `
127
192
  <View
128
193
  renderToHardwareTextureAndroid={true}
129
194
  style={
130
- {
131
- "alignItems": "center",
132
- "height": null,
133
- "justifyContent": "center",
134
- "width": "100%",
135
- }
195
+ [
196
+ {
197
+ "alignItems": "center",
198
+ "justifyContent": "center",
199
+ "width": "100%",
200
+ },
201
+ {
202
+ "height": null,
203
+ },
204
+ ]
136
205
  }
137
206
  >
138
207
  <ActivityIndicator
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
- import TestRenderer from "react-test-renderer";
3
- import { cleanup } from "@testing-library/react-native";
2
+ import { cleanup, render } from "@testing-library/react-native";
4
3
  import { Provider } from "react-redux";
5
4
  import configureStore from "redux-mock-store";
6
5
 
@@ -81,6 +80,13 @@ const mockScreenData = {
81
80
  id: "A1234",
82
81
  };
83
82
 
83
+ jest.mock("@applicaster/zapp-react-native-redux/AppStore", () => ({
84
+ appStore: {
85
+ get: jest.fn((prop) => mockStore[prop]),
86
+ getState: jest.fn(),
87
+ },
88
+ }));
89
+
84
90
  jest.mock("@applicaster/zapp-react-native-utils/localizationUtils", () => ({
85
91
  useIsRTL: jest.fn(() => mock_rtl_flag),
86
92
  }));
@@ -153,7 +159,13 @@ const plugins = [];
153
159
  const navigation = {};
154
160
 
155
161
  const props = { components, cellStyles, riverComponents, navigation };
156
- const store = mockStore({ components, cellStyles, plugins });
162
+
163
+ const store = mockStore({
164
+ components,
165
+ cellStyles,
166
+ plugins,
167
+ getState: jest.fn(),
168
+ });
157
169
 
158
170
  jest.useFakeTimers();
159
171
 
@@ -170,12 +182,12 @@ describe("componentsMap", () => {
170
182
  .spyOn(themeUtils, "useTheme")
171
183
  .mockImplementation(() => () => theme);
172
184
 
173
- const wrapper = TestRenderer.create(
185
+ const { toJSON } = render(
174
186
  <Provider store={store}>
175
187
  <ComponentsMap {...props} />
176
188
  </Provider>
177
189
  );
178
190
 
179
- expect(wrapper.toJSON()).toMatchSnapshot();
191
+ expect(toJSON()).toMatchSnapshot();
180
192
  });
181
193
  });
@@ -0,0 +1,56 @@
1
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
+ import {
3
+ useGetScreenOrientation,
4
+ isOrientationCompatible,
5
+ } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
6
+ import {
7
+ useCurrentScreenData,
8
+ useDimensions,
9
+ useRoute,
10
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
11
+ import { useMemo, useEffect, useState } from "react";
12
+
13
+ export const useWaitForValidOrientation = () => {
14
+ const {
15
+ width: screenWidth,
16
+ height,
17
+ deviceInfo,
18
+ } = useDimensions("screen", {
19
+ fullDimensions: true,
20
+ updateForInactiveScreens: false,
21
+ });
22
+
23
+ const currentScreenData = useCurrentScreenData();
24
+
25
+ const { screenData } = useRoute();
26
+
27
+ const [readyState, setReadyState] = useState(false);
28
+
29
+ const isTablet = deviceInfo?.isTablet;
30
+
31
+ const { appData } = usePickFromState(["appData"]);
32
+ const isTabletPortrait = appData?.isTabletPortrait;
33
+
34
+ const layoutData = useMemo(
35
+ () => ({ isTablet, isTabletPortrait, width: screenWidth, height }),
36
+ [isTablet, isTabletPortrait, screenWidth, height]
37
+ );
38
+
39
+ const targetScreenData =
40
+ currentScreenData || (screenData as any)?.targetScreen || screenData;
41
+
42
+ const orientation = useGetScreenOrientation(targetScreenData);
43
+
44
+ const isReadyForDisplay = isOrientationCompatible({
45
+ orientation,
46
+ layoutData,
47
+ });
48
+
49
+ useEffect(() => {
50
+ if (isReadyForDisplay && !readyState) {
51
+ setReadyState(true);
52
+ }
53
+ }, [readyState, orientation, layoutData]);
54
+
55
+ return readyState;
56
+ };
@@ -2,10 +2,6 @@
2
2
  import React from "react";
3
3
  import { View } from "react-native";
4
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";
9
5
 
10
6
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
11
7
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
@@ -15,7 +11,6 @@ import {
15
11
  getScreenId,
16
12
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
17
13
  import {
18
- useDimensions,
19
14
  useRoute,
20
15
  useCurrentScreenData,
21
16
  useNavbarState,
@@ -27,6 +22,7 @@ import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/Ap
27
22
  import { RouteManager } from "../RouteManager";
28
23
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
29
24
  import { isValidColor } from "./utils";
25
+ import { useWaitForValidOrientation } from "./hooks";
30
26
 
31
27
  const screenStyles = {
32
28
  flex: 1,
@@ -50,14 +46,6 @@ export function Screen(_props: Props) {
50
46
  const currentScreenData = useCurrentScreenData();
51
47
  const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
52
48
 
53
- const {
54
- width: screenWidth,
55
- height,
56
- deviceInfo,
57
- } = useDimensions("screen", {
58
- fullDimensions: true,
59
- });
60
-
61
49
  const { screenData, pathname } = useRoute();
62
50
 
63
51
  const currentRiver = useScreenData(
@@ -66,13 +54,6 @@ export function Screen(_props: Props) {
66
54
 
67
55
  const { title } = useNavbarState();
68
56
 
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
57
  const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
77
58
 
78
59
  const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
@@ -108,30 +89,23 @@ export function Screen(_props: Props) {
108
89
  [theme.app_background_color, backgroundColor]
109
90
  );
110
91
 
111
- const targetScreenData =
112
- currentScreenData || (screenData as any)?.targetScreen || screenData;
113
-
114
- const orientation = useGetScreenOrientation(targetScreenData);
92
+ // Set ready state when screen is rotated to desired orientation
93
+ const isReady = useWaitForValidOrientation();
115
94
 
116
95
  // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
117
96
  // 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
- }
126
-
127
97
  return (
128
98
  <View style={style}>
129
- {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
130
-
131
- <OfflineFallbackScreen>
132
- {/* @TODO RouteManager doesn't use props, can they be removed ? */}
133
- <RouteManager pathname={pathname} screenData={screenData} />
134
- </OfflineFallbackScreen>
99
+ {isReady ? (
100
+ <>
101
+ {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
102
+
103
+ <OfflineFallbackScreen>
104
+ {/* @TODO RouteManager doesn't use props, can they be removed ? */}
105
+ <RouteManager pathname={pathname} screenData={screenData} />
106
+ </OfflineFallbackScreen>
107
+ </>
108
+ ) : null}
135
109
  </View>
136
110
  );
137
111
  }