Skip to content

Commit a07adcb

Browse files
Merge pull request #7 from offendingcommit/feat/deep-linking
feat: deep linking for hosted URLs and openconcho:// scheme
2 parents 387bfa4 + f9e26d4 commit a07adcb

11 files changed

Lines changed: 297 additions & 18 deletions

File tree

packages/desktop/src-tauri/Cargo.lock

Lines changed: 116 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/desktop/src-tauri/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ tauri-build = { version = "2", features = [] }
1414
tauri = { version = "2", features = [] }
1515
tauri-plugin-http = "2"
1616
tauri-plugin-shell = "2"
17+
tauri-plugin-deep-link = "2"
1718
serde = { version = "1", features = ["derive"] }
1819
serde_json = "1"
Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
{
2-
"$schema": "../gen/schemas/desktop-schema.json",
3-
"identifier": "default",
4-
"description": "Default capabilities for the OpenConcho desktop window",
5-
"windows": ["main"],
6-
"permissions": [
7-
"core:default",
8-
{
9-
"identifier": "http:default",
10-
"allow": [
11-
{ "url": "http://*" },
12-
{ "url": "http://*:*" },
13-
{ "url": "https://*" },
14-
{ "url": "https://*:*" }
15-
]
16-
},
17-
"shell:allow-open"
18-
]
2+
"$schema": "../gen/schemas/desktop-schema.json",
3+
"identifier": "default",
4+
"description": "Default capabilities for the OpenConcho desktop window",
5+
"windows": ["main"],
6+
"permissions": [
7+
"core:default",
8+
{
9+
"identifier": "http:default",
10+
"allow": [
11+
{ "url": "http://*" },
12+
{ "url": "http://*:*" },
13+
{ "url": "https://*" },
14+
{ "url": "https://*:*" }
15+
]
16+
},
17+
"shell:allow-open",
18+
"deep-link:default"
19+
]
1920
}

packages/desktop/src-tauri/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub fn run() {
33
tauri::Builder::default()
44
.plugin(tauri_plugin_http::init())
55
.plugin(tauri_plugin_shell::init())
6+
.plugin(tauri_plugin_deep_link::init())
67
.run(tauri::generate_context!())
78
.expect("error while running tauri application");
89
}

packages/desktop/src-tauri/tauri.conf.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,13 @@
3232
"security": {
3333
"csp": null
3434
}
35+
},
36+
"plugins": {
37+
"deep-link": {
38+
"mobile": [],
39+
"desktop": {
40+
"schemes": ["openconcho"]
41+
}
42+
}
3543
}
3644
}

packages/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@tanstack/react-query": "^5.74.4",
2727
"@tanstack/react-router": "^1.120.3",
2828
"@tauri-apps/api": "^2",
29+
"@tauri-apps/plugin-deep-link": "^2.4.9",
2930
"@tauri-apps/plugin-http": "^2",
3031
"@tauri-apps/plugin-shell": "^2",
3132
"class-variance-authority": "^0.7.1",

packages/web/src/lib/deep-link.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { Router } from "@tanstack/react-router";
2+
3+
const SCHEME = "openconcho:";
4+
5+
function isTauri(): boolean {
6+
return typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
7+
}
8+
9+
function navigateFromUrl(router: Router<never, never>, raw: string): void {
10+
let parsed: URL;
11+
try {
12+
parsed = new URL(raw);
13+
} catch {
14+
return;
15+
}
16+
if (parsed.protocol !== SCHEME) return;
17+
18+
const host = parsed.hostname || parsed.pathname.replace(/^\/+/, "").split("/")[0];
19+
const search = parsed.search;
20+
21+
if (host === "explore") {
22+
router.navigate({ to: `/explore${search}` as never });
23+
return;
24+
}
25+
26+
const path = parsed.pathname.startsWith("/") ? parsed.pathname : `/${parsed.pathname}`;
27+
router.navigate({ to: `${path}${search}` as never });
28+
}
29+
30+
export async function initDeepLinks(router: Router<never, never>): Promise<void> {
31+
if (!isTauri()) return;
32+
const { onOpenUrl, getCurrent } = await import("@tauri-apps/plugin-deep-link");
33+
34+
const initial = await getCurrent();
35+
if (initial?.length) navigateFromUrl(router, initial[0]);
36+
37+
await onOpenUrl((urls) => {
38+
if (urls[0]) navigateFromUrl(router, urls[0]);
39+
});
40+
}

packages/web/src/main.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createRouter, RouterProvider } from "@tanstack/react-router";
33
import { StrictMode } from "react";
44
import { createRoot } from "react-dom/client";
55
import { DemoProvider } from "./context/DemoContext";
6+
import { initDeepLinks } from "./lib/deep-link";
67
import { routeTree } from "./routeTree.gen";
78
import "./index.css";
89

@@ -27,6 +28,8 @@ declare module "@tanstack/react-router" {
2728
}
2829
}
2930

31+
void initDeepLinks(router as never);
32+
3033
const root = document.getElementById("root");
3134
if (!root) throw new Error("Missing #root element");
3235

0 commit comments

Comments
 (0)