Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(deep-link): Add deep link support for desktop #916

Merged
merged 29 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3d15bba
initial windows support
FabianLars Nov 7, 2023
8b7467b
bundle type role for macos
FabianLars Nov 22, 2023
fc07cad
macos
FabianLars Nov 27, 2023
e30de3d
fix windows after macos changes
FabianLars Nov 27, 2023
ec54df1
linux
FabianLars Nov 28, 2023
675a202
Merge remote-tracking branch 'origin/v2' into desktop-deep-links
FabianLars Jan 25, 2024
a2dd3df
Merge remote-tracking branch 'origin/v2' into desktop-deep-links
FabianLars Mar 27, 2024
bb6463a
update to beta (windows)
FabianLars Mar 27, 2024
c4fed8f
enable ci for deep link plugin
FabianLars Mar 27, 2024
1b9bd19
linux
FabianLars Mar 27, 2024
9ec7a77
android maybe?
FabianLars Mar 27, 2024
6485034
linux
FabianLars Mar 27, 2024
e62d270
js api
FabianLars Mar 28, 2024
419878e
readme
FabianLars Mar 28, 2024
f762106
android and permissions regen
FabianLars Mar 28, 2024
37299b9
return true on unsupported platforms
FabianLars Mar 28, 2024
cf64d40
js api fix and docs
FabianLars Mar 28, 2024
e150e26
mobile for realsies
FabianLars Mar 28, 2024
fe6547f
dunce
FabianLars Mar 29, 2024
a91c67b
windows-registry
FabianLars Mar 29, 2024
6d06de2
Merge remote-tracking branch 'origin/v2' into desktop-deep-links
FabianLars Apr 17, 2024
89770d9
re-add -handler suffix
FabianLars Apr 17, 2024
9ccd3d3
linux: fix is_registered
FabianLars Apr 17, 2024
bc9292b
linux: fix register and add unregister (both untested)
FabianLars Apr 17, 2024
8c26e84
return add Error::Unsupported platform and fix docs
FabianLars Apr 17, 2024
387bc49
fix docs again
FabianLars Apr 17, 2024
a0350cb
changed my mind, let's not add is_registered on macos for now
FabianLars Apr 17, 2024
c47d9d6
fix target_os cfgs
FabianLars Apr 17, 2024
0882c36
merge from v2
lucasfernog May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ jobs:
tauri-plugin-clipboard-manager:
- .github/workflows/test-rust.yml
- plugins/clipboard-manager/**
tauri-plugin-deep-link:
- .github/workflows/test-rust.yml
- plugins/deep-link/**
tauri-plugin-dialog:
- .github/workflows/test-rust.yml
- plugins/dialog/**
Expand Down
82 changes: 81 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ log = "0.4"
tauri = "2.0.0-beta.17"
tauri-build = "2.0.0-beta.13"
tauri-plugin = "2.0.0-beta.13"
tauri-utils = "2.0.0-beta.13"
serde_json = "1"
thiserror = "1"
url = "2"
Expand Down
10 changes: 10 additions & 0 deletions plugins/deep-link/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,22 @@ targets = [ "x86_64-linux-android" ]
[build-dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
tauri-utils = { workspace = true }
tauri-plugin = { workspace = true, features = [ "build" ] }

[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
tauri = { workspace = true }
tauri-utils = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }

[target."cfg(windows)".dependencies]
dunce = "1"
windows-registry = "0.1"
windows-result = "0.1"

[target.'cfg(target_os = "linux")'.dependencies]
rust-ini = "0.21"
13 changes: 9 additions & 4 deletions plugins/deep-link/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,19 @@ See [supporting associated domains](https://developer.apple.com/documentation/xc

## Configuration

Under `tauri.conf.json > plugins > deep-link`, configure the domains you want to associate with your application:
Under `tauri.conf.json > plugins > deep-link`, configure the domains (mobile) and schemes (desktop) you want to associate with your application:

```json
{
"plugins": {
"deep-link": {
"domains": [
"mobile": [
{ "host": "your.website.com", "pathPrefix": ["/open"] },
{ "host": "another.site.br" }
]
],
"desktop": {
"schemes": ["something", "my-tauri-app"]
}
}
}
}
Expand All @@ -128,10 +131,12 @@ Afterwards all the plugin's APIs are available through the JavaScript guest bind
```javascript
import { onOpenUrl } from "@tauri-apps/plugin-deep-link";
await onOpenUrl((urls) => {
console.log('deep link:', urls);
console.log("deep link:", urls);
});
```

Note that the Plugin will only emit events on macOS, iOS and Android. On Windows and Linux the OS will spawn a new instance of your app with the URL as a CLI argument. If you want your app to behave on Windows & Linux similar to the other platforms you can use the [single-instance](../single-instance/) plugin.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also mention that the URL will be passed as a CLI argument, and maybe showcase an example of using both plugins, maybe take https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app as inspiration

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to include the single-instance plugin on the website (the url param is mentioned)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would probably still make sense to include the example here as well so it can be found on npm and docs.rs as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm ok


## Contributing

PRs accepted. Please make sure to read the Contributing Guide before making a pull request.
Expand Down
2 changes: 1 addition & 1 deletion plugins/deep-link/api-iife.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions plugins/deep-link/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
mod config;
use config::{AssociatedDomain, Config};

const COMMANDS: &[&str] = &["get_current"];
const COMMANDS: &[&str] = &["get_current", "register", "unregister", "is_registered"];

// TODO: Consider using activity-alias in case users may have multiple activities in their app.
// TODO: Do we want to support the other path* configs too?
Expand Down Expand Up @@ -48,7 +48,7 @@ fn main() {
"DEEP LINK PLUGIN",
"activity",
config
.domains
.mobile
.iter()
.map(intent_filter)
.collect::<Vec<_>>()
Expand All @@ -62,7 +62,7 @@ fn main() {
entitlements.insert(
"com.apple.developer.associated-domains".into(),
config
.domains
.mobile
.into_iter()
.map(|d| format!("applinks:{}", d.host).into())
.collect::<Vec<_>>()
Expand Down
16 changes: 7 additions & 9 deletions plugins/deep-link/examples/app/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,13 @@
"hello": "world"
},
"deep-link": {
"domains": [
{
"host": "fabianlars.de",
"pathPrefix": ["/intent"]
},
{
"host": "tauri.app"
}
]
"mobile": [
{ "host": "fabianlars.de", "pathPrefix": ["/intent"] },
{ "host": "tauri.app" }
],
"desktop": {
"schemes": ["fabianlars", "my-tauri-app"]
}
}
},
"bundle": {
Expand Down
2 changes: 1 addition & 1 deletion plugins/deep-link/examples/app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"target": "ESNext",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"moduleResolution": "bundler",
"strict": true,
"sourceMap": true,
"resolveJsonModule": true,
Expand Down
87 changes: 85 additions & 2 deletions plugins/deep-link/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,95 @@
import { invoke } from "@tauri-apps/api/core";
import { type UnlistenFn, listen } from "@tauri-apps/api/event";

/**
* Get the current URLs that triggered the deep link. Use this on app load to check whether your app was started via a deep link.
*
* @example
* ```typescript
* import { getCurrent } from '@tauri-apps/plugin-deep-link';
* const urls = await getCurrent();
* ```
*
* #### - **Windows / Linux**: Unsupported.
*
* @since 2.0.0
*/
export async function getCurrent(): Promise<string[] | null> {
return await invoke<string[] | null>("plugin:deep-link|get_current");
return await invoke("plugin:deep-link|get_current");
}

/**
* Register the app as the default handler for the specified protocol.
*
* @param protocol The name of the protocol without `://`. For example, if you want your app to handle `tauri://` links, call this method with `tauri` as the protocol.
*
* @example
* ```typescript
* import { register } from '@tauri-apps/plugin-deep-link';
* await register("my-scheme");
* ```
*
* #### - **macOS / Android / iOS**: Unsupported.
*
* @since 2.0.0
*/
export async function register(protocol: string): Promise<null> {
return await invoke("plugin:deep-link|register", { protocol });
}

/**
* Unregister the app as the default handler for the specified protocol.
*
* @param protocol The name of the protocol without `://`.
*
* @example
* ```typescript
* import { unregister } from '@tauri-apps/plugin-deep-link';
* await unregister("my-scheme");
* ```
*
* #### - **macOS / Linux / Android / iOS**: Unsupported.
*
* @since 2.0.0
*/
export async function unregister(protocol: string): Promise<null> {
return await invoke("plugin:deep-link|unregister", { protocol });
}

// return await invoke("plugin:deep-link|get_current");
/**
* Check whether the app is the default handler for the specified protocol.
*
* @param protocol The name of the protocol without `://`.
*
* @example
* ```typescript
* import { isRegistered } from '@tauri-apps/plugin-deep-link';
* await isRegistered("my-scheme");
* ```
*
* #### - **macOS / Android / iOS**: Unsupported, always returns `true`.
*
* @since 2.0.0
*/
export async function isRegistered(protocol: string): Promise<boolean> {
return await invoke("plugin:deep-link|i_registered", { protocol });
}

/**
* Helper function for the `deep-link://new-url` event to run a function each time the protocol is triggered while the app is running. Use `getCurrent` on app load to check whether your app was started via a deep link.
*
* @param protocol The name of the protocol without `://`.
*
* @example
* ```typescript
* import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
* await onOpenUrl((urls) => { console.log(urls) });
* ```
*
* #### - **Windows / Linux**: Unsupported, the OS will spawn a new app instance passing the URL as a CLI argument.
*
* @since 2.0.0
*/
export async function onOpenUrl(
handler: (urls: string[]) => void,
): Promise<UnlistenFn> {
Expand Down
Loading
Loading