diff --git a/package.json b/package.json index 1971987..29cfe02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "creddy", - "version": "0.6.2", + "version": "0.6.3", "scripts": { "dev": "vite", "build": "vite build", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 90fc83d..c8ccee7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1217,7 +1217,7 @@ dependencies = [ [[package]] name = "creddy" -version = "0.6.2" +version = "0.6.3" dependencies = [ "argon2", "auto-launch", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1836bc3..4b51746 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "creddy" -version = "0.6.2" +version = "0.6.3" description = "A friendly AWS credentials manager" authors = ["Joseph Montanaro"] license = "" diff --git a/src-tauri/creddy_cli/src/cli/mod.rs b/src-tauri/creddy_cli/src/cli/mod.rs index 87f14ee..f88a143 100644 --- a/src-tauri/creddy_cli/src/cli/mod.rs +++ b/src-tauri/creddy_cli/src/cli/mod.rs @@ -65,7 +65,7 @@ pub struct GlobalArgs { #[derive(Debug, Subcommand)] pub enum Action { /// Launch Creddy - Run, + Run(RunArgs), /// Request credentials from Creddy and output to stdout Get(GetArgs), /// Inject credentials into the environment of another command @@ -78,6 +78,14 @@ pub enum Action { } +#[derive(Debug, Args)] +pub struct RunArgs { + /// Minimize to system tray on launch + #[arg(long, default_value_t = false)] + pub minimized: bool, +} + + #[derive(Debug, Args)] pub struct GetArgs { /// If unspecified, use default credentials diff --git a/src-tauri/creddy_cli/src/lib.rs b/src-tauri/creddy_cli/src/lib.rs index 94cfce0..c1c993b 100644 --- a/src-tauri/creddy_cli/src/lib.rs +++ b/src-tauri/creddy_cli/src/lib.rs @@ -6,6 +6,7 @@ pub use cli::{ exec, get, GlobalArgs, + RunArgs, invoke_shortcut, }; diff --git a/src-tauri/creddy_cli/src/main.rs b/src-tauri/creddy_cli/src/main.rs index 5aab1e2..0c51d9b 100644 --- a/src-tauri/creddy_cli/src/main.rs +++ b/src-tauri/creddy_cli/src/main.rs @@ -1,13 +1,17 @@ use std::env; use std::process::{self, Command}; -use creddy_cli::{Action, Cli}; - +use creddy_cli::{ + Action, + Cli, + RunArgs, +}; fn main() { let cli = Cli::parse(); let res = match cli.action { - None | Some(Action::Run)=> launch_gui(), + None => launch_gui(RunArgs { minimized: false }), + Some(Action::Run(run_args)) => launch_gui(run_args), Some(Action::Get(args)) => creddy_cli::get(args, cli.global_args), Some(Action::Exec(args)) => creddy_cli::exec(args, cli.global_args), Some(Action::Shortcut(args)) => creddy_cli::invoke_shortcut(args, cli.global_args), @@ -21,7 +25,7 @@ fn main() { } -fn launch_gui() -> anyhow::Result<()> { +fn launch_gui(run_args: RunArgs) -> anyhow::Result<()> { let mut path = env::current_exe()?; path.pop(); // bin dir @@ -31,6 +35,10 @@ fn launch_gui() -> anyhow::Result<()> { path.push("creddy.exe"); // exe in main install dir (aka gui exe) - Command::new(path).spawn()?; + let mut cmd = Command::new(path); + if run_args.minimized { + cmd.arg("--minimized"); + } + cmd.spawn()?; Ok(()) } diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index d7fcdcb..8ff4ae5 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -15,7 +15,7 @@ use tauri::{ RunEvent, WindowEvent, }; -use creddy_cli::GlobalArgs; +use creddy_cli::{GlobalArgs, RunArgs}; use crate::{ config::{self, AppConfig}, @@ -32,7 +32,7 @@ use crate::{ pub static APP: OnceCell = OnceCell::new(); -pub fn run(global_args: GlobalArgs) -> tauri::Result<()> { +pub fn run(run_args: RunArgs, global_args: GlobalArgs) -> tauri::Result<()> { if let Ok(_) = creddy_cli::show_window(global_args) { // app is already running, so terminate return Ok(()); @@ -62,7 +62,7 @@ pub fn run(global_args: GlobalArgs) -> tauri::Result<()> { ipc::get_devmode, ipc::exit, ]) - .setup(|app| rt::block_on(setup(app))) + .setup(|app| rt::block_on(setup(app, run_args))) .build(tauri::generate_context!())? .run(|app, run_event| { if let RunEvent::WindowEvent { event, .. } = run_event { @@ -88,11 +88,11 @@ pub async fn connect_db() -> Result { } -async fn setup(app: &mut App) -> Result<(), Box> { +async fn setup(app: &mut App, run_args: RunArgs) -> Result<(), Box> { APP.set(app.handle().clone()).unwrap(); tray::setup(app)?; // get_or_create_db_path doesn't create the actual db file, just the directory - let is_first_launch = !config::get_or_create_db_path()?.exists(); + let is_first_launch = !config::get_or_create_db_path()?.try_exists()?; let pool = connect_db().await?; let mut setup_errors: Vec = vec![]; @@ -111,10 +111,16 @@ async fn setup(app: &mut App) -> Result<(), Box> { creddy_server::serve(app.handle().clone())?; agent::serve(app.handle().clone())?; - config::set_auto_launch(conf.start_on_login)?; - if let Err(_e) = config::set_auto_launch(conf.start_on_login) { - setup_errors.push("Error: Failed to manage autolaunch.".into()); + // if this is the first launch, setup system with default auto-launch settings + if is_first_launch { + if let Err(e) = conf.set_auto_launch() { + setup_errors.push(format!("Failed to manage autolaunch: {e}")); + } } + // otherwise, treat the system as the source of truth and ensure ours matches + else { + conf.match_auto_launch(&pool).await?; + }; // if hotkeys fail to register, disable them so that this error doesn't have to keep showing up if let Err(_e) = shortcuts::register_hotkeys(&conf.hotkeys) { @@ -127,7 +133,7 @@ async fn setup(app: &mut App) -> Result<(), Box> { .map(|names| names.split(':').any(|n| n == "GNOME")) .unwrap_or(false); - if !conf.start_minimized || is_first_launch { + if !run_args.minimized { show_main_window(&app.handle())?; } diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index 596cc8c..5ef24d5 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use std::time::Duration; -use auto_launch::AutoLaunchBuilder; +use auto_launch::{AutoLaunch, AutoLaunchBuilder}; use is_terminal::IsTerminal; use serde::{Serialize, Deserialize}; use sqlx::SqlitePool; @@ -89,29 +89,49 @@ impl AppConfig { pub async fn save(&self, pool: &SqlitePool) -> Result<(), sqlx::error::Error> { kv::save(pool, "config", self).await } -} + /// Configure system with auto-launch settings + pub fn set_auto_launch(&self) -> Result<(), SetupError> { + let mgr = self.auto_launch_manager()?; -pub fn set_auto_launch(is_configured: bool) -> Result<(), SetupError> { - let path_buf = std::env::current_exe() - .map_err(|e| auto_launch::Error::Io(e))?; - let path = path_buf - .to_string_lossy(); + // if enabled, disabled regardless of desired end state because either: + // a) we are just going to leave it disabled, or + // b) we need to disable-and-reenable in case args are different + if mgr.is_enabled()? { + mgr.disable()?; + } + if self.start_on_login { + mgr.enable()?; + } - let auto = AutoLaunchBuilder::new() - .set_app_name("Creddy") - .set_app_path(&path) - .build()?; - - let is_enabled = auto.is_enabled()?; - if is_configured && !is_enabled { - auto.enable()?; - } - else if !is_configured && is_enabled { - auto.disable()?; + Ok(()) } - Ok(()) + /// Match own auto-launch settings to system + pub async fn match_auto_launch(&mut self, pool: &SqlitePool) -> Result<(), SetupError> { + let mgr = self.auto_launch_manager()?; + let is_enabled = mgr.is_enabled()?; + if is_enabled != self.start_on_login { + self.start_on_login = is_enabled; + self.save(pool).await?; + } + Ok(()) + } + + fn auto_launch_manager(&self) -> Result { + let path_buf = std::env::current_exe() + .map_err(|e| auto_launch::Error::Io(e))?; + + let name = if cfg!(debug_assertions) { "Creddy" } else { "Creddy (dev)" }; + let mut builder = AutoLaunchBuilder::new(); + builder.set_app_name(name); + builder.set_app_path(&path_buf.to_string_lossy()); + if self.start_minimized { + builder.set_args(&["run", "--minimized"]); + } + + Ok(builder.build()?) + } } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5ff4a5c..cf984c0 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -8,14 +8,23 @@ use creddy::{ app, errors::ShowError, }; -use creddy_cli::{Action, Cli}; +use creddy_cli::{ + Action, + Cli, + RunArgs, +}; fn main() { let cli = Cli::parse(); let res = match cli.action { - None | Some(Action::Run) => { - app::run(cli.global_args).error_popup("Creddy encountered an error"); + None => { + let run_args = RunArgs { minimized: false }; + app::run(run_args, cli.global_args).error_popup("Creddy encountered an error"); + Ok(()) + } + Some(Action::Run(run_args)) => { + app::run(run_args, cli.global_args).error_popup("Creddy encountered an error"); Ok(()) }, Some(Action::Get(args)) => creddy_cli::get(args, cli.global_args), diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index 15d11ff..e43d1db 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -22,7 +22,7 @@ use crate::credentials::{ DockerCredential, SshKey, }; -use crate::{config, config::AppConfig}; +use crate::config::AppConfig; use crate::credentials::{ AwsBaseCredential, Credential, @@ -204,8 +204,9 @@ impl AppState { let mut live_config = self.config.write().await; // update autostart if necessary - if new_config.start_on_login != live_config.start_on_login { - config::set_auto_launch(new_config.start_on_login)?; + if new_config.start_on_login != live_config.start_on_login + || new_config.start_minimized != live_config.start_minimized { + new_config.set_auto_launch()?; } // re-register hotkeys if necessary diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index eacef81..bfec188 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -50,7 +50,7 @@ } }, "productName": "creddy", - "version": "0.6.2", + "version": "0.6.3", "identifier": "creddy", "plugins": {}, "app": { diff --git a/src/views/Settings.svelte b/src/views/Settings.svelte index 70c4e07..7b6e95b 100644 --- a/src/views/Settings.svelte +++ b/src/views/Settings.svelte @@ -20,7 +20,6 @@ let error = null; async function save() { try { - throw('wtf'); await invoke('save_config', {config}); $appState.config = await invoke('get_config'); } @@ -41,18 +40,20 @@
- + Start Creddy when you log in to your computer. - - - Minimize to the system tray at startup. - - + {#if config.start_on_login} + + + Minimize to the system tray when starting on login. + + + {/if}