From 877c15c9590efde8963bfc2f8b9a20c9fbf2df3f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 20 Aug 2024 09:41:25 -0300 Subject: [PATCH 1/2] feat(core): resources on mobile apps --- .changes/inject-mobile-resources.md | 6 ++++++ .changes/resource-dir-ios.md | 5 +++++ core/tauri-utils/src/platform.rs | 5 +++++ tooling/cli/src/helpers/fs.rs | 21 +++++++++++++++++++++ tooling/cli/src/helpers/mod.rs | 1 + tooling/cli/src/mobile/android/build.rs | 4 ++-- tooling/cli/src/mobile/android/dev.rs | 4 ++-- tooling/cli/src/mobile/android/mod.rs | 21 +++++++++++++++++++-- tooling/cli/src/mobile/ios/build.rs | 4 ++-- tooling/cli/src/mobile/ios/dev.rs | 4 ++-- tooling/cli/src/mobile/ios/mod.rs | 24 +++++++++++++++++++++--- 11 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 .changes/inject-mobile-resources.md create mode 100644 .changes/resource-dir-ios.md create mode 100644 tooling/cli/src/helpers/fs.rs diff --git a/.changes/inject-mobile-resources.md b/.changes/inject-mobile-resources.md new file mode 100644 index 000000000000..45833640338f --- /dev/null +++ b/.changes/inject-mobile-resources.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:feat +"@tauri-apps/cli": patch:feat +--- + +Inject configured resources on mobil apps. diff --git a/.changes/resource-dir-ios.md b/.changes/resource-dir-ios.md new file mode 100644 index 000000000000..e4650a698b6b --- /dev/null +++ b/.changes/resource-dir-ios.md @@ -0,0 +1,5 @@ +--- +"tauri-utils": patch:bug +--- + +Fix `resource_dir` on iOS. diff --git a/core/tauri-utils/src/platform.rs b/core/tauri-utils/src/platform.rs index 5b0040264b9d..6b80e3f3244a 100644 --- a/core/tauri-utils/src/platform.rs +++ b/core/tauri-utils/src/platform.rs @@ -320,6 +320,11 @@ fn resource_dir_from>( .map_err(Into::into); } + #[cfg(target_os = "ios")] + { + res = exe_dir.join("assets").canonicalize().map_err(Into::into); + } + res } diff --git a/tooling/cli/src/helpers/fs.rs b/tooling/cli/src/helpers/fs.rs new file mode 100644 index 000000000000..dd7491db13d4 --- /dev/null +++ b/tooling/cli/src/helpers/fs.rs @@ -0,0 +1,21 @@ +// Copyright 2019-2024 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +use anyhow::Result; +use std::path::Path; + +pub fn copy_file(from: impl AsRef, to: impl AsRef) -> Result<()> { + let from = from.as_ref(); + let to = to.as_ref(); + if !from.exists() { + return Err(anyhow::anyhow!("{:?} does not exist", from)); + } + if !from.is_file() { + return Err(anyhow::anyhow!("{:?} is not a file", from)); + } + let dest_dir = to.parent().expect("No data in parent"); + std::fs::create_dir_all(dest_dir)?; + std::fs::copy(from, to)?; + Ok(()) +} diff --git a/tooling/cli/src/helpers/mod.rs b/tooling/cli/src/helpers/mod.rs index 58bdd06edd90..e67929439c00 100644 --- a/tooling/cli/src/helpers/mod.rs +++ b/tooling/cli/src/helpers/mod.rs @@ -8,6 +8,7 @@ pub mod cargo_manifest; pub mod config; pub mod flock; pub mod framework; +pub mod fs; pub mod npm; pub mod plugins; pub mod prompts; diff --git a/tooling/cli/src/mobile/android/build.rs b/tooling/cli/src/mobile/android/build.rs index ad29b1de38a0..557f4e1a890a 100644 --- a/tooling/cli/src/mobile/android/build.rs +++ b/tooling/cli/src/mobile/android/build.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use super::{ - configure_cargo, delete_codegen_vars, ensure_init, env, get_app, get_config, inject_assets, + configure_cargo, delete_codegen_vars, ensure_init, env, get_app, get_config, inject_resources, log_finished, open_and_wait, MobileTarget, OptionsHandle, }; use crate::{ @@ -209,7 +209,7 @@ fn run_build( cli_options, )?; - inject_assets(config, tauri_config.lock().unwrap().as_ref().unwrap())?; + inject_resources(config, tauri_config.lock().unwrap().as_ref().unwrap())?; let apk_outputs = if options.apk { apk::build( diff --git a/tooling/cli/src/mobile/android/dev.rs b/tooling/cli/src/mobile/android/dev.rs index bb22c3fde9f6..89b666127b83 100644 --- a/tooling/cli/src/mobile/android/dev.rs +++ b/tooling/cli/src/mobile/android/dev.rs @@ -4,7 +4,7 @@ use super::{ configure_cargo, delete_codegen_vars, device_prompt, ensure_init, env, get_app, get_config, - inject_assets, open_and_wait, MobileTarget, + inject_resources, open_and_wait, MobileTarget, }; use crate::{ dev::Options as DevOptions, @@ -244,7 +244,7 @@ fn run_dev( cli_options, )?; - inject_assets(config, tauri_config.lock().unwrap().as_ref().unwrap())?; + inject_resources(config, tauri_config.lock().unwrap().as_ref().unwrap())?; if open { open_and_wait(config, &env) diff --git a/tooling/cli/src/mobile/android/mod.rs b/tooling/cli/src/mobile/android/mod.rs index ebbecfb3fe65..9a4ff0ee5912 100644 --- a/tooling/cli/src/mobile/android/mod.rs +++ b/tooling/cli/src/mobile/android/mod.rs @@ -25,6 +25,7 @@ use std::{ time::Duration, }; use sublime_fuzzy::best_match; +use tauri_utils::resources::ResourcePaths; use super::{ ensure_init, get_app, @@ -32,7 +33,10 @@ use super::{ log_finished, read_options, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; -use crate::{helpers::config::Config as TauriConfig, Result}; +use crate::{ + helpers::config::{BundleResources, Config as TauriConfig}, + Result, +}; mod android_studio_script; mod build; @@ -296,7 +300,7 @@ fn open_and_wait(config: &AndroidConfig, env: &Env) -> ! { } } -fn inject_assets(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<()> { +fn inject_resources(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<()> { let asset_dir = config .project_dir() .join("app/src/main") @@ -308,5 +312,18 @@ fn inject_assets(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<( serde_json::to_string(&tauri_config)?, )?; + let resources = match &tauri_config.bundle.resources { + Some(BundleResources::List(paths)) => Some(ResourcePaths::new(paths.as_slice(), true)), + Some(BundleResources::Map(map)) => Some(ResourcePaths::from_map(map, true)), + None => None, + }; + if let Some(resources) = resources { + for resource in resources.iter() { + let resource = resource?; + let dest = asset_dir.join(resource.target()); + crate::helpers::fs::copy_file(resource.path(), dest)?; + } + } + Ok(()) } diff --git a/tooling/cli/src/mobile/ios/build.rs b/tooling/cli/src/mobile/ios/build.rs index 74e1a3ef958c..f3022473613f 100644 --- a/tooling/cli/src/mobile/ios/build.rs +++ b/tooling/cli/src/mobile/ios/build.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use super::{ - configure_cargo, detect_target_ok, ensure_init, env, get_app, get_config, inject_assets, + configure_cargo, detect_target_ok, ensure_init, env, get_app, get_config, inject_resources, log_finished, merge_plist, open_and_wait, MobileTarget, OptionsHandle, }; use crate::{ @@ -164,7 +164,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { config.project_dir(), MobileTarget::Ios, )?; - inject_assets(&config)?; + inject_resources(&config, tauri_config.lock().unwrap().as_ref().unwrap())?; let info_plist_path = config .project_dir() diff --git a/tooling/cli/src/mobile/ios/dev.rs b/tooling/cli/src/mobile/ios/dev.rs index a3ee3b6c81b4..d8b382eac2ca 100644 --- a/tooling/cli/src/mobile/ios/dev.rs +++ b/tooling/cli/src/mobile/ios/dev.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use super::{ - configure_cargo, device_prompt, ensure_init, env, get_app, get_config, inject_assets, + configure_cargo, device_prompt, ensure_init, env, get_app, get_config, inject_resources, merge_plist, open_and_wait, MobileTarget, }; use crate::{ @@ -179,7 +179,7 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { config.project_dir(), MobileTarget::Ios, )?; - inject_assets(&config)?; + inject_resources(&config, tauri_config.lock().unwrap().as_ref().unwrap())?; let info_plist_path = config .project_dir() diff --git a/tooling/cli/src/mobile/ios/mod.rs b/tooling/cli/src/mobile/ios/mod.rs index 9e53853a866c..44c5a7baf8f5 100644 --- a/tooling/cli/src/mobile/ios/mod.rs +++ b/tooling/cli/src/mobile/ios/mod.rs @@ -20,6 +20,7 @@ use cargo_mobile2::{ }; use clap::{Parser, Subcommand}; use sublime_fuzzy::best_match; +use tauri_utils::resources::ResourcePaths; use super::{ ensure_init, env, get_app, @@ -28,7 +29,10 @@ use super::{ MIN_DEVICE_MATCH_SCORE, }; use crate::{ - helpers::{app_paths::tauri_dir, config::Config as TauriConfig}, + helpers::{ + app_paths::tauri_dir, + config::{BundleResources, Config as TauriConfig}, + }, Result, }; @@ -304,9 +308,23 @@ fn open_and_wait(config: &AppleConfig, env: &Env) -> ! { } } -fn inject_assets(config: &AppleConfig) -> Result<()> { +fn inject_resources(config: &AppleConfig, tauri_config: &TauriConfig) -> Result<()> { let asset_dir = config.project_dir().join(DEFAULT_ASSET_DIR); - create_dir_all(asset_dir)?; + create_dir_all(&asset_dir)?; + + let resources = match &tauri_config.bundle.resources { + Some(BundleResources::List(paths)) => Some(ResourcePaths::new(paths.as_slice(), true)), + Some(BundleResources::Map(map)) => Some(ResourcePaths::from_map(map, true)), + None => None, + }; + if let Some(resources) = resources { + for resource in resources.iter() { + let resource = resource?; + let dest = asset_dir.join(resource.target()); + crate::helpers::fs::copy_file(resource.path(), dest)?; + } + } + Ok(()) } From 6e20a96dd3aa6c8aa69c4cc59102718e6bbe9aaa Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 20 Aug 2024 13:29:55 -0300 Subject: [PATCH 2/2] resources dir on android --- .changes/inject-mobile-resources.md | 2 +- .changes/resource-dir-android.md | 5 +++++ core/tauri-utils/src/platform.rs | 9 +++++++++ .../src/main/java/app/tauri/PathPlugin.kt | 5 +++-- examples/api/src-tauri/Cargo.lock | 16 ++++++++-------- 5 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 .changes/resource-dir-android.md diff --git a/.changes/inject-mobile-resources.md b/.changes/inject-mobile-resources.md index 45833640338f..6d83411c66ec 100644 --- a/.changes/inject-mobile-resources.md +++ b/.changes/inject-mobile-resources.md @@ -3,4 +3,4 @@ "@tauri-apps/cli": patch:feat --- -Inject configured resources on mobil apps. +Inject configured resources on mobile apps. diff --git a/.changes/resource-dir-android.md b/.changes/resource-dir-android.md new file mode 100644 index 000000000000..05480021b2fc --- /dev/null +++ b/.changes/resource-dir-android.md @@ -0,0 +1,5 @@ +--- +"tauri-utils": patch:bug +--- + +Implemented `resource_dir` on Android, which returns a URI that needs to be resolved using [AssetManager::open](https://developer.android.com/reference/android/content/res/AssetManager#open(java.lang.String,%20int)). This will be handled by the file system plugin. diff --git a/core/tauri-utils/src/platform.rs b/core/tauri-utils/src/platform.rs index 6b80e3f3244a..81df60b9c129 100644 --- a/core/tauri-utils/src/platform.rs +++ b/core/tauri-utils/src/platform.rs @@ -15,6 +15,9 @@ use crate::{Env, PackageInfo}; mod starting_binary; +#[cfg(target_os = "android")] +pub const ANDROID_ASSET_PROTOCOL_URI_PREFIX: &str = "asset://localhost/"; + /// Platform target. #[derive(PartialEq, Eq, Copy, Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] @@ -256,7 +259,13 @@ fn is_cargo_output_directory(path: &Path) -> bool { /// `${exe_dir}/../lib/${exe_name}`. /// /// On MacOS, it's `${exe_dir}../Resources` (inside .app). +/// +/// On iOS, it's `${exe_dir}/assets`. +/// +/// Android uses a special URI prefix that is resolved by the Tauri file system plugin `asset://localhost/` pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> crate::Result { + #[cfg(target_os = "android")] + return Ok(PathBuf::from(ANDROID_ASSET_PROTOCOL_URI_PREFIX)); let exe = current_exe()?; resource_dir_from(exe, package_info, env) } diff --git a/core/tauri/mobile/android/src/main/java/app/tauri/PathPlugin.kt b/core/tauri/mobile/android/src/main/java/app/tauri/PathPlugin.kt index e33a9597e771..ec72d008ad0e 100644 --- a/core/tauri/mobile/android/src/main/java/app/tauri/PathPlugin.kt +++ b/core/tauri/mobile/android/src/main/java/app/tauri/PathPlugin.kt @@ -12,6 +12,8 @@ import app.tauri.plugin.Plugin import app.tauri.plugin.Invoke import app.tauri.plugin.JSObject +const val TAURI_ASSETS_DIRECTORY_URI = "asset://localhost/" + @TauriPlugin class PathPlugin(private val activity: Activity): Plugin(activity) { private fun resolvePath(invoke: Invoke, path: String?) { @@ -67,8 +69,7 @@ class PathPlugin(private val activity: Activity): Plugin(activity) { @Command fun getResourcesDir(invoke: Invoke) { - // TODO - resolvePath(invoke, activity.cacheDir.absolutePath) + resolvePath(invoke, TAURI_ASSETS_DIRECTORY_URI) } @Command diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 8590b7440128..8273f8e9879f 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -3221,7 +3221,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "anyhow", "bytes", @@ -3271,7 +3271,7 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "anyhow", "cargo_toml", @@ -3293,7 +3293,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "base64 0.22.1", "brotli", @@ -3318,7 +3318,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3330,7 +3330,7 @@ dependencies = [ [[package]] name = "tauri-plugin" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "anyhow", "glob", @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "dpi", "gtk", @@ -3373,7 +3373,7 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "cocoa 0.26.0", "gtk", @@ -3395,7 +3395,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-rc.3" +version = "2.0.0-rc.4" dependencies = [ "aes-gcm", "brotli",