// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#[path = "src/config.rs"]
mod config;
use config::{AssociatedDomain, Config};
const COMMANDS: &[&str] = &["get_current", "register", "unregister", "is_registered"];
// 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();
let auto_verify = if domain.is_app_link() {
r#"android:autoVerify="true" "#.to_string()
} else {
String::new()
};
format!(
r#"
{schemes}
{host}
{domains}
{path_patterns}
{path_prefixes}
{path_suffixes}
"#,
schemes = domain
.scheme
.iter()
.map(|scheme| format!(r#""#))
.collect::>()
.join("\n "),
host = host,
domains = domain
.path
.iter()
.map(|path| format!(r#""#))
.collect::>()
.join("\n "),
path_patterns = domain
.path_pattern
.iter()
.map(|pattern| format!(r#""#))
.collect::>()
.join("\n "),
path_prefixes = domain
.path_prefix
.iter()
.map(|prefix| format!(r#""#))
.collect::>()
.join("\n "),
path_suffixes = domain
.path_suffix
.iter()
.map(|suffix| format!(r#""#))
.collect::>()
.join("\n "),
)
.trim()
.to_string()
}
fn main() {
let result = tauri_plugin::Builder::new(COMMANDS)
.global_api_script_path("./api-iife.js")
.android_path("android")
.try_build();
// when building documentation for Android the plugin build result is always Err() (docs.rs mounts the sources read-only) and is irrelevant to the crate documentation build
// `cfg(docsrs)` only reaches rustdoc, build scripts must check the `DOCS_RS` env var instead
if !(std::env::var_os("DOCS_RS").is_some()
&& std::env::var("TARGET").unwrap().contains("android"))
{
result.unwrap();
}
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",
config
.mobile
.iter()
.map(intent_filter)
.collect::>()
.join("\n"),
)
.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 because then they
// are just going to complain and not be built or signed
tauri_plugin::mobile::update_entitlements(|entitlements| {
let current = entitlements
.get("com.apple.developer.associated-domains")
.and_then(|domains| domains.as_array())
.map(|domains| {
domains
.iter()
.filter_map(|domain| domain.as_string())
.map(ToString::to_string)
.collect::>()
})
.unwrap_or_default();
let associated_domains = config.ios_associated_domains(¤t);
if associated_domains.is_empty() {
entitlements.remove("com.apple.developer.associated-domains");
} else {
entitlements.insert(
"com.apple.developer.associated-domains".into(),
associated_domains
.into_iter()
.map(Into::into)
.collect::>()
.into(),
);
}
})
.expect("failed to update entitlements");
let url_types = config.ios_url_types();
tauri_plugin::mobile::update_info_plist(|info_plist| {
if url_types.is_empty() {
info_plist.remove("CFBundleURLTypes");
} else {
info_plist.insert(
"CFBundleURLTypes".into(),
url_types
.into_iter()
.map(|url_type| {
let mut dict = plist::Dictionary::new();
dict.insert(
"CFBundleURLSchemes".into(),
url_type
.schemes
.into_iter()
.map(Into::into)
.collect::>()
.into(),
);
dict.insert("CFBundleURLName".into(), url_type.name.into());
plist::Value::Dictionary(dict)
})
.collect::>()
.into(),
);
}
})
.expect("failed to update Info.plist");
}
}
}