From 1177c2d3a99b0b9a08093628826205567c05b0bf Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:43:37 +0000 Subject: [PATCH] feat: wire up deeplink2 plugin with desktop app - Add tauri-plugin-deep-link dependency to deeplink2 plugin - Hook into tauri_plugin_deep_link to listen for deep link URLs - Parse deep link URLs and emit DeepLinkEvent - Wire up frontend to listen for DeepLinkEvent and navigate - Update notification route to handle key search param Co-Authored-By: yujonglee --- Cargo.lock | 2 ++ apps/desktop/src/routes/__root.tsx | 21 +++++++++++++--- apps/desktop/src/routes/notification.tsx | 10 +++++++- plugins/deeplink2/Cargo.toml | 2 ++ plugins/deeplink2/src/lib.rs | 31 +++++++++++++++++++++++- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7d335b021..79c877f231 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14927,9 +14927,11 @@ dependencies = [ "strum 0.26.3", "tauri", "tauri-plugin", + "tauri-plugin-deep-link", "tauri-specta", "thiserror 2.0.17", "tokio", + "tracing", "url", ] diff --git a/apps/desktop/src/routes/__root.tsx b/apps/desktop/src/routes/__root.tsx index 79dafa57e0..f516b91176 100644 --- a/apps/desktop/src/routes/__root.tsx +++ b/apps/desktop/src/routes/__root.tsx @@ -7,7 +7,10 @@ import { import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"; import { lazy, useEffect } from "react"; -import type { DeepLink } from "@hypr/plugin-deeplink2"; +import { + type DeepLink, + events as deeplink2Events, +} from "@hypr/plugin-deeplink2"; import { events as windowsEvents } from "@hypr/plugin-windows"; import { AuthProvider } from "../auth"; @@ -41,7 +44,8 @@ const useNavigationEvents = () => { const navigate = useNavigate(); useEffect(() => { - let unlisten: (() => void) | undefined; + let unlistenNavigate: (() => void) | undefined; + let unlistenDeepLink: (() => void) | undefined; const webview = getCurrentWebviewWindow(); @@ -51,11 +55,20 @@ const useNavigationEvents = () => { navigate({ to: payload.path, search: payload.search ?? undefined }); }) .then((fn) => { - unlisten = fn; + unlistenNavigate = fn; + }); + + deeplink2Events.deepLinkEvent + .listen(({ payload }) => { + navigate({ to: payload.to, search: payload.search }); + }) + .then((fn) => { + unlistenDeepLink = fn; }); return () => { - unlisten?.(); + unlistenNavigate?.(); + unlistenDeepLink?.(); }; }, [navigate]); }; diff --git a/apps/desktop/src/routes/notification.tsx b/apps/desktop/src/routes/notification.tsx index be137a4eae..c21cace719 100644 --- a/apps/desktop/src/routes/notification.tsx +++ b/apps/desktop/src/routes/notification.tsx @@ -1,7 +1,15 @@ import { createFileRoute, redirect } from "@tanstack/react-router"; +import type { NotificationSearch } from "@hypr/plugin-deeplink2"; + export const Route = createFileRoute("/notification")({ - beforeLoad: async () => { + validateSearch: (search): NotificationSearch => { + return { + key: (search as NotificationSearch).key ?? "", + }; + }, + beforeLoad: async ({ search }) => { + console.log("notification deeplink received", search); throw redirect({ to: "/app/main" }); }, }); diff --git a/plugins/deeplink2/Cargo.toml b/plugins/deeplink2/Cargo.toml index c024ee7d0a..c37e733535 100644 --- a/plugins/deeplink2/Cargo.toml +++ b/plugins/deeplink2/Cargo.toml @@ -19,6 +19,7 @@ serde_yaml = { workspace = true } [dependencies] tauri = { workspace = true, features = ["test"] } +tauri-plugin-deep-link = { workspace = true } tauri-specta = { workspace = true, features = ["derive", "typescript"] } serde = { workspace = true } @@ -26,4 +27,5 @@ specta = { workspace = true } strum = { workspace = true, features = ["derive"] } thiserror = { workspace = true } +tracing = { workspace = true } url = { workspace = true } diff --git a/plugins/deeplink2/src/lib.rs b/plugins/deeplink2/src/lib.rs index 6fd0dff2a4..2de8c42475 100644 --- a/plugins/deeplink2/src/lib.rs +++ b/plugins/deeplink2/src/lib.rs @@ -5,6 +5,12 @@ mod types; mod docs; pub use error::{Error, Result}; +pub use types::{DeepLink, DeepLinkEvent}; + +use std::str::FromStr; + +use tauri_plugin_deep_link::DeepLinkExt; +use tauri_specta::Event; const PLUGIN_NAME: &str = "deeplink2"; @@ -22,7 +28,30 @@ pub fn init() -> tauri::plugin::TauriPlugin { tauri::plugin::Builder::new(PLUGIN_NAME) .invoke_handler(specta_builder.invoke_handler()) - .setup(|_app, _api| Ok(())) + .setup(|app, _api| { + let app_handle = app.clone(); + + app.deep_link().on_open_url(move |event| { + for url in event.urls() { + let url_str = url.as_str(); + tracing::info!(url = url_str, "deeplink_received"); + + match DeepLink::from_str(url_str) { + Ok(deep_link) => { + tracing::info!(deep_link = ?deep_link, "deeplink_parsed"); + if let Err(e) = DeepLinkEvent(deep_link).emit(&app_handle) { + tracing::error!(error = ?e, "deeplink_event_emit_failed"); + } + } + Err(e) => { + tracing::warn!(error = ?e, url = url_str, "deeplink_parse_failed"); + } + } + } + }); + + Ok(()) + }) .build() }