From dbcbd5408635052f53767b0335c238645a515d49 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Wed, 23 Jul 2025 13:35:16 +0530 Subject: [PATCH 01/20] feat: android deeplinks --- package.json | 3 +- plugins/deep-link/build.rs | 27 ++++++++++++--- plugins/deep-link/examples/app/package.json | 2 +- .../gen/android/app/build.gradle.kts | 11 ++++--- .../android/app/src/main/AndroidManifest.xml | 21 ++++++++++-- .../tauri/deep_link_example/MainActivity.kt | 14 +++++--- .../src-tauri/gen/android/build.gradle.kts | 2 +- .../gen/android/buildSrc/build.gradle.kts | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../project.pbxproj | 8 ++--- .../apple/deep-link-example_iOS/Info.plist | 15 +++++++++ .../examples/app/src-tauri/tauri.conf.json | 5 ++- plugins/deep-link/src/config.rs | 33 ++++++++++++------- pnpm-lock.yaml | 2 +- 14 files changed, 109 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 76b24b29fd..bcab2538bf 100644 --- a/package.json +++ b/package.json @@ -35,5 +35,6 @@ }, "engines": { "pnpm": "^10.0.0" - } + }, + "packageManager": "pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184" } diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index 418746b234..0b00afcea0 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -10,13 +10,19 @@ const COMMANDS: &[&str] = &["get_current", "register", "unregister", "is_registe // TODO: Consider using activity-alias in case users may have multiple activities in their app. fn intent_filter(domain: &AssociatedDomain) -> String { + let host = domain + .host + .as_ref() + .map(|h| format!(r#""#)) + .unwrap_or_default(); + format!( r#" {} - + {} {} {} {} @@ -28,7 +34,7 @@ fn intent_filter(domain: &AssociatedDomain) -> String { .map(|scheme| format!(r#""#)) .collect::>() .join("\n "), - domain.host, + host, domain .path .iter() @@ -68,6 +74,17 @@ fn main() { } if let Some(config) = tauri_plugin::plugin_config::("deep-link") { + let errors: Vec = config + .mobile + .iter() + .filter_map(|d| d.validate().err()) + .collect(); + + if !errors.is_empty() { + panic!("Deep link config validation failed:\n{}", errors.join("\n")); + } + + tauri_plugin::mobile::update_android_manifest( "DEEP LINK PLUGIN", "activity", @@ -80,6 +97,7 @@ fn main() { ) .expect("failed to rewrite AndroidManifest.xml"); + #[cfg(target_os = "macos")] { tauri_plugin::mobile::update_entitlements(|entitlements| { @@ -87,8 +105,9 @@ fn main() { "com.apple.developer.associated-domains".into(), config .mobile - .into_iter() - .map(|d| format!("applinks:{}", d.host).into()) + .iter() + .filter_map(|d| d.host.as_ref()) + .map(|host| format!("applinks:{}", host).into()) .collect::>() .into(), ); diff --git a/plugins/deep-link/examples/app/package.json b/plugins/deep-link/examples/app/package.json index 0df59d8505..17770c260c 100644 --- a/plugins/deep-link/examples/app/package.json +++ b/plugins/deep-link/examples/app/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@tauri-apps/api": "2.7.0", - "@tauri-apps/plugin-deep-link": "2.4.1" + "@tauri-apps/plugin-deep-link": "link:../.." }, "devDependencies": { "@tauri-apps/cli": "2.7.1", diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts b/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts index f434bbfb0d..13ec1ffd66 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts @@ -14,13 +14,13 @@ val tauriProperties = Properties().apply { } android { - compileSdk = 34 + compileSdk = 36 namespace = "com.tauri.deep_link_example" defaultConfig { manifestPlaceholders["usesCleartextTraffic"] = "false" applicationId = "com.tauri.deep_link_example" minSdk = 24 - targetSdk = 34 + targetSdk = 36 versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0") } @@ -58,9 +58,10 @@ rust { } dependencies { - implementation("androidx.webkit:webkit:1.6.1") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("com.google.android.material:material:1.8.0") + implementation("androidx.webkit:webkit:1.14.0") + implementation("androidx.appcompat:appcompat:1.7.1") + implementation("androidx.activity:activity-ktx:1.10.1") + implementation("com.google.android.material:material:1.12.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.4") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0") diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml index 05265e325f..a650714ce7 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -27,19 +27,36 @@ - + + + + - + + + + + + + + + + + + + + + diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt index e13fb99560..313161c226 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt @@ -1,7 +1,11 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - package com.tauri.deep_link_example -class MainActivity : TauriActivity() +import android.os.Bundle +import androidx.activity.enableEdgeToEdge + +class MainActivity : TauriActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + } +} diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/build.gradle.kts b/plugins/deep-link/examples/app/src-tauri/gen/android/build.gradle.kts index c5ef452a67..607240bc8f 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/build.gradle.kts +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/build.gradle.kts @@ -4,7 +4,7 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.5.1") + classpath("com.android.tools.build:gradle:8.11.0") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25") } } diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/build.gradle.kts b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/build.gradle.kts index 39e90b0543..5c55bba71c 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/build.gradle.kts +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/build.gradle.kts @@ -18,6 +18,6 @@ repositories { dependencies { compileOnly(gradleApi()) - implementation("com.android.tools.build:gradle:8.5.1") + implementation("com.android.tools.build:gradle:8.11.0") } diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties b/plugins/deep-link/examples/app/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties index 0df10d556c..c5f9a53c27 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue May 10 19:22:52 CST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj index 450bd84706..3307dbf8ed 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj @@ -322,7 +322,7 @@ CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Q93MBH6S2F; + DEVELOPMENT_TEAM = 7F2T2WK6DR; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = "arm64-sim x86_64"; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -356,7 +356,7 @@ "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.tauri.deep-link-example; + PRODUCT_BUNDLE_IDENTIFIER = com.kodski.deep-link-example; PRODUCT_NAME = "deep-link-example"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -432,7 +432,7 @@ CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Q93MBH6S2F; + DEVELOPMENT_TEAM = 7F2T2WK6DR; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = "arm64-sim x86_64"; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -466,7 +466,7 @@ "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.tauri.deep-link-example; + PRODUCT_BUNDLE_IDENTIFIER = com.kodski.deep-link-example; PRODUCT_NAME = "deep-link-example"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist index 7ce8661409..3d3c9ef3c1 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist @@ -16,6 +16,21 @@ APPL CFBundleShortVersionString 0.0.0 + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLIconFile + Assets + CFBundleURLName + com.tauri.deep-link-example + CFBundleURLSchemes + + w3ds + + + CFBundleVersion 0.1.0 LSRequiresIPhoneOS diff --git a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json index ac1c292b46..2df503a61d 100644 --- a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json +++ b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "productName": "deep-link-example", "version": "0.1.0", - "identifier": "com.tauri.deep-link-example", + "identifier": "com.kodski.deep-link-example", "build": { "devUrl": "http://localhost:1420", "frontendDist": "../dist", @@ -35,6 +35,9 @@ }, { "host": "tauri.app" + }, + { + "scheme": ["taurideeplink"] } ], "desktop": { diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 88222a2461..0ba3424662 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -12,8 +12,8 @@ pub struct AssociatedDomain { #[serde(default = "default_schemes")] pub scheme: Vec, - #[serde(deserialize_with = "deserialize_associated_host")] - pub host: String, + #[serde(default, deserialize_with = "deserialize_associated_host")] + pub host: Option, // Optional custom uri schemes dont NEED a host (may have one still), but required for https/http schemes #[serde(default)] pub path: Vec, @@ -25,23 +25,34 @@ pub struct AssociatedDomain { pub path_suffix: Vec, } +impl AssociatedDomain { + pub fn validate(&self) -> Result<(), String> { + if self.host.is_none() && self.scheme.iter().any(|s| s == "https" || s == "http") { + return Err("host is required when using https/http schemes".into()); + } + Ok(()) + } +} + + // TODO: Consider removing this in v3 fn default_schemes() -> Vec { vec!["https".to_string(), "http".to_string()] } -fn deserialize_associated_host<'de, D>(deserializer: D) -> Result +fn deserialize_associated_host<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, -{ - let host = String::deserialize(deserializer)?; - if let Some((scheme, _host)) = host.split_once("://") { - Err(serde::de::Error::custom(format!( - "host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix" - ))) - } else { - Ok(host) +{ + let opt = Option::::deserialize(deserializer)?; + if let Some(ref host) = opt { + if let Some((scheme, _)) = host.split_once("://") { + return Err(serde::de::Error::custom(format!( + "host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix" + ))); + } } + Ok(opt) } #[derive(Deserialize, Clone)] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cfdd2320f6..2458fc0fd4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,7 +184,7 @@ importers: specifier: 2.7.0 version: 2.7.0 '@tauri-apps/plugin-deep-link': - specifier: 2.4.1 + specifier: link:../.. version: link:../.. devDependencies: '@tauri-apps/cli': From ef89071ac1835d74e568f3c1bf12e5fce26081d4 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Wed, 23 Jul 2025 22:39:09 +0530 Subject: [PATCH 02/20] feat: explicit app link declarations --- plugins/deep-link/build.rs | 34 +++- .../app/src-tauri/gen/android/app/.gitignore | 2 +- .../gen/android/app/build.gradle.kts | 4 +- .../android/app/src/main/AndroidManifest.xml | 2 +- .../deep_link_example/MainActivity.kt | 2 +- .../deep_link_example/kotlin/BuildTask.kt | 0 .../deep_link_example/kotlin/RustPlugin.kt | 0 .../AppIcon.appiconset/Contents.json | 154 +++++++++--------- .../gen/apple/Assets.xcassets/Contents.json | 8 +- .../gen/apple/LaunchScreen.storyboard | 2 +- .../project.pbxproj | 42 ++--- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../apple/deep-link-example_iOS/Info.plist | 17 +- .../deep-link-example_iOS.entitlements | 8 +- .../app/src-tauri/gen/apple/project.yml | 22 +-- plugins/deep-link/src/config.rs | 31 +++- 16 files changed, 158 insertions(+), 178 deletions(-) rename plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/{tauri => kodski}/deep_link_example/MainActivity.kt (86%) rename plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/{tauri => kodski}/deep_link_example/kotlin/BuildTask.kt (100%) rename plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/{tauri => kodski}/deep_link_example/kotlin/RustPlugin.kt (100%) delete mode 100644 plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index 0b00afcea0..dd3041c6fd 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -84,7 +84,6 @@ fn main() { panic!("Deep link config validation failed:\n{}", errors.join("\n")); } - tauri_plugin::mobile::update_android_manifest( "DEEP LINK PLUGIN", "activity", @@ -98,21 +97,38 @@ fn main() { .expect("failed to rewrite AndroidManifest.xml"); - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "ios"))] { - tauri_plugin::mobile::update_entitlements(|entitlements| { - entitlements.insert( - "com.apple.developer.associated-domains".into(), - config + // we need to ensure that the entitlements are only + // generated for explicit app links and not + // other deep links or web links because then they + // are just going to complain and not be built or signed + let has_app_links = config + .mobile + .iter() + .any(|d| d.is_app_link()); + + if !has_app_links { + tauri_plugin::mobile::update_entitlements(|entitlements| { + entitlements.remove("com.apple.developer.associated-domains"); + }) + .expect("failed to update entitlements"); + } else { + tauri_plugin::mobile::update_entitlements(|entitlements| { + entitlements.insert( + "com.apple.developer.associated-domains".into(), + config .mobile .iter() + .filter(|d| d.is_app_link()) .filter_map(|d| d.host.as_ref()) .map(|host| format!("applinks:{}", host).into()) .collect::>() .into(), - ); - }) - .expect("failed to update entitlements"); + ); + }) + .expect("failed to update entitlements"); + } } } } diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore b/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore index 1efb55bd0a..1289b4de81 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore @@ -1,4 +1,4 @@ -/src/main/java/com/tauri/deep_link_example/generated +/src/main/java/com/kodski/deep_link_example/generated /src/main/jniLibs/**/*.so /src/main/assets/tauri.conf.json /tauri.build.gradle.kts diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts b/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts index 13ec1ffd66..5474ef7ad0 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts @@ -15,10 +15,10 @@ val tauriProperties = Properties().apply { android { compileSdk = 36 - namespace = "com.tauri.deep_link_example" + namespace = "com.kodski.deep_link_example" defaultConfig { manifestPlaceholders["usesCleartextTraffic"] = "false" - applicationId = "com.tauri.deep_link_example" + applicationId = "com.kodski.deep_link_example" minSdk = 24 targetSdk = 36 versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml index a650714ce7..93f382ce9a 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -51,7 +51,7 @@ - + diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt similarity index 86% rename from plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt rename to plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt index 313161c226..472a33a3af 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt @@ -1,4 +1,4 @@ -package com.tauri.deep_link_example +package com.kodski.deep_link_example import android.os.Bundle import androidx.activity.enableEdgeToEdge diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/BuildTask.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/BuildTask.kt similarity index 100% rename from plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/BuildTask.kt rename to plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/BuildTask.kt diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/RustPlugin.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/RustPlugin.kt similarity index 100% rename from plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/RustPlugin.kt rename to plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/RustPlugin.kt diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json b/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json index dd3b8bcc55..90eea7ec7e 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,116 +1,116 @@ { - "images": [ + "images" : [ { - "size": "20x20", - "idiom": "iphone", - "filename": "AppIcon-20x20@2x.png", - "scale": "2x" + "size" : "20x20", + "idiom" : "iphone", + "filename" : "AppIcon-20x20@2x.png", + "scale" : "2x" }, { - "size": "20x20", - "idiom": "iphone", - "filename": "AppIcon-20x20@3x.png", - "scale": "3x" + "size" : "20x20", + "idiom" : "iphone", + "filename" : "AppIcon-20x20@3x.png", + "scale" : "3x" }, { - "size": "29x29", - "idiom": "iphone", - "filename": "AppIcon-29x29@2x-1.png", - "scale": "2x" + "size" : "29x29", + "idiom" : "iphone", + "filename" : "AppIcon-29x29@2x-1.png", + "scale" : "2x" }, { - "size": "29x29", - "idiom": "iphone", - "filename": "AppIcon-29x29@3x.png", - "scale": "3x" + "size" : "29x29", + "idiom" : "iphone", + "filename" : "AppIcon-29x29@3x.png", + "scale" : "3x" }, { - "size": "40x40", - "idiom": "iphone", - "filename": "AppIcon-40x40@2x.png", - "scale": "2x" + "size" : "40x40", + "idiom" : "iphone", + "filename" : "AppIcon-40x40@2x.png", + "scale" : "2x" }, { - "size": "40x40", - "idiom": "iphone", - "filename": "AppIcon-40x40@3x.png", - "scale": "3x" + "size" : "40x40", + "idiom" : "iphone", + "filename" : "AppIcon-40x40@3x.png", + "scale" : "3x" }, { - "size": "60x60", - "idiom": "iphone", - "filename": "AppIcon-60x60@2x.png", - "scale": "2x" + "size" : "60x60", + "idiom" : "iphone", + "filename" : "AppIcon-60x60@2x.png", + "scale" : "2x" }, { - "size": "60x60", - "idiom": "iphone", - "filename": "AppIcon-60x60@3x.png", - "scale": "3x" + "size" : "60x60", + "idiom" : "iphone", + "filename" : "AppIcon-60x60@3x.png", + "scale" : "3x" }, { - "size": "20x20", - "idiom": "ipad", - "filename": "AppIcon-20x20@1x.png", - "scale": "1x" + "size" : "20x20", + "idiom" : "ipad", + "filename" : "AppIcon-20x20@1x.png", + "scale" : "1x" }, { - "size": "20x20", - "idiom": "ipad", - "filename": "AppIcon-20x20@2x-1.png", - "scale": "2x" + "size" : "20x20", + "idiom" : "ipad", + "filename" : "AppIcon-20x20@2x-1.png", + "scale" : "2x" }, { - "size": "29x29", - "idiom": "ipad", - "filename": "AppIcon-29x29@1x.png", - "scale": "1x" + "size" : "29x29", + "idiom" : "ipad", + "filename" : "AppIcon-29x29@1x.png", + "scale" : "1x" }, { - "size": "29x29", - "idiom": "ipad", - "filename": "AppIcon-29x29@2x.png", - "scale": "2x" + "size" : "29x29", + "idiom" : "ipad", + "filename" : "AppIcon-29x29@2x.png", + "scale" : "2x" }, { - "size": "40x40", - "idiom": "ipad", - "filename": "AppIcon-40x40@1x.png", - "scale": "1x" + "size" : "40x40", + "idiom" : "ipad", + "filename" : "AppIcon-40x40@1x.png", + "scale" : "1x" }, { - "size": "40x40", - "idiom": "ipad", - "filename": "AppIcon-40x40@2x-1.png", - "scale": "2x" + "size" : "40x40", + "idiom" : "ipad", + "filename" : "AppIcon-40x40@2x-1.png", + "scale" : "2x" }, { - "size": "76x76", - "idiom": "ipad", - "filename": "AppIcon-76x76@1x.png", - "scale": "1x" + "size" : "76x76", + "idiom" : "ipad", + "filename" : "AppIcon-76x76@1x.png", + "scale" : "1x" }, { - "size": "76x76", - "idiom": "ipad", - "filename": "AppIcon-76x76@2x.png", - "scale": "2x" + "size" : "76x76", + "idiom" : "ipad", + "filename" : "AppIcon-76x76@2x.png", + "scale" : "2x" }, { - "size": "83.5x83.5", - "idiom": "ipad", - "filename": "AppIcon-83.5x83.5@2x.png", - "scale": "2x" + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "AppIcon-83.5x83.5@2x.png", + "scale" : "2x" }, { - "size": "1024x1024", - "idiom": "ios-marketing", - "filename": "AppIcon-512@2x.png", - "scale": "1x" + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "AppIcon-512@2x.png", + "scale" : "1x" } ], - "info": { - "version": 1, - "author": "xcode" + "info" : { + "version" : 1, + "author" : "xcode" } -} +} \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/Contents.json b/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/Contents.json index 97a8662ebd..da4a164c91 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/Contents.json +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info": { - "version": 1, - "author": "xcode" + "info" : { + "version" : 1, + "author" : "xcode" } -} +} \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/LaunchScreen.storyboard b/plugins/deep-link/examples/app/src-tauri/gen/apple/LaunchScreen.storyboard index dd79351ec8..81b5f90e2f 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/LaunchScreen.storyboard +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/LaunchScreen.storyboard @@ -1,5 +1,5 @@ - + diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj index 3307dbf8ed..8ce845b09e 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 63; objects = { /* Begin PBXBuildFile section */ @@ -167,6 +167,8 @@ dependencies = ( ); name = "deep-link-example_iOS"; + packageProductDependencies = ( + ); productName = "deep-link-example_iOS"; productReference = 1CAAFA750FD735A285DC1238 /* deep-link-example.app */; productType = "com.apple.product-type.application"; @@ -189,6 +191,7 @@ en, ); mainGroup = 1DC58B1705AA3ECC6B887FE7; + minimizedProjectReferenceProxies = 1; projectDirPath = ""; projectRoot = ""; targets = ( @@ -227,7 +230,6 @@ outputPaths = ( "$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a", "$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a", - "$(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/libapp.a", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -314,18 +316,13 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ARCHS = ( - arm64, - "arm64-sim", - ); + ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7F2T2WK6DR; ENABLE_BITCODE = NO; - "EXCLUDED_ARCHS[sdk=iphoneos*]" = "arm64-sim x86_64"; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\".\"", @@ -335,13 +332,6 @@ "$(inherited)", "@executable_path/Frameworks", ); - "LIBRARY_SEARCH_PATHS[arch=arm64-sim]" = ( - "$(inherited)", - "$(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION)", - "$(SDKROOT)/usr/lib/swift", - "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", - "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", - ); "LIBRARY_SEARCH_PATHS[arch=arm64]" = ( "$(inherited)", "$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)", @@ -360,7 +350,7 @@ PRODUCT_NAME = "deep-link-example"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "arm64 arm64-sim"; + VALID_ARCHS = arm64; }; name = debug; }; @@ -424,18 +414,13 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ARCHS = ( - arm64, - "arm64-sim", - ); + ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7F2T2WK6DR; ENABLE_BITCODE = NO; - "EXCLUDED_ARCHS[sdk=iphoneos*]" = "arm64-sim x86_64"; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; + "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\".\"", @@ -445,13 +430,6 @@ "$(inherited)", "@executable_path/Frameworks", ); - "LIBRARY_SEARCH_PATHS[arch=arm64-sim]" = ( - "$(inherited)", - "$(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION)", - "$(SDKROOT)/usr/lib/swift", - "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", - "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", - ); "LIBRARY_SEARCH_PATHS[arch=arm64]" = ( "$(inherited)", "$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)", @@ -470,7 +448,7 @@ PRODUCT_NAME = "deep-link-example"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "arm64 arm64-sim"; + VALID_ARCHS = arm64; }; name = release; }; diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d..0000000000 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist index 3d3c9ef3c1..e0b133532b 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist @@ -15,22 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.0.0 - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLIconFile - Assets - CFBundleURLName - com.tauri.deep-link-example - CFBundleURLSchemes - - w3ds - - - + 0.1.0 CFBundleVersion 0.1.0 LSRequiresIPhoneOS diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements index 3216c743b7..21e2f8d830 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements @@ -1,11 +1,5 @@ - - com.apple.developer.associated-domains - - applinks:fabianlars.de - applinks:tauri.app - - + \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml b/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml index c924ca77bd..e7ad23d4a0 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml @@ -1,10 +1,6 @@ -# Copyright 2019-2023 Tauri Programme within The Commons Conservancy -# SPDX-License-Identifier: Apache-2.0 -# SPDX-License-Identifier: MIT - name: deep-link-example options: - bundleIdPrefix: com.tauri.deep-link-example + bundleIdPrefix: com.kodski.deep-link-example deploymentTarget: iOS: 13.0 fileGroups: [../../src] @@ -15,8 +11,7 @@ settingGroups: app: base: PRODUCT_NAME: deep-link-example - PRODUCT_BUNDLE_IDENTIFIER: com.tauri.deep-link-example - DEVELOPMENT_TEAM: Q93MBH6S2F + PRODUCT_BUNDLE_IDENTIFIER: com.kodski.deep-link-example targetTemplates: app: type: application @@ -56,8 +51,8 @@ targets: - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - CFBundleShortVersionString: 0.0.0 - CFBundleVersion: 0.0.0 + CFBundleShortVersionString: 0.1.0 + CFBundleVersion: '0.1.0' entitlements: path: deep-link-example_iOS/deep-link-example_iOS.entitlements scheme: @@ -67,14 +62,12 @@ targets: settings: base: ENABLE_BITCODE: false - ARCHS: [arm64, arm64-sim] - VALID_ARCHS: arm64 arm64-sim + ARCHS: [arm64] + VALID_ARCHS: arm64 LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) - LIBRARY_SEARCH_PATHS[arch=arm64-sim]: $(inherited) $(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true - EXCLUDED_ARCHS[sdk=iphonesimulator*]: arm64 - EXCLUDED_ARCHS[sdk=iphoneos*]: arm64-sim x86_64 + EXCLUDED_ARCHS[sdk=iphoneos*]: x86_64 groups: [app] dependencies: - framework: libapp.a @@ -93,4 +86,3 @@ targets: outputFiles: - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a - - $(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/libapp.a diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 0ba3424662..2f98f30f68 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -11,10 +11,8 @@ use tauri_utils::config::DeepLinkProtocol; pub struct AssociatedDomain { #[serde(default = "default_schemes")] pub scheme: Vec, - #[serde(default, deserialize_with = "deserialize_associated_host")] pub host: Option, // Optional custom uri schemes dont NEED a host (may have one still), but required for https/http schemes - #[serde(default)] pub path: Vec, #[serde(default, alias = "path-pattern", rename = "pathPattern")] @@ -23,13 +21,38 @@ pub struct AssociatedDomain { pub path_prefix: Vec, #[serde(default, alias = "path-suffix", rename = "pathSuffix")] pub path_suffix: Vec, + #[serde(default, alias = "app-link", rename = "appLink")] + pub app_link: bool, } impl AssociatedDomain { + /// Returns true if the domain uses http or https scheme and has a host. + pub fn is_web_link(&self) -> bool { + self.host.is_some() && self.scheme.iter().any(|s| s == "https" || s == "http") + } + + /// Returns true if marked as AppLink and has proper configuration. + pub fn is_app_link(&self) -> bool { + self.app_link && self.is_web_link() && self.host.is_some() + } + pub fn validate(&self) -> Result<(), String> { - if self.host.is_none() && self.scheme.iter().any(|s| s == "https" || s == "http") { - return Err("host is required when using https/http schemes".into()); + // Rule 1: All web links require a host. + if self.is_web_link() && self.host.is_none() { + return Err("Web link requires a host".into()); } + + // Rule 2: If it's an App Link, ensure http(s) and host. + if self.app_link { + if !self.is_web_link() { + return Err("AppLink must be a valid web link (https/http + host)".into()); + } + + if self.scheme.iter().any(|s| s == "http") && !self.scheme.iter().any(|s| s == "https") { + eprintln!("Warning: AppLink uses only 'http' — allowed on Android but not secure for production."); + } + } + Ok(()) } } From d6d26e5070733992789dab00c486d627a6ddeaa2 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 00:39:44 +0530 Subject: [PATCH 03/20] feat: add ios code --- plugins/deep-link/build.rs | 1 + plugins/deep-link/ios/.gitignore | 10 ++ plugins/deep-link/ios/Package.swift | 32 +++++ plugins/deep-link/ios/README.md | 3 + .../ios/Sources/DeepLinkPlugin.swift | 113 ++++++++++++++++++ .../ios/Tests/PluginTests/PluginTests.swift | 8 ++ plugins/deep-link/package.json | 3 + plugins/deep-link/src/lib.rs | 54 +++++++-- pnpm-lock.yaml | 4 + 9 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 plugins/deep-link/ios/.gitignore create mode 100644 plugins/deep-link/ios/Package.swift create mode 100644 plugins/deep-link/ios/README.md create mode 100644 plugins/deep-link/ios/Sources/DeepLinkPlugin.swift create mode 100644 plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index dd3041c6fd..f3c375c2c3 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -66,6 +66,7 @@ fn main() { let result = tauri_plugin::Builder::new(COMMANDS) .global_api_script_path("./api-iife.js") .android_path("android") + .ios_path("ios") .try_build(); // when building documentation for Android the plugin build result is always Err() and is irrelevant to the crate documentation build diff --git a/plugins/deep-link/ios/.gitignore b/plugins/deep-link/ios/.gitignore new file mode 100644 index 0000000000..5922fdaa56 --- /dev/null +++ b/plugins/deep-link/ios/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc +Package.resolved diff --git a/plugins/deep-link/ios/Package.swift b/plugins/deep-link/ios/Package.swift new file mode 100644 index 0000000000..b41ec6f8f8 --- /dev/null +++ b/plugins/deep-link/ios/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "tauri-plugin-deep-link", + platforms: [ + .macOS(.v10_13), + .iOS(.v13), + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "tauri-plugin-deep-link", + type: .static, + targets: ["tauri-plugin-deep-link"]), + ], + dependencies: [ + .package(name: "Tauri", path: "../.tauri/tauri-api") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "tauri-plugin-deep-link", + dependencies: [ + .byName(name: "Tauri") + ], + path: "Sources") + ] +) diff --git a/plugins/deep-link/ios/README.md b/plugins/deep-link/ios/README.md new file mode 100644 index 0000000000..a8eb054dfd --- /dev/null +++ b/plugins/deep-link/ios/README.md @@ -0,0 +1,3 @@ +# Tauri Plugin deep-link + +A description of this package. diff --git a/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift b/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift new file mode 100644 index 0000000000..1486dbe404 --- /dev/null +++ b/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift @@ -0,0 +1,113 @@ +import SwiftRs +import Tauri +import UIKit +import WebKit + +struct SetEventHandlerArgs: Decodable { + let handler: Channel +} + +@objc class DeepLinkPlugin: Plugin { + private var webView: WKWebView? + private var currentUrl: String? + private var channel: Channel? + + // Called when the plugin is loaded + @objc public override func load(webview: WKWebView) { + super.load(webview: webview) + self.webView = webview + DeepLinkPlugin.instance = self + + // Check if app was launched via URL + if let url = DeepLinkPlugin.launchedUrl { + // If so, send to JS + var event = JSObject() + event["url"] = url.absoluteString + self.channel?.send(event) + } + } + + // JS command: return current URL + @objc public func getCurrent(_ invoke: Invoke) throws { + var ret = JSObject() + ret["url"] = self.currentUrl + invoke.resolve(ret) + } + + // JS command: set the JS callback handler channel + @objc public func setEventHandler(_ invoke: Invoke) throws { + let args = try invoke.parseArgs(SetEventHandlerArgs.self) + self.channel = args.handler + invoke.resolve() + } + + // Static helpers to store/dispatch URLs + static var instance: DeepLinkPlugin? + static var launchedUrl: URL? + static func handleOpenUrl(_ url: URL) { + // Called from AppDelegate/SceneDelegate + if let plugin = DeepLinkPlugin.instance { + plugin.currentUrl = url.absoluteString + if let ch = plugin.channel { + var event = JSObject() + event["url"] = url.absoluteString + ch.send(event) + } + } else { + // App not yet initialized; save for load() + DeepLinkPlugin.launchedUrl = url + } + } +} + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + DeepLinkPlugin.handleOpenUrl(url) + return true + } +} + + + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + // Called when a scene is being created and connected + func scene(_ scene: UIScene, + willConnectTo session: UISceneSession, + options connectionOptions: UIScene.ConnectionOptions) { + + // Handle initial URL if app was launched via a deep link + if let urlContext = connectionOptions.urlContexts.first { + DeepLinkPlugin.handleOpenUrl(urlContext.url) + } + } + + // Called when the app receives a deep link while already running + func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { + guard let url = URLContexts.first?.url else { return } + DeepLinkPlugin.handleOpenUrl(url) + } +} + +@_cdecl("init_plugin_deep_link") +func initPlugin() -> Plugin { + return DeepLinkPlugin() +} + +// import Tauri +// import UIKit +// import WebKit + +// class PingArgs: Decodable { +// let value: String? +// } + +// class ExamplePlugin: Plugin { +// @objc public func ping(_ invoke: Invoke) throws { +// let args = try invoke.parseArgs(PingArgs.self) +// invoke.resolve(["value": args.value ?? ""]) +// } +// } diff --git a/plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift b/plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift new file mode 100644 index 0000000000..4f8e9ace33 --- /dev/null +++ b/plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift @@ -0,0 +1,8 @@ +import XCTest +@testable import ExamplePlugin + +final class ExamplePluginTests: XCTestCase { + func testExample() throws { + let plugin = ExamplePlugin() + } +} diff --git a/plugins/deep-link/package.json b/plugins/deep-link/package.json index b316c481dd..fc1feb12bc 100644 --- a/plugins/deep-link/package.json +++ b/plugins/deep-link/package.json @@ -26,5 +26,8 @@ ], "dependencies": { "@tauri-apps/api": "^2.6.0" + }, + "devDependencies": { + "@tauri-apps/cli": "2.7.1" } } diff --git a/plugins/deep-link/src/lib.rs b/plugins/deep-link/src/lib.rs index 1cd13b580a..6280ee91f3 100644 --- a/plugins/deep-link/src/lib.rs +++ b/plugins/deep-link/src/lib.rs @@ -16,11 +16,14 @@ pub use error::{Error, Result}; #[cfg(target_os = "android")] const PLUGIN_IDENTIFIER: &str = "app.tauri.deep_link"; +#[cfg(target_os = "ios")] +tauri::ios_plugin_binding!(init_plugin_deep_link); + fn init_deep_link( app: &AppHandle, api: PluginApi>, ) -> crate::Result> { - #[cfg(target_os = "android")] + #[cfg(mobile)] { let _api = api; @@ -29,8 +32,12 @@ fn init_deep_link( Emitter, }; + #[cfg(target_os = "android")] let handle = _api.register_android_plugin(PLUGIN_IDENTIFIER, "DeepLinkPlugin")?; + #[cfg(target_os = "ios")] + let handle = _api.register_ios_plugin(init_plugin_deep_link)?; + #[derive(serde::Deserialize)] struct Event { url: String, @@ -56,20 +63,49 @@ fn init_deep_link( }), }, )?; + + #[cfg(target_os = "android")] + { + return Ok(DeepLink { + app: app.clone(), + plugin_handle: handle, + }); + } + + #[cfg(target_os = "ios")] + { + return Ok(DeepLink { + app: app.clone(), + current: Default::default(), + config: api.config().clone(), + plugin_handle: handle, + }) + } + } + #[cfg(target_os = "ios")] + { + + let _api = api; + + use tauri::{ + ipc::{Channel, InvokeResponseBody}, + Emitter, + }; + + #[derive(serde::Deserialize)] + struct Event { + url: String, + } + + let handle = _api.register_ios_plugin(init_plugin_deep_link)?; return Ok(DeepLink { app: app.clone(), - plugin_handle: handle, + current: Default::default(), + config: api.config().clone(), }); } - #[cfg(target_os = "ios")] - return Ok(DeepLink { - app: app.clone(), - current: Default::default(), - config: api.config().clone(), - }); - #[cfg(desktop)] { let args = std::env::args(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2458fc0fd4..34bc4dfe43 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,6 +177,10 @@ importers: '@tauri-apps/api': specifier: ^2.6.0 version: 2.7.0 + devDependencies: + '@tauri-apps/cli': + specifier: 2.7.1 + version: 2.7.1 plugins/deep-link/examples/app: dependencies: From 5327809755efb7b761c174e5fa4cd438113f3878 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 01:25:30 +0530 Subject: [PATCH 04/20] fix: add ios deeplink adaptation --- .../examples/app/src-tauri/Info.ios.plist | 17 ++++++++++ .../apple/deep-link-example_iOS/Info.plist | 11 +++++++ plugins/deep-link/src/lib.rs | 33 ++++--------------- 3 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 plugins/deep-link/examples/app/src-tauri/Info.ios.plist diff --git a/plugins/deep-link/examples/app/src-tauri/Info.ios.plist b/plugins/deep-link/examples/app/src-tauri/Info.ios.plist new file mode 100644 index 0000000000..c13033adbb --- /dev/null +++ b/plugins/deep-link/examples/app/src-tauri/Info.ios.plist @@ -0,0 +1,17 @@ + + + + + CFBundleURLTypes + + + CFBundleURLName + com.kodski.deep-link-example + CFBundleURLSchemes + + taurideeplink + + + + + diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist index e0b133532b..13148133d8 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist @@ -40,5 +40,16 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + CFBundleURLTypes + + + CFBundleURLName + com.kodski.deep-link-example + CFBundleURLSchemes + + taurideeplink + + + \ No newline at end of file diff --git a/plugins/deep-link/src/lib.rs b/plugins/deep-link/src/lib.rs index 6280ee91f3..f5284957e0 100644 --- a/plugins/deep-link/src/lib.rs +++ b/plugins/deep-link/src/lib.rs @@ -76,36 +76,12 @@ fn init_deep_link( { return Ok(DeepLink { app: app.clone(), - current: Default::default(), - config: api.config().clone(), plugin_handle: handle, + current: Default::default(), }) } } - #[cfg(target_os = "ios")] - { - - let _api = api; - - use tauri::{ - ipc::{Channel, InvokeResponseBody}, - Emitter, - }; - - #[derive(serde::Deserialize)] - struct Event { - url: String, - } - - let handle = _api.register_ios_plugin(init_plugin_deep_link)?; - return Ok(DeepLink { - app: app.clone(), - current: Default::default(), - config: api.config().clone(), - }); - } - #[cfg(desktop)] { let args = std::env::args(); @@ -120,8 +96,9 @@ fn init_deep_link( } } -#[cfg(target_os = "android")] +#[cfg(mobile)] mod imp { + use std::sync::Mutex; use tauri::{ipc::Channel, plugin::PluginHandle, AppHandle, Runtime}; use serde::{Deserialize, Serialize}; @@ -142,6 +119,8 @@ mod imp { pub struct DeepLink { pub(crate) app: AppHandle, pub(crate) plugin_handle: PluginHandle, + #[cfg(target_os = "ios")] + pub(crate) current: Mutex>>, } impl DeepLink { @@ -195,7 +174,7 @@ mod imp { } } -#[cfg(not(target_os = "android"))] +#[cfg(not(mobile))] mod imp { use std::sync::Mutex; #[cfg(target_os = "linux")] From b3b6db2a46d33008e70e85eb4b85f535e916e9e2 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 02:19:44 +0530 Subject: [PATCH 05/20] feat: ios working (some swift plugin api improvements needed) --- .../ios/Sources/DeepLinkPlugin.swift | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift b/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift index 1486dbe404..d0a6a51928 100644 --- a/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift +++ b/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift @@ -31,10 +31,12 @@ struct SetEventHandlerArgs: Decodable { @objc public func getCurrent(_ invoke: Invoke) throws { var ret = JSObject() ret["url"] = self.currentUrl + Logger.info("getCurrent: \(String(describing: ret))") invoke.resolve(ret) } - // JS command: set the JS callback handler channel + // This command should not be added to the `build.rs` and exposed as it is only + // used internally from the rust backend. @objc public func setEventHandler(_ invoke: Invoke) throws { let args = try invoke.parseArgs(SetEventHandlerArgs.self) self.channel = args.handler @@ -64,33 +66,34 @@ struct SetEventHandlerArgs: Decodable { class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { DeepLinkPlugin.handleOpenUrl(url) + Logger.info("AppDelegate: Opened URL: \(url)") return true } } -class SceneDelegate: UIResponder, UIWindowSceneDelegate { +// class SceneDelegate: UIResponder, UIWindowSceneDelegate { - var window: UIWindow? +// var window: UIWindow? - // Called when a scene is being created and connected - func scene(_ scene: UIScene, - willConnectTo session: UISceneSession, - options connectionOptions: UIScene.ConnectionOptions) { +// // Called when a scene is being created and connected +// func scene(_ scene: UIScene, +// willConnectTo session: UISceneSession, +// options connectionOptions: UIScene.ConnectionOptions) { - // Handle initial URL if app was launched via a deep link - if let urlContext = connectionOptions.urlContexts.first { - DeepLinkPlugin.handleOpenUrl(urlContext.url) - } - } +// // Handle initial URL if app was launched via a deep link +// if let urlContext = connectionOptions.urlContexts.first { +// DeepLinkPlugin.handleOpenUrl(urlContext.url) +// } +// } - // Called when the app receives a deep link while already running - func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { - guard let url = URLContexts.first?.url else { return } - DeepLinkPlugin.handleOpenUrl(url) - } -} +// // Called when the app receives a deep link while already running +// func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { +// guard let url = URLContexts.first?.url else { return } +// DeepLinkPlugin.handleOpenUrl(url) +// } +// } @_cdecl("init_plugin_deep_link") func initPlugin() -> Plugin { From f6aae7a7f55dbb5872f0515d9ef863cd2aa48764 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 15:32:58 +0530 Subject: [PATCH 06/20] fix: revert ios to prior logic --- plugins/deep-link/build.rs | 1 - plugins/deep-link/index.html | 3 + plugins/deep-link/ios/.gitignore | 10 -- plugins/deep-link/ios/Package.swift | 32 ----- plugins/deep-link/ios/README.md | 3 - .../ios/Sources/DeepLinkPlugin.swift | 116 ------------------ .../ios/Tests/PluginTests/PluginTests.swift | 8 -- plugins/deep-link/src/lib.rs | 51 +++----- 8 files changed, 20 insertions(+), 204 deletions(-) create mode 100644 plugins/deep-link/index.html delete mode 100644 plugins/deep-link/ios/.gitignore delete mode 100644 plugins/deep-link/ios/Package.swift delete mode 100644 plugins/deep-link/ios/README.md delete mode 100644 plugins/deep-link/ios/Sources/DeepLinkPlugin.swift delete mode 100644 plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index f3c375c2c3..dd3041c6fd 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -66,7 +66,6 @@ fn main() { let result = tauri_plugin::Builder::new(COMMANDS) .global_api_script_path("./api-iife.js") .android_path("android") - .ios_path("ios") .try_build(); // when building documentation for Android the plugin build result is always Err() and is irrelevant to the crate documentation build diff --git a/plugins/deep-link/index.html b/plugins/deep-link/index.html new file mode 100644 index 0000000000..b0a14c370c --- /dev/null +++ b/plugins/deep-link/index.html @@ -0,0 +1,3 @@ +test
+ +cant touch this diff --git a/plugins/deep-link/ios/.gitignore b/plugins/deep-link/ios/.gitignore deleted file mode 100644 index 5922fdaa56..0000000000 --- a/plugins/deep-link/ios/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -.DS_Store -/.build -/Packages -/*.xcodeproj -xcuserdata/ -DerivedData/ -.swiftpm/config/registries.json -.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata -.netrc -Package.resolved diff --git a/plugins/deep-link/ios/Package.swift b/plugins/deep-link/ios/Package.swift deleted file mode 100644 index b41ec6f8f8..0000000000 --- a/plugins/deep-link/ios/Package.swift +++ /dev/null @@ -1,32 +0,0 @@ -// swift-tools-version:5.3 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "tauri-plugin-deep-link", - platforms: [ - .macOS(.v10_13), - .iOS(.v13), - ], - products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. - .library( - name: "tauri-plugin-deep-link", - type: .static, - targets: ["tauri-plugin-deep-link"]), - ], - dependencies: [ - .package(name: "Tauri", path: "../.tauri/tauri-api") - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. - .target( - name: "tauri-plugin-deep-link", - dependencies: [ - .byName(name: "Tauri") - ], - path: "Sources") - ] -) diff --git a/plugins/deep-link/ios/README.md b/plugins/deep-link/ios/README.md deleted file mode 100644 index a8eb054dfd..0000000000 --- a/plugins/deep-link/ios/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Tauri Plugin deep-link - -A description of this package. diff --git a/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift b/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift deleted file mode 100644 index d0a6a51928..0000000000 --- a/plugins/deep-link/ios/Sources/DeepLinkPlugin.swift +++ /dev/null @@ -1,116 +0,0 @@ -import SwiftRs -import Tauri -import UIKit -import WebKit - -struct SetEventHandlerArgs: Decodable { - let handler: Channel -} - -@objc class DeepLinkPlugin: Plugin { - private var webView: WKWebView? - private var currentUrl: String? - private var channel: Channel? - - // Called when the plugin is loaded - @objc public override func load(webview: WKWebView) { - super.load(webview: webview) - self.webView = webview - DeepLinkPlugin.instance = self - - // Check if app was launched via URL - if let url = DeepLinkPlugin.launchedUrl { - // If so, send to JS - var event = JSObject() - event["url"] = url.absoluteString - self.channel?.send(event) - } - } - - // JS command: return current URL - @objc public func getCurrent(_ invoke: Invoke) throws { - var ret = JSObject() - ret["url"] = self.currentUrl - Logger.info("getCurrent: \(String(describing: ret))") - invoke.resolve(ret) - } - - // This command should not be added to the `build.rs` and exposed as it is only - // used internally from the rust backend. - @objc public func setEventHandler(_ invoke: Invoke) throws { - let args = try invoke.parseArgs(SetEventHandlerArgs.self) - self.channel = args.handler - invoke.resolve() - } - - // Static helpers to store/dispatch URLs - static var instance: DeepLinkPlugin? - static var launchedUrl: URL? - static func handleOpenUrl(_ url: URL) { - // Called from AppDelegate/SceneDelegate - if let plugin = DeepLinkPlugin.instance { - plugin.currentUrl = url.absoluteString - if let ch = plugin.channel { - var event = JSObject() - event["url"] = url.absoluteString - ch.send(event) - } - } else { - // App not yet initialized; save for load() - DeepLinkPlugin.launchedUrl = url - } - } -} - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - DeepLinkPlugin.handleOpenUrl(url) - Logger.info("AppDelegate: Opened URL: \(url)") - return true - } -} - - - -// class SceneDelegate: UIResponder, UIWindowSceneDelegate { - -// var window: UIWindow? - -// // Called when a scene is being created and connected -// func scene(_ scene: UIScene, -// willConnectTo session: UISceneSession, -// options connectionOptions: UIScene.ConnectionOptions) { - -// // Handle initial URL if app was launched via a deep link -// if let urlContext = connectionOptions.urlContexts.first { -// DeepLinkPlugin.handleOpenUrl(urlContext.url) -// } -// } - -// // Called when the app receives a deep link while already running -// func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { -// guard let url = URLContexts.first?.url else { return } -// DeepLinkPlugin.handleOpenUrl(url) -// } -// } - -@_cdecl("init_plugin_deep_link") -func initPlugin() -> Plugin { - return DeepLinkPlugin() -} - -// import Tauri -// import UIKit -// import WebKit - -// class PingArgs: Decodable { -// let value: String? -// } - -// class ExamplePlugin: Plugin { -// @objc public func ping(_ invoke: Invoke) throws { -// let args = try invoke.parseArgs(PingArgs.self) -// invoke.resolve(["value": args.value ?? ""]) -// } -// } diff --git a/plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift b/plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift deleted file mode 100644 index 4f8e9ace33..0000000000 --- a/plugins/deep-link/ios/Tests/PluginTests/PluginTests.swift +++ /dev/null @@ -1,8 +0,0 @@ -import XCTest -@testable import ExamplePlugin - -final class ExamplePluginTests: XCTestCase { - func testExample() throws { - let plugin = ExamplePlugin() - } -} diff --git a/plugins/deep-link/src/lib.rs b/plugins/deep-link/src/lib.rs index f5284957e0..4bc6e1ac8f 100644 --- a/plugins/deep-link/src/lib.rs +++ b/plugins/deep-link/src/lib.rs @@ -16,14 +16,11 @@ pub use error::{Error, Result}; #[cfg(target_os = "android")] const PLUGIN_IDENTIFIER: &str = "app.tauri.deep_link"; -#[cfg(target_os = "ios")] -tauri::ios_plugin_binding!(init_plugin_deep_link); - fn init_deep_link( app: &AppHandle, api: PluginApi>, ) -> crate::Result> { - #[cfg(mobile)] + #[cfg(target_os = "android")] { let _api = api; @@ -32,12 +29,8 @@ fn init_deep_link( Emitter, }; - #[cfg(target_os = "android")] let handle = _api.register_android_plugin(PLUGIN_IDENTIFIER, "DeepLinkPlugin")?; - #[cfg(target_os = "ios")] - let handle = _api.register_ios_plugin(init_plugin_deep_link)?; - #[derive(serde::Deserialize)] struct Event { url: String, @@ -64,25 +57,23 @@ fn init_deep_link( }, )?; - #[cfg(target_os = "android")] - { - return Ok(DeepLink { - app: app.clone(), - plugin_handle: handle, - }); - } + return Ok(DeepLink { + app: app.clone(), + plugin_handle: handle, + }); + } - #[cfg(target_os = "ios")] - { - return Ok(DeepLink { - app: app.clone(), - plugin_handle: handle, - current: Default::default(), - }) - } + #[cfg(target_os = "ios")] + { + let deep_link = DeepLink { + app: app.clone(), + current: Default::default(), + config: api.config().clone(), + }; + Ok(deep_link) } - #[cfg(desktop)] + #[cfg(any(desktop))] { let args = std::env::args(); let deep_link = DeepLink { @@ -96,7 +87,7 @@ fn init_deep_link( } } -#[cfg(mobile)] +#[cfg(target_os = "android")] mod imp { use std::sync::Mutex; use tauri::{ipc::Channel, plugin::PluginHandle, AppHandle, Runtime}; @@ -115,14 +106,6 @@ mod imp { pub url: Option, } - /// Access to the deep-link APIs. - pub struct DeepLink { - pub(crate) app: AppHandle, - pub(crate) plugin_handle: PluginHandle, - #[cfg(target_os = "ios")] - pub(crate) current: Mutex>>, - } - impl DeepLink { /// 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. /// @@ -174,7 +157,7 @@ mod imp { } } -#[cfg(not(mobile))] +#[cfg(not(target_os = "android"))] mod imp { use std::sync::Mutex; #[cfg(target_os = "linux")] From 24eb8b8b61b43186ea42b57d97270e7faf87df2b Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 15:49:14 +0530 Subject: [PATCH 07/20] fix(cleanup): regen android files with old names --- .../app/src-tauri/gen/android/app/.gitignore | 2 +- .../gen/android/app/build.gradle.kts | 4 +- .../kodski/deep_link_example/MainActivity.kt | 11 --- .../deep_link_example/kotlin/BuildTask.kt | 52 ------------ .../deep_link_example/kotlin/RustPlugin.kt | 85 ------------------- .../examples/app/src-tauri/tauri.conf.json | 2 +- plugins/deep-link/src/lib.rs | 26 +++--- 7 files changed, 18 insertions(+), 164 deletions(-) delete mode 100644 plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt delete mode 100644 plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/BuildTask.kt delete mode 100644 plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/RustPlugin.kt diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore b/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore index 1289b4de81..1efb55bd0a 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/.gitignore @@ -1,4 +1,4 @@ -/src/main/java/com/kodski/deep_link_example/generated +/src/main/java/com/tauri/deep_link_example/generated /src/main/jniLibs/**/*.so /src/main/assets/tauri.conf.json /tauri.build.gradle.kts diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts b/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts index 5474ef7ad0..13ec1ffd66 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/build.gradle.kts @@ -15,10 +15,10 @@ val tauriProperties = Properties().apply { android { compileSdk = 36 - namespace = "com.kodski.deep_link_example" + namespace = "com.tauri.deep_link_example" defaultConfig { manifestPlaceholders["usesCleartextTraffic"] = "false" - applicationId = "com.kodski.deep_link_example" + applicationId = "com.tauri.deep_link_example" minSdk = 24 targetSdk = 36 versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt deleted file mode 100644 index 472a33a3af..0000000000 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/kodski/deep_link_example/MainActivity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.kodski.deep_link_example - -import android.os.Bundle -import androidx.activity.enableEdgeToEdge - -class MainActivity : TauriActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - enableEdgeToEdge() - super.onCreate(savedInstanceState) - } -} diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/BuildTask.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/BuildTask.kt deleted file mode 100644 index f987482584..0000000000 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/BuildTask.kt +++ /dev/null @@ -1,52 +0,0 @@ -import java.io.File -import org.apache.tools.ant.taskdefs.condition.Os -import org.gradle.api.DefaultTask -import org.gradle.api.GradleException -import org.gradle.api.logging.LogLevel -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction - -open class BuildTask : DefaultTask() { - @Input - var rootDirRel: String? = null - @Input - var target: String? = null - @Input - var release: Boolean? = null - - @TaskAction - fun assemble() { - val executable = """pnpm"""; - try { - runTauriCli(executable) - } catch (e: Exception) { - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - runTauriCli("$executable.cmd") - } else { - throw e; - } - } - } - - fun runTauriCli(executable: String) { - val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null") - val target = target ?: throw GradleException("target cannot be null") - val release = release ?: throw GradleException("release cannot be null") - val args = listOf("tauri", "android", "android-studio-script"); - - project.exec { - workingDir(File(project.projectDir, rootDirRel)) - executable(executable) - args(args) - if (project.logger.isEnabled(LogLevel.DEBUG)) { - args("-vv") - } else if (project.logger.isEnabled(LogLevel.INFO)) { - args("-v") - } - if (release) { - args("--release") - } - args(listOf("--target", target)) - }.assertNormalExitValue() - } -} \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/RustPlugin.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/RustPlugin.kt deleted file mode 100644 index 4aa7fcaf67..0000000000 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/kodski/deep_link_example/kotlin/RustPlugin.kt +++ /dev/null @@ -1,85 +0,0 @@ -import com.android.build.api.dsl.ApplicationExtension -import org.gradle.api.DefaultTask -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.get - -const val TASK_GROUP = "rust" - -open class Config { - lateinit var rootDirRel: String -} - -open class RustPlugin : Plugin { - private lateinit var config: Config - - override fun apply(project: Project) = with(project) { - config = extensions.create("rust", Config::class.java) - - val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64"); - val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList - - val defaultArchList = listOf("arm64", "arm", "x86", "x86_64"); - val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList - - val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64") - - extensions.configure { - @Suppress("UnstableApiUsage") - flavorDimensions.add("abi") - productFlavors { - create("universal") { - dimension = "abi" - ndk { - abiFilters += abiList - } - } - defaultArchList.forEachIndexed { index, arch -> - create(arch) { - dimension = "abi" - ndk { - abiFilters.add(defaultAbiList[index]) - } - } - } - } - } - - afterEvaluate { - for (profile in listOf("debug", "release")) { - val profileCapitalized = profile.replaceFirstChar { it.uppercase() } - val buildTask = tasks.maybeCreate( - "rustBuildUniversal$profileCapitalized", - DefaultTask::class.java - ).apply { - group = TASK_GROUP - description = "Build dynamic library in $profile mode for all targets" - } - - tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask) - - for (targetPair in targetsList.withIndex()) { - val targetName = targetPair.value - val targetArch = archList[targetPair.index] - val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() } - val targetBuildTask = project.tasks.maybeCreate( - "rustBuild$targetArchCapitalized$profileCapitalized", - BuildTask::class.java - ).apply { - group = TASK_GROUP - description = "Build dynamic library in $profile mode for $targetArch" - rootDirRel = config.rootDirRel - target = targetName - release = profile == "release" - } - - buildTask.dependsOn(targetBuildTask) - tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn( - targetBuildTask - ) - } - } - } - } -} \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json index 2df503a61d..61f7394df6 100644 --- a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json +++ b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "productName": "deep-link-example", "version": "0.1.0", - "identifier": "com.kodski.deep-link-example", + "identifier": "com.tauri.deep-link-example", "build": { "devUrl": "http://localhost:1420", "frontendDist": "../dist", diff --git a/plugins/deep-link/src/lib.rs b/plugins/deep-link/src/lib.rs index 4bc6e1ac8f..403d68c2fd 100644 --- a/plugins/deep-link/src/lib.rs +++ b/plugins/deep-link/src/lib.rs @@ -56,7 +56,7 @@ fn init_deep_link( }), }, )?; - + return Ok(DeepLink { app: app.clone(), plugin_handle: handle, @@ -64,16 +64,13 @@ fn init_deep_link( } #[cfg(target_os = "ios")] - { - let deep_link = DeepLink { - app: app.clone(), - current: Default::default(), - config: api.config().clone(), - }; - Ok(deep_link) - } + return Ok(DeepLink { + app: app.clone(), + current: Default::default(), + config: api.config().clone(), + }); - #[cfg(any(desktop))] + #[cfg(desktop)] { let args = std::env::args(); let deep_link = DeepLink { @@ -89,7 +86,6 @@ fn init_deep_link( #[cfg(target_os = "android")] mod imp { - use std::sync::Mutex; use tauri::{ipc::Channel, plugin::PluginHandle, AppHandle, Runtime}; use serde::{Deserialize, Serialize}; @@ -106,6 +102,12 @@ mod imp { pub url: Option, } + /// Access to the deep-link APIs. + pub struct DeepLink { + pub(crate) app: AppHandle, + pub(crate) plugin_handle: PluginHandle, + } + impl DeepLink { /// 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. /// @@ -527,4 +529,4 @@ pub fn init() -> TauriPlugin> { } }) .build() -} +} \ No newline at end of file From 499c10efcbe01cdc1256e56650b321f636395f4d Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 16:04:50 +0530 Subject: [PATCH 08/20] fix: web link criteria --- plugins/deep-link/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 2f98f30f68..4c91824774 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -28,7 +28,7 @@ pub struct AssociatedDomain { impl AssociatedDomain { /// Returns true if the domain uses http or https scheme and has a host. pub fn is_web_link(&self) -> bool { - self.host.is_some() && self.scheme.iter().any(|s| s == "https" || s == "http") + self.scheme.iter().any(|s| s == "https" || s == "http") } /// Returns true if marked as AppLink and has proper configuration. From bf4a10763adc8d3507c11f3d248ceee4087e9141 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 16:57:16 +0530 Subject: [PATCH 09/20] fix: conditional auto verify intent filter for android app links --- plugins/deep-link/build.rs | 8 +++++++- .../gen/android/app/src/main/AndroidManifest.xml | 6 +++--- plugins/deep-link/examples/app/src-tauri/tauri.conf.json | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index dd3041c6fd..f01631b1d2 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -16,8 +16,14 @@ fn intent_filter(domain: &AssociatedDomain) -> String { .map(|h| format!(r#""#)) .unwrap_or_default(); + let auto_verify = if domain.is_app_link() { + r#"android:autoVerify="true" "#.to_string() + } else { + String::new() + }; + format!( - r#" + r#" diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml index 93f382ce9a..9369a1edcc 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -23,7 +23,7 @@ - + @@ -35,7 +35,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json index 61f7394df6..cda424305b 100644 --- a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json +++ b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json @@ -34,7 +34,8 @@ "pathPrefix": ["/intent"] }, { - "host": "tauri.app" + "host": "tauri.app", + "appLink": true }, { "scheme": ["taurideeplink"] From 139f157710f744f1cf20770cea1f179a69d48b52 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 17:52:58 +0530 Subject: [PATCH 10/20] fix: default to true --- .../android/app/src/main/AndroidManifest.xml | 2 +- .../tauri/deep_link_example/MainActivity.kt | 11 +++ .../deep_link_example/kotlin/BuildTask.kt | 52 ++++++++++++ .../deep_link_example/kotlin/RustPlugin.kt | 85 +++++++++++++++++++ .../examples/app/src-tauri/tauri.conf.json | 6 +- plugins/deep-link/src/config.rs | 8 +- 6 files changed, 158 insertions(+), 6 deletions(-) create mode 100644 plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt create mode 100644 plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/BuildTask.kt create mode 100644 plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/RustPlugin.kt diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml index 9369a1edcc..591f3c61e3 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -23,7 +23,7 @@ - + diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt new file mode 100644 index 0000000000..313161c226 --- /dev/null +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/app/src/main/java/com/tauri/deep_link_example/MainActivity.kt @@ -0,0 +1,11 @@ +package com.tauri.deep_link_example + +import android.os.Bundle +import androidx.activity.enableEdgeToEdge + +class MainActivity : TauriActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + } +} diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/BuildTask.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/BuildTask.kt new file mode 100644 index 0000000000..f987482584 --- /dev/null +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/BuildTask.kt @@ -0,0 +1,52 @@ +import java.io.File +import org.apache.tools.ant.taskdefs.condition.Os +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.logging.LogLevel +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +open class BuildTask : DefaultTask() { + @Input + var rootDirRel: String? = null + @Input + var target: String? = null + @Input + var release: Boolean? = null + + @TaskAction + fun assemble() { + val executable = """pnpm"""; + try { + runTauriCli(executable) + } catch (e: Exception) { + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + runTauriCli("$executable.cmd") + } else { + throw e; + } + } + } + + fun runTauriCli(executable: String) { + val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null") + val target = target ?: throw GradleException("target cannot be null") + val release = release ?: throw GradleException("release cannot be null") + val args = listOf("tauri", "android", "android-studio-script"); + + project.exec { + workingDir(File(project.projectDir, rootDirRel)) + executable(executable) + args(args) + if (project.logger.isEnabled(LogLevel.DEBUG)) { + args("-vv") + } else if (project.logger.isEnabled(LogLevel.INFO)) { + args("-v") + } + if (release) { + args("--release") + } + args(listOf("--target", target)) + }.assertNormalExitValue() + } +} \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/RustPlugin.kt b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/RustPlugin.kt new file mode 100644 index 0000000000..4aa7fcaf67 --- /dev/null +++ b/plugins/deep-link/examples/app/src-tauri/gen/android/buildSrc/src/main/java/com/tauri/deep_link_example/kotlin/RustPlugin.kt @@ -0,0 +1,85 @@ +import com.android.build.api.dsl.ApplicationExtension +import org.gradle.api.DefaultTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.get + +const val TASK_GROUP = "rust" + +open class Config { + lateinit var rootDirRel: String +} + +open class RustPlugin : Plugin { + private lateinit var config: Config + + override fun apply(project: Project) = with(project) { + config = extensions.create("rust", Config::class.java) + + val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64"); + val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList + + val defaultArchList = listOf("arm64", "arm", "x86", "x86_64"); + val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList + + val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64") + + extensions.configure { + @Suppress("UnstableApiUsage") + flavorDimensions.add("abi") + productFlavors { + create("universal") { + dimension = "abi" + ndk { + abiFilters += abiList + } + } + defaultArchList.forEachIndexed { index, arch -> + create(arch) { + dimension = "abi" + ndk { + abiFilters.add(defaultAbiList[index]) + } + } + } + } + } + + afterEvaluate { + for (profile in listOf("debug", "release")) { + val profileCapitalized = profile.replaceFirstChar { it.uppercase() } + val buildTask = tasks.maybeCreate( + "rustBuildUniversal$profileCapitalized", + DefaultTask::class.java + ).apply { + group = TASK_GROUP + description = "Build dynamic library in $profile mode for all targets" + } + + tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask) + + for (targetPair in targetsList.withIndex()) { + val targetName = targetPair.value + val targetArch = archList[targetPair.index] + val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() } + val targetBuildTask = project.tasks.maybeCreate( + "rustBuild$targetArchCapitalized$profileCapitalized", + BuildTask::class.java + ).apply { + group = TASK_GROUP + description = "Build dynamic library in $profile mode for $targetArch" + rootDirRel = config.rootDirRel + target = targetName + release = profile == "release" + } + + buildTask.dependsOn(targetBuildTask) + tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn( + targetBuildTask + ) + } + } + } + } +} \ No newline at end of file diff --git a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json index cda424305b..55737578d7 100644 --- a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json +++ b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json @@ -34,11 +34,11 @@ "pathPrefix": ["/intent"] }, { - "host": "tauri.app", - "appLink": true + "host": "tauri.app" }, { - "scheme": ["taurideeplink"] + "scheme": ["taurideeplink"], + "appLink": false } ], "desktop": { diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 4c91824774..1619291781 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -7,6 +7,10 @@ use serde::{Deserialize, Deserializer}; use tauri_utils::config::DeepLinkProtocol; +fn default_true() -> bool { + true +} + #[derive(Deserialize, Clone)] pub struct AssociatedDomain { #[serde(default = "default_schemes")] @@ -19,9 +23,9 @@ pub struct AssociatedDomain { pub path_pattern: Vec, #[serde(default, alias = "path-prefix", rename = "pathPrefix")] pub path_prefix: Vec, - #[serde(default, alias = "path-suffix", rename = "pathSuffix")] + #[serde(default, alias = "pa₹th-suffix", rename = "pathSuffix")] pub path_suffix: Vec, - #[serde(default, alias = "app-link", rename = "appLink")] + #[serde(default="default_true", alias = "app-link", rename = "appLink")] pub app_link: bool, } From be12db254f3513908038f0cf7b202f24e8a683e9 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 17:56:03 +0530 Subject: [PATCH 11/20] fix: typo --- plugins/deep-link/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 1619291781..26db17fcd6 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -23,7 +23,7 @@ pub struct AssociatedDomain { pub path_pattern: Vec, #[serde(default, alias = "path-prefix", rename = "pathPrefix")] pub path_prefix: Vec, - #[serde(default, alias = "pa₹th-suffix", rename = "pathSuffix")] + #[serde(default, alias = "path-suffix", rename = "pathSuffix")] pub path_suffix: Vec, #[serde(default="default_true", alias = "app-link", rename = "appLink")] pub app_link: bool, From 3b0983747e93ac3c22e8822b30f7e9310fa05c04 Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 19:34:58 +0530 Subject: [PATCH 12/20] fix: pnpm version --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index bcab2538bf..76b24b29fd 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,5 @@ }, "engines": { "pnpm": "^10.0.0" - }, - "packageManager": "pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184" + } } From 340ed4920e44b946e3181a0998f77c9f68991067 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 24 Jul 2025 11:08:38 -0300 Subject: [PATCH 13/20] cleanup --- plugins/deep-link/build.rs | 58 +++++++++---------- .../examples/app/src-tauri/Info.ios.plist | 2 +- .../project.pbxproj | 8 +-- .../apple/deep-link-example_iOS/Info.plist | 2 +- .../app/src-tauri/gen/apple/project.yml | 4 +- .../examples/app/src-tauri/tauri.conf.json | 3 +- plugins/deep-link/index.html | 3 - plugins/deep-link/src/config.rs | 23 +++----- 8 files changed, 44 insertions(+), 59 deletions(-) delete mode 100644 plugins/deep-link/index.html diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index f01631b1d2..3029357d87 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -11,10 +11,10 @@ const COMMANDS: &[&str] = &["get_current", "register", "unregister", "is_registe // TODO: Consider using activity-alias in case users may have multiple activities in their app. fn intent_filter(domain: &AssociatedDomain) -> String { let host = domain - .host - .as_ref() - .map(|h| format!(r#""#)) - .unwrap_or_default(); + .host + .as_ref() + .map(|h| format!(r#""#)) + .unwrap_or_default(); let auto_verify = if domain.is_app_link() { r#"android:autoVerify="true" "#.to_string() @@ -27,39 +27,39 @@ fn intent_filter(domain: &AssociatedDomain) -> String { - {} - {} - {} - {} - {} - {} + {schemes} + {host} + {domains} + {path_patterns} + {path_prefixes} + {path_suffixes} "#, - domain + schemes = domain .scheme .iter() .map(|scheme| format!(r#""#)) .collect::>() .join("\n "), - host, - domain + host = host, + domains = domain .path .iter() .map(|path| format!(r#""#)) .collect::>() .join("\n "), - domain + path_patterns = domain .path_pattern .iter() .map(|pattern| format!(r#""#)) .collect::>() .join("\n "), - domain + path_prefixes = domain .path_prefix .iter() .map(|prefix| format!(r#""#)) .collect::>() .join("\n "), - domain + path_suffixes = domain .path_suffix .iter() .map(|suffix| format!(r#""#)) @@ -102,17 +102,13 @@ fn main() { ) .expect("failed to rewrite AndroidManifest.xml"); - #[cfg(any(target_os = "macos", target_os = "ios"))] { - // we need to ensure that the entitlements are only - // generated for explicit app links and not - // other deep links or web links because then they + // we need to ensure that the entitlements are only + // generated for explicit app links and not + // other deep links because then they // are just going to complain and not be built or signed - let has_app_links = config - .mobile - .iter() - .any(|d| d.is_app_link()); + let has_app_links = config.mobile.iter().any(|d| d.is_app_link()); if !has_app_links { tauri_plugin::mobile::update_entitlements(|entitlements| { @@ -124,13 +120,13 @@ fn main() { entitlements.insert( "com.apple.developer.associated-domains".into(), config - .mobile - .iter() - .filter(|d| d.is_app_link()) - .filter_map(|d| d.host.as_ref()) - .map(|host| format!("applinks:{}", host).into()) - .collect::>() - .into(), + .mobile + .iter() + .filter(|d| d.is_app_link()) + .filter_map(|d| d.host.as_ref()) + .map(|host| format!("applinks:{}", host).into()) + .collect::>() + .into(), ); }) .expect("failed to update entitlements"); diff --git a/plugins/deep-link/examples/app/src-tauri/Info.ios.plist b/plugins/deep-link/examples/app/src-tauri/Info.ios.plist index c13033adbb..3d26e1ed95 100644 --- a/plugins/deep-link/examples/app/src-tauri/Info.ios.plist +++ b/plugins/deep-link/examples/app/src-tauri/Info.ios.plist @@ -6,7 +6,7 @@ CFBundleURLName - com.kodski.deep-link-example + com.tauri.deep-link-example CFBundleURLSchemes taurideeplink diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj index 8ce845b09e..97cd096b95 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj @@ -320,7 +320,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = 7F2T2WK6DR; + DEVELOPMENT_TEAM = Q93MBH6S2F; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; FRAMEWORK_SEARCH_PATHS = ( @@ -346,7 +346,7 @@ "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.kodski.deep-link-example; + PRODUCT_BUNDLE_IDENTIFIER = com.tauri.deep-link-example; PRODUCT_NAME = "deep-link-example"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -418,7 +418,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = 7F2T2WK6DR; + DEVELOPMENT_TEAM = Q93MBH6S2F; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; FRAMEWORK_SEARCH_PATHS = ( @@ -444,7 +444,7 @@ "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.kodski.deep-link-example; + PRODUCT_BUNDLE_IDENTIFIER = com.tauri.deep-link-example; PRODUCT_NAME = "deep-link-example"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist index 13148133d8..354b188820 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist @@ -44,7 +44,7 @@ CFBundleURLName - com.kodski.deep-link-example + com.tauri.deep-link-example CFBundleURLSchemes taurideeplink diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml b/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml index e7ad23d4a0..74d0ab4919 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/project.yml @@ -1,6 +1,6 @@ name: deep-link-example options: - bundleIdPrefix: com.kodski.deep-link-example + bundleIdPrefix: com.tauri.deep-link-example deploymentTarget: iOS: 13.0 fileGroups: [../../src] @@ -11,7 +11,7 @@ settingGroups: app: base: PRODUCT_NAME: deep-link-example - PRODUCT_BUNDLE_IDENTIFIER: com.kodski.deep-link-example + PRODUCT_BUNDLE_IDENTIFIER: com.tauri.deep-link-example targetTemplates: app: type: application diff --git a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json index 55737578d7..61f7394df6 100644 --- a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json +++ b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json @@ -37,8 +37,7 @@ "host": "tauri.app" }, { - "scheme": ["taurideeplink"], - "appLink": false + "scheme": ["taurideeplink"] } ], "desktop": { diff --git a/plugins/deep-link/index.html b/plugins/deep-link/index.html deleted file mode 100644 index b0a14c370c..0000000000 --- a/plugins/deep-link/index.html +++ /dev/null @@ -1,3 +0,0 @@ -test
- -cant touch this diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 26db17fcd6..7279744a6c 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -7,10 +7,6 @@ use serde::{Deserialize, Deserializer}; use tauri_utils::config::DeepLinkProtocol; -fn default_true() -> bool { - true -} - #[derive(Deserialize, Clone)] pub struct AssociatedDomain { #[serde(default = "default_schemes")] @@ -25,19 +21,17 @@ pub struct AssociatedDomain { pub path_prefix: Vec, #[serde(default, alias = "path-suffix", rename = "pathSuffix")] pub path_suffix: Vec, - #[serde(default="default_true", alias = "app-link", rename = "appLink")] - pub app_link: bool, } impl AssociatedDomain { - /// Returns true if the domain uses http or https scheme and has a host. - pub fn is_web_link(&self) -> bool { + /// Returns true if the domain uses http or https scheme. + fn is_web_link(&self) -> bool { self.scheme.iter().any(|s| s == "https" || s == "http") } - /// Returns true if marked as AppLink and has proper configuration. + /// Returns true if the domain uses http or https scheme and has proper host configuration. pub fn is_app_link(&self) -> bool { - self.app_link && self.is_web_link() && self.host.is_some() + self.is_web_link() && self.host.is_some() } pub fn validate(&self) -> Result<(), String> { @@ -47,12 +41,12 @@ impl AssociatedDomain { } // Rule 2: If it's an App Link, ensure http(s) and host. - if self.app_link { + if self.host.is_some() { if !self.is_web_link() { return Err("AppLink must be a valid web link (https/http + host)".into()); } - - if self.scheme.iter().any(|s| s == "http") && !self.scheme.iter().any(|s| s == "https") { + if self.scheme.iter().any(|s| s == "http") && !self.scheme.iter().any(|s| s == "https") + { eprintln!("Warning: AppLink uses only 'http' — allowed on Android but not secure for production."); } } @@ -61,7 +55,6 @@ impl AssociatedDomain { } } - // TODO: Consider removing this in v3 fn default_schemes() -> Vec { vec!["https".to_string(), "http".to_string()] @@ -70,7 +63,7 @@ fn default_schemes() -> Vec { fn deserialize_associated_host<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, -{ +{ let opt = Option::::deserialize(deserializer)?; if let Some(ref host) = opt { if let Some((scheme, _)) = host.split_once("://") { From d3bdc5c1a94a8da92cef95f2d6b06d0e061e277c Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 24 Jul 2025 20:19:25 +0530 Subject: [PATCH 14/20] fix: web link regression --- plugins/deep-link/src/config.rs | 12 +++++++++--- plugins/deep-link/src/lib.rs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 7279744a6c..2eac8681f2 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -7,6 +7,10 @@ use serde::{Deserialize, Deserializer}; use tauri_utils::config::DeepLinkProtocol; +fn default_true() -> bool { + true +} + #[derive(Deserialize, Clone)] pub struct AssociatedDomain { #[serde(default = "default_schemes")] @@ -21,17 +25,19 @@ pub struct AssociatedDomain { pub path_prefix: Vec, #[serde(default, alias = "path-suffix", rename = "pathSuffix")] pub path_suffix: Vec, + #[serde(default = "default_true", alias = "app-link", rename = "appLink")] + pub app_link: bool, } impl AssociatedDomain { /// Returns true if the domain uses http or https scheme. - fn is_web_link(&self) -> bool { + pub fn is_web_link(&self) -> bool { self.scheme.iter().any(|s| s == "https" || s == "http") } /// Returns true if the domain uses http or https scheme and has proper host configuration. pub fn is_app_link(&self) -> bool { - self.is_web_link() && self.host.is_some() + self.app_link && self.is_web_link() && self.host.is_some() } pub fn validate(&self) -> Result<(), String> { @@ -41,7 +47,7 @@ impl AssociatedDomain { } // Rule 2: If it's an App Link, ensure http(s) and host. - if self.host.is_some() { + if self.app_link { if !self.is_web_link() { return Err("AppLink must be a valid web link (https/http + host)".into()); } diff --git a/plugins/deep-link/src/lib.rs b/plugins/deep-link/src/lib.rs index 403d68c2fd..1cd13b580a 100644 --- a/plugins/deep-link/src/lib.rs +++ b/plugins/deep-link/src/lib.rs @@ -529,4 +529,4 @@ pub fn init() -> TauriPlugin> { } }) .build() -} \ No newline at end of file +} From 19ee9342831c2d9bac669b26bea372c8c9e0f71f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 24 Jul 2025 13:58:06 -0300 Subject: [PATCH 15/20] trim androidmanifest update --- plugins/deep-link/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index 3029357d87..12bb3a03b8 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -66,6 +66,8 @@ fn intent_filter(domain: &AssociatedDomain) -> String { .collect::>() .join("\n "), ) + .trim() + .to_string() } fn main() { From 0668697944f15eaa999a4a4a39445557377f1da4 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 24 Jul 2025 14:51:22 -0300 Subject: [PATCH 16/20] fix deep link validation broken due to appLink=true default --- plugins/deep-link/src/config.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 2eac8681f2..3c19ea95d9 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -25,8 +25,8 @@ pub struct AssociatedDomain { pub path_prefix: Vec, #[serde(default, alias = "path-suffix", rename = "pathSuffix")] pub path_suffix: Vec, - #[serde(default = "default_true", alias = "app-link", rename = "appLink")] - pub app_link: bool, + #[serde(default, alias = "app-link", rename = "appLink")] + pub app_link: Option, } impl AssociatedDomain { @@ -37,7 +37,8 @@ impl AssociatedDomain { /// Returns true if the domain uses http or https scheme and has proper host configuration. pub fn is_app_link(&self) -> bool { - self.app_link && self.is_web_link() && self.host.is_some() + self.app_link + .unwrap_or_else(|| self.is_web_link() && self.host.is_some()) } pub fn validate(&self) -> Result<(), String> { @@ -47,7 +48,7 @@ impl AssociatedDomain { } // Rule 2: If it's an App Link, ensure http(s) and host. - if self.app_link { + if self.is_app_link() { if !self.is_web_link() { return Err("AppLink must be a valid web link (https/http + host)".into()); } From 66346caed0d36be9551f5bdb5f574cc2dc2a60be Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 24 Jul 2025 14:55:28 -0300 Subject: [PATCH 17/20] implement update_info_plist from https://github.com/tauri-apps/tauri/pull/13888 --- Cargo.lock | 161 +++++++++++++----- Cargo.toml | 4 + plugins/deep-link/Cargo.toml | 3 + plugins/deep-link/build.rs | 54 ++++++ .../examples/app/src-tauri/Info.ios.plist | 17 -- .../project.pbxproj | 4 +- .../apple/deep-link-example_iOS/Info.plist | 4 +- .../deep-link-example_iOS.entitlements | 8 +- 8 files changed, 193 insertions(+), 62 deletions(-) delete mode 100644 plugins/deep-link/examples/app/src-tauri/Info.ios.plist diff --git a/Cargo.lock b/Cargo.lock index 0551b9b885..965d656b00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,7 +213,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-barcode-scanner", "tauri-plugin-biometric", "tauri-plugin-cli", @@ -246,7 +246,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-updater", "time", "tiny_http", @@ -259,7 +259,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-updater", "tiny_http", ] @@ -271,7 +271,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-store", ] @@ -1418,7 +1418,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-deep-link", "tauri-plugin-log", "tauri-plugin-single-instance", @@ -3605,9 +3605,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de14a9b5d569ca68d7c891d613b390cf5ab4f851c77aaa2f9e435555d3d9492" +checksum = "58b89bf91c19bf036347f1ab85a81c560f08c0667c8601bece664d860a600988" dependencies = [ "crossbeam-channel", "dpi", @@ -5719,7 +5719,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-cli", "tauri-plugin-single-instance", ] @@ -6338,16 +6338,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7a0f4019c80391d143ee26cd7cd1ed271ac241d3087d333f99f3269ba90812" +version = "2.7.0" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" dependencies = [ "anyhow", "bytes", "dirs 6.0.0", "dunce", "embed_plist", - "getrandom 0.2.15", + "getrandom 0.3.2", "glob", "gtk", "heck 0.5.0", @@ -6373,11 +6372,11 @@ dependencies = [ "serialize-to-javascript", "specta", "swift-rs", - "tauri-build", + "tauri-build 2.3.1", "tauri-macros", "tauri-runtime", "tauri-runtime-wry", - "tauri-utils", + "tauri-utils 2.6.0", "thiserror 2.0.12", "tokio", "tray-icon", @@ -6407,8 +6406,29 @@ dependencies = [ "semver", "serde", "serde_json", - "tauri-codegen", - "tauri-utils", + "tauri-codegen 2.3.0", + "tauri-utils 2.5.0", + "tauri-winres", + "toml", + "walkdir", +] + +[[package]] +name = "tauri-build" +version = "2.3.1" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs 6.0.0", + "glob", + "heck 0.5.0", + "json-patch", + "schemars", + "semver", + "serde", + "serde_json", + "tauri-utils 2.6.0", "tauri-winres", "toml", "walkdir", @@ -6432,7 +6452,32 @@ dependencies = [ "serde_json", "sha2", "syn 2.0.100", - "tauri-utils", + "tauri-utils 2.5.0", + "thiserror 2.0.12", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.3.1" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +dependencies = [ + "base64 0.22.1", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "syn 2.0.100", + "tauri-utils 2.6.0", "thiserror 2.0.12", "time", "url", @@ -6442,23 +6487,21 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f59e1d1fa9651212dcb890a0c66226d819b716490b0cf43c078514da3591705" +version = "2.3.2" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.100", - "tauri-codegen", - "tauri-utils", + "tauri-codegen 2.3.1", + "tauri-utils 2.6.0", ] [[package]] name = "tauri-plugin" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3" +version = "2.3.1" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" dependencies = [ "anyhow", "glob", @@ -6466,7 +6509,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "tauri-utils", + "tauri-utils 2.6.0", "toml", "walkdir", ] @@ -6539,12 +6582,13 @@ name = "tauri-plugin-deep-link" version = "2.4.1" dependencies = [ "dunce", + "plist", "rust-ini", "serde", "serde_json", "tauri", "tauri-plugin", - "tauri-utils", + "tauri-utils 2.5.0", "thiserror 2.0.12", "tracing", "url", @@ -6584,7 +6628,7 @@ dependencies = [ "serde_repr", "tauri", "tauri-plugin", - "tauri-utils", + "tauri-utils 2.5.0", "thiserror 2.0.12", "toml", "url", @@ -6958,9 +7002,8 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4" +version = "2.7.1" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" dependencies = [ "cookie", "dpi", @@ -6972,7 +7015,7 @@ dependencies = [ "raw-window-handle", "serde", "serde_json", - "tauri-utils", + "tauri-utils 2.6.0", "thiserror 2.0.12", "url", "windows 0.61.1", @@ -6980,9 +7023,8 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe52ed0ef40fd7ad51a620ecb3018e32eba3040bb95025216a962a37f6f050c5" +version = "2.7.2" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" dependencies = [ "gtk", "http", @@ -6997,7 +7039,7 @@ dependencies = [ "softbuffer", "tao", "tauri-runtime", - "tauri-utils", + "tauri-utils 2.6.0", "url", "webkit2gtk", "webview2-com", @@ -7045,6 +7087,45 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-utils" +version = "2.6.0" +source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +dependencies = [ + "aes-gcm", + "anyhow", + "cargo_metadata", + "ctor", + "dunce", + "getrandom 0.3.2", + "glob", + "html5ever", + "http", + "infer", + "json-patch", + "kuchikiki", + "log", + "memchr", + "phf 0.11.3", + "proc-macro2", + "quote", + "regex", + "schemars", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "serialize-to-javascript", + "swift-rs", + "thiserror 2.0.12", + "toml", + "url", + "urlpattern", + "uuid", + "walkdir", +] + [[package]] name = "tauri-winres" version = "0.3.0" @@ -7452,9 +7533,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d433764348e7084bad2c5ea22c96c71b61b17afe3a11645710f533bd72b6a2b5" +checksum = "2da75ec677957aa21f6e0b361df0daab972f13a5bee3606de0638fd4ee1c666a" dependencies = [ "crossbeam-channel", "dirs 6.0.0", @@ -7643,7 +7724,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-updater", "time", "tiny_http", @@ -8059,7 +8140,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.3.0", "tauri-plugin-websocket", "tokio", "tokio-tungstenite", diff --git a/Cargo.toml b/Cargo.toml index 2d1b4c0e62..0ca4cdc57c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,3 +39,7 @@ codegen-units = 1 lto = true incremental = false opt-level = "s" + +[patch.crates-io] +tauri = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } +tauri-plugin = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } diff --git a/plugins/deep-link/Cargo.toml b/plugins/deep-link/Cargo.toml index 7c8524bfcb..2b0cd5c522 100644 --- a/plugins/deep-link/Cargo.toml +++ b/plugins/deep-link/Cargo.toml @@ -27,6 +27,9 @@ serde_json = { workspace = true } tauri-utils = { workspace = true } tauri-plugin = { workspace = true, features = ["build"] } +[target."cfg(target_os = \"macos\")".build-dependencies] +plist = "1" + [dependencies] serde = { workspace = true } serde_json = { workspace = true } diff --git a/plugins/deep-link/build.rs b/plugins/deep-link/build.rs index 12bb3a03b8..16d2a96e57 100644 --- a/plugins/deep-link/build.rs +++ b/plugins/deep-link/build.rs @@ -133,6 +133,60 @@ fn main() { }) .expect("failed to update entitlements"); } + + let deep_link_domains = config + .mobile + .iter() + .filter_map(|domain| { + if domain.is_app_link() { + return None; + } + + Some(domain) + }) + .collect::>(); + + if deep_link_domains.is_empty() { + tauri_plugin::mobile::update_info_plist(|info_plist| { + info_plist.remove("CFBundleURLTypes"); + }) + .expect("failed to update Info.plist"); + } else { + tauri_plugin::mobile::update_info_plist(|info_plist| { + info_plist.insert( + "CFBundleURLTypes".into(), + deep_link_domains + .iter() + .map(|domain| { + let schemes = domain + .scheme + .iter() + .filter(|scheme| { + scheme.as_str() != "https" && scheme.as_str() != "http" + }) + .collect::>(); + + let mut dict = plist::Dictionary::new(); + dict.insert( + "CFBundleURLSchemes".into(), + schemes + .iter() + .map(|s| s.to_string().into()) + .collect::>() + .into(), + ); + dict.insert( + "CFBundleURLName".into(), + format!("{}", domain.scheme[0]).into(), + ); + plist::Value::Dictionary(dict) + }) + .collect::>() + .into(), + ); + }) + .expect("failed to update Info.plist"); + } } } } diff --git a/plugins/deep-link/examples/app/src-tauri/Info.ios.plist b/plugins/deep-link/examples/app/src-tauri/Info.ios.plist deleted file mode 100644 index 3d26e1ed95..0000000000 --- a/plugins/deep-link/examples/app/src-tauri/Info.ios.plist +++ /dev/null @@ -1,17 +0,0 @@ - - - - - CFBundleURLTypes - - - CFBundleURLName - com.tauri.deep-link-example - CFBundleURLSchemes - - taurideeplink - - - - - diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj index 97cd096b95..4c01a958a8 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example.xcodeproj/project.pbxproj @@ -320,7 +320,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = Q93MBH6S2F; + DEVELOPMENT_TEAM = "Q93MBH6S2F"; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; FRAMEWORK_SEARCH_PATHS = ( @@ -418,7 +418,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = Q93MBH6S2F; + DEVELOPMENT_TEAM = "Q93MBH6S2F"; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; FRAMEWORK_SEARCH_PATHS = ( diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist index 354b188820..bc74b01bc2 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/Info.plist @@ -43,12 +43,12 @@ CFBundleURLTypes - CFBundleURLName - com.tauri.deep-link-example CFBundleURLSchemes taurideeplink + CFBundleURLName + taurideeplink
diff --git a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements index 21e2f8d830..3216c743b7 100644 --- a/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements +++ b/plugins/deep-link/examples/app/src-tauri/gen/apple/deep-link-example_iOS/deep-link-example_iOS.entitlements @@ -1,5 +1,11 @@ - + + com.apple.developer.associated-domains + + applinks:fabianlars.de + applinks:tauri.app + + \ No newline at end of file From 40b4747274f6b16f9c9140e82e949b0aedb1dcea Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Tue, 29 Jul 2025 10:34:39 +0530 Subject: [PATCH 18/20] fix: remove old patch crates --- Cargo.lock | 150 +++++++++++++---------------------------------------- Cargo.toml | 6 +-- 2 files changed, 38 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 965d656b00..63aa915324 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,7 +213,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-barcode-scanner", "tauri-plugin-biometric", "tauri-plugin-cli", @@ -246,7 +246,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-updater", "time", "tiny_http", @@ -259,7 +259,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-updater", "tiny_http", ] @@ -271,7 +271,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-store", ] @@ -1418,7 +1418,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-deep-link", "tauri-plugin-log", "tauri-plugin-single-instance", @@ -5719,7 +5719,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-cli", "tauri-plugin-single-instance", ] @@ -6338,8 +6338,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.7.0" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "124e129c9c0faa6bec792c5948c89e86c90094133b0b9044df0ce5f0a8efaa0d" dependencies = [ "anyhow", "bytes", @@ -6372,11 +6373,11 @@ dependencies = [ "serialize-to-javascript", "specta", "swift-rs", - "tauri-build 2.3.1", + "tauri-build", "tauri-macros", "tauri-runtime", "tauri-runtime-wry", - "tauri-utils 2.6.0", + "tauri-utils", "thiserror 2.0.12", "tokio", "tray-icon", @@ -6406,29 +6407,8 @@ dependencies = [ "semver", "serde", "serde_json", - "tauri-codegen 2.3.0", - "tauri-utils 2.5.0", - "tauri-winres", - "toml", - "walkdir", -] - -[[package]] -name = "tauri-build" -version = "2.3.1" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" -dependencies = [ - "anyhow", - "cargo_toml", - "dirs 6.0.0", - "glob", - "heck 0.5.0", - "json-patch", - "schemars", - "semver", - "serde", - "serde_json", - "tauri-utils 2.6.0", + "tauri-codegen", + "tauri-utils", "tauri-winres", "toml", "walkdir", @@ -6452,32 +6432,7 @@ dependencies = [ "serde_json", "sha2", "syn 2.0.100", - "tauri-utils 2.5.0", - "thiserror 2.0.12", - "time", - "url", - "uuid", - "walkdir", -] - -[[package]] -name = "tauri-codegen" -version = "2.3.1" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" -dependencies = [ - "base64 0.22.1", - "ico", - "json-patch", - "plist", - "png", - "proc-macro2", - "quote", - "semver", - "serde", - "serde_json", - "sha2", - "syn 2.0.100", - "tauri-utils 2.6.0", + "tauri-utils", "thiserror 2.0.12", "time", "url", @@ -6487,21 +6442,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.3.2" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f237fbea5866fa5f2a60a21bea807a2d6e0379db070d89c3a10ac0f2d4649bbc" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.100", - "tauri-codegen 2.3.1", - "tauri-utils 2.6.0", + "tauri-codegen", + "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.3.1" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3" dependencies = [ "anyhow", "glob", @@ -6509,7 +6466,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "tauri-utils 2.6.0", + "tauri-utils", "toml", "walkdir", ] @@ -6588,7 +6545,7 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "tauri-utils 2.5.0", + "tauri-utils", "thiserror 2.0.12", "tracing", "url", @@ -6628,7 +6585,7 @@ dependencies = [ "serde_repr", "tauri", "tauri-plugin", - "tauri-utils 2.5.0", + "tauri-utils", "thiserror 2.0.12", "toml", "url", @@ -7002,8 +6959,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.7.1" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4" dependencies = [ "cookie", "dpi", @@ -7015,7 +6973,7 @@ dependencies = [ "raw-window-handle", "serde", "serde_json", - "tauri-utils 2.6.0", + "tauri-utils", "thiserror 2.0.12", "url", "windows 0.61.1", @@ -7023,8 +6981,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.7.2" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad" dependencies = [ "gtk", "http", @@ -7039,7 +6998,7 @@ dependencies = [ "softbuffer", "tao", "tauri-runtime", - "tauri-utils 2.6.0", + "tauri-utils", "url", "webkit2gtk", "webview2-com", @@ -7087,45 +7046,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "tauri-utils" -version = "2.6.0" -source = "git+https://github.com/tauri-apps/tauri?branch=feat/update-info-plist-fn#27f0fa44ccd14a97a030f0b8db8c578265b433d3" -dependencies = [ - "aes-gcm", - "anyhow", - "cargo_metadata", - "ctor", - "dunce", - "getrandom 0.3.2", - "glob", - "html5ever", - "http", - "infer", - "json-patch", - "kuchikiki", - "log", - "memchr", - "phf 0.11.3", - "proc-macro2", - "quote", - "regex", - "schemars", - "semver", - "serde", - "serde-untagged", - "serde_json", - "serde_with", - "serialize-to-javascript", - "swift-rs", - "thiserror 2.0.12", - "toml", - "url", - "urlpattern", - "uuid", - "walkdir", -] - [[package]] name = "tauri-winres" version = "0.3.0" @@ -7724,7 +7644,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-updater", "time", "tiny_http", @@ -8140,7 +8060,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-build 2.3.0", + "tauri-build", "tauri-plugin-websocket", "tokio", "tokio-tungstenite", diff --git a/Cargo.toml b/Cargo.toml index 0ca4cdc57c..cfdeee9bce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,6 @@ lto = true incremental = false opt-level = "s" -[patch.crates-io] -tauri = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } -tauri-plugin = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } +# [patch.crates-io] +# tauri = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } +# tauri-plugin = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } From bcd73b0087cfd93be7460721a276c0459b80c55d Mon Sep 17 00:00:00 2001 From: Soham Jaiswal Date: Thu, 31 Jul 2025 12:17:07 +0530 Subject: [PATCH 19/20] fix: use latest patch tauri --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cfdeee9bce..6046c99398 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,5 +41,5 @@ incremental = false opt-level = "s" # [patch.crates-io] -# tauri = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } -# tauri-plugin = { git = "https://github.com/tauri-apps/tauri", branch = "feat/update-info-plist-fn" } +tauri = { git = "https://github.com/tauri-apps/tauri", rev = "bbcea1f" } +tauri-plugin = { git = "https://github.com/tauri-apps/tauri", rev = "bbcea1f" } From ebb6afa903713c00db44a238a6a40526ea0ac11e Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 19 Aug 2025 10:20:34 -0300 Subject: [PATCH 20/20] lint --- plugins/deep-link/src/config.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/deep-link/src/config.rs b/plugins/deep-link/src/config.rs index 3c19ea95d9..49de68e3de 100644 --- a/plugins/deep-link/src/config.rs +++ b/plugins/deep-link/src/config.rs @@ -7,10 +7,6 @@ use serde::{Deserialize, Deserializer}; use tauri_utils::config::DeepLinkProtocol; -fn default_true() -> bool { - true -} - #[derive(Deserialize, Clone)] pub struct AssociatedDomain { #[serde(default = "default_schemes")]