improve start-minimized and start-on-login behavior
Previously, when Creddy was configured to start minimized, it would always start minimized, regardless of how it was launched. Really, though, when you use this setting what you probably want is for it to start minimized only when it's being launched automatically, i.e. on login. This update changes its behavior so that it will only start minimized when auto-launching. Additionally, if Creddy detects on startup that its start-on-login configuration doesn't match the system, it will modify its own settings to match the system (unless it's the very first launch, of course.) That way if you disable Creddy's start-on-login behavior from your system dialog, it will respect your change.
This commit is contained in:
parent
efbf6c687c
commit
cd4c613758
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "creddy",
|
"name": "creddy",
|
||||||
"version": "0.6.2",
|
"version": "0.6.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@ -1217,7 +1217,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "creddy"
|
name = "creddy"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"auto-launch",
|
"auto-launch",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "creddy"
|
name = "creddy"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
description = "A friendly AWS credentials manager"
|
description = "A friendly AWS credentials manager"
|
||||||
authors = ["Joseph Montanaro"]
|
authors = ["Joseph Montanaro"]
|
||||||
license = ""
|
license = ""
|
||||||
|
@ -65,7 +65,7 @@ pub struct GlobalArgs {
|
|||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
/// Launch Creddy
|
/// Launch Creddy
|
||||||
Run,
|
Run(RunArgs),
|
||||||
/// Request credentials from Creddy and output to stdout
|
/// Request credentials from Creddy and output to stdout
|
||||||
Get(GetArgs),
|
Get(GetArgs),
|
||||||
/// Inject credentials into the environment of another command
|
/// 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)]
|
#[derive(Debug, Args)]
|
||||||
pub struct GetArgs {
|
pub struct GetArgs {
|
||||||
/// If unspecified, use default credentials
|
/// If unspecified, use default credentials
|
||||||
|
@ -6,6 +6,7 @@ pub use cli::{
|
|||||||
exec,
|
exec,
|
||||||
get,
|
get,
|
||||||
GlobalArgs,
|
GlobalArgs,
|
||||||
|
RunArgs,
|
||||||
invoke_shortcut,
|
invoke_shortcut,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::process::{self, Command};
|
use std::process::{self, Command};
|
||||||
|
|
||||||
use creddy_cli::{Action, Cli};
|
use creddy_cli::{
|
||||||
|
Action,
|
||||||
|
Cli,
|
||||||
|
RunArgs,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let res = match cli.action {
|
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::Get(args)) => creddy_cli::get(args, cli.global_args),
|
||||||
Some(Action::Exec(args)) => creddy_cli::exec(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),
|
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()?;
|
let mut path = env::current_exe()?;
|
||||||
path.pop(); // bin dir
|
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)
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use tauri::{
|
|||||||
RunEvent,
|
RunEvent,
|
||||||
WindowEvent,
|
WindowEvent,
|
||||||
};
|
};
|
||||||
use creddy_cli::GlobalArgs;
|
use creddy_cli::{GlobalArgs, RunArgs};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{self, AppConfig},
|
config::{self, AppConfig},
|
||||||
@ -32,7 +32,7 @@ use crate::{
|
|||||||
pub static APP: OnceCell<AppHandle> = OnceCell::new();
|
pub static APP: OnceCell<AppHandle> = 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) {
|
if let Ok(_) = creddy_cli::show_window(global_args) {
|
||||||
// app is already running, so terminate
|
// app is already running, so terminate
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -62,7 +62,7 @@ pub fn run(global_args: GlobalArgs) -> tauri::Result<()> {
|
|||||||
ipc::get_devmode,
|
ipc::get_devmode,
|
||||||
ipc::exit,
|
ipc::exit,
|
||||||
])
|
])
|
||||||
.setup(|app| rt::block_on(setup(app)))
|
.setup(|app| rt::block_on(setup(app, run_args)))
|
||||||
.build(tauri::generate_context!())?
|
.build(tauri::generate_context!())?
|
||||||
.run(|app, run_event| {
|
.run(|app, run_event| {
|
||||||
if let RunEvent::WindowEvent { event, .. } = run_event {
|
if let RunEvent::WindowEvent { event, .. } = run_event {
|
||||||
@ -88,11 +88,11 @@ pub async fn connect_db() -> Result<SqlitePool, SetupError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
async fn setup(app: &mut App, run_args: RunArgs) -> Result<(), Box<dyn Error>> {
|
||||||
APP.set(app.handle().clone()).unwrap();
|
APP.set(app.handle().clone()).unwrap();
|
||||||
tray::setup(app)?;
|
tray::setup(app)?;
|
||||||
// get_or_create_db_path doesn't create the actual db file, just the directory
|
// 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 pool = connect_db().await?;
|
||||||
let mut setup_errors: Vec<String> = vec![];
|
let mut setup_errors: Vec<String> = vec![];
|
||||||
|
|
||||||
@ -111,10 +111,16 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
|||||||
creddy_server::serve(app.handle().clone())?;
|
creddy_server::serve(app.handle().clone())?;
|
||||||
agent::serve(app.handle().clone())?;
|
agent::serve(app.handle().clone())?;
|
||||||
|
|
||||||
config::set_auto_launch(conf.start_on_login)?;
|
// if this is the first launch, setup system with default auto-launch settings
|
||||||
if let Err(_e) = config::set_auto_launch(conf.start_on_login) {
|
if is_first_launch {
|
||||||
setup_errors.push("Error: Failed to manage autolaunch.".into());
|
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 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) {
|
if let Err(_e) = shortcuts::register_hotkeys(&conf.hotkeys) {
|
||||||
@ -127,7 +133,7 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
|||||||
.map(|names| names.split(':').any(|n| n == "GNOME"))
|
.map(|names| names.split(':').any(|n| n == "GNOME"))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !conf.start_minimized || is_first_launch {
|
if !run_args.minimized {
|
||||||
show_main_window(&app.handle())?;
|
show_main_window(&app.handle())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use auto_launch::AutoLaunchBuilder;
|
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
||||||
use is_terminal::IsTerminal;
|
use is_terminal::IsTerminal;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
@ -89,29 +89,49 @@ impl AppConfig {
|
|||||||
pub async fn save(&self, pool: &SqlitePool) -> Result<(), sqlx::error::Error> {
|
pub async fn save(&self, pool: &SqlitePool) -> Result<(), sqlx::error::Error> {
|
||||||
kv::save(pool, "config", self).await
|
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> {
|
// if enabled, disabled regardless of desired end state because either:
|
||||||
let path_buf = std::env::current_exe()
|
// a) we are just going to leave it disabled, or
|
||||||
.map_err(|e| auto_launch::Error::Io(e))?;
|
// b) we need to disable-and-reenable in case args are different
|
||||||
let path = path_buf
|
if mgr.is_enabled()? {
|
||||||
.to_string_lossy();
|
mgr.disable()?;
|
||||||
|
}
|
||||||
|
if self.start_on_login {
|
||||||
|
mgr.enable()?;
|
||||||
|
}
|
||||||
|
|
||||||
let auto = AutoLaunchBuilder::new()
|
Ok(())
|
||||||
.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(())
|
/// 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<AutoLaunch, SetupError> {
|
||||||
|
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()?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,14 +8,23 @@ use creddy::{
|
|||||||
app,
|
app,
|
||||||
errors::ShowError,
|
errors::ShowError,
|
||||||
};
|
};
|
||||||
use creddy_cli::{Action, Cli};
|
use creddy_cli::{
|
||||||
|
Action,
|
||||||
|
Cli,
|
||||||
|
RunArgs,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let res = match cli.action {
|
let res = match cli.action {
|
||||||
None | Some(Action::Run) => {
|
None => {
|
||||||
app::run(cli.global_args).error_popup("Creddy encountered an error");
|
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(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Some(Action::Get(args)) => creddy_cli::get(args, cli.global_args),
|
Some(Action::Get(args)) => creddy_cli::get(args, cli.global_args),
|
||||||
|
@ -22,7 +22,7 @@ use crate::credentials::{
|
|||||||
DockerCredential,
|
DockerCredential,
|
||||||
SshKey,
|
SshKey,
|
||||||
};
|
};
|
||||||
use crate::{config, config::AppConfig};
|
use crate::config::AppConfig;
|
||||||
use crate::credentials::{
|
use crate::credentials::{
|
||||||
AwsBaseCredential,
|
AwsBaseCredential,
|
||||||
Credential,
|
Credential,
|
||||||
@ -204,8 +204,9 @@ impl AppState {
|
|||||||
let mut live_config = self.config.write().await;
|
let mut live_config = self.config.write().await;
|
||||||
|
|
||||||
// update autostart if necessary
|
// update autostart if necessary
|
||||||
if new_config.start_on_login != live_config.start_on_login {
|
if new_config.start_on_login != live_config.start_on_login
|
||||||
config::set_auto_launch(new_config.start_on_login)?;
|
|| new_config.start_minimized != live_config.start_minimized {
|
||||||
|
new_config.set_auto_launch()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-register hotkeys if necessary
|
// re-register hotkeys if necessary
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"productName": "creddy",
|
"productName": "creddy",
|
||||||
"version": "0.6.2",
|
"version": "0.6.3",
|
||||||
"identifier": "creddy",
|
"identifier": "creddy",
|
||||||
"plugins": {},
|
"plugins": {},
|
||||||
"app": {
|
"app": {
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
let error = null;
|
let error = null;
|
||||||
async function save() {
|
async function save() {
|
||||||
try {
|
try {
|
||||||
throw('wtf');
|
|
||||||
await invoke('save_config', {config});
|
await invoke('save_config', {config});
|
||||||
$appState.config = await invoke('get_config');
|
$appState.config = await invoke('get_config');
|
||||||
}
|
}
|
||||||
@ -48,11 +47,13 @@
|
|||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ToggleSetting>
|
</ToggleSetting>
|
||||||
|
|
||||||
<ToggleSetting title="Start minimized" bind:value={config.start_minimized}>
|
{#if config.start_on_login}
|
||||||
<svelte:fragment slot="description">
|
<ToggleSetting title="Start minimized" bind:value={config.start_minimized}>
|
||||||
Minimize to the system tray at startup.
|
<svelte:fragment slot="description">
|
||||||
</svelte:fragment>
|
Minimize to the system tray when starting on login.
|
||||||
</ToggleSetting>
|
</svelte:fragment>
|
||||||
|
</ToggleSetting>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<NumericSetting title="Re-hide delay" bind:value={config.rehide_ms} min={0} unit="Milliseconds">
|
<NumericSetting title="Re-hide delay" bind:value={config.rehide_ms} min={0} unit="Milliseconds">
|
||||||
<svelte:fragment slot="description">
|
<svelte:fragment slot="description">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user