@applicaster/zapp-react-native-ui-components 16.0.0-alpha.7128076344 → 16.0.0-alpha.8047301539

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 (37) hide show
  1. package/Components/BackgroundImage/BackgroundImage.tsx +42 -0
  2. package/Components/BackgroundImage/BackgroundImage.tv.android.tsx +28 -0
  3. package/Components/BackgroundImage/BackgroundImage.tv.ios.tsx +24 -0
  4. package/Components/BackgroundImage/index.ts +1 -0
  5. package/Components/CellRendererResolver/index.ts +1 -1
  6. package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
  7. package/Components/FocusableGroup/FocusableTvOS.tsx +11 -7
  8. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +35 -0
  9. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +61 -0
  10. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  11. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  12. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
  13. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  14. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +54 -0
  15. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +53 -0
  16. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
  17. package/Components/GeneralContentScreen/index.ts +2 -0
  18. package/Components/Layout/TV/ScreenContainer.tsx +5 -0
  19. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +0 -1
  20. package/Components/Layout/TV/index.tsx +3 -4
  21. package/Components/Layout/TV/index.web.tsx +2 -3
  22. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +16 -5
  23. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +1 -1
  24. package/Components/PlayerContainer/PlayerContainer.tsx +5 -7
  25. package/Components/Screen/TV/hooks/__tests__/useAfterPaint.test.ts +60 -0
  26. package/Components/Screen/TV/hooks/index.ts +2 -0
  27. package/Components/Screen/TV/hooks/useAfterPaint.ts +23 -0
  28. package/Components/Screen/TV/index.web.tsx +16 -7
  29. package/Components/ScreenRevealManager/Overlay.tsx +34 -0
  30. package/Components/ScreenRevealManager/__tests__/Overlay.test.tsx +88 -0
  31. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +8 -19
  32. package/Components/VideoLive/LiveImageManager.ts +56 -45
  33. package/Components/VideoLive/PlayerLiveImageComponent.tsx +4 -2
  34. package/Components/VideoModal/utils.ts +6 -1
  35. package/Helpers/index.js +7 -1
  36. package/package.json +5 -5
  37. package/Components/Layout/TV/LayoutBackground.tsx +0 -31
@@ -0,0 +1,53 @@
1
+ import { shouldSkipHook } from "./validationHelper";
2
+ import { requestToSkipHook } from "./networkService";
3
+ import { log_debug, log_error } from "./logger";
4
+
5
+ /**
6
+ * Headless pre-hook for the General Content Screen.
7
+ *
8
+ * `configuration` is the Hook object passed by the HooksManager, which has the
9
+ * hook river merged into it. The skip-hook fields are defined under the `rules`
10
+ * section of the General Content Screen manifest, so they are read from
11
+ * `configuration.rules` (unlike the standalone hook-screen-wrapper plugin, which
12
+ * defines them under `general`).
13
+ */
14
+ export const runInBackground = async (
15
+ item,
16
+ callback,
17
+ configuration,
18
+ presentUI
19
+ ) => {
20
+ try {
21
+ const skipHookIfKeysExist = configuration?.rules?.skip_hook_storage_key;
22
+
23
+ if (skipHookIfKeysExist) {
24
+ const shouldSkip = await shouldSkipHook(skipHookIfKeysExist);
25
+
26
+ if (shouldSkip) {
27
+ log_debug(
28
+ `runInBackground: Storage key found: ${skipHookIfKeysExist}. Skipping hook.`
29
+ );
30
+
31
+ return callback({ success: true, error: null, payload: item });
32
+ }
33
+ }
34
+
35
+ const skipHookEndpoint = configuration?.rules?.skip_hook_endpoint;
36
+
37
+ if (skipHookEndpoint?.source) {
38
+ const success = await requestToSkipHook(skipHookEndpoint, item);
39
+
40
+ if (success) {
41
+ log_debug(
42
+ "runInBackground: Network call forced to finish hook. Skipping hook."
43
+ );
44
+
45
+ return callback({ success: true, error: null, payload: item });
46
+ }
47
+ }
48
+ } catch (error) {
49
+ log_error(`runInBackground: Error: ${error.message}`);
50
+ }
51
+
52
+ return presentUI();
53
+ };
@@ -0,0 +1,72 @@
1
+ import { getNamespaceAndKey } from "@applicaster/zapp-react-native-utils/appUtils/contextKeysManager/utils";
2
+ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
3
+ import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";
4
+ import { log_error, log_info } from "./logger";
5
+
6
+ type ParseKey = { key: string; namespace?: string };
7
+
8
+ export function parseKeyEntries(input: string): ParseKey[] {
9
+ return input
10
+ .split(",")
11
+ .map((item) => item.trim())
12
+ .filter((item) => item.length > 0)
13
+ .map((item) => getNamespaceAndKey(item));
14
+ }
15
+
16
+ export const getKeyToSkipHook = async (key: string, namespace?: string) => {
17
+ const value = await sessionStorage.getItem(key, namespace);
18
+
19
+ if (value) {
20
+ return value;
21
+ }
22
+
23
+ return await localStorage.getItem(key, namespace);
24
+ };
25
+
26
+ export const shouldSkipHook = async (
27
+ skipHookIfKeysExist?: string
28
+ ): Promise<boolean> => {
29
+ if (!skipHookIfKeysExist?.trim()) {
30
+ log_info("shouldSkipHook: No skipping condition provided");
31
+
32
+ return false;
33
+ }
34
+
35
+ const keyEntries = parseKeyEntries(skipHookIfKeysExist);
36
+
37
+ if (keyEntries.length === 0) {
38
+ log_info("shouldSkipHook: No valid keys provided");
39
+
40
+ return false;
41
+ }
42
+
43
+ for (const entry of keyEntries) {
44
+ try {
45
+ const value = await getKeyToSkipHook(entry.key, entry.namespace);
46
+
47
+ if (value) {
48
+ log_info(
49
+ `shouldSkipHook: Hook will be skipped due to: ${
50
+ entry.namespace ?? ""
51
+ } ${entry.key}. Finishing hook flow`
52
+ );
53
+
54
+ return true;
55
+ }
56
+ } catch (error) {
57
+ log_error(
58
+ `shouldSkipHook: Error: ${error.message} checking key: ${
59
+ entry.namespace ?? ""
60
+ } ${entry.key}`,
61
+ { error }
62
+ );
63
+ }
64
+ }
65
+
66
+ log_info(
67
+ // eslint-disable-next-line max-len
68
+ "shouldSkipHook: No skipping condition met, none of the provided keys found in storage, proceeding with hook"
69
+ );
70
+
71
+ return false;
72
+ };
@@ -1 +1,3 @@
1
1
  export { GeneralContentScreen } from "./GeneralContentScreen";
2
+
3
+ export { GeneralContentScreenHookAdapter } from "./GeneralContentScreenHookAdapter";
@@ -129,6 +129,11 @@ export const ScreenContainer = React.memo(function ScreenContainer({
129
129
  []
130
130
  );
131
131
 
132
+ // We need to render menu first and then proceed with screen content,
133
+ // otherwise screen will stay black until everything is loaded and screen
134
+ // rendering put huge load the CPU pushing rendering even further.
135
+ // With this approach, menu will be rendered immediately and screen content
136
+ // will be rendered after paint, which makes it more responsive and prevents black screen.
132
137
  const [navBarReady, setNavBarReady] = React.useState(false);
133
138
 
134
139
  const navBarContainer = (
@@ -2,7 +2,6 @@
2
2
 
3
3
  exports[`Layout TV renders 1`] = `
4
4
  <View
5
- backgroundColor="#000000"
6
5
  testID="background-component"
7
6
  >
8
7
  <View
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { useAppSelector } from "@applicaster/zapp-react-native-redux/hooks";
3
3
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
+ import { selectAppReady } from "@applicaster/zapp-react-native-redux";
4
5
 
5
6
  import { LayoutContainer } from "./LayoutContainer";
6
7
  import { ScreenContainer } from "./ScreenContainer";
@@ -9,8 +10,6 @@ import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
9
10
  import { PathnameContext } from "../../../Contexts/PathnameContext";
10
11
  import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
11
12
  import { ScreenContextProvider } from "../../../Contexts/ScreenContext";
12
- import { LayoutBackground } from "./LayoutBackground";
13
- import { selectAppReady } from "@applicaster/zapp-react-native-redux";
14
13
 
15
14
  type Components = {
16
15
  NavBar: React.ComponentType<any>;
@@ -39,7 +38,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
39
38
  return (
40
39
  <LayoutContainer>
41
40
  <ScreenLayoutContextProvider>
42
- <LayoutBackground Background={Components.Background}>
41
+ <Components.Background>
43
42
  <ScreenDataContext.Provider value={navigator.data}>
44
43
  <PathnameContext.Provider value={navigator.currentRoute}>
45
44
  <ScreenContextProvider pathname={navigator.currentRoute}>
@@ -52,7 +51,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
52
51
  </ScreenContextProvider>
53
52
  </PathnameContext.Provider>
54
53
  </ScreenDataContext.Provider>
55
- </LayoutBackground>
54
+ </Components.Background>
56
55
  </ScreenLayoutContextProvider>
57
56
  </LayoutContainer>
58
57
  );
@@ -4,7 +4,6 @@ import { useAppSelector } from "@applicaster/zapp-react-native-redux/hooks";
4
4
 
5
5
  import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
6
6
  import { StackNavigator } from "../../Navigator";
7
- import { LayoutBackground } from "./LayoutBackground";
8
7
  import { selectAppReady } from "@applicaster/zapp-react-native-redux";
9
8
 
10
9
  type Components = {
@@ -25,9 +24,9 @@ const Layout = ({ Components }: Props) => {
25
24
 
26
25
  return (
27
26
  <ScreenLayoutContextProvider>
28
- <LayoutBackground Background={Components.Background}>
27
+ <Components.Background>
29
28
  <StackNavigator Components={Components} />
30
- </LayoutBackground>
29
+ </Components.Background>
31
30
  </ScreenLayoutContextProvider>
32
31
  );
33
32
  };
@@ -37,13 +37,16 @@ function getAssetValue(asset, flavour, fallbackAsset = null) {
37
37
  return null;
38
38
  }
39
39
 
40
- if (typeof asset === "string") return asset;
40
+ if (typeof asset === "string") return fallbackAsset || asset;
41
41
 
42
42
  if (Array.isArray(asset)) {
43
43
  const flavourIndex = Number(flavour.replace("flavour_", ""));
44
- if (flavour && flavourIndex > -1) return asset[flavourIndex - 1];
45
44
 
46
- return asset[0];
45
+ if (flavour && flavourIndex > -1) {
46
+ return fallbackAsset || asset[flavourIndex - 1];
47
+ }
48
+
49
+ return fallbackAsset || asset[0];
47
50
  }
48
51
 
49
52
  return asset.src || fallbackAsset;
@@ -109,13 +112,21 @@ export const ActionButton = React.memo(function ActionButtonComponent(
109
112
  <Image
110
113
  fadeDuration={0}
111
114
  style={asset?.style || props?.style}
112
- uri={getAssetValue(actionState.asset, flavour, asset?.src)}
115
+ uri={getAssetValue(
116
+ actionState.asset,
117
+ flavour,
118
+ actionState.state === 1 ? asset?.src.active : asset?.src.inactive
119
+ )}
113
120
  {...asset?.props}
114
121
  />
115
122
  ) : (
116
123
  <AssetComponent
117
124
  flavour={flavour}
118
- asset={getAssetValue(asset, flavour)}
125
+ asset={getAssetValue(
126
+ asset,
127
+ flavour,
128
+ actionState.state === 1 ? asset?.src.active : asset?.src.inactive
129
+ )}
119
130
  cellUUID={cellUUID}
120
131
  {...(props?.extraProps ?? {})}
121
132
  />
@@ -8,7 +8,7 @@ export function ButtonContainerView({
8
8
  children,
9
9
  }: ContainerProps) {
10
10
  return (
11
- <View style={style}>
11
+ <View style={style} pointerEvents="box-none">
12
12
  <View style={contentStyle}>{children}</View>
13
13
  </View>
14
14
  );
@@ -265,14 +265,12 @@ const PlayerContainerComponent = (props: Props) => {
265
265
  navigator.goBack();
266
266
  }, [isModal, state.playerId, showNavBar, navigator]);
267
267
 
268
- const pluginConfiguration = React.useMemo(() => {
269
- return (
270
- playerManager.getPluginConfiguration() ||
271
- R.prop("__plugin_configuration", Player)
272
- );
273
- }, [playerManager.isRegistered()]);
268
+ const pluginConfiguration = React.useMemo(
269
+ () => player?.getPluginConfiguration(),
270
+ [player]
271
+ );
274
272
 
275
- const playEntry = (entry) => navigator.replaceTop(entry, { mode });
273
+ const playEntry = (entry: ZappEntry) => navigator.replaceTop(entry, { mode });
276
274
 
277
275
  const onPlayNextPerformNextVideoPlay = React.useCallback(() => {
278
276
  if (!playNextOverlayState.entry) {
@@ -0,0 +1,60 @@
1
+ import { renderHook, act } from "@testing-library/react-native";
2
+
3
+ import { useAfterPaint } from "../useAfterPaint";
4
+
5
+ describe("useAfterPaint", () => {
6
+ let frameCallbacks: FrameRequestCallback[];
7
+ let originalRaf: typeof requestAnimationFrame;
8
+ let originalCancelRaf: typeof cancelAnimationFrame;
9
+
10
+ const flushFrame = () => {
11
+ const callbacks = frameCallbacks;
12
+ frameCallbacks = [];
13
+
14
+ act(() => {
15
+ callbacks.forEach((cb) => cb(0));
16
+ });
17
+ };
18
+
19
+ beforeEach(() => {
20
+ frameCallbacks = [];
21
+ originalRaf = global.requestAnimationFrame;
22
+ originalCancelRaf = global.cancelAnimationFrame;
23
+
24
+ global.requestAnimationFrame = jest.fn((cb: FrameRequestCallback) => {
25
+ frameCallbacks.push(cb);
26
+
27
+ return frameCallbacks.length;
28
+ }) as unknown as typeof requestAnimationFrame;
29
+
30
+ global.cancelAnimationFrame = jest.fn();
31
+ });
32
+
33
+ afterEach(() => {
34
+ global.requestAnimationFrame = originalRaf;
35
+ global.cancelAnimationFrame = originalCancelRaf;
36
+ });
37
+
38
+ it("returns false on the initial render", () => {
39
+ const { result } = renderHook(() => useAfterPaint());
40
+
41
+ expect(result.current).toBe(false);
42
+ });
43
+
44
+ it("stays false after only one animation frame (before paint completes)", () => {
45
+ const { result } = renderHook(() => useAfterPaint());
46
+
47
+ flushFrame();
48
+
49
+ expect(result.current).toBe(false);
50
+ });
51
+
52
+ it("returns true after two animation frames (a real post-paint boundary)", () => {
53
+ const { result } = renderHook(() => useAfterPaint());
54
+
55
+ flushFrame();
56
+ flushFrame();
57
+
58
+ expect(result.current).toBe(true);
59
+ });
60
+ });
@@ -1 +1,3 @@
1
1
  export { useInitialFocus } from "./useInitialFocus";
2
+
3
+ export { useAfterPaint } from "./useAfterPaint";
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+
3
+ export const useAfterPaint = (): boolean => {
4
+ const [painted, setPainted] = React.useState(false);
5
+
6
+ React.useEffect(() => {
7
+ let secondFrame: number | undefined;
8
+
9
+ const firstFrame = requestAnimationFrame(() => {
10
+ secondFrame = requestAnimationFrame(() => setPainted(true));
11
+ });
12
+
13
+ return () => {
14
+ cancelAnimationFrame(firstFrame);
15
+
16
+ if (secondFrame !== undefined) {
17
+ cancelAnimationFrame(secondFrame);
18
+ }
19
+ };
20
+ }, []);
21
+
22
+ return painted;
23
+ };
@@ -21,7 +21,7 @@ import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/he
21
21
 
22
22
  import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
23
23
  import { ScreenResolver } from "../../ScreenResolver";
24
- import { useInitialFocus } from "./hooks";
24
+ import { useInitialFocus, useAfterPaint } from "./hooks";
25
25
  import { isPlayerPlugin } from "@applicaster/zapp-react-native-utils/pluginUtils";
26
26
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils";
27
27
  import { FreezeWithCallback } from "../../FreezeWithCallback";
@@ -157,6 +157,13 @@ export const Screen = ({ route, Components }: Props) => {
157
157
 
158
158
  const isScreenActive = useIsScreenActive();
159
159
 
160
+ // We need to render menu first and then proceed with screen content,
161
+ // otherwise screen will stay black until everything is loaded and screen
162
+ // rendering put huge load the CPU pushing rendering even further.
163
+ // With this approach, menu will be rendered immediately and screen content
164
+ // will be rendered after paint, which makes it more responsive and prevents black screen.
165
+ const isContentReady = useAfterPaint();
166
+
160
167
  return (
161
168
  <FreezeWithCallback freeze={!isScreenActive} onRelease={onRelease}>
162
169
  <View style={[styles.container, { backgroundColor }]}>
@@ -167,12 +174,14 @@ export const Screen = ({ route, Components }: Props) => {
167
174
  navigationProps={navigationProps}
168
175
  />
169
176
  </NavBarContainer>
170
- <ScreenResolver
171
- screenType={screenType}
172
- screenId={screenId}
173
- screenData={screenData}
174
- groupId={route}
175
- />
177
+ {isContentReady ? (
178
+ <ScreenResolver
179
+ screenType={screenType}
180
+ screenId={screenId}
181
+ screenData={screenData}
182
+ groupId={route}
183
+ />
184
+ ) : null}
176
185
  </View>
177
186
  </FreezeWithCallback>
178
187
  );
@@ -0,0 +1,34 @@
1
+ import * as React from "react";
2
+ import { Animated, StyleSheet } from "react-native";
3
+
4
+ import { BackgroundImage } from "@applicaster/zapp-react-native-ui-components/Components/BackgroundImage";
5
+
6
+ const styles = StyleSheet.create({
7
+ container: {
8
+ ...StyleSheet.absoluteFillObject,
9
+ position: "absolute",
10
+ },
11
+ });
12
+
13
+ export const Overlay = ({
14
+ opacity,
15
+ backgroundColor,
16
+ }: {
17
+ opacity: Animated.Value;
18
+ backgroundColor: string;
19
+ }) => {
20
+ return (
21
+ <Animated.View
22
+ style={[
23
+ styles.container,
24
+ {
25
+ opacity,
26
+ backgroundColor,
27
+ },
28
+ ]}
29
+ testID="animated-component"
30
+ >
31
+ <BackgroundImage />
32
+ </Animated.View>
33
+ );
34
+ };
@@ -0,0 +1,88 @@
1
+ import React from "react";
2
+ import { Animated } from "react-native";
3
+ import { render } from "@testing-library/react-native";
4
+
5
+ jest.mock(
6
+ "@applicaster/zapp-react-native-ui-components/Components/BackgroundImage",
7
+ () => {
8
+ const { Text } = require("react-native");
9
+
10
+ return {
11
+ BackgroundImage: () => (
12
+ <Text testID="background-image">BackgroundImage</Text>
13
+ ),
14
+ };
15
+ }
16
+ );
17
+
18
+ import { Overlay } from "../Overlay";
19
+
20
+ const flattenStyle = (style: unknown): Record<string, unknown> => {
21
+ if (!style) {
22
+ return {};
23
+ }
24
+
25
+ if (Array.isArray(style)) {
26
+ return style.reduce<Record<string, unknown>>(
27
+ (acc, item) => ({ ...acc, ...flattenStyle(item) }),
28
+ {}
29
+ );
30
+ }
31
+
32
+ if (typeof style === "object") {
33
+ return style as Record<string, unknown>;
34
+ }
35
+
36
+ return {};
37
+ };
38
+
39
+ describe("Overlay", () => {
40
+ it("renders the animated overlay container", () => {
41
+ const opacity = new Animated.Value(1);
42
+
43
+ const { getByTestId } = render(
44
+ <Overlay opacity={opacity} backgroundColor="#000000" />
45
+ );
46
+
47
+ expect(getByTestId("animated-component")).toBeTruthy();
48
+ });
49
+
50
+ it("applies opacity and backgroundColor to the overlay", () => {
51
+ const opacity = new Animated.Value(0.5);
52
+
53
+ const { getByTestId } = render(
54
+ <Overlay opacity={opacity} backgroundColor="#ff0000" />
55
+ );
56
+
57
+ const style = flattenStyle(getByTestId("animated-component").props.style);
58
+
59
+ expect(style.backgroundColor).toBe("#ff0000");
60
+ expect(style.opacity).toBe(0.5);
61
+ });
62
+
63
+ it("positions the overlay with absolute fill layout", () => {
64
+ const opacity = new Animated.Value(1);
65
+
66
+ const { getByTestId } = render(
67
+ <Overlay opacity={opacity} backgroundColor="#000000" />
68
+ );
69
+
70
+ const style = flattenStyle(getByTestId("animated-component").props.style);
71
+
72
+ expect(style.position).toBe("absolute");
73
+ expect(style.top).toBe(0);
74
+ expect(style.left).toBe(0);
75
+ expect(style.right).toBe(0);
76
+ expect(style.bottom).toBe(0);
77
+ });
78
+
79
+ it("renders BackgroundImage inside the overlay", () => {
80
+ const opacity = new Animated.Value(1);
81
+
82
+ const { getByTestId } = render(
83
+ <Overlay opacity={opacity} backgroundColor="#000000" />
84
+ );
85
+
86
+ expect(getByTestId("background-image")).toBeTruthy();
87
+ });
88
+ });
@@ -1,8 +1,10 @@
1
1
  import * as React from "react";
2
- import { Animated, StyleSheet } from "react-native";
2
+ import { Animated } from "react-native";
3
+
3
4
  import { isFirstComponentScreenPicker } from "@applicaster/zapp-react-native-utils/componentsUtils";
4
5
  import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
5
6
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
7
+ import { Overlay } from "./Overlay";
6
8
 
7
9
  import { ScreenRevealManager } from "./ScreenRevealManager";
8
10
  import {
@@ -10,13 +12,6 @@ import {
10
12
  emitScreenRevealManagerIsNotReadyToShow,
11
13
  } from "./utils";
12
14
 
13
- const styles = StyleSheet.create({
14
- container: {
15
- ...StyleSheet.absoluteFillObject,
16
- position: "absolute",
17
- },
18
- });
19
-
20
15
  export const TIMEOUT = 300; // 300 ms
21
16
 
22
17
  const HIDDEN = 0; // opacity = 0
@@ -93,17 +88,11 @@ export const withScreenRevealManager = (Component) => {
93
88
  onLoadFailedFromScreenRevealManager={managerRef.current.onLoadFailed}
94
89
  />
95
90
  {isShowOverlay ? (
96
- <Animated.View
97
- style={[
98
- styles.container,
99
- {
100
- opacity: opacityRef.current,
101
- // TODO: we should support background image as well, but for now we will use background color from theme
102
- backgroundColor:
103
- props.backgroundColor ?? theme.app_background_color,
104
- },
105
- ]}
106
- testID="animated-component"
91
+ <Overlay
92
+ opacity={opacityRef.current}
93
+ backgroundColor={
94
+ props.backgroundColor ?? theme.app_background_color
95
+ }
107
96
  />
108
97
  ) : null}
109
98
  </>