diff --git a/package.json b/package.json index f3cd54b6..83aa787e 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@tauri-apps/plugin-notification": "^2.3.1", "@tauri-apps/plugin-opener": "^2.5.0", "@tauri-apps/plugin-os": "^2.3.1", + "@tauri-apps/plugin-process": "^2.3.0", "@tauri-apps/plugin-window-state": "^2.4.0", "@types/byte-size": "^8.1.2", "@use-gesture/react": "^10.3.1", @@ -92,6 +93,7 @@ "react-click-away-listener": "^2.4.0", "react-dom": "^19.1.1", "react-hook-form": "^7.63.0", + "react-hotkeys-hook": "^5.2.1", "react-loading-skeleton": "^3.5.0", "react-markdown": "^10.1.0", "react-qr-code": "^2.0.18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b2cd5ffb..524c4d09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@tauri-apps/plugin-os': specifier: ^2.3.1 version: 2.3.1 + '@tauri-apps/plugin-process': + specifier: ^2.3.0 + version: 2.3.0 '@tauri-apps/plugin-window-state': specifier: ^2.4.0 version: 2.4.0 @@ -143,6 +146,9 @@ importers: react-hook-form: specifier: ^7.63.0 version: 7.63.0(react@19.1.1) + react-hotkeys-hook: + specifier: ^5.2.1 + version: 5.2.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-loading-skeleton: specifier: ^3.5.0 version: 3.5.0(react@19.1.1) @@ -1207,6 +1213,9 @@ packages: '@tauri-apps/plugin-os@2.3.1': resolution: {integrity: sha512-ty5V8XDUIFbSnrk3zsFoP3kzN+vAufYzalJSlmrVhQTImIZa1aL1a03bOaP2vuBvfR+WDRC6NgV2xBl8G07d+w==} + '@tauri-apps/plugin-process@2.3.0': + resolution: {integrity: sha512-0DNj6u+9csODiV4seSxxRbnLpeGYdojlcctCuLOCgpH9X3+ckVZIEj6H7tRQ7zqWr7kSTEWnrxtAdBb0FbtrmQ==} + '@tauri-apps/plugin-window-state@2.4.0': resolution: {integrity: sha512-hRSzPNi2NG0lPFthfVY0V5C1MyWN/gGaQtQYw7i9zZhLzrhZveHZ2omHG1rIiIsjfTGbO7fhjydSoeTTK9GqLw==} @@ -2458,6 +2467,12 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 + react-hotkeys-hook@5.2.1: + resolution: {integrity: sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -3845,6 +3860,10 @@ snapshots: dependencies: '@tauri-apps/api': 2.8.0 + '@tauri-apps/plugin-process@2.3.0': + dependencies: + '@tauri-apps/api': 2.8.0 + '@tauri-apps/plugin-window-state@2.4.0': dependencies: '@tauri-apps/api': 2.8.0 @@ -5285,6 +5304,11 @@ snapshots: dependencies: react: 19.1.1 + react-hotkeys-hook@5.2.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + dependencies: + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-is@16.13.1: {} react-is@18.3.1: {} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3c7eba8d..dc335b73 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1293,12 +1293,12 @@ dependencies = [ "tauri-plugin-deep-link", "tauri-plugin-dialog", "tauri-plugin-fs", - "tauri-plugin-global-shortcut", "tauri-plugin-http", "tauri-plugin-log", "tauri-plugin-notification", "tauri-plugin-opener", "tauri-plugin-os", + "tauri-plugin-process", "tauri-plugin-single-instance", "tauri-plugin-window-state", "thiserror 2.0.16", @@ -2299,24 +2299,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[package]] -name = "global-hotkey" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" -dependencies = [ - "crossbeam-channel", - "keyboard-types", - "objc2 0.6.2", - "objc2-app-kit", - "once_cell", - "serde", - "thiserror 2.0.16", - "windows-sys 0.59.0", - "x11rb", - "xkeysym", -] - [[package]] name = "gloo-timers" version = "0.3.0" @@ -6310,21 +6292,6 @@ dependencies = [ "url", ] -[[package]] -name = "tauri-plugin-global-shortcut" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df9f0f7bf2fe768b85fee4951c2505a35b72c44df1f6403e74e110bc13c5f58" -dependencies = [ - "global-hotkey", - "log", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror 2.0.16", -] - [[package]] name = "tauri-plugin-http" version = "2.5.2" @@ -6430,6 +6397,16 @@ dependencies = [ "thiserror 2.0.16", ] +[[package]] +name = "tauri-plugin-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7461c622a5ea00eb9cd9f7a08dbd3bf79484499fd5c21aa2964677f64ca651ab" +dependencies = [ + "tauri", + "tauri-plugin", +] + [[package]] name = "tauri-plugin-single-instance" version = "2.3.4" @@ -8465,12 +8442,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "xkeysym" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" - [[package]] name = "yoke" version = "0.8.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 85b570e7..6fc6485b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -110,7 +110,7 @@ x25519-dalek = { version = "2", features = [ "serde", "static_secrets", ] } -tauri-plugin-global-shortcut = "2.3.0" +tauri-plugin-process = "2.3.0" [target.'cfg(unix)'.dependencies] hyper-util = "0.1" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index c171d2b6..d8b4de1b 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -48,6 +48,7 @@ "os:allow-hostname", "dialog:default", "clipboard-manager:allow-write-text", + "process:allow-exit", { "identifier": "http:default", "allow": [ diff --git a/src-tauri/deny.toml b/src-tauri/deny.toml index f0d3f368..d7769622 100644 --- a/src-tauri/deny.toml +++ b/src-tauri/deny.toml @@ -87,6 +87,11 @@ ignore = [ { id = "RUSTSEC-2024-0420", reason = "Tauri v2 GTK3 dependency (unmaintained)" }, { id = "RUSTSEC-2025-0052", reason = "Discontinued, but dark-light v2.0.0 needs it" }, { id = "RUSTSEC-2025-0057", reason = "Tauri needs it" }, + { id = "RUSTSEC-2025-0075", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0080", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0081", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0098", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0100", reason = "Tauri v2 dependency (unmaintained)" }, ] # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index 76514a4a..0b4411e6 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -28,7 +28,6 @@ use log::{Level, LevelFilter}; #[cfg(target_os = "macos")] use tauri::{process, Env}; use tauri::{AppHandle, Builder, Manager, RunEvent, WindowEvent}; -use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState}; use tauri_plugin_log::{Target, TargetKind}; #[macro_use] @@ -185,6 +184,7 @@ fn main() { .plugin(tauri_plugin_window_state::Builder::new().build()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_os::init()) + .plugin(tauri_plugin_process::init()) .setup(|app| { // Register for linux and dev windows builds #[cfg(any(target_os = "linux", all(debug_assertions, windows)))] @@ -264,20 +264,6 @@ fn main() { .build(), )?; - // Setup ctrl-q keyboard shortcut - let ctrl_q_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyQ); - app_handle.plugin( - tauri_plugin_global_shortcut::Builder::new() - .with_handler(move |app, shortcut, event| { - if shortcut == &ctrl_q_shortcut && event.state() == ShortcutState::Pressed { - info!("Ctrl-Q pressed, closing active connections and exiting"); - app.exit(0); - } - }) - .build(), - )?; - app.global_shortcut().register(ctrl_q_shortcut)?; - let state = AppState::new(config); app.manage(state); diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index 5bc83de6..df7132cf 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -4,7 +4,7 @@ import '../../shared/scss/index.scss'; import { QueryClient } from '@tanstack/query-core'; import { QueryClientProvider } from '@tanstack/react-query'; -import { debug } from '@tauri-apps/plugin-log'; +import { debug, info } from '@tauri-apps/plugin-log'; import { openUrl } from '@tauri-apps/plugin-opener'; import dayjs from 'dayjs'; import customParseData from 'dayjs/plugin/customParseFormat'; @@ -38,6 +38,8 @@ import { useTheme } from '../../shared/defguard-ui/hooks/theme/useTheme'; import { ThemeProvider } from '../../shared/providers/ThemeProvider/ThemeProvider'; import { routes } from '../../shared/routes'; import { ApplicationUpdateManager } from '../ApplicationUpdateManager/ApplicationUpdateManager'; +import { exit } from '@tauri-apps/plugin-process'; +import { useHotkeys } from 'react-hotkeys-hook'; dayjs.extend(duration); dayjs.extend(utc); @@ -186,6 +188,12 @@ export const App = () => { }; }, []); + // register ctrl+q keyboard shortcut + useHotkeys('ctrl+q', () => { + info("Ctrl-Q pressed, exiting."); + exit(0); + }); + if (!appLoaded) return null; return (