diff --git a/app/renderer/package.json b/app/renderer/package.json index e2856fb4..ddcea6bf 100644 --- a/app/renderer/package.json +++ b/app/renderer/package.json @@ -35,6 +35,7 @@ "@pomatez/shareables": "*", "@tauri-apps/api": "2.0.0-alpha.8", "@tauri-apps/plugin-autostart": "^2.0.0-alpha.1", + "@tauri-apps/plugin-global-shortcut": "^2.0.0-alpha.1", "@tauri-apps/plugin-window": "^2.0.0-alpha.1", "@types/autosize": "^3.0.7", "@types/jest": "^26.0.24", diff --git a/app/tauri/Cargo.lock b/app/tauri/Cargo.lock index d72e4954..69e5f41e 100644 --- a/app/tauri/Cargo.lock +++ b/app/tauri/Cargo.lock @@ -1263,6 +1263,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "global-hotkey" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c12993a445d59000c3994fcd3d179e7da026a4234cc46db652987aa2785e4a" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "once_cell", + "thiserror", + "windows-sys 0.48.0", + "x11-dl", +] + [[package]] name = "gobject-sys" version = "0.16.3" @@ -2318,6 +2332,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-autostart", + "tauri-plugin-global-shortcut", "tauri-plugin-window", ] @@ -3223,6 +3238,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "tauri-plugin-global-shortcut" +version = "2.0.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a55e25d565b5eafaa4357ac49d52dd5826ac78c8eb0dc6a9c2d6ff60ab75ce" +dependencies = [ + "global-hotkey", + "log", + "serde", + "serde_json", + "tauri", + "thiserror", +] + [[package]] name = "tauri-plugin-window" version = "2.0.0-alpha.2" diff --git a/app/tauri/Cargo.toml b/app/tauri/Cargo.toml index 1a5bea2f..12a3328d 100644 --- a/app/tauri/Cargo.toml +++ b/app/tauri/Cargo.toml @@ -24,6 +24,9 @@ tauri-plugin-window = "2.0.0-alpha" tauri-plugin-autostart = "2.0.0-alpha" base64 = { version = "0.21.4", features = [] } +[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] +tauri-plugin-global-shortcut = "2.0.0-alpha" + [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL diff --git a/app/tauri/src/commands.rs b/app/tauri/src/commands.rs index 102e9196..e9ee8714 100644 --- a/app/tauri/src/commands.rs +++ b/app/tauri/src/commands.rs @@ -3,20 +3,13 @@ use std::sync::Mutex; // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command -use tauri::{Builder, Icon, PhysicalSize, Runtime, Wry}; -use tauri::{ - menu::{MenuBuilder, MenuItemBuilder}, - tray::{ClickType, TrayIconBuilder}, -}; - -use tauri::Manager; -use base64; -use base64::Engine; -use base64::engine::general_purpose; +use tauri::{Builder, PhysicalSize, Runtime, Wry}; #[non_exhaustive] struct WindowSize; +use crate::system_tray; + impl WindowSize { // Not sure why, if its due to UI scaling or what though these values seem to size smaller than the same values on electron @@ -159,32 +152,9 @@ fn set_native_titlebar(use_native_titlebar: bool, window: tauri::Win Ok(_) => (), Err(e) => println!("There was a problem setting the window decorations! {:?}", e), } - window.start_dragging(); println!("set_native_titlebar! {}", use_native_titlebar); } -#[tauri::command] -fn tray_icon_update(data_url: String, window: tauri::Window) { - println!("tray_icon_update!"); - let base64_str = data_url.trim_start_matches("data:image/png;base64,"); - - let decoded_vec = match general_purpose::STANDARD.decode(base64_str) { - Ok(vec) => vec, - Err(e) => { - eprintln!("Error decoding Base64 string: {}", e); - return; - } - }; - - let icon: Icon = Icon::Raw(decoded_vec); - let tray = window.app_handle().tray(); - - if let Some(tray) = tray { - if let Err(e) = tray.set_icon(Some(icon)) { - eprintln!("Error setting tray icon: {}", e); - } - } -} /** * We could do this by passing the object into a custom function that adds the commands but I wanted @@ -193,52 +163,14 @@ fn tray_icon_update(data_url: String, window: tauri::Window) { * Switch to a function that takes and returns tauri::Builder or uses a reference if we need to * switch it. */ -pub trait PomatezExtras { +pub trait PomatezCommands { fn register_pomatez_commands(self) -> tauri::Builder; - fn set_pomatez_system_tray(self) -> tauri::Builder; } -impl PomatezExtras for Builder { +impl PomatezCommands for Builder { fn register_pomatez_commands(self) -> tauri::Builder { self.invoke_handler(tauri::generate_handler![set_show, set_always_on_top, set_fullscreen_break, set_compact_mode, set_ui_theme, set_native_titlebar, - tray_icon_update, set_close, set_minimize]) - } - - fn set_pomatez_system_tray(self) -> tauri::Builder { - println!("Setting system tray"); - self.setup(|app| { - // Was defined in tauri.config.json to start in v1 - // That was created with an id of 1 though this gives more control - - let show = MenuItemBuilder::with_id("show", "Show").build(app); - let quit = MenuItemBuilder::with_id("quit", "Quit").build(app); - let menu = MenuBuilder::new(app).items(&[&show, &quit]).build()?; - let tray = TrayIconBuilder::new() - .menu(&menu) - .tooltip("Pomatez") - .on_menu_event(move |app, event| match event.id().as_ref() { - "show" => { - let window = app.get_window("main").unwrap(); - window.show().unwrap(); - window.set_focus().unwrap(); - } - "quit" => { - app.exit(0); - } - _ => {} - }) - .on_tray_event(|tray, event| { - if event.click_type == ClickType::Left { - let app = tray.app_handle(); - let window = app.get_window("main").unwrap(); - window.show().unwrap(); - window.set_focus().unwrap(); - } - }) - .icon(Icon::File("./icons/icon.png".into())) - .build(app)?; - Ok(()) - }) + system_tray::tray_icon_update, set_close, set_minimize]) } } diff --git a/app/tauri/src/global_shortcuts.rs b/app/tauri/src/global_shortcuts.rs new file mode 100644 index 00000000..e69de29b diff --git a/app/tauri/src/main.rs b/app/tauri/src/main.rs index e9e42b9b..812b48bd 100644 --- a/app/tauri/src/main.rs +++ b/app/tauri/src/main.rs @@ -9,7 +9,11 @@ use tauri_plugin_window; #[macro_use] mod commands; -use commands::PomatezExtras; +mod system_tray; +mod global_shortcuts; + +use commands::PomatezCommands; +use system_tray::PomatezTray; fn main() { tauri::Builder::default() diff --git a/app/tauri/src/system_tray.rs b/app/tauri/src/system_tray.rs new file mode 100644 index 00000000..adec9025 --- /dev/null +++ b/app/tauri/src/system_tray.rs @@ -0,0 +1,94 @@ +use std::path::PathBuf; +use tauri::{Builder, Icon, Manager, Runtime, Wry}; +use tauri::{ + menu::{MenuBuilder, MenuItemBuilder}, + tray::{ClickType, TrayIconBuilder}, +}; +use tauri::path::BaseDirectory; + +use base64; +use base64::Engine; +use base64::engine::general_purpose; + +#[tauri::command] +pub fn tray_icon_update(data_url: String, window: tauri::Window) { + println!("tray_icon_update!"); + let base64_str = data_url.trim_start_matches("data:image/png;base64,"); + + let decoded_vec = match general_purpose::STANDARD.decode(base64_str) { + Ok(vec) => vec, + Err(e) => { + eprintln!("Error decoding Base64 string: {}", e); + return; + } + }; + + let icon: Icon = Icon::Raw(decoded_vec); + let tray = window.app_handle().tray(); + + if let Some(tray) = tray { + if let Err(e) = tray.set_icon(Some(icon)) { + eprintln!("Error setting tray icon: {}", e); + } + } +} + + +/** +* We could do this by passing the object into a custom function that adds the commands but I wanted +* to practice more with rust. Plus it makes the setup cleaner. + +* Switch to a function that takes and returns tauri::Builder or uses a reference if we need to +* switch it. + */ +pub trait PomatezTray { + fn set_pomatez_system_tray(self) -> tauri::Builder; +} + +impl PomatezTray for Builder { + + /* + * The icon is updated after rendering on the frontend so that is handled in the commands file. + * However the initial setup and behavior is handled here. + */ + fn set_pomatez_system_tray(self) -> tauri::Builder { + println!("Setting system tray"); + self.setup(|app| { + // Was defined in tauri.config.json to start in v1 + // That was created with an id of 1 though this gives more control + + let show = MenuItemBuilder::with_id("show", "Show").build(app); + let quit = MenuItemBuilder::with_id("quit", "Quit").build(app); + let menu = MenuBuilder::new(app).items(&[&show, &quit]).build()?; + + let icon_path = app.path().resolve::("icons/icon.png".into(), BaseDirectory::Resource) + .expect("failed to resolve icon path, this should not happen as it is an internal file"); + + let _ = TrayIconBuilder::new() + .menu(&menu) + .tooltip("Pomatez") + .on_menu_event(move |app, event| match event.id().as_ref() { + "show" => { + let window = app.get_window("main").unwrap(); + window.show().unwrap(); + window.set_focus().unwrap(); + } + "quit" => { + app.exit(0); + } + _ => {} + }) + .on_tray_event(|tray, event| { + if event.click_type == ClickType::Left { + let app = tray.app_handle(); + let window = app.get_window("main").unwrap(); + window.show().unwrap(); + window.set_focus().unwrap(); + } + }) + .icon(Icon::File(icon_path)) + .build(app)?; + Ok(()) + }) + } +} diff --git a/app/tauri/tauri.conf.json b/app/tauri/tauri.conf.json index b090dca0..9e3fd477 100644 --- a/app/tauri/tauri.conf.json +++ b/app/tauri/tauri.conf.json @@ -37,9 +37,9 @@ "signingIdentity": null }, "publisher": "Roldan Montilla Jr", - "resources": [], + "resources": ["icons/icon.png"], "shortDescription": "", - "targets": "all", + "targets": ["deb", "appimage", "msi", "dmg", "updater"], "windows": { "certificateThumbprint": null, "digestAlgorithm": "sha256", diff --git a/tsconfig.json b/tsconfig.json index 1b84e1e2..01f8b5cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "suppressImplicitAnyIndexErrors": true, + "ignoreDeprecations": "5.0", "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, diff --git a/yarn.lock b/yarn.lock index 3576b390..945dad4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3732,6 +3732,13 @@ dependencies: "@tauri-apps/api" "2.0.0-alpha.6" +"@tauri-apps/plugin-global-shortcut@^2.0.0-alpha.1": + version "2.0.0-alpha.1" + resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-global-shortcut/-/plugin-global-shortcut-2.0.0-alpha.1.tgz#d5abec71d7b731b3530712fb21c05bf6d11fd9c4" + integrity sha512-86pqnvoylSZV7R/SjK1WlLhTWydIhRS5qjHl6IqIcY4sYRuBMovMNj8fMLhFt2Ppq4dRiSx5jbrlQDY82HJtaQ== + dependencies: + "@tauri-apps/api" "2.0.0-alpha.6" + "@tauri-apps/plugin-window@^2.0.0-alpha.1": version "2.0.0-alpha.1" resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-window/-/plugin-window-2.0.0-alpha.1.tgz#28a0217100fc5a34fb2a6d76103ba056b2348286"