Skip to content

Commit

Permalink
feat(tauri): add global show and hide shortcuts as well as block reload
Browse files Browse the repository at this point in the history
  • Loading branch information
sekwah41 committed Nov 12, 2023
1 parent 027dc7c commit ef17d00
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 56 deletions.
17 changes: 16 additions & 1 deletion app/renderer/src/contexts/connectors/TauriConnector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
SET_FULLSCREEN_BREAK,
SET_MINIMIZE,
SET_NATIVE_TITLEBAR,
SET_OPEN_AT_LOGIN,
SET_SHOW,
SET_UI_THEME,
TRAY_ICON_UPDATE,
Expand All @@ -25,6 +24,22 @@ export const TauriConnectorProvider: React.FC = ({ children }) => {
(state: AppStateTypes) => state.settings
);

useEffect(() => {
function handleKeyDown(event: KeyboardEvent) {
if (
(event.ctrlKey && (event.key === "r" || event.key === "R")) ||
event.key === "F5"
) {
event.preventDefault();
}
}

window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, []);

/**
* Rust uses lowercase snake_case for function names so we need to convert to lower case for the calls.
* @param event
Expand Down
1 change: 1 addition & 0 deletions app/tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions app/tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ serde = { version = "1.0", features = ["derive"] }
tauri = { version = "2.0.0-alpha.14", features = ["tray-icon", "icon-png"] }
tauri-plugin-window = "2.0.0-alpha"
tauri-plugin-autostart = "2.0.0-alpha"
lazy_static = "1.4.0"
base64 = { version = "0.21.4", features = [] }

# This one is for toying with global hotkeys from the browser mostly
# We can use https://github.com/tauri-apps/global-hotkey directly tbh
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
tauri-plugin-global-shortcut = "2.0.0-alpha"

Expand Down
2 changes: 1 addition & 1 deletion app/tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn set_minimize<R: Runtime>(minimize_to_tray: bool, window: tauri::Window<R>) {
if minimize_to_tray {
window.hide().unwrap();
} else {
window.close().unwrap();
window.minimize().unwrap();
}
}

Expand Down
71 changes: 59 additions & 12 deletions app/tauri/src/global_shortcuts.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,59 @@
/*
Key combos to block
WIndows at least
const blockKeys = [
"CommandOrControl+R",
"CommandOrControl+Shift+R",
"CommandOrControl+Alt+Q",
"F11",
];

When in fullscreen CommandOrControl+W
*/
use lazy_static::lazy_static;
use tauri::{Wry, Builder, Manager, AppHandle, App};
use tauri_plugin_global_shortcut::{GlobalShortcutExt, Modifiers, Shortcut};
use tauri_plugin_global_shortcut::Code;

lazy_static! {
static ref SHOW_SHORTCUT: Shortcut = Shortcut::new(Some(Modifiers::SHIFT | Modifiers::ALT), Code::KeyS);
static ref HIDE_SHORTCUT: Shortcut = Shortcut::new(Some(Modifiers::SHIFT | Modifiers::ALT), Code::KeyH);
static ref REFRESH: Shortcut = Shortcut::new(None, Code::F5);
}

pub trait PomatezGlobalShortcutsSetup {
fn setup_global_shortcuts(&self);
}

impl PomatezGlobalShortcutsSetup for App {
fn setup_global_shortcuts(&self) {
let window = self.get_window("main").expect("Failed to get window");
let global_shortcut_plugin = {
tauri_plugin_global_shortcut::Builder::with_handler(move |shortcut| {
println!("Shortcut pressed: {:?}", shortcut);
match shortcut.id() {
key if SHOW_SHORTCUT.id() == key => {
window.show().expect("Failed to show window");
window.set_focus().expect("Failed to focus window");
}
key if HIDE_SHORTCUT.id() == key => {
window.hide().expect("Failed to hide window");
}
_ => println!("Shortcut pressed: {:?}", shortcut),
}
if shortcut.matches(Modifiers::ALT | Modifiers::SHIFT, Code::KeyH) {
window.hide().expect("Failed to hide window");
} else {
println!("Shortcut pressed: {:?}", shortcut);
}
}).build()
};
let app_handle = self.handle();

app_handle.plugin(global_shortcut_plugin).expect("failed to register global shortcut plugin");

println!("Registered global shortcut plugin");
}
}

pub trait PomatezGlobalShortcutsRegister {
fn register_global_shortcuts(&self);
}

impl PomatezGlobalShortcutsRegister for AppHandle {
fn register_global_shortcuts(&self) {
let global_shortcut = self.global_shortcut();
global_shortcut.register(SHOW_SHORTCUT.clone()).expect("failed to register global shortcut");
global_shortcut.register(HIDE_SHORTCUT.clone()).expect("failed to register global shortcut");

println!("Registered global shortcuts");
}
}
23 changes: 19 additions & 4 deletions app/tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,39 @@ all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]

use tauri::RunEvent;
use tauri_plugin_autostart::MacosLauncher;
use tauri_plugin_global_shortcut::GlobalShortcutExt;
use tauri_plugin_window;

#[macro_use]
mod commands;

mod system_tray;
mod global_shortcuts;

use commands::PomatezCommands;
use system_tray::PomatezTray;
use global_shortcuts::{PomatezGlobalShortcutsSetup, PomatezGlobalShortcutsRegister};

fn main() {
tauri::Builder::default()
let app = tauri::Builder::default()
.plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, None))
.plugin(tauri_plugin_window::init())
.register_pomatez_commands()
.set_pomatez_system_tray()
.run(tauri::generate_context!())
.setup(|app| {
app.setup_global_shortcuts();
app.set_pomatez_system_tray();

Ok(())
})
.build(tauri::generate_context!())
.expect("error while running tauri application");

app.run(|app_handle, e| match e {
RunEvent::Ready => {
app_handle.register_global_shortcuts();
println!("Pomatez is ready");
}
_ => {}
});
}
73 changes: 35 additions & 38 deletions app/tauri/src/system_tray.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::path::PathBuf;
use tauri::{Builder, Icon, Manager, Runtime, Wry};
use tauri::{App, Builder, Icon, Manager, Runtime, Wry};
use tauri::{
menu::{MenuBuilder, MenuItemBuilder},
tray::{ClickType, TrayIconBuilder},
Expand Down Expand Up @@ -42,53 +42,50 @@ pub fn tray_icon_update<R: Runtime>(data_url: String, window: tauri::Window<R>)
* switch it.
*/
pub trait PomatezTray {
fn set_pomatez_system_tray(self) -> tauri::Builder<Wry>;
fn set_pomatez_system_tray(&self);
}

impl PomatezTray for Builder<Wry> {
impl PomatezTray for App {

/*
* 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<Wry> {
fn set_pomatez_system_tray(&self) {
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
// 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 show = MenuItemBuilder::with_id("show", "Show").build(self);
let quit = MenuItemBuilder::with_id("quit", "Quit").build(self);
let menu = MenuBuilder::new(self).items(&[&show, &quit]).build().expect("failed to build menu");

let icon_path = app.path().resolve::<PathBuf>("icons/icon.png".into(), BaseDirectory::Resource)
.expect("failed to resolve icon path, this should not happen as it is an internal file");
let icon_path = self.path().resolve::<PathBuf>("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(())
})
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(self).expect("failed to build tray icon");
}
}

0 comments on commit ef17d00

Please sign in to comment.