diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0696848..c9e8dcb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1879,6 +1879,30 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "libappindicator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + [[package]] name = "libc" version = "0.2.126" @@ -1894,6 +1918,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libsodium-sys" version = "0.2.7" @@ -3622,6 +3656,7 @@ dependencies = [ "core-foundation", "core-graphics", "crossbeam-channel", + "dirs-next", "dispatch", "gdk", "gdk-pixbuf", @@ -3635,6 +3670,7 @@ dependencies = [ "instant", "jni 0.19.0", "lazy_static", + "libappindicator", "libc", "log", "ndk", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cb6be0d..63fb592 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.0.4", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.0.5", features = ["api-all"] } +tauri = { version = "1.0.5", features = ["api-all", "system-tray"] } sodiumoxide = "0.2.7" tokio = { version = ">=1.19", features = ["full"] } sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls"] } diff --git a/src-tauri/src/ipc.rs b/src-tauri/src/ipc.rs index cfa284f..f053485 100644 --- a/src-tauri/src/ipc.rs +++ b/src-tauri/src/ipc.rs @@ -1,5 +1,8 @@ +use core::time::Duration; + use serde::{Serialize, Deserialize}; use tauri::State; +use tokio::time::sleep; use crate::clientinfo::Client; use crate::state::{AppState, Session, Credentials}; @@ -27,9 +30,20 @@ pub enum Approval { #[tauri::command] -pub fn respond(response: RequestResponse, app_state: State<'_, AppState>) -> Result<(), String> { +pub fn respond( + response: RequestResponse, + window: tauri::Window, + app_state: State<'_, AppState> +) -> Result<(), String> { app_state.send_response(response) - .map_err(|e| format!("Error responding to request: {e}")) + .map_err(|e| format!("Error responding to request: {e}"))?; + + tauri::async_runtime::spawn(async move { + sleep(Duration::from_secs(3)).await; + let _ = window.hide(); + }); + + Ok(()) } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 9775293..21e5bde 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -11,6 +11,7 @@ mod clientinfo; mod ipc; mod state; mod server; +mod tray; use state::AppState; @@ -23,6 +24,8 @@ fn main() { tauri::Builder::default() .manage(initial_state) + .system_tray(tray::create()) + .on_system_tray_event(tray::handle_event) .invoke_handler(tauri::generate_handler![ ipc::unlock, ipc::respond, @@ -36,6 +39,16 @@ fn main() { tauri::async_runtime::spawn(server::serve(addr, app.handle())); Ok(()) }) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); + .build(tauri::generate_context!()) + .expect("error while running tauri application") + .run(|app, run_event| match run_event { + tauri::RunEvent::WindowEvent { label, event, .. } => match event { + tauri::WindowEvent::CloseRequested { api, .. } => { + let _ = app.get_window(&label).map(|w| w.hide()); + api.prevent_close(); + } + _ => () + } + _ => () + }) } \ No newline at end of file diff --git a/src-tauri/src/server.rs b/src-tauri/src/server.rs index 1cb45d7..0175100 100644 --- a/src-tauri/src/server.rs +++ b/src-tauri/src/server.rs @@ -93,7 +93,10 @@ impl Handler { async fn notify_frontend(&self, req: &Request) -> Result<(), RequestError> { self.app.emit_all("credentials-request", req)?; let window = self.app.get_window("main").ok_or(RequestError::NoMainWindow)?; - window.unminimize()?; + if !window.is_visible()? { + window.unminimize()?; + window.show()?; + } window.set_focus()?; Ok(()) } diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs new file mode 100644 index 0000000..71a8ddd --- /dev/null +++ b/src-tauri/src/tray.rs @@ -0,0 +1,36 @@ +use tauri::{ + AppHandle, + Manager, + SystemTray, + SystemTrayEvent, + SystemTrayMenu, + CustomMenuItem, +}; + + +pub fn create() -> SystemTray { + let show = CustomMenuItem::new("show".to_string(), "Show"); + let quit = CustomMenuItem::new("exit".to_string(), "Exit"); + + let menu = SystemTrayMenu::new() + .add_item(show) + .add_item(quit); + + SystemTray::new().with_menu(menu) +} + + +pub fn handle_event(app: &AppHandle, event: SystemTrayEvent) { + match event { + SystemTrayEvent::MenuItemClick{ id, .. } => { + match id.as_str() { + "exit" => app.exit(0), + "show" => { + let _ = app.get_window("main").map(|w| w.show()); + } + _ => (), + } + } + _ => (), + } +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 0187091..dc5e048 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -62,6 +62,10 @@ "title": "Creddy", "width": 800 } - ] + ], + "systemTray": { + "iconPath": "icons/icon.png", + "iconAsTemplate": true + } } } \ No newline at end of file diff --git a/src/views/Approve.svelte b/src/views/Approve.svelte index 47de640..9fb0a71 100644 --- a/src/views/Approve.svelte +++ b/src/views/Approve.svelte @@ -27,6 +27,9 @@ if (event.shiftKey && (event.code === 'Enter' || event.code === 'NumpadEnter')) { approve(); } + else if (event.code === 'Escape') { + deny(); + } } diff --git a/src/views/ShowDenied.svelte b/src/views/ShowDenied.svelte index 551ca06..eb08a76 100644 --- a/src/views/ShowDenied.svelte +++ b/src/views/ShowDenied.svelte @@ -4,18 +4,31 @@ import { invoke } from '@tauri-apps/api/tauri'; export let appState; + let error = null; - onMount(async () => { + const dispatch = createEventDispatcher(); + async function respond() { let response = { id: appState.currentRequest.id, approval: 'Denied', } - await invoke('respond', {response}); - appState.currentRequest = null; - }); - const dispatch = createEventDispatcher(); - window.setTimeout(() => dispatch('navigate', {target: 'Home'}), 3000); + try { + await invoke('respond', {response}); + appState.currentRequest = null; + } + catch (e) { + error = e; + } + + window.setTimeout(() => dispatch('navigate', {target: 'Home'}), 3000); + } + + onMount(respond); -

Denied!

\ No newline at end of file +{#if error} +
{error}
+{:else} +

Denied!

+{/if} \ No newline at end of file