From a42a9f37822936dd4c45c45a7cb7474e58463f7e Mon Sep 17 00:00:00 2001 From: kwoktung Date: Wed, 2 Aug 2023 09:08:59 +0800 Subject: [PATCH] fix: lazy render app lock when the portal is not found (#3340) * Revert "fix: portal container init (#3335)" This reverts commit 358fb2a961d03ceb76a46880b00af80345cdba49. * fix: lazy render app lock when the portal is not found --- .../NavigationBar/MobileBottomTabBar.tsx | 6 +- .../components/src/OverlayContainer/index.tsx | 4 +- .../src/Select/Container/Mobile.tsx | 4 +- packages/ext/src/ui/uiJsBridge.ts | 2 +- .../kit/src/components/AppLock/AppLock.tsx | 20 ++++- packages/kit/src/provider/AppLoading.tsx | 6 +- .../kit/src/provider/NavigationProvider.tsx | 4 +- packages/kit/src/utils/overlayUtils.tsx | 35 ++++----- packages/kit/src/views/Developer/index.tsx | 2 +- .../Explorer/Mobile/ControllerBarMobile.tsx | 6 +- .../src/views/Market/ScreenMarketOrSwap.tsx | 11 +-- packages/kit/src/views/Overlay/RootPortal.tsx | 76 +++++++------------ 12 files changed, 81 insertions(+), 95 deletions(-) diff --git a/packages/components/src/Layout/NavigationBar/MobileBottomTabBar.tsx b/packages/components/src/Layout/NavigationBar/MobileBottomTabBar.tsx index 8998565444d..de451353194 100644 --- a/packages/components/src/Layout/NavigationBar/MobileBottomTabBar.tsx +++ b/packages/components/src/Layout/NavigationBar/MobileBottomTabBar.tsx @@ -19,7 +19,7 @@ import { swapAndMarketRoutes, } from '@onekeyhq/kit/src/routes/Root/Main/Tab/routes/tabRoutes.base'; import { TabRoutes } from '@onekeyhq/kit/src/routes/routesEnum'; -import { PortalContainer } from '@onekeyhq/kit/src/views/Overlay/RootPortal'; +import { PortalExit } from '@onekeyhq/kit/src/views/Overlay/RootPortal'; import platformEnv from '@onekeyhq/shared/src/platformEnv'; import Box from '../../Box'; @@ -206,8 +206,8 @@ export default function MobileBottomTabBar({ > {tabs} - diff --git a/packages/components/src/OverlayContainer/index.tsx b/packages/components/src/OverlayContainer/index.tsx index 606db9f8af8..5e2470ad7fc 100644 --- a/packages/components/src/OverlayContainer/index.tsx +++ b/packages/components/src/OverlayContainer/index.tsx @@ -3,7 +3,7 @@ import type { FC } from 'react'; import { StyleSheet, View } from 'react-native'; import { FULLWINDOW_OVERLAY_PORTAL } from '@onekeyhq/kit/src/utils/overlayUtils'; -import { PortalRender } from '@onekeyhq/kit/src/views/Overlay/RootPortal'; +import { PortalEntry } from '@onekeyhq/kit/src/views/Overlay/RootPortal'; import type { StyleProp, ViewStyle } from 'react-native'; @@ -20,7 +20,7 @@ const OverlayContainer: FC<{ /> ); return ( - {content} + {content} ); }; export default OverlayContainer; diff --git a/packages/components/src/Select/Container/Mobile.tsx b/packages/components/src/Select/Container/Mobile.tsx index c7785649770..8e4d524c114 100644 --- a/packages/components/src/Select/Container/Mobile.tsx +++ b/packages/components/src/Select/Container/Mobile.tsx @@ -4,7 +4,7 @@ import { Modalize } from 'react-native-modalize'; import { useSafeAreaInsets, useThemeValue } from '@onekeyhq/components'; import { FULLWINDOW_OVERLAY_PORTAL } from '@onekeyhq/kit/src/utils/overlayUtils'; -import { PortalRender } from '@onekeyhq/kit/src/views/Overlay/RootPortal'; +import { PortalEntry } from '@onekeyhq/kit/src/views/Overlay/RootPortal'; import Box from '../../Box'; import Button from '../../Button'; @@ -148,7 +148,7 @@ function Mobile({ ); return ( - {content} + {content} ); } diff --git a/packages/ext/src/ui/uiJsBridge.ts b/packages/ext/src/ui/uiJsBridge.ts index 21d4888ee64..6d056525a9a 100644 --- a/packages/ext/src/ui/uiJsBridge.ts +++ b/packages/ext/src/ui/uiJsBridge.ts @@ -14,7 +14,7 @@ import type { function init() { const jsBridgeReceiveHandler = (payload: IJsBridgeMessagePayload) => { - // console.log('jsBridgeReceiveHandler Ext-UI', payload); + console.log('jsBridgeReceiveHandler Ext-UI', payload); const { method, params } = payload.data as IJsonRpcRequest; if (method === DISPATCH_ACTION_BROADCAST_METHOD_NAME) { const { actions } = params as IDispatchActionBroadcastParams; diff --git a/packages/kit/src/components/AppLock/AppLock.tsx b/packages/kit/src/components/AppLock/AppLock.tsx index d22400e7bdc..2d8df428190 100644 --- a/packages/kit/src/components/AppLock/AppLock.tsx +++ b/packages/kit/src/components/AppLock/AppLock.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { useEffect, useMemo } from 'react'; +import { Fragment, useEffect, useMemo } from 'react'; import { Box, OverlayContainer } from '@onekeyhq/components'; import platformEnv from '@onekeyhq/shared/src/platformEnv'; @@ -8,6 +8,9 @@ import backgroundApiProxy from '../../background/instance/backgroundApiProxy'; import { useAppSelector, useDebounce } from '../../hooks'; import { unlockWhiteListUrls } from '../../routes/linking.path'; import { setAppRenderReady } from '../../store/reducers/data'; +import { FULLWINDOW_OVERLAY_PORTAL } from '../../utils/overlayUtils'; +import { isPortalExisted } from '../../views/Overlay/RootPortal'; +import { LazyDisplayView } from '../LazyDisplayView'; import { AppStateHeartbeat } from './AppStateHeartbeat'; import { AppStateUnlock } from './AppStateUnlock'; @@ -53,12 +56,21 @@ export const AppLockView: FC = ({ return ; } + const Parent = + !isPortalExisted(FULLWINDOW_OVERLAY_PORTAL) && + showUnlockView && + renderAsOverlay + ? LazyDisplayView + : Fragment; + return ( {showUnlockView && renderAsOverlay ? ( - - - + + + + + ) : null} {prerequisites && isUnlock ? : null} {isUnlock ? : null} diff --git a/packages/kit/src/provider/AppLoading.tsx b/packages/kit/src/provider/AppLoading.tsx index 903f37d5ed1..1071c613409 100644 --- a/packages/kit/src/provider/AppLoading.tsx +++ b/packages/kit/src/provider/AppLoading.tsx @@ -91,7 +91,7 @@ const AppLoading: FC = ({ children }) => { } useEffect(() => { - function main() { + async function main() { // TODO initApp too slow, maybe do not need waiting for initApp in UI // await Promise.all([ // serviceApp.waitForAppInited({ @@ -100,9 +100,9 @@ const AppLoading: FC = ({ children }) => { // ]); // redux ready check move to ThemeApp - // serviceApp.initApp(); - serviceApp.checkLockStatus(); + // serviceApp.initApp(); + await serviceApp.checkLockStatus(); setInitDataReady(true); // end splash screen to show AnimatedSplash after 50ms to avoid twinkling diff --git a/packages/kit/src/provider/NavigationProvider.tsx b/packages/kit/src/provider/NavigationProvider.tsx index 8bc81166d99..0728491fb31 100644 --- a/packages/kit/src/provider/NavigationProvider.tsx +++ b/packages/kit/src/provider/NavigationProvider.tsx @@ -25,7 +25,7 @@ import '../routes/deepLink'; import buildLinking from '../routes/linking'; import { createLazyComponent } from '../utils/createLazyComponent'; import { FULLWINDOW_OVERLAY_PORTAL } from '../utils/overlayUtils'; -import { PortalContainer } from '../views/Overlay/RootPortal'; +import { PortalExit } from '../views/Overlay/RootPortal'; import RedirectProvider from './RedirectProvider'; @@ -133,7 +133,7 @@ const NavigationApp = () => { - + ), [], diff --git a/packages/kit/src/utils/overlayUtils.tsx b/packages/kit/src/utils/overlayUtils.tsx index d3001550424..da791b46bc1 100644 --- a/packages/kit/src/utils/overlayUtils.tsx +++ b/packages/kit/src/utils/overlayUtils.tsx @@ -4,27 +4,26 @@ import { cloneElement } from 'react'; import { throttle } from 'lodash'; import { StyleSheet, View } from 'react-native'; -import { renderToPortal } from '../views/Overlay/RootPortal'; +import { enterPortal } from '../views/Overlay/RootPortal'; import type { PortalManager } from '../views/Overlay/RootPortal'; export const FULLWINDOW_OVERLAY_PORTAL = 'Root-FullWindowOverlay'; -type IOverlayContentRender = (closeOverlay: () => void) => ReactElement; export const showOverlay = throttle( - (renderOverlay: IOverlayContentRender) => { + (renderOverlay: (closeOverlay: () => void) => ReactElement) => { let portal: PortalManager | null; const closeOverlay = () => { portal?.destroy(); portal = null; }; + const content = ( + + {renderOverlay(closeOverlay)} + + ); setTimeout(() => { - const content = ( - - {renderOverlay(closeOverlay)} - - ); - portal = renderToPortal(FULLWINDOW_OVERLAY_PORTAL, content); + portal = enterPortal(FULLWINDOW_OVERLAY_PORTAL, content); }); return closeOverlay; }, @@ -36,14 +35,12 @@ export const showOverlay = throttle( ); export const showDialog = (render: ReactElement) => - showOverlay( - // - (closeOverlay) => - cloneElement(render, { - onClose: () => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - render.props.onClose?.(); - closeOverlay(); - }, - }), + showOverlay((onClose) => + cloneElement(render, { + onClose: () => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + render.props.onClose?.(); + onClose(); + }, + }), ); diff --git a/packages/kit/src/views/Developer/index.tsx b/packages/kit/src/views/Developer/index.tsx index 353130d6a75..aad71600db7 100644 --- a/packages/kit/src/views/Developer/index.tsx +++ b/packages/kit/src/views/Developer/index.tsx @@ -825,7 +825,7 @@ export const Debug = () => { }); }} > - Open Gas Panel000 + Open Gas Panel { ); return ( - + { {tabController} - + ); }; diff --git a/packages/kit/src/views/Market/ScreenMarketOrSwap.tsx b/packages/kit/src/views/Market/ScreenMarketOrSwap.tsx index b271953378a..a02bab51f87 100644 --- a/packages/kit/src/views/Market/ScreenMarketOrSwap.tsx +++ b/packages/kit/src/views/Market/ScreenMarketOrSwap.tsx @@ -10,7 +10,7 @@ import { import platformEnv from '@onekeyhq/shared/src/platformEnv'; import { TabRoutes } from '../../routes/routesEnum'; -import { PortalContainer, PortalRender } from '../Overlay/RootPortal'; +import { PortalEntry, PortalExit } from '../Overlay/RootPortal'; import Swap from '../Swap'; import MarketHeader from './Components/MarketList/MarketTopHeader'; @@ -32,9 +32,9 @@ export function ScreenMarketOrSwap({ useCallback(() => { if (isNativeSmall) { sharedMobileTabRef.update( - + - , + , ); } }, [routeName, isNativeSmall]), @@ -43,10 +43,7 @@ export function ScreenMarketOrSwap({ return ( {isNativeSmall ? ( - + ) : ( <> diff --git a/packages/kit/src/views/Overlay/RootPortal.tsx b/packages/kit/src/views/Overlay/RootPortal.tsx index 9fb0c768731..9bef3f0eecf 100644 --- a/packages/kit/src/views/Overlay/RootPortal.tsx +++ b/packages/kit/src/views/Overlay/RootPortal.tsx @@ -11,15 +11,6 @@ import type { RootSiblingManager } from 'react-native-root-siblings/lib/wrapRoot const portalManagers: Map = new Map(); let portalUuid = 0; -function setPortalManager(name: string, manager: RootSiblingManager) { - portalManagers.set(name, manager); - - // simulate lazy set portal manager - // setTimeout(() => { - // portalManagers.set(name, manager); - // }, 600); -} - function createPortalId(id: number): string { return `portal:${id}`; } @@ -36,19 +27,19 @@ export interface PortalManager { destroy: (destroyCallback?: () => void) => void; } -export function renderToPortal( - container: string, +export function enterPortal( + target: string, guest: ReactNode, callback?: () => void, ): PortalManager { - const manager = portalManagers.get(container); + const manager = portalManagers.get(target); const id = createPortalId(++portalUuid); if (manager) { manager.update(id, guest, callback); } else { throw new Error( - `react-native-root-portal: Can not find target PortalContainer named:'${container}'.`, + `react-native-root-portal: Can not find target PortalExit named:'${target}'.`, ); } @@ -62,50 +53,32 @@ export function renderToPortal( }; } -export function PortalRender(props: { - children: ReactNode; - container?: string; -}) { - const { children, container } = props; - const [retry, setRetry] = useState(false); +export function PortalEntry(props: { children: ReactNode; target?: string }) { + const { children, target } = props; + const manager = target ? portalManagers.get(target) : null; + const [id] = useState(() => ++portalUuid); useEffect(() => { - if (!container) { - return; - } - const manager = container ? portalManagers.get(container) : null; - if (manager) { - const portalId = createPortalId(++portalUuid); - manager.update(portalId, <>{children}); - return () => { - // destroy component - manager.destroy(portalId); - }; + return () => manager.destroy(createPortalId(id)); } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [manager]); + + if (manager) { + manager.update(createPortalId(id), <>{children}); + } else if (target) { console.error( - `react-native-root-portal: Can not find target PortalContainer named:'${container}'.`, + `react-native-root-portal: Can not find target PortalExit named:'${target}'.`, ); - if (!retry) { - // manager not exists, may be portalManagers not init yet, - // try again in 600ms - setTimeout(() => { - console.error( - `react-native-root-portal: retry load PortalContainer:'${container}'.`, - ); - setRetry(true); - }, 800); - } - }, [children, container, retry]); - - if (!container) { + } else { return <>{children}; } return null; } -export function PortalContainer(props: { +export function PortalExit(props: { name: string; renderSibling?: (sibling: ReactNode) => ReactNode; children?: ReactNode; @@ -120,11 +93,11 @@ export function PortalContainer(props: { if (isPortalExisted(name)) { console.warn( - `react-native-root-portal: Another PortalContainer named:'${name}' is already existed.`, + `react-native-root-portal: Another PortalExit named:'${name}' is already existed.`, ); } - setPortalManager(name, manager); + portalManagers.set(name, manager); return { Root, manager, @@ -134,7 +107,7 @@ export function PortalContainer(props: { useEffect(() => { if (!portalManagers.has(name)) { - setPortalManager(name, sibling.manager); + portalManagers.set(name, sibling.manager); } return () => { @@ -151,3 +124,10 @@ export function PortalContainer(props: { ); } + +export default { + Entry: PortalEntry, + Exit: PortalExit, + isExisted: isPortalExisted, + enter: enterPortal, +};