@applicaster/quick-brick-core 13.0.0-rc.12 → 13.0.0-rc.120

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 (49) hide show
  1. package/App/ActionsProvider/__tests__/__snapshots__/ActionsProvider.test.js.snap +7 -7
  2. package/App/AssetCache/__tests__/__snapshots__/assetCache.test.ts.snap +103 -103
  3. package/App/AssetCache/__tests__/assetCache.test.ts +3 -2
  4. package/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/__tests__/__snapshots__/schemeHandlerHooks.test.ts.snap +1 -1
  5. package/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/__tests__/useOpenSchemeHandler.test.tsx +45 -116
  6. package/App/DeepLinking/URLSchemeHandler/__tests__/__snapshots__/URLSchemeHandler.test.tsx.snap +3 -3
  7. package/App/DeepLinking/URLSchemeListener/URLSchemeContextProvider.tsx +30 -3
  8. package/App/DeepLinking/URLSchemeListener/__tests__/URLSchemeListener.test.js +40 -0
  9. package/App/DeepLinking/URLSchemeListener/index.tsx +1 -1
  10. package/App/ErrorBoundary/__tests__/errorBoundary.test.jsx +232 -0
  11. package/App/ErrorBoundary/__tests__/store.test.js +143 -0
  12. package/App/ErrorBoundary/index.tsx +45 -21
  13. package/App/ErrorBoundary/store.ts +26 -0
  14. package/App/LoadingOverlay/LoadingOverlayManager.tsx +27 -0
  15. package/App/LoadingOverlay/index.tsx +49 -0
  16. package/App/LoadingOverlay/useLoadingOverlayVisibility.tsx +18 -0
  17. package/App/ModalProvider/ModalBottomSheet/DraggableBottomSheet/index.tsx +0 -1
  18. package/App/ModalProvider/ModalBottomSheet/ModalBottomSheetFrame.tsx +68 -10
  19. package/App/ModalProvider/ModalBottomSheet/Overlay.tsx +5 -7
  20. package/App/ModalProvider/ModalBottomSheet/index.tsx +18 -46
  21. package/App/ModalProvider/ModalPresenter.tsx +1 -1
  22. package/App/ModalProvider/index.tsx +6 -3
  23. package/App/NavigationProvider/NavigationProvider.tsx +77 -63
  24. package/App/NavigationProvider/__tests__/navigationProvider.test.tsx +0 -44
  25. package/App/NavigationProvider/navigator/__tests__/__snapshots__/reducer.test.ts.snap +189 -189
  26. package/App/NetworkStatusProvider/utils.ts +0 -1
  27. package/App/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +2 -2
  28. package/App/StoreConnector/__tests__/storeConnector.test.js +17 -11
  29. package/App/appLifeCycleManager/__tests__/appLifeCycleManager.test.tsx +146 -0
  30. package/App/appLifeCycleManager/index.tsx +6 -7
  31. package/App/index.tsx +6 -3
  32. package/App/remoteContextReloader/__tests__/remoteContextReloader.test.js +11 -21
  33. package/App/remoteContextReloader/consts.ts +2 -0
  34. package/App/remoteContextReloader/getRemoteContextData/getNativeRemoteContextData.ts +31 -6
  35. package/createZappApp/__tests__/__snapshots__/createZappApp.test.js.snap +5 -128
  36. package/createZappApp/__tests__/createZappApp.test.js +7 -20
  37. package/defaults/__tests__/defaults.test.js +3 -4
  38. package/index.d.ts +1 -1
  39. package/package.json +26 -14
  40. package/App/DeepLinking/URLSchemeListener/__tests__/URLSchemeListenerTest.js +0 -177
  41. package/App/ErrorBoundary/__tests__/__snapshots__/errorBoundary.test.js.snap +0 -9
  42. package/App/ErrorBoundary/__tests__/errorBoundary.test.js +0 -72
  43. package/App/ModalProvider/ModalChildrenWrapper/index.web.ts +0 -1
  44. package/App/NavigationProvider/__tests__/__snapshots__/navigationProvider.test.tsx.snap +0 -70
  45. package/App/StoreConnector/__tests__/__snapshots__/storeConnector.test.js.snap +0 -35
  46. package/App/appLifeCycleManager/__tests__/__snapshots__/appLifeCycleManager.test.js.snap +0 -30
  47. package/App/appLifeCycleManager/__tests__/appLifeCycleManager.test.js +0 -134
  48. package/App/remoteContextReloader/__tests__/__snapshots__/remoteContextReloader.test.js.snap +0 -43
  49. /package/App/ModalProvider/ModalChildrenWrapper/{index.ios.ts → index.ts} +0 -0
@@ -1,21 +1,32 @@
1
1
  import React from "react";
2
- import { StyleSheet, View } from "react-native";
2
+ import { LayoutChangeEvent, StyleSheet, View } from "react-native";
3
3
 
4
4
  import { Handle, HandleProps } from "./Handle";
5
5
  import { DraggableBottomSheet } from "./DraggableBottomSheet";
6
+ import {
7
+ SafeAreaView,
8
+ useSafeAreaInsets,
9
+ } from "react-native-safe-area-context";
10
+ import {
11
+ isAndroidPlatform,
12
+ isAndroidVersionAtLeast,
13
+ platformSelect,
14
+ } from "@applicaster/zapp-react-native-utils/reactUtils";
6
15
 
7
16
  type Props = {
8
17
  children: React.ReactChild;
9
18
  backgroundColor: string;
10
19
  cornerRadius: number;
11
- contentHeight: number;
12
20
  maxHeight: number;
13
21
  maxWidth: number;
14
22
  visible: boolean;
15
23
  handleProps: HandleProps;
16
24
  closeToast: () => void;
17
- dimensions: { width: number; height: number };
18
- paddingBottom: number;
25
+ dimensions: {
26
+ statusBarHeight: any;
27
+ width: number;
28
+ height: number;
29
+ };
19
30
  };
20
31
 
21
32
  const styles = StyleSheet.create({
@@ -25,6 +36,34 @@ const styles = StyleSheet.create({
25
36
  },
26
37
  });
27
38
 
39
+ const defaultBottomOffset = platformSelect({
40
+ ios: 34,
41
+ android: 0,
42
+ });
43
+
44
+ const getSheetHeight = ({ height, bottomOffset, maxHeight, dimensions }) => {
45
+ return platformSelect({
46
+ ios: height - bottomOffset,
47
+ default:
48
+ !isAndroidVersionAtLeast(35) && isAndroidPlatform()
49
+ ? (height || maxHeight) - (bottomOffset + dimensions.statusBarHeight)
50
+ : height || maxHeight,
51
+ });
52
+ };
53
+
54
+ const useGetSheetHeight = (height, maxHeight, dimensions) => {
55
+ const { bottom = defaultBottomOffset } = useSafeAreaInsets();
56
+
57
+ const bottomOffset = bottom;
58
+
59
+ return getSheetHeight({
60
+ height,
61
+ bottomOffset,
62
+ maxHeight,
63
+ dimensions,
64
+ });
65
+ };
66
+
28
67
  export function ModalBottomSheetFrame(props: Props) {
29
68
  const {
30
69
  children,
@@ -34,9 +73,7 @@ export function ModalBottomSheetFrame(props: Props) {
34
73
  maxWidth,
35
74
  visible,
36
75
  handleProps,
37
- contentHeight,
38
76
  dimensions,
39
- paddingBottom,
40
77
  } = props;
41
78
 
42
79
  const extraStyles = {
@@ -44,21 +81,42 @@ export function ModalBottomSheetFrame(props: Props) {
44
81
  borderTopLeftRadius: cornerRadius,
45
82
  borderTopRightRadius: cornerRadius,
46
83
  maxHeight,
47
- paddingBottom,
48
84
  maxWidth: Math.min(Number(maxWidth), dimensions.width),
49
85
  };
50
86
 
87
+ const [height, setHeight] = React.useState(0);
88
+
89
+ const onLayout = (event: LayoutChangeEvent) => {
90
+ const { height } = event.nativeEvent.layout;
91
+
92
+ if (height !== 0) {
93
+ setHeight((oldHeight) => oldHeight || height);
94
+ }
95
+ };
96
+
97
+ const { bottom = defaultBottomOffset } = useSafeAreaInsets();
98
+
99
+ const bottomOffset = bottom;
100
+
101
+ const sheetHeight = useGetSheetHeight(height, maxHeight, dimensions);
102
+
51
103
  return (
52
104
  <DraggableBottomSheet
53
- sheetHeight={contentHeight}
54
- visible={visible}
105
+ sheetHeight={sheetHeight}
106
+ visible={height > 0 && visible}
55
107
  dismiss={props.closeToast}
56
108
  hasHeader={handleProps.enabled}
57
109
  header={(dragging) => <Handle {...handleProps} focused={dragging} />}
58
110
  maxWidth={maxWidth}
59
111
  {...dimensions}
112
+ height={dimensions.height - bottomOffset}
60
113
  >
61
- <View style={[styles.toastFrameContainer, extraStyles]}>{children}</View>
114
+ <SafeAreaView
115
+ edges={["left", "right", "bottom"]}
116
+ style={[styles.toastFrameContainer, extraStyles]}
117
+ >
118
+ <View onLayout={onLayout}>{children}</View>
119
+ </SafeAreaView>
62
120
  </DraggableBottomSheet>
63
121
  );
64
122
  }
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { StyleSheet, TouchableOpacity, Easing, View } from "react-native";
3
3
 
4
4
  import { AnimatedInOut } from "@applicaster/zapp-react-native-ui-components/Components/AnimatedInOut";
5
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
5
+ import { dismissModal } from "@applicaster/zapp-react-native-utils/modalState";
6
6
 
7
7
  type Props = {
8
8
  overlayColor: string;
@@ -35,21 +35,19 @@ const fadeInAnimation = {
35
35
  delay,
36
36
  };
37
37
 
38
- const animationConfig = (onAnimationEnd) => ({
38
+ const animationConfig = {
39
39
  in: fadeInAnimation,
40
40
  out: {
41
41
  ...fadeInAnimation,
42
- onAnimationEnd,
42
+ onAnimationEnd: dismissModal,
43
43
  },
44
- });
44
+ };
45
45
 
46
46
  export function Overlay(props: Props) {
47
- const navigator = useNavigation();
48
-
49
47
  return (
50
48
  <AnimatedInOut
51
49
  visible={props.visible}
52
- animationConfig={animationConfig(navigator.closeModalBottomSheet)}
50
+ animationConfig={animationConfig}
53
51
  staticStyles={styles.container}
54
52
  >
55
53
  <TouchableOpacity
@@ -1,10 +1,8 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
3
- import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
4
- import { useSafeAreaInsets } from "react-native-safe-area-context";
5
3
 
6
- import React, { useCallback, useEffect, useMemo, useState } from "react";
7
- import { View, StyleSheet, Keyboard } from "react-native";
4
+ import React, { useCallback, useEffect, useState } from "react";
5
+ import { Keyboard, StyleSheet, View } from "react-native";
8
6
 
9
7
  import { Overlay } from "./Overlay";
10
8
  import { ModalBottomSheetFrame } from "./ModalBottomSheetFrame";
@@ -29,59 +27,38 @@ type Props = {
29
27
  modalBottomSheetContentProps: Record<string, any>;
30
28
  };
31
29
 
32
- const defaultBottomOffset = platformSelect({
33
- ios: 34,
34
- android: 0,
35
- });
36
-
37
30
  export function ModalBottomSheet(props: Props) {
38
31
  const theme = useTheme<BaseThemePropertiesMobile>();
39
32
  const navigator = useNavigation();
40
33
  const dimensions = useDimensions();
41
- const [sheetHeight, setSheetHeight] = useState(0);
42
34
  const [visible, setVisible] = useState(true);
43
- const dismiss = () => setVisible(false);
44
- const { bottom = defaultBottomOffset } = useSafeAreaInsets();
45
-
46
- const bottomOffset = bottom + dimensions.statusBarHeight;
47
35
 
48
36
  const {
49
37
  modal_bottom_sheet_background_color: sheetBackgroundColor,
50
38
  modal_bottom_sheet_overlay_color: sheetOverlayColor,
51
39
  modal_bottom_sheet_top_corner_radius: sheetCornerRadius,
52
- modal_bottom_sheet_max_height: sheetMaxHeight,
53
40
  modal_bottom_sheet_handle: sheetHandleEnabled,
54
41
  modal_bottom_sheet_handle_color: sheetHandleColor,
55
42
  modal_bottom_sheet_handle_focus_color: sheetHandleFocusedColor,
56
43
  modal_bottom_sheet_tablet_max_width: sheetTabletMaxWidth,
57
44
  } = theme;
58
45
 
46
+ const sheetMaxHeight = dimensions.height * 0.75; // Set a default max height
47
+
59
48
  const {
60
49
  ModalBottomSheetContent = ModalComponent,
61
50
  modalBottomSheetContentProps,
62
51
  } = props;
63
52
 
64
- const onLayout = useCallback(({ nativeEvent }) => {
65
- const calculatedHeight = nativeEvent?.layout?.height;
66
-
67
- if (calculatedHeight > 0 && sheetHeight === 0) {
68
- setSheetHeight(Math.min(calculatedHeight, sheetMaxHeight));
69
- }
70
- }, []);
71
-
72
53
  useEffect(() => {
73
54
  Keyboard.dismiss();
74
55
  }, []);
75
56
 
57
+ const dismiss = useCallback(() => setVisible(false), []);
58
+
76
59
  const isTablet = useIsTablet();
77
60
 
78
- const maxWidth = useMemo(
79
- () =>
80
- isTablet
81
- ? Math.max(sheetTabletMaxWidth, dimensions.width)
82
- : dimensions.width,
83
- [isTablet]
84
- );
61
+ const maxWidth = isTablet ? sheetTabletMaxWidth : dimensions.width;
85
62
 
86
63
  return (
87
64
  <View style={styles.container}>
@@ -93,12 +70,10 @@ export function ModalBottomSheet(props: Props) {
93
70
  <ModalBottomSheetFrame
94
71
  backgroundColor={sheetBackgroundColor}
95
72
  cornerRadius={sheetCornerRadius}
96
- contentHeight={sheetHeight + bottomOffset}
97
- maxHeight={sheetMaxHeight + bottomOffset}
98
- paddingBottom={bottomOffset}
73
+ maxHeight={sheetMaxHeight}
99
74
  maxWidth={maxWidth}
100
75
  dimensions={dimensions}
101
- visible={visible && sheetHeight > 0}
76
+ visible={visible}
102
77
  closeToast={dismiss}
103
78
  handleProps={{
104
79
  enabled: sheetHandleEnabled,
@@ -106,18 +81,15 @@ export function ModalBottomSheet(props: Props) {
106
81
  focusedColor: sheetHandleFocusedColor,
107
82
  }}
108
83
  >
109
- <View onLayout={onLayout}>
110
- <ModalBottomSheetContent
111
- width={
112
- Math.min(sheetTabletMaxWidth, dimensions.width) ||
113
- dimensions.width
114
- }
115
- maxHeight={sheetMaxHeight}
116
- {...modalBottomSheetContentProps}
117
- dismiss={dismiss}
118
- currentRoute={navigator.currentRoute}
119
- />
120
- </View>
84
+ <ModalBottomSheetContent
85
+ width={
86
+ Math.min(sheetTabletMaxWidth, dimensions.width) || dimensions.width
87
+ }
88
+ maxHeight={sheetMaxHeight}
89
+ {...modalBottomSheetContentProps}
90
+ dismiss={dismiss}
91
+ currentRoute={navigator.currentRoute}
92
+ />
121
93
  </ModalBottomSheetFrame>
122
94
  </View>
123
95
  );
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Modal, ModalProps } from "react-native";
3
3
 
4
- type Props = {
4
+ type Props = ModalProps & {
5
5
  children: React.ReactChild;
6
6
  ModalContainer?: React.FC<ModalProps> | React.ComponentClass<ModalProps>;
7
7
  visible: boolean;
@@ -6,10 +6,10 @@ import { ModalChildrenWrapper } from "./ModalChildrenWrapper";
6
6
  import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
7
7
  import { ScreenContextProvider } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenContext";
8
8
  import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
9
- import { useModalStore } from "@applicaster/zapp-react-native-utils/modalState";
9
+ import { useModalStoreState } from "@applicaster/zapp-react-native-utils/modalState";
10
10
 
11
11
  export function ModalProvider() {
12
- const { modalState } = useModalStore();
12
+ const modalState = useModalStoreState();
13
13
 
14
14
  const [modalVisible, setModalVisible] = React.useState(false);
15
15
  const [modalShown, setModalShown] = React.useState(false);
@@ -35,12 +35,15 @@ export function ModalProvider() {
35
35
 
36
36
  const pathname = `${ROUTE_TYPES.MODAL}/${modalScreenProps?.screenId}`;
37
37
 
38
+ const shouldShowModal = modalVisible && modalState?.visible;
39
+
38
40
  return (
39
41
  <PathnameContext.Provider value={pathname}>
40
42
  <ScreenContextProvider pathname={pathname}>
41
43
  <ModalPresenter
42
- visible={modalVisible && modalState?.visible}
44
+ visible={shouldShowModal}
43
45
  {...modalState?.options}
46
+ statusBarTranslucent
44
47
  >
45
48
  <ModalChildrenWrapper>
46
49
  <ModalContent modalScreenProps={modalScreenProps} />
@@ -49,6 +49,7 @@ import { coreAppLogger } from "../logger";
49
49
  import {
50
50
  getPlatform,
51
51
  isTV,
52
+ isVizioPlatform,
52
53
  } from "@applicaster/zapp-react-native-utils/reactUtils";
53
54
  import { useConnectionInfo } from "@applicaster/zapp-react-native-utils/reactHooks/connection";
54
55
  import {
@@ -57,15 +58,26 @@ import {
57
58
  legacyScreenData,
58
59
  openExternalUrl,
59
60
  } from "./utils";
60
- import { debounce } from "@applicaster/zapp-react-native-utils/functionUtils";
61
+ import {
62
+ debounce,
63
+ getJsonReplacer,
64
+ } from "@applicaster/zapp-react-native-utils/functionUtils";
61
65
 
62
66
  import { findParent } from "@applicaster/zapp-react-native-ui-components/Contexts/ZappPipesContext/ZappPipesEntryContext";
63
67
  import { ZappPipesEntryContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
64
68
  import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
65
69
  import { inflateUrl } from "@applicaster/zapp-react-native-ui-components/Components/LinkHandler/LinkHandler";
66
- import { useModalStore } from "@applicaster/zapp-react-native-utils/modalState";
70
+ import {
71
+ dismissModal,
72
+ modalStore,
73
+ openModal,
74
+ } from "@applicaster/zapp-react-native-utils/modalState";
67
75
  import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
68
76
  import { QBUIComponentEvents } from "@applicaster/zapp-react-native-ui-components/events";
77
+ import { Hook } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager/Hook";
78
+ import { URLSchemeContext } from "../DeepLinking/URLSchemeListener/URLSchemeContextProvider";
79
+
80
+ import { loadingOverlayManager } from "../LoadingOverlay";
69
81
 
70
82
  const logger = coreAppLogger.addSubsystem("Navigator");
71
83
 
@@ -75,17 +87,6 @@ type Props = {
75
87
  plugins?: QuickBrickPlugin[];
76
88
  };
77
89
 
78
- type EntryWithParent = ZappEntry & { parent?: EntryWithParent };
79
-
80
- type SingleEntry = {
81
- data: EntryWithParent;
82
- route: string;
83
- id: string;
84
- parentId?: string;
85
- };
86
-
87
- type EntryContextType = { [K in string]: SingleEntry };
88
-
89
90
  const navigationActions = {
90
91
  [ACTIONS.PUSH]: push,
91
92
  [ACTIONS.REPLACE]: replace,
@@ -96,6 +97,8 @@ const navigationActions = {
96
97
  const platform = getPlatform();
97
98
 
98
99
  export function NavigationProvider({ children }: Props) {
100
+ const { url: deepLinkURL } = React.useContext(URLSchemeContext);
101
+
99
102
  const {
100
103
  appData: { layoutVersion },
101
104
  rivers,
@@ -122,11 +125,7 @@ export function NavigationProvider({ children }: Props) {
122
125
  const pathname = state?.location?.pathname;
123
126
  const pathnameRef = React.useRef(pathname);
124
127
 
125
- const { context }: EntryContextType = React.useContext(
126
- ZappPipesEntryContext.Context
127
- );
128
-
129
- const { openModal, dismissModal } = useModalStore();
128
+ const { context } = React.useContext(ZappPipesEntryContext.Context);
130
129
 
131
130
  const playNextOverlayState = React.useRef();
132
131
 
@@ -153,7 +152,7 @@ export function NavigationProvider({ children }: Props) {
153
152
  );
154
153
 
155
154
  const getModalState: () => ModalState = () => {
156
- const { modalState } = useModalStore.getState();
155
+ const { modalState } = modalStore.getState();
157
156
 
158
157
  return modalState;
159
158
  };
@@ -380,13 +379,24 @@ export function NavigationProvider({ children }: Props) {
380
379
  }
381
380
  };
382
381
 
383
- const handleHookPresent = ({ hookPlugin, route, payload }, dispose) => {
382
+ const handleHookPresent = (
383
+ {
384
+ hookPlugin,
385
+ route,
386
+ payload,
387
+ }: {
388
+ hookPlugin: Hook;
389
+ route: string;
390
+ payload: object;
391
+ },
392
+ dispose
393
+ ) => {
384
394
  if (hookPlugin?.lastHook) {
385
395
  dispose();
386
396
  }
387
397
 
388
398
  if (hookPlugin.isModalHook()) {
389
- navigator.openModal({
399
+ openModal({
390
400
  item: payload,
391
401
  props: { screenType: "hooks" },
392
402
  options: { ModalContainer: hookPlugin.getModalContainer() },
@@ -394,6 +404,8 @@ export function NavigationProvider({ children }: Props) {
394
404
  } else {
395
405
  dispatch(push(route, { entry: payload, screen: hookPlugin }));
396
406
  }
407
+
408
+ closeLoadingOverlay();
397
409
  };
398
410
 
399
411
  const handleHookError = ({ error, hookPlugin, callback }, dispose) => {
@@ -404,7 +416,7 @@ export function NavigationProvider({ children }: Props) {
404
416
  }
405
417
 
406
418
  if (hookPlugin.isModalHook()) {
407
- navigator.dismissModal();
419
+ dismissModal();
408
420
  } else {
409
421
  goBack(true, true);
410
422
  }
@@ -412,9 +424,11 @@ export function NavigationProvider({ children }: Props) {
412
424
  if (callback && typeof callback === "function") {
413
425
  callback();
414
426
  }
427
+
428
+ closeLoadingOverlay();
415
429
  };
416
430
 
417
- const handleHookCancel = ({ hookPlugin, callback }, dispose) => {
431
+ const handleHookCancel = ({ hookPlugin, callback, abort }, dispose) => {
418
432
  dispose();
419
433
  setStartUpHooks(false);
420
434
 
@@ -422,21 +436,29 @@ export function NavigationProvider({ children }: Props) {
422
436
  callback();
423
437
  }
424
438
 
425
- if (hookPlugin.isModalHook()) {
426
- navigator.dismissModal();
427
- } else {
428
- goBack(true, true);
439
+ if (!abort) {
440
+ if (hookPlugin.isModalHook()) {
441
+ dismissModal();
442
+ } else {
443
+ goBack(true, true);
444
+ }
429
445
  }
446
+
447
+ closeLoadingOverlay();
430
448
  };
431
449
 
432
450
  const handleHookSuccess = ({ hookPlugin, callback }) => {
433
451
  callback?.();
434
452
 
435
453
  if (hookPlugin.isModalHook()) {
436
- navigator.dismissModal();
454
+ dismissModal();
437
455
  }
438
456
  };
439
457
 
458
+ const handleBackgroundHook = () => {
459
+ openLoadingOverlay();
460
+ };
461
+
440
462
  const checkStartUpHooks = React.useMemo(() => {
441
463
  if (!pluginConfigurations) return false;
442
464
 
@@ -498,8 +520,7 @@ export function NavigationProvider({ children }: Props) {
498
520
  ({ hookPlugin, payload, callback }, dispose) => {
499
521
  if (hookPlugin?.lastHook) {
500
522
  dispose({ disposeAll: true });
501
-
502
- startUpHooks.current && setStartUpHooks(false);
523
+ currentStartUpHooks.current && setStartUpHooks(false);
503
524
  }
504
525
 
505
526
  dispatch(
@@ -507,6 +528,8 @@ export function NavigationProvider({ children }: Props) {
507
528
  );
508
529
 
509
530
  callback?.();
531
+
532
+ closeLoadingOverlay();
510
533
  };
511
534
 
512
535
  const offlinePlugin = React.useMemo(() => {
@@ -614,25 +637,37 @@ export function NavigationProvider({ children }: Props) {
614
637
  },
615
638
  };
616
639
 
617
- HooksManager(hooksOptions)
640
+ const hooksManager = HooksManager(hooksOptions);
641
+
642
+ hooksManager.subscriber
618
643
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, handleHookPresent)
619
644
  .on(HOOKS_EVENTS.ERROR, handleHookError)
620
645
  .on(HOOKS_EVENTS.CANCEL, handleHookCancel)
621
646
  .on(HOOKS_EVENTS.SUCCESS, handleHookSuccess)
647
+ .on(HOOKS_EVENTS.START_BACKGROUND_HOOK, handleBackgroundHook)
622
648
  .on(
623
649
  HOOKS_EVENTS.COMPLETE,
624
650
  handleHookComplete(navigationAction, targetRoute, {
625
651
  screen,
626
652
  options,
627
653
  })
628
- )
629
- .handleHooks(legacyScreenData({ entry, screen }));
654
+ );
655
+
656
+ hooksManager.handleHooks(legacyScreenData({ entry, screen }));
630
657
  } else {
631
658
  dispatch(navigationAction(targetRoute, { screen, entry, options }));
632
659
  }
633
660
  },
634
661
  });
635
662
 
663
+ const openLoadingOverlay = React.useCallback(() => {
664
+ deepLinkURL && isVizioPlatform() && loadingOverlayManager.show();
665
+ }, [deepLinkURL]);
666
+
667
+ const closeLoadingOverlay = React.useCallback(() => {
668
+ loadingOverlayManager.hide();
669
+ }, []);
670
+
636
671
  const openPiP = React.useCallback(() => {
637
672
  dispatch(setVideoPiP());
638
673
  }, []);
@@ -653,33 +688,6 @@ export function NavigationProvider({ children }: Props) {
653
688
  }
654
689
  }, [state?.options?.videoModal?.previousMode]);
655
690
 
656
- const openModalBottomSheet = React.useCallback(
657
- ({
658
- ModalBottomSheetContent,
659
- modalBottomSheetContentProps,
660
- props = {},
661
- options = {},
662
- }) => {
663
- openModal({
664
- item: {
665
- ModalBottomSheetContent,
666
- modalBottomSheetContentProps,
667
- },
668
- props,
669
- options: {
670
- animationType: "none",
671
- animated: false,
672
- ...options,
673
- },
674
- });
675
- },
676
- [openModal]
677
- );
678
-
679
- const closeModalBottomSheet = React.useCallback(() => {
680
- dismissModal();
681
- }, [dismissModal]);
682
-
683
691
  const getNestedEntry = () => state?.location?.state?.nested?.entry ?? null;
684
692
 
685
693
  // It will only work for the regular stack and pathname, It won't work for modals
@@ -720,8 +728,6 @@ export function NavigationProvider({ children }: Props) {
720
728
  openModal,
721
729
  dismissModal,
722
730
  getModalState,
723
- openModalBottomSheet,
724
- closeModalBottomSheet,
725
731
  videoModalState: state.options.videoModal,
726
732
  openVideoModal,
727
733
  closeVideoModal,
@@ -738,7 +744,15 @@ export function NavigationProvider({ children }: Props) {
738
744
  getStackForPathname,
739
745
  mainStack: state.stack.mainStack,
740
746
  }),
741
- [rivers, plugins, JSON.stringify(state), appLaunched, startUpHooks]
747
+ [
748
+ rivers,
749
+ plugins,
750
+ // TODO: Compare entire screen data from state must be removed
751
+ // State size could be large ~150kb and take 80ms on android tv on 8 rails
752
+ JSON.stringify(state, getJsonReplacer()),
753
+ appLaunched,
754
+ startUpHooks,
755
+ ]
742
756
  );
743
757
 
744
758
  // when running the tests, we pass the dispatch function
@@ -461,48 +461,4 @@ describe("<NavigationProvider />", () => {
461
461
  });
462
462
  });
463
463
  });
464
-
465
- describe("modal feature", () => {
466
- it("sets the modalState when opening a modal", () => {
467
- act(() => {
468
- wrapper = renderContextConsumer();
469
- });
470
-
471
- const view = getByTestId(wrapper, "WrapperView");
472
- act(() => view.props.navigator.openModal({ item: rivers.A1234 }));
473
- expect(view.props.navigator.get).toMatchSnapshot();
474
- });
475
-
476
- it("removes the visible flag when dismissing a modal", () => {
477
- act(() => {
478
- wrapper = renderContextConsumer();
479
- });
480
-
481
- const view = getByTestId(wrapper, "WrapperView");
482
- act(() => view.props.navigator.openModal({ item: rivers.A1234 }));
483
- expect(view.props.navigator.getModalState()).toMatchSnapshot();
484
- act(() => view.props.navigator.dismissModal());
485
- expect(view.props.navigator.getModalState().visible).toBeFalsy();
486
- expect(view.props.navigator.getModalState()).toMatchSnapshot();
487
- });
488
-
489
- it("should reset state to initial when dismissing a modal ( closeModalBottomSheet ) opened by openModalBottomSheet", () => {
490
- act(() => {
491
- wrapper = renderContextConsumer();
492
- });
493
-
494
- const view = getByTestId(wrapper, "WrapperView");
495
-
496
- act(() =>
497
- view.props.navigator.openModalBottomSheet({
498
- ModalBottomSheetContent: rivers.A1234,
499
- modalBottomSheetContentProps: { some: "props" },
500
- })
501
- );
502
-
503
- expect(view.props.navigator.getModalState()).toMatchSnapshot();
504
- act(() => view.props.navigator.closeModalBottomSheet());
505
- expect(view.props.navigator.getModalState()).toMatchSnapshot();
506
- });
507
- });
508
464
  });