diff --git a/doc/todo.md b/doc/todo.md index 7bd06b0..43d4cc8 100644 --- a/doc/todo.md +++ b/doc/todo.md @@ -3,8 +3,10 @@ * ~~Switch to "process" provider for AWS credentials (much less hacky)~~ * ~~Frontend needs to react when request is cancelled from backend~~ * Session timeout (plain duration, or activity-based?) +* Indicate on approval screen when additional requests are pending * ~~Fix rehide behavior when new request comes in while old one is still being resolved~~ * Additional hotkey configuration (approve/deny at the very least) +* ~~Switch tray menu item to Hide when window is visible~~ * Logging * Icon * Auto-updates diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index 0ca865e..bc11af5 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -31,8 +31,8 @@ pub static APP: OnceCell = OnceCell::new(); pub fn run() -> tauri::Result<()> { tauri::Builder::default() .plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| { - app.get_window("main") - .map(|w| w.show().error_popup("Failed to show main window")); + show_main_window(app) + .error_popup("Failed to show main window"); })) .system_tray(tray::create()) .on_system_tray_event(tray::handle_event) @@ -49,9 +49,9 @@ pub fn run() -> tauri::Result<()> { .setup(|app| rt::block_on(setup(app))) .build(tauri::generate_context!())? .run(|app, run_event| match run_event { - tauri::RunEvent::WindowEvent { label, event, .. } => match event { + tauri::RunEvent::WindowEvent { event, .. } => match event { tauri::WindowEvent::CloseRequested { api, .. } => { - let _ = app.get_window(&label).map(|w| w.hide()); + let _ = hide_main_window(app); api.prevent_close(); } _ => () @@ -114,12 +114,41 @@ async fn setup(app: &mut App) -> Result<(), Box> { // if session is empty, this is probably the first launch, so don't autohide if !conf.start_minimized || is_first_launch { - app.get_window("main") - .ok_or(HandlerError::NoMainWindow)? - .show()?; + show_main_window(&app.handle())?; } let state = AppState::new(conf, session, pool, setup_errors, desktop_is_gnome); app.manage(state); Ok(()) } + + +pub fn show_main_window(app: &AppHandle) -> Result<(), WindowError> { + let w = app.get_window("main").ok_or(WindowError::NoMainWindow)?; + w.show()?; + app.tray_handle() + .get_item("show_hide") + .set_title("Hide")?; + Ok(()) +} + + +pub fn hide_main_window(app: &AppHandle) -> Result<(), WindowError> { + let w = app.get_window("main").ok_or(WindowError::NoMainWindow)?; + w.hide()?; + app.tray_handle() + .get_item("show_hide") + .set_title("Show")?; + Ok(()) +} + + +pub fn toggle_main_window(app: &AppHandle) -> Result<(), WindowError> { + let w = app.get_window("main").ok_or(WindowError::NoMainWindow)?; + if w.is_visible()? { + hide_main_window(app) + } + else { + show_main_window(app) + } +} diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index 6d590c1..c410580 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -11,6 +11,7 @@ use tauri::{ async_runtime as rt, }; +use crate::app; use crate::credentials::{ Session, BaseCredentials, @@ -42,19 +43,19 @@ impl Visibility { // `original` represents the visibility of the window before any leases were acquired // None means we don't know, Some(false) means it was previously hidden, // Some(true) means it was previously visible + let is_visible = window.is_visible()?; if self.original.is_none() { - let is_visible = window.is_visible()?; self.original = Some(is_visible); } let state = app.state::(); - if matches!(self.original, Some(true)) && state.desktop_is_gnome { + if is_visible && state.desktop_is_gnome { // Gnome has a really annoying "focus-stealing prevention" behavior means we // can't just pop up when the window is already visible, so to work around it // we hide and then immediately unhide the window window.hide()?; } - window.show()?; + app::show_main_window(&app)?; window.set_focus()?; let (tx, rx) = oneshot::channel(); @@ -72,7 +73,7 @@ impl Visibility { visibility.leases -= 1; if visibility.leases == 0 { if let Some(false) = visibility.original { - window.hide().error_print(); + app::hide_main_window(&handle).error_print(); } visibility.original = None; } diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 71a8ddd..2630069 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -1,15 +1,16 @@ use tauri::{ AppHandle, - Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, CustomMenuItem, }; +use crate::app; + pub fn create() -> SystemTray { - let show = CustomMenuItem::new("show".to_string(), "Show"); + let show = CustomMenuItem::new("show_hide".to_string(), "Show"); let quit = CustomMenuItem::new("exit".to_string(), "Exit"); let menu = SystemTrayMenu::new() @@ -25,8 +26,8 @@ pub fn handle_event(app: &AppHandle, event: SystemTrayEvent) { SystemTrayEvent::MenuItemClick{ id, .. } => { match id.as_str() { "exit" => app.exit(0), - "show" => { - let _ = app.get_window("main").map(|w| w.show()); + "show_hide" => { + let _ = app::toggle_main_window(app); } _ => (), }