diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index fc6ef55..fa3fa19 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -137,48 +137,6 @@ async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), Strin Ok(()) } -#[tauri::command] -async fn check_and_handle_startup_url(app_handle: tauri::AppHandle) -> Result { - println!("check_and_handle_startup_url called"); - - let pending_urls = { - let mut pending = PENDING_URLS.lock().unwrap(); - let urls = pending.clone(); - pending.clear(); // Clear after getting them - urls - }; - - println!("Found {} pending URLs", pending_urls.len()); - - if !pending_urls.is_empty() { - println!( - "Handling {} pending URLs from frontend request", - pending_urls.len() - ); - - // Ensure the main window is visible and focused - if let Some(window) = app_handle.get_webview_window("main") { - let _ = window.show(); - let _ = window.set_focus(); - let _ = window.unminimize(); - - // Give the window a moment to become visible - tokio::time::sleep(tokio::time::Duration::from_millis(200)).await; - } - - for url in pending_urls { - println!("Emitting show-profile-selector event for URL: {url}"); - if let Err(e) = app_handle.emit("show-profile-selector", url.clone()) { - eprintln!("Failed to emit URL event: {e}"); - return Err(format!("Failed to emit URL event: {e}")); - } - } - - return Ok(true); - } - - Ok(false) -} #[tauri::command] async fn create_stored_proxy( @@ -456,7 +414,6 @@ pub fn run() { open_url_with_profile, set_as_default_browser, smart_open_url, - check_and_handle_startup_url, trigger_manual_version_update, get_version_update_status, check_for_browser_updates, diff --git a/src/app/page.tsx b/src/app/page.tsx index 97afddc..f5bde75 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -156,25 +156,47 @@ export default function Home() { setProxyDataReloadTrigger((prev) => prev + 1); }, []); - const handleUrlOpen = useCallback(async (url: string) => { - try { - // Use smart profile selection - const result = await invoke("smart_open_url", { - url, - }); - console.log("Smart URL opening succeeded:", result); - // URL was handled successfully, no need to show selector - } catch (error: unknown) { - console.log( - "Smart URL opening failed or requires profile selection:", - error, - ); + const [processingUrls, setProcessingUrls] = useState>(new Set()); - // Show profile selector for manual selection - // Replace any existing pending URL with the new one - setPendingUrls([{ id: Date.now().toString(), url }]); - } - }, []); + const handleUrlOpen = useCallback( + async (url: string) => { + // Prevent duplicate processing of the same URL + if (processingUrls.has(url)) { + console.log("URL already being processed:", url); + return; + } + + setProcessingUrls((prev) => new Set(prev).add(url)); + + try { + // Use smart profile selection + const result = await invoke("smart_open_url", { + url, + }); + console.log("Smart URL opening succeeded:", result); + // URL was handled successfully, no need to show selector + } catch (error: unknown) { + console.log( + "Smart URL opening failed or requires profile selection:", + error, + ); + + // Show profile selector for manual selection + // Replace any existing pending URL with the new one + setPendingUrls([{ id: Date.now().toString(), url }]); + } finally { + // Remove URL from processing set after a short delay to prevent rapid duplicates + setTimeout(() => { + setProcessingUrls((prev) => { + const next = new Set(prev); + next.delete(url); + return next; + }); + }, 1000); + } + }, + [processingUrls], + ); // Version updater for handling version fetching progress events and auto-updates useVersionUpdater(); @@ -279,19 +301,6 @@ export default function Home() { } }, [isMicrophoneAccessGranted, isCameraAccessGranted]); - const checkStartupUrls = useCallback(async () => { - try { - const hasStartupUrl = await invoke( - "check_and_handle_startup_url", - ); - if (hasStartupUrl) { - console.log("Handled startup URL successfully"); - } - } catch (error) { - console.error("Failed to check startup URLs:", error); - } - }, []); - const listenForUrlEvents = useCallback(async () => { try { // Listen for URL open events from the deep link handler (when app is already running) @@ -564,7 +573,6 @@ export default function Home() { void listenForUrlEvents(); // Check for startup URLs (when app was launched as default browser) - void checkStartupUrls(); void checkCurrentUrl(); // Set up periodic update checks (every 30 minutes) @@ -581,10 +589,9 @@ export default function Home() { }, [ loadProfilesWithUpdateCheck, checkForUpdates, - checkCurrentUrl, checkStartupPrompt, listenForUrlEvents, - checkStartupUrls, + checkCurrentUrl, ]); useEffect(() => {