From 0cc76b55aedcfc48628859aafa357fe81418e056 Mon Sep 17 00:00:00 2001 From: Bruno Barbieri <1247834+brunobar79@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:36:45 -0400 Subject: [PATCH] allow open in new tab (#5610) --- src/components/DappBrowser/BrowserContext.tsx | 52 ++++++++++--------- src/components/DappBrowser/DappBrowser.tsx | 28 ++++++++-- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/components/DappBrowser/BrowserContext.tsx b/src/components/DappBrowser/BrowserContext.tsx index d56ddb0c75d..2e2d645513d 100644 --- a/src/components/DappBrowser/BrowserContext.tsx +++ b/src/components/DappBrowser/BrowserContext.tsx @@ -46,7 +46,7 @@ interface BrowserContextType { goBack: () => void; goForward: () => void; loadProgress: SharedValue | undefined; - newTabWorklet: () => void; + newTabWorklet: (url?: string) => void; onRefresh: () => void; searchInputRef: React.RefObject; searchViewProgress: SharedValue | undefined; @@ -74,6 +74,7 @@ interface TabOperation { type: TabOperationType; tabId: string; newActiveIndex: number | undefined; + url?: string; } export const RAINBOW_HOME = 'RAINBOW_HOME'; @@ -107,7 +108,7 @@ const DEFAULT_BROWSER_CONTEXT: BrowserContextType = { goForward: () => { return; }, - newTabWorklet: () => { + newTabWorklet: (url?: string) => { return; }, onRefresh: () => { @@ -311,7 +312,7 @@ export const BrowserContextProvider = ({ children }: { children: React.ReactNode canGoBack: false, canGoForward: false, uniqueId: operation.tabId, - url: RAINBOW_HOME, + url: operation.url || RAINBOW_HOME, }; newTabStates.push(newTab); shouldToggleTabView = true; @@ -357,27 +358,30 @@ export const BrowserContextProvider = ({ children }: { children: React.ReactNode tabViewVisible, ]); - const newTabWorklet = useCallback(() => { - 'worklet'; - const tabIdsInStates = new Set(tabStates?.map(state => state.uniqueId)); - const isNewTabOperationPending = - tabOperationQueue.value.some(operation => operation.type === 'newTab') || - currentlyOpenTabIds.value.some(tabId => !tabIdsInStates.has(tabId)); - - // The first check is mainly to guard against an edge case that happens when the new tab button is - // pressed just after the last tab is closed, but before a new blank tab has opened programatically, - // which results in two tabs being created when the user most certainly only wanted one. - if (!isNewTabOperationPending && (tabViewVisible.value || currentlyOpenTabIds.value.length === 0)) { - const tabIdForNewTab = generateUniqueIdWorklet(); - const newActiveIndex = currentlyOpenTabIds.value.length - 1; - - currentlyOpenTabIds.modify(value => { - value.push(tabIdForNewTab); - return value; - }); - requestTabOperationsWorklet({ type: 'newTab', tabId: tabIdForNewTab, newActiveIndex }); - } - }, [currentlyOpenTabIds, requestTabOperationsWorklet, tabOperationQueue, tabStates, tabViewVisible]); + const newTabWorklet = useCallback( + (url?: string) => { + 'worklet'; + const tabIdsInStates = new Set(tabStates?.map(state => state.uniqueId)); + const isNewTabOperationPending = + tabOperationQueue.value.some(operation => operation.type === 'newTab') || + currentlyOpenTabIds.value.some(tabId => !tabIdsInStates.has(tabId)); + + // The first check is mainly to guard against an edge case that happens when the new tab button is + // pressed just after the last tab is closed, but before a new blank tab has opened programatically, + // which results in two tabs being created when the user most certainly only wanted one. + if (url || (!isNewTabOperationPending && (tabViewVisible.value || currentlyOpenTabIds.value.length === 0))) { + const tabIdForNewTab = generateUniqueIdWorklet(); + const newActiveIndex = currentlyOpenTabIds.value.length - 1; + + currentlyOpenTabIds.modify(value => { + value.push(tabIdForNewTab); + return value; + }); + requestTabOperationsWorklet({ type: 'newTab', tabId: tabIdForNewTab, newActiveIndex, url }); + } + }, + [currentlyOpenTabIds, requestTabOperationsWorklet, tabOperationQueue, tabStates, tabViewVisible] + ); const closeTabWorklet = useCallback( (tabId: string, tabIndex: number) => { diff --git a/src/components/DappBrowser/DappBrowser.tsx b/src/components/DappBrowser/DappBrowser.tsx index 7b1cc040423..ee706166e73 100644 --- a/src/components/DappBrowser/DappBrowser.tsx +++ b/src/components/DappBrowser/DappBrowser.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import { StyleSheet } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; -import Animated, { interpolateColor, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated'; +import Animated, { interpolateColor, runOnJS, useAnimatedProps, useAnimatedReaction, useAnimatedStyle } from 'react-native-reanimated'; import RNFS from 'react-native-fs'; import { Page } from '@/components/layout'; @@ -15,6 +15,7 @@ import { Search } from './search/Search'; import { TabViewToolbar } from './TabViewToolbar'; import { SheetGestureBlocker } from '../sheet/SheetGestureBlocker'; import { ProgressBar } from './ProgressBar'; +import { RouteProp, useRoute } from '@react-navigation/native'; const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView); @@ -28,10 +29,33 @@ const getInjectedJS = async () => { } }; +export type DappBrowserParams = { + url: string; +}; + +type RouteParams = { + DappBrowserParams: DappBrowserParams; +}; + const DappBrowserComponent = () => { const { isDarkMode } = useColorMode(); const [injectedJS, setInjectedJS] = useState(''); + const { scrollViewRef, tabStates, tabViewProgress, tabViewVisible, newTabWorklet, toggleTabViewWorklet } = useBrowserContext(); + + const route = useRoute>(); + + useAnimatedReaction( + () => route.params?.url, + (current, previous) => { + if (current !== previous && route.params?.url) { + newTabWorklet(current); + toggleTabViewWorklet(); + } + }, + [newTabWorklet, route.params?.url] + ); + useEffect(() => { const loadInjectedJS = async () => { try { @@ -44,8 +68,6 @@ const DappBrowserComponent = () => { loadInjectedJS(); }, []); - const { scrollViewRef, tabStates, tabViewProgress, tabViewVisible } = useBrowserContext(); - useEffect(() => { pruneScreenshots(tabStates); // eslint-disable-next-line react-hooks/exhaustive-deps