context.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use crate::embedded_assets::{AssetOptions, EmbeddedAssets, EmbeddedAssetsError};
  5. use proc_macro2::TokenStream;
  6. use quote::quote;
  7. use std::path::{Path, PathBuf};
  8. use tauri_utils::config::{AppUrl, Config, WindowUrl};
  9. /// Necessary data needed by [`context_codegen`] to generate code for a Tauri application context.
  10. pub struct ContextData {
  11. pub dev: bool,
  12. pub config: Config,
  13. pub config_parent: PathBuf,
  14. pub root: TokenStream,
  15. }
  16. /// Build a `tauri::Context` for including in application code.
  17. pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsError> {
  18. let ContextData {
  19. dev,
  20. config,
  21. config_parent,
  22. root,
  23. } = data;
  24. let mut options = AssetOptions::new();
  25. if let Some(csp) = &config.tauri.security.csp {
  26. options = options.csp(csp.clone());
  27. }
  28. let app_url = if dev {
  29. &config.build.dev_path
  30. } else {
  31. &config.build.dist_dir
  32. };
  33. let assets = match app_url {
  34. AppUrl::Url(url) => match url {
  35. WindowUrl::External(_) => Default::default(),
  36. WindowUrl::App(path) => {
  37. if path.components().count() == 0 {
  38. panic!(
  39. "The `{}` configuration cannot be empty",
  40. if dev { "devPath" } else { "distDir" }
  41. )
  42. }
  43. let assets_path = config_parent.join(path);
  44. if !assets_path.exists() {
  45. panic!(
  46. "The `{}` configuration is set to `{:?}` but this path doesn't exist",
  47. if dev { "devPath" } else { "distDir" },
  48. path
  49. )
  50. }
  51. EmbeddedAssets::new(&assets_path, options)?
  52. }
  53. _ => unimplemented!(),
  54. },
  55. AppUrl::Files(files) => EmbeddedAssets::load_paths(
  56. files.iter().map(|p| config_parent.join(p)).collect(),
  57. options,
  58. )?,
  59. _ => unimplemented!(),
  60. };
  61. // handle default window icons for Windows targets
  62. let default_window_icon = if cfg!(windows) {
  63. let icon_path = find_icon(
  64. &config,
  65. &config_parent,
  66. |i| i.ends_with(".ico"),
  67. "icons/icon.ico",
  68. );
  69. quote!(Some(include_bytes!(#icon_path).to_vec()))
  70. } else if cfg!(target_os = "linux") {
  71. let icon_path = find_icon(
  72. &config,
  73. &config_parent,
  74. |i| i.ends_with(".png"),
  75. "icons/icon.png",
  76. );
  77. quote!(Some(include_bytes!(#icon_path).to_vec()))
  78. } else {
  79. quote!(None)
  80. };
  81. let package_name = if let Some(product_name) = &config.package.product_name {
  82. quote!(#product_name.to_string())
  83. } else {
  84. quote!(env!("CARGO_PKG_NAME").to_string())
  85. };
  86. let package_version = if let Some(version) = &config.package.version {
  87. quote!(#version.to_string())
  88. } else {
  89. quote!(env!("CARGO_PKG_VERSION").to_string())
  90. };
  91. let package_info = quote!(
  92. #root::PackageInfo {
  93. name: #package_name,
  94. version: #package_version,
  95. }
  96. );
  97. #[cfg(target_os = "linux")]
  98. let system_tray_icon = if let Some(tray) = &config.tauri.system_tray {
  99. let mut system_tray_icon_path = tray.icon_path.clone();
  100. system_tray_icon_path.set_extension("png");
  101. if dev {
  102. let system_tray_icon_path = config_parent
  103. .join(system_tray_icon_path)
  104. .display()
  105. .to_string();
  106. quote!(Some(#root::Icon::File(::std::path::PathBuf::from(#system_tray_icon_path))))
  107. } else {
  108. let system_tray_icon_file_path = system_tray_icon_path.to_string_lossy().to_string();
  109. quote!(
  110. Some(
  111. #root::Icon::File(
  112. #root::api::path::resolve_path(
  113. &#config, &#package_info,
  114. #system_tray_icon_file_path,
  115. Some(#root::api::path::BaseDirectory::Resource)
  116. ).expect("failed to resolve resource dir")
  117. )
  118. )
  119. )
  120. }
  121. } else {
  122. quote!(None)
  123. };
  124. #[cfg(not(target_os = "linux"))]
  125. let system_tray_icon = if let Some(tray) = &config.tauri.system_tray {
  126. let mut system_tray_icon_path = tray.icon_path.clone();
  127. system_tray_icon_path.set_extension(if cfg!(windows) { "ico" } else { "png" });
  128. let system_tray_icon_path = config_parent
  129. .join(system_tray_icon_path)
  130. .display()
  131. .to_string();
  132. quote!(Some(#root::Icon::Raw(include_bytes!(#system_tray_icon_path).to_vec())))
  133. } else {
  134. quote!(None)
  135. };
  136. #[cfg(target_os = "macos")]
  137. let info_plist = {
  138. if dev {
  139. let info_plist_path = config_parent.join("Info.plist");
  140. if info_plist_path.exists() {
  141. let info_plist_path = info_plist_path.display().to_string();
  142. quote!({
  143. tauri::embed_plist::embed_info_plist!(#info_plist_path);
  144. })
  145. } else {
  146. quote!(())
  147. }
  148. } else {
  149. quote!(())
  150. }
  151. };
  152. #[cfg(not(target_os = "macos"))]
  153. let info_plist = quote!(());
  154. // double braces are purposeful to force the code into a block expression
  155. Ok(quote!(#root::Context::new(
  156. #config,
  157. ::std::sync::Arc::new(#assets),
  158. #default_window_icon,
  159. #system_tray_icon,
  160. #package_info,
  161. #info_plist,
  162. )))
  163. }
  164. fn find_icon<F: Fn(&&String) -> bool>(
  165. config: &Config,
  166. config_parent: &Path,
  167. predicate: F,
  168. default: &str,
  169. ) -> String {
  170. let icon_path = config
  171. .tauri
  172. .bundle
  173. .icon
  174. .iter()
  175. .find(|i| predicate(i))
  176. .cloned()
  177. .unwrap_or_else(|| default.to_string());
  178. config_parent.join(icon_path).display().to_string()
  179. }