Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

refactor(core): read tray icon only on desktop, refactor Context #6719

Merged
merged 5 commits into from Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/remove-tray-icon-mobile.md
@@ -0,0 +1,6 @@
---
"tauri-codegen": patch
"tauri": patch
---

Refactor the `Context` conditional fields and only parse the tray icon on desktop.
92 changes: 57 additions & 35 deletions core/tauri-codegen/src/context.rs
Expand Up @@ -125,6 +125,16 @@ enum Target {
Ios,
}

impl Target {
fn mobile(&self) -> bool {
matches!(self, Target::Android | Target::Ios)
}

fn desktop(&self) -> bool {
!self.mobile()
}
Copy link
Member

Choose a reason for hiding this comment

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

Not 100% sure we've been following this convention throughout the codebase, but since these aren't returning a "field" on the item but a property of it we may want to use the is_ prefix.

Suggested change
fn mobile(&self) -> bool {
matches!(self, Target::Android | Target::Ios)
}
fn desktop(&self) -> bool {
!self.mobile()
}
fn is_mobile(&self) -> bool {
matches!(self, Target::Android | Target::Ios)
}
fn is_desktop(&self) -> bool {
!self.mobile()
}

}

/// Build a `tauri::Context` for including in application code.
pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsError> {
let ContextData {
Expand Down Expand Up @@ -247,15 +257,15 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
"icons/icon.ico",
);
if icon_path.exists() {
ico_icon(&root, &out_dir, icon_path)?
ico_icon(&root, &out_dir, icon_path).map(|i| quote!(::std::option::Option::Some(#i)))?
} else {
let icon_path = find_icon(
&config,
&config_parent,
|i| i.ends_with(".png"),
"icons/icon.png",
);
png_icon(&root, &out_dir, icon_path)?
png_icon(&root, &out_dir, icon_path).map(|i| quote!(::std::option::Option::Some(#i)))?
}
} else if target == Target::Linux {
// handle default window icons for Linux targets
Expand All @@ -265,9 +275,9 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|i| i.ends_with(".png"),
"icons/icon.png",
);
png_icon(&root, &out_dir, icon_path)?
png_icon(&root, &out_dir, icon_path).map(|i| quote!(::std::option::Option::Some(#i)))?
} else {
quote!(None)
quote!(::std::option::Option::None)
}
};

Expand All @@ -288,7 +298,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
}
raw_icon(&out_dir, icon_path)?
} else {
quote!(None)
quote!(::std::option::Option::None)
};

let package_name = if let Some(product_name) = &config.package.product_name {
Expand All @@ -312,20 +322,26 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
}
);

let system_tray_icon = if let Some(tray) = &config.tauri.system_tray {
let system_tray_icon_path = config_parent.join(&tray.icon_path);
let ext = system_tray_icon_path.extension();
if ext.map_or(false, |e| e == "ico") {
ico_icon(&root, &out_dir, system_tray_icon_path)?
} else if ext.map_or(false, |e| e == "png") {
png_icon(&root, &out_dir, system_tray_icon_path)?
let with_system_tray_icon_code = if target.desktop() {
if let Some(tray) = &config.tauri.system_tray {
let system_tray_icon_path = config_parent.join(&tray.icon_path);
let ext = system_tray_icon_path.extension();
if ext.map_or(false, |e| e == "ico") {
ico_icon(&root, &out_dir, system_tray_icon_path)
.map(|i| quote!(context.with_system_tray_icon(#i);))?
} else if ext.map_or(false, |e| e == "png") {
png_icon(&root, &out_dir, system_tray_icon_path)
.map(|i| quote!(context.with_system_tray_icon(#i);))?
} else {
quote!(compile_error!(
"The tray icon extension must be either `.ico` or `.png`."
))
}
} else {
quote!(compile_error!(
"The tray icon extension must be either `.ico` or `.png`."
))
quote!()
}
} else {
quote!(None)
quote!()
};

#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -409,7 +425,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
};

#[cfg(feature = "shell-scope")]
let shell_scope_config = {
let with_shell_scope_code = {
use regex::Regex;
use tauri_utils::config::ShellAllowlistOpen;

Expand All @@ -433,26 +449,30 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
_ => panic!("unknown shell open format, unable to prepare"),
};

quote!(#root::ShellScopeConfig {
quote!(context.with_shell_scope(#root::ShellScopeConfig {
open: #shell_scope_open,
scopes: #shell_scopes
})
});)
};

#[cfg(not(feature = "shell-scope"))]
let shell_scope_config = quote!();

Ok(quote!(#root::Context::new(
#config,
::std::sync::Arc::new(#assets),
#default_window_icon,
#app_icon,
#system_tray_icon,
#package_info,
#info_plist,
#pattern,
#shell_scope_config
)))
let with_shell_scope_code = quote!();

Ok(quote!({
#[allow(unused_mut, clippy::let_and_return)]
let mut context = #root::Context::new(
#config,
::std::sync::Arc::new(#assets),
#default_window_icon,
#app_icon,
#package_info,
#info_plist,
#pattern,
);
#with_system_tray_icon_code
#with_shell_scope_code
context
}))
}

fn ico_icon<P: AsRef<Path>>(
Expand Down Expand Up @@ -483,7 +503,7 @@ fn ico_icon<P: AsRef<Path>>(

let out_path = out_path.display().to_string();

let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
let icon = quote!(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height });
Ok(icon)
}

Expand All @@ -501,7 +521,9 @@ fn raw_icon<P: AsRef<Path>>(out_dir: &Path, path: P) -> Result<TokenStream, Embe

let out_path = out_path.display().to_string();

let icon = quote!(Some(include_bytes!(#out_path).to_vec()));
let icon = quote!(::std::option::Option::Some(
include_bytes!(#out_path).to_vec()
));
Ok(icon)
}

Expand Down Expand Up @@ -533,7 +555,7 @@ fn png_icon<P: AsRef<Path>>(

let out_path = out_path.display().to_string();

let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
let icon = quote!(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height });
Ok(icon)
}

Expand Down
29 changes: 24 additions & 5 deletions core/tauri/src/lib.rs
Expand Up @@ -552,6 +552,7 @@ pub struct Context<A: Assets> {
pub(crate) assets: Arc<A>,
pub(crate) default_window_icon: Option<Icon>,
pub(crate) app_icon: Option<Vec<u8>>,
#[cfg(desktop)]
pub(crate) system_tray_icon: Option<Icon>,
pub(crate) package_info: PackageInfo,
pub(crate) _info_plist: (),
Expand All @@ -566,9 +567,12 @@ impl<A: Assets> fmt::Debug for Context<A> {
d.field("config", &self.config)
.field("default_window_icon", &self.default_window_icon)
.field("app_icon", &self.app_icon)
.field("system_tray_icon", &self.system_tray_icon)
.field("package_info", &self.package_info)
.field("pattern", &self.pattern);

#[cfg(desktop)]
d.field("system_tray_icon", &self.system_tray_icon);

#[cfg(shell_scope)]
d.field("shell_scope", &self.shell_scope);
d.finish()
Expand Down Expand Up @@ -613,12 +617,14 @@ impl<A: Assets> Context<A> {
}

/// The icon to use on the system tray UI.
#[cfg(desktop)]
#[inline(always)]
pub fn system_tray_icon(&self) -> Option<&Icon> {
self.system_tray_icon.as_ref()
}

/// A mutable reference to the icon to use on the system tray UI.
#[cfg(desktop)]
#[inline(always)]
pub fn system_tray_icon_mut(&mut self) -> &mut Option<Icon> {
&mut self.system_tray_icon
Expand Down Expand Up @@ -657,25 +663,38 @@ impl<A: Assets> Context<A> {
assets: Arc<A>,
default_window_icon: Option<Icon>,
app_icon: Option<Vec<u8>>,
system_tray_icon: Option<Icon>,
package_info: PackageInfo,
info_plist: (),
pattern: Pattern,
#[cfg(shell_scope)] shell_scope: scope::ShellScopeConfig,
) -> Self {
Self {
config,
assets,
default_window_icon,
app_icon,
system_tray_icon,
#[cfg(desktop)]
system_tray_icon: None,
package_info,
_info_plist: info_plist,
pattern,
#[cfg(shell_scope)]
shell_scope,
shell_scope: Default::default(),
}
}

/// Sets the app tray icon.
#[cfg(desktop)]
#[inline(always)]
pub fn with_system_tray_icon(&mut self, icon: Icon) {
self.system_tray_icon.replace(icon);
}

/// Sets the app shell scope.
#[cfg(shell_scope)]
#[inline(always)]
pub fn with_shell_scope(&mut self, scope: scope::ShellScopeConfig) {
Copy link
Member

Choose a reason for hiding this comment

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

with_ prefixed methods are typically used for alternative constructors, not replacements of a single field. If there is a self being passed to a with_ function, then it's probably named wrong. I think set_ in this case works best since it's completely replacing a single item.

Suggested change
pub fn with_system_tray_icon(&mut self, icon: Icon) {
self.system_tray_icon.replace(icon);
}
/// Sets the app shell scope.
#[cfg(shell_scope)]
#[inline(always)]
pub fn with_shell_scope(&mut self, scope: scope::ShellScopeConfig) {
pub fn set_system_tray_icon(&mut self, icon: Icon) {
self.system_tray_icon.replace(icon);
}
/// Sets the app shell scope.
#[cfg(shell_scope)]
#[inline(always)]
pub fn set_shell_scope(&mut self, scope: scope::ShellScopeConfig) {

self.shell_scope = scope;
}
}

// TODO: expand these docs
Expand Down
16 changes: 11 additions & 5 deletions core/tauri/src/manager.rs
Expand Up @@ -219,6 +219,7 @@ pub struct InnerWindowManager<R: Runtime> {
assets: Arc<dyn Assets>,
pub(crate) default_window_icon: Option<Icon>,
pub(crate) app_icon: Option<Vec<u8>>,
#[cfg(desktop)]
pub(crate) tray_icon: Option<Icon>,

package_info: PackageInfo,
Expand All @@ -240,17 +241,21 @@ pub struct InnerWindowManager<R: Runtime> {

impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InnerWindowManager")
.field("plugins", &self.plugins)
let mut d = f.debug_struct("InnerWindowManager");

d.field("plugins", &self.plugins)
.field("state", &self.state)
.field("config", &self.config)
.field("default_window_icon", &self.default_window_icon)
.field("app_icon", &self.app_icon)
.field("tray_icon", &self.tray_icon)
.field("package_info", &self.package_info)
.field("menu", &self.menu)
.field("pattern", &self.pattern)
.finish()
.field("pattern", &self.pattern);

#[cfg(desktop)]
d.field("tray_icon", &self.tray_icon);

d.finish()
}
}

Expand Down Expand Up @@ -322,6 +327,7 @@ impl<R: Runtime> WindowManager<R> {
assets: context.assets,
default_window_icon: context.default_window_icon,
app_icon: context.app_icon,
#[cfg(desktop)]
tray_icon: context.system_tray_icon,
package_info: context.package_info,
pattern: context.pattern,
Expand Down
4 changes: 2 additions & 2 deletions core/tauri/src/scope/shell.rs
Expand Up @@ -58,7 +58,7 @@ impl From<Vec<String>> for ExecuteArgs {
}

/// Shell scope configuration.
#[derive(Debug, Clone)]
#[derive(Debug, Default, Clone)]
Copy link
Member

Choose a reason for hiding this comment

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

This derive will have the open field set to None by default, which means that it is not matched through the default regex. It should probably match the default of ^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+. We may want to adjust how we create it from the config so that we don't need to have the "default" filtering regex in more than 1 place, to reduce future duplication mistakes.

pub struct ScopeConfig {
/// The validation regex that `shell > open` paths must match against.
pub open: Option<Regex>,
Expand Down Expand Up @@ -106,7 +106,7 @@ impl ScopeAllowedArg {
}

/// Scope for filesystem access.
#[derive(Clone)]
#[derive(Default, Clone)]
pub struct Scope(ScopeConfig);

/// All errors that can happen while validating a scoped command.
Expand Down
1 change: 1 addition & 0 deletions core/tauri/src/test/mod.rs
Expand Up @@ -60,6 +60,7 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
assets: Arc::new(assets),
default_window_icon: None,
app_icon: None,
#[cfg(desktop)]
system_tray_icon: None,
package_info: crate::PackageInfo {
name: "test".into(),
Expand Down