From 28d960b04f5f2e33cbe28cb55dc49db8f21f1577 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 2 Jul 2026 22:57:09 -0400 Subject: [PATCH] fix(native): dedupe cold-start deep-link double navigation (D4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on_open_url and the argv fallback can both forward the same launch matrix: URL on cold start, navigating the room twice. forward_deeplink now drops a repeat of the same URL within ~1s (plain std Mutex/Instant — no windows-crate surface). Co-Authored-By: Claude Opus 4.8 --- src-tauri/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d051a37..912d5c8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -27,6 +27,24 @@ fn show_main(app: &tauri::AppHandle) { /// CustomEvent the client listens for (see useDeepLinkNavigate.ts). Uses /// `eval` so we don't need the @tauri-apps/api event package on the web side. fn forward_deeplink(app: &tauri::AppHandle, url: &str) { + // Dedupe: on a cold start the deep-link plugin's `on_open_url` AND the argv + // fallback (`matrix_url_from_args(std::env::args())`) can both forward the + // same launch URL, navigating the room twice (re-show/re-focus + a duplicate + // `lotus-deeplink`). Drop a repeat of the same URL within a short window. + { + use std::sync::Mutex; + use std::time::{Duration, Instant}; + static LAST: Mutex> = Mutex::new(None); + if let Ok(mut last) = LAST.lock() { + let now = Instant::now(); + if let Some((prev_url, prev_at)) = last.as_ref() { + if prev_url == url && now.duration_since(*prev_at) < Duration::from_millis(1000) { + return; + } + } + *last = Some((url.to_string(), now)); + } + } show_main(app); if let Some(window) = app.get_webview_window("main") { if let Ok(json) = serde_json::to_string(url) {