diff --git a/apps/mobile/src/components/WebView/DappWebViewControl2/DappWebViewControl2.tsx b/apps/mobile/src/components/WebView/DappWebViewControl2/DappWebViewControl2.tsx index 42d685742..a7a55efeb 100644 --- a/apps/mobile/src/components/WebView/DappWebViewControl2/DappWebViewControl2.tsx +++ b/apps/mobile/src/components/WebView/DappWebViewControl2/DappWebViewControl2.tsx @@ -36,6 +36,7 @@ import { PATCH_ANCHOR_TARGET } from '@/core/bridges/builtInScripts/patchAnchor'; import { IS_ANDROID } from '@/core/native/utils'; import { checkShouldStartLoadingWithRequestForDappWebView } from '../utils'; import { FontNames } from '@/core/utils/fonts'; +import { DappWebViewHideContext } from '@/screens/Dapps/hooks/useDappView'; function errorLog(...info: any) { // devLog('[DappWebViewControl2::error]', ...info); @@ -81,7 +82,9 @@ type DappWebViewControlProps = { */ embedHtml?: string; initialUrl?: string; - onPressHeaderLeftClose?: (ctx: { defaultAction: () => void }) => void; + onPressHeaderLeftClose?: ( + ctx: { defaultAction: () => void } & DappWebViewHideContext, + ) => void; headerRight?: React.ReactNode | (() => React.ReactNode); headerNode?: @@ -236,11 +239,18 @@ const DappWebViewControl2 = React.forwardRef< if (typeof onPressHeaderLeftClose === 'function') { return onPressHeaderLeftClose({ defaultAction: handlePressCloseDefault, + latestUrl: latestUrl, + webviewId: webviewIdRef.current, }); } return handlePressCloseDefault(); - }, [handlePressCloseDefault, onPressHeaderLeftClose]); + }, [ + handlePressCloseDefault, + onPressHeaderLeftClose, + latestUrl, + webviewIdRef, + ]); const { headerRightNode, finalNavControlNode } = useDefaultNodes({ headerRight, diff --git a/apps/mobile/src/screens/Dapps/DappsScreen/components/WebViewsStub.tsx b/apps/mobile/src/screens/Dapps/DappsScreen/components/WebViewsStub.tsx index 753341925..d0db9c340 100644 --- a/apps/mobile/src/screens/Dapps/DappsScreen/components/WebViewsStub.tsx +++ b/apps/mobile/src/screens/Dapps/DappsScreen/components/WebViewsStub.tsx @@ -5,6 +5,7 @@ import { useOpenDappView, useActiveViewSheetModalRefs, OPEN_DAPP_VIEW_INDEXES, + DappWebViewHideContext, } from '../../hooks/useDappView'; import { devLog } from '@/utils/logger'; import { @@ -211,7 +212,6 @@ export function OpenedDappWebViewStub() { collapseDappWebViewModal, closeOpenedDapp, clearActiveDappOrigin, - collapseActiveOpenedDapp, } = useOpenDappView(); const { @@ -224,10 +224,13 @@ export function OpenedDappWebViewStub() { const { isDappConnected, disconnectDapp, updateFavorite } = useDapps(); - const hideDappSheetModal = useCallback(() => { - collapseDappWebViewModal(); - clearActiveDappOrigin(); - }, [collapseDappWebViewModal, clearActiveDappOrigin]); + const hideDappSheetModal = useCallback( + (ctx?: DappWebViewHideContext) => { + collapseDappWebViewModal(ctx); + clearActiveDappOrigin(); + }, + [collapseDappWebViewModal, clearActiveDappOrigin], + ); const handleBottomSheetChanges = useCallback< BottomSheetModalProps['onChange'] & object @@ -276,10 +279,15 @@ export function OpenedDappWebViewStub() { useHandleBackPressClosable( useCallback(() => { const control = activeDappWebViewControlRef.current; - if (control?.getWebViewState().canGoBack) { + const state = control?.getWebViewState(); + if (state?.canGoBack) { control?.getWebViewActions().handleGoBack(); } else if (activeDapp) { - hideDappSheetModal(); + hideDappSheetModal({ + // webViewId: control?.getWebViewId(), + latestUrl: state?.url, + webviewId: control?.getWebViewId(), + }); } return !activeDapp; }, [activeDapp, hideDappSheetModal]), @@ -364,7 +372,7 @@ export function OpenedDappWebViewStub() { globalSetActiveDappState({ dappOrigin: dappInfo.origin }); // @ts-expect-error activeDappWebViewControlRef.current = inst; - const activeTabId = inst?.getWebViewId() ?? undefined; + // const activeTabId = inst?.getWebViewId() ?? undefined; globalSetActiveDappState({ dappOrigin: dappInfo.origin, tabId: dappInfo.dappTabId, @@ -397,8 +405,7 @@ export function OpenedDappWebViewStub() { }} headerRight={} onPressHeaderLeftClose={ctx => { - hideDappSheetModal(); - collapseActiveOpenedDapp(); + hideDappSheetModal(ctx); }} // headerNode={({ header }) => { // return ; diff --git a/apps/mobile/src/screens/Dapps/DappsScreen/index.tsx b/apps/mobile/src/screens/Dapps/DappsScreen/index.tsx index d058d3b49..eaaececd0 100644 --- a/apps/mobile/src/screens/Dapps/DappsScreen/index.tsx +++ b/apps/mobile/src/screens/Dapps/DappsScreen/index.tsx @@ -42,13 +42,21 @@ export function DappsScreen(): JSX.Element { const navigation = useNavigation(); const searchState = useSearchDapps(); - const handleOpenURL = useMemoizedFn((url: string) => { - openUrlAsDapp(url, { - showSheetModalFirst: true, - }); - setBrowserHistory(safeGetOrigin(url)); - Keyboard.dismiss(); - }); + type OpenUrlAsDappOptions = Pick< + Parameters[1] & object, + 'useLatestWebViewId' + >; + const handleOpenURL = useMemoizedFn( + (url: string, options?: OpenUrlAsDappOptions) => { + openUrlAsDapp(url, { + useLatestWebViewId: true, + ...options, + showSheetModalFirst: true, + }); + setBrowserHistory(safeGetOrigin(url)); + Keyboard.dismiss(); + }, + ); const handleFavoriteDapp = useMemoizedFn((dapp: DappInfo) => { const v = !dapp.isFavorite; diff --git a/apps/mobile/src/screens/Dapps/FavoriteDappsScreen/index.tsx b/apps/mobile/src/screens/Dapps/FavoriteDappsScreen/index.tsx index 9519f6c0f..68aaa84c9 100644 --- a/apps/mobile/src/screens/Dapps/FavoriteDappsScreen/index.tsx +++ b/apps/mobile/src/screens/Dapps/FavoriteDappsScreen/index.tsx @@ -37,12 +37,20 @@ export function FavoriteDappsScreen(): JSX.Element { getStyle, }); - const handleOpenURL = useMemoizedFn((url: string) => { - openUrlAsDapp(url, { - showSheetModalFirst: true, - }); - setBrowserHistory(safeGetOrigin(url)); - }); + type OpenUrlAsDappOptions = Pick< + Parameters[1] & object, + 'useLatestWebViewId' + >; + const handleOpenURL = useMemoizedFn( + (url: string, options?: OpenUrlAsDappOptions) => { + openUrlAsDapp(url, { + useLatestWebViewId: true, + ...options, + showSheetModalFirst: true, + }); + setBrowserHistory(safeGetOrigin(url)); + }, + ); const handleFavoriteDapp = useMemoizedFn((dapp: DappInfo) => { updateFavorite(dapp.origin, !dapp.isFavorite); diff --git a/apps/mobile/src/screens/Dapps/hooks/useDappView.ts b/apps/mobile/src/screens/Dapps/hooks/useDappView.ts index 209912cb6..41d214f2a 100644 --- a/apps/mobile/src/screens/Dapps/hooks/useDappView.ts +++ b/apps/mobile/src/screens/Dapps/hooks/useDappView.ts @@ -15,7 +15,6 @@ import { } from '@/core/bridges/state'; import useDebounceValue from '@/hooks/common/useDebounceValue'; import { stringUtils } from '@rabby-wallet/base-utils'; -import { useAccountSceneVisible } from '@/components/AccountSwitcher/hooks'; import { isSameAccount, useSceneAccountInfo, @@ -61,6 +60,7 @@ export type OpenedDappItem = { * **/ openTime: number; + lastOpenWebViewId?: string | null; }; const DAPPS_VIEW_LIMIT = { maxCount: 3, @@ -175,6 +175,11 @@ export const OPEN_DAPP_VIEW_INDEXES = { expanded: 1, collapsed: 0, }; +export type DappWebViewHideContext = { + webviewId: string | undefined; + dappOrigin?: string; + latestUrl?: string; +}; export function useOpenDappView() { const { dapps, addDapp } = useDapps(); const [activeDappOrigin, _setActiveDappOrigin] = @@ -235,12 +240,34 @@ export function useOpenDappView() { ); }, [toggleShowSheetModal]); - const collapseDappWebViewModal = useCallback(() => { - toggleShowSheetModal( - 'openedDappWebviewSheetModalRef', - OPEN_DAPP_VIEW_INDEXES.collapsed, - ); - }, [toggleShowSheetModal]); + const setLastWebViewIdByDappOrigin = useCallback( + (dappOrigin: DappInfo['origin'], webviewId?: string) => { + // if (urlUtils.canoicalizeDappUrl(url).httpOrigin !== dappOrigin) return ; + + setOpenedOriginsDapps(prev => { + const itemIdx = prev.findIndex(item => item.origin === dappOrigin); + if (itemIdx === -1) return prev; + + prev[itemIdx].lastOpenWebViewId = webviewId || null; + + return [...prev]; + }); + }, + [setOpenedOriginsDapps], + ); + + const collapseDappWebViewModal = useCallback( + (ctx?: DappWebViewHideContext) => { + toggleShowSheetModal( + 'openedDappWebviewSheetModalRef', + OPEN_DAPP_VIEW_INDEXES.collapsed, + ); + if (ctx?.dappOrigin && ctx.webviewId) { + setLastWebViewIdByDappOrigin(ctx.dappOrigin, ctx.webviewId); + } + }, + [toggleShowSheetModal, setLastWebViewIdByDappOrigin], + ); const openUrlAsDapp = useCallback( ( @@ -250,10 +277,14 @@ export function useOpenDappView() { isActiveDapp?: boolean; /** @default {false} */ showSheetModalFirst?: boolean; + useLatestWebViewId?: boolean; }, ) => { - const { isActiveDapp = true, showSheetModalFirst = false } = - options || {}; + const { + isActiveDapp = true, + showSheetModalFirst = false, + useLatestWebViewId = false, + } = options || {}; const item = typeof dappUrl === 'string' @@ -264,8 +295,9 @@ export function useOpenDappView() { } : dappUrl; - const itemUrl = item.origin; - const { origin: targetOrigin, urlInfo } = canoicalizeDappUrl(itemUrl); + const itemDappOrigin = item.origin; + const { httpOrigin: targetOrigin, urlInfo } = + canoicalizeDappUrl(itemDappOrigin); if (!isOrHasWithAllowedProtocol(urlInfo?.protocol)) return false; if (showSheetModalFirst) showDappWebViewModal(); @@ -284,9 +316,9 @@ export function useOpenDappView() { syncBasicDappInfo(item.origin); - item.$openParams = { + const $openParams = { ...item.$openParams, - initialUrl: item.$openParams?.initialUrl || itemUrl, + initialUrl: item.$openParams?.initialUrl || itemDappOrigin, }; setOpenedOriginsDapps(prev => { @@ -297,14 +329,24 @@ export function useOpenDappView() { return [...prev, item]; } - prev[itemIdx] = { - ...prev[itemIdx], - $openParams: { - ...prev[itemIdx].$openParams, - ...item.$openParams, - }, - openTime: Date.now(), - }; + if ( + useLatestWebViewId && + prev[itemIdx].lastOpenWebViewId === prev[itemIdx].dappTabId + ) { + // call to open active id + setActiveDappOrigin(item.origin); + console.debug(`open existed dapp webview ${prev[itemIdx].dappTabId}`); + } else { + prev[itemIdx] = { + ...prev[itemIdx], + $openParams: { + ...prev[itemIdx].$openParams, + ...$openParams, + }, + openTime: Date.now(), + }; + console.debug('will open new dapp webview'); + } return [...prev]; }); @@ -351,9 +393,12 @@ export function useOpenDappView() { collapseDappWebViewModal(); }, [collapseDappWebViewModal, removeOpenedDapp, activeDappOrigin]); - const collapseActiveOpenedDapp = useCallback(() => { - collapseDappWebViewModal(); - }, [collapseDappWebViewModal]); + const collapseActiveOpenedDapp = useCallback( + (ctx: DappWebViewHideContext) => { + collapseDappWebViewModal(ctx); + }, + [collapseDappWebViewModal], + ); const closeOpenedDapp = useCallback( (dappOrigin: DappInfo['origin']) => { diff --git a/apps/mobile/src/screens/Testkits/DevUIDapps.tsx b/apps/mobile/src/screens/Testkits/DevUIDapps.tsx index 607255188..c3dfe095f 100644 --- a/apps/mobile/src/screens/Testkits/DevUIDapps.tsx +++ b/apps/mobile/src/screens/Testkits/DevUIDapps.tsx @@ -96,6 +96,10 @@ function DevUIDapps() { Open ID/Origin: {record.origin} {' '.repeat(100)} + + Open Last WebView ID: {record.lastOpenWebViewId || '-'}{' '} + {' '.repeat(100)} + Open Time:{' '} {dayjs(record.openTime)