From 9e9bc2b0ae6a3d0c50d2ed7bcadf63daea1bbb49 Mon Sep 17 00:00:00 2001 From: Joseph Montanaro Date: Fri, 27 Dec 2024 08:17:49 -0500 Subject: [PATCH] separate dev and production instances and add visual indicators of dev mode --- package.json | 2 +- src-tauri/Cargo.lock | 48 +----------------------- src-tauri/Cargo.toml | 3 +- src-tauri/creddy_cli/src/cli/mod.rs | 2 +- src-tauri/creddy_cli/src/lib.rs | 14 +++++-- src-tauri/src/app.rs | 22 ++++++----- src-tauri/src/ipc.rs | 6 +++ src-tauri/src/main.rs | 2 +- src-tauri/src/state.rs | 10 ++++- src-tauri/src/tray.rs | 57 ++++++++++++++++++++++++++--- src-tauri/tauri.conf.json | 2 +- src/App.svelte | 9 ++++- 12 files changed, 104 insertions(+), 73 deletions(-) diff --git a/package.json b/package.json index 70868be..69b659c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "creddy", - "version": "0.6.0", + "version": "0.6.1", "scripts": { "dev": "vite", "build": "vite build", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7bc8af2..de170e2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -218,30 +218,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-executor" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-fs" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - [[package]] name = "async-io" version = "2.3.3" @@ -1241,7 +1217,7 @@ dependencies = [ [[package]] name = "creddy" -version = "0.6.0" +version = "0.6.1" dependencies = [ "argon2", "auto-launch", @@ -1275,7 +1251,6 @@ dependencies = [ "tauri-plugin-dialog", "tauri-plugin-global-shortcut", "tauri-plugin-os", - "tauri-plugin-single-instance", "thiserror", "time", "tokio", @@ -5647,21 +5622,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "tauri-plugin-single-instance" -version = "2.0.0-beta.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ecafcc5214a5d3cd7a720c11e9c03cbd45ccaff721963485ec4ab481bdf4540" -dependencies = [ - "log", - "serde", - "serde_json", - "tauri", - "thiserror", - "windows-sys 0.52.0", - "zbus", -] - [[package]] name = "tauri-runtime" version = "2.0.0-beta.18" @@ -7042,15 +7002,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" dependencies = [ "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", "async-process", "async-recursion", - "async-task", "async-trait", - "blocking", "derivative", "enumflags2", "event-listener 5.3.1", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 31edf53..7714fda 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "creddy" -version = "0.6.0" +version = "0.6.1" description = "A friendly AWS credentials manager" authors = ["Joseph Montanaro"] license = "" @@ -49,7 +49,6 @@ chacha20poly1305 = { version = "0.10.1", features = ["std"] } which = "4.4.0" windows = { version = "0.51.1", features = ["Win32_Foundation", "Win32_System_Pipes"] } time = "0.3.31" -tauri-plugin-single-instance = "2.0.0-beta.9" tauri-plugin-global-shortcut = "2.0.0-beta.6" tauri-plugin-os = "2.0.0-beta.6" tauri-plugin-dialog = "2.0.0-beta.9" diff --git a/src-tauri/creddy_cli/src/cli/mod.rs b/src-tauri/creddy_cli/src/cli/mod.rs index dedf139..87f14ee 100644 --- a/src-tauri/creddy_cli/src/cli/mod.rs +++ b/src-tauri/creddy_cli/src/cli/mod.rs @@ -102,7 +102,7 @@ pub struct ExecArgs { #[derive(Debug, Args)] pub struct InvokeArgs { #[arg(value_name = "ACTION", value_enum)] - shortcut_action: ShortcutAction, + pub shortcut_action: ShortcutAction, } diff --git a/src-tauri/creddy_cli/src/lib.rs b/src-tauri/creddy_cli/src/lib.rs index 8488828..d8043c4 100644 --- a/src-tauri/creddy_cli/src/lib.rs +++ b/src-tauri/creddy_cli/src/lib.rs @@ -1,11 +1,12 @@ mod cli; pub use cli::{ - Cli, Action, + Cli, + docker_credential_helper, exec, get, + GlobalArgs, invoke_shortcut, - docker_credential_helper, }; pub(crate) use platform::connect; @@ -14,13 +15,20 @@ pub use platform::server_addr; pub mod proto; +pub fn show_window(global_args: GlobalArgs) -> anyhow::Result<()> { + let invoke = cli::InvokeArgs { shortcut_action: proto::ShortcutAction::ShowWindow }; + cli::invoke_shortcut(invoke, global_args) +} + + #[cfg(unix)] mod platform { use std::path::PathBuf; use tokio::net::UnixStream; pub async fn connect(addr: Option) -> Result { - let path = addr.unwrap_or_else(|| server_addr("creddy-server")); + let default = if cfg!(debug_assertions) { "creddy-server-dev" } else { "creddy-server" }; + let path = addr.unwrap_or_else(|| server_addr(default)); UnixStream::connect(&path).await } diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index c35e849..d7fcdcb 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -15,7 +15,7 @@ use tauri::{ RunEvent, WindowEvent, }; -use tauri::menu::MenuItem; +use creddy_cli::GlobalArgs; use crate::{ config::{self, AppConfig}, @@ -32,12 +32,13 @@ use crate::{ pub static APP: OnceCell = OnceCell::new(); -pub fn run() -> tauri::Result<()> { +pub fn run(global_args: GlobalArgs) -> tauri::Result<()> { + if let Ok(_) = creddy_cli::show_window(global_args) { + // app is already running, so terminate + return Ok(()); + } + tauri::Builder::default() - .plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| { - show_main_window(app) - .error_popup("Failed to show main window") - })) .plugin(tauri_plugin_global_shortcut::Builder::default().build()) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_dialog::init()) @@ -58,6 +59,7 @@ pub fn run() -> tauri::Result<()> { ipc::save_config, ipc::launch_terminal, ipc::get_setup_errors, + ipc::get_devmode, ipc::exit, ]) .setup(|app| rt::block_on(setup(app))) @@ -158,8 +160,8 @@ fn start_auto_locker(app: AppHandle) { pub fn show_main_window(app: &AppHandle) -> Result<(), WindowError> { let w = app.get_webview_window("main").ok_or(WindowError::NoMainWindow)?; w.show()?; - let show_hide = app.state::>(); - show_hide.set_text("Hide")?; + let menu = app.state::(); + menu.after_show()?; Ok(()) } @@ -167,8 +169,8 @@ pub fn show_main_window(app: &AppHandle) -> Result<(), WindowError> { pub fn hide_main_window(app: &AppHandle) -> Result<(), WindowError> { let w = app.get_webview_window("main").ok_or(WindowError::NoMainWindow)?; w.hide()?; - let show_hide = app.state::>(); - show_hide.set_text("Show")?; + let menu = app.state::(); + menu.after_hide()?; Ok(()) } diff --git a/src-tauri/src/ipc.rs b/src-tauri/src/ipc.rs index 77c3ebc..4014744 100644 --- a/src-tauri/src/ipc.rs +++ b/src-tauri/src/ipc.rs @@ -204,6 +204,12 @@ pub async fn get_setup_errors(app_state: State<'_, AppState>) -> Result bool { + cfg!(debug_assertions) +} + + #[tauri::command] pub fn exit(app_handle: AppHandle) { app_handle.exit(0) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0fb5cfe..5ff4a5c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -15,7 +15,7 @@ fn main() { let cli = Cli::parse(); let res = match cli.action { None | Some(Action::Run) => { - app::run().error_popup("Creddy encountered an error"); + app::run(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 d7cdcae..15d11ff 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -32,6 +32,7 @@ use crate::credentials::{ use crate::ipc::{self, RequestResponse}; use crate::errors::*; use crate::shortcuts; +use crate::tray; #[derive(Debug)] @@ -252,7 +253,11 @@ impl AppState { pub async fn unlock(&self, passphrase: &str) -> Result<(), UnlockError> { let mut session = self.app_session.write().await; - session.unlock(passphrase) + session.unlock(passphrase)?; + let app_handle = app::APP.get().unwrap(); + let menu = app_handle.state::(); + let _ = menu.after_unlock(); // we don't care if this fails, it's non-essential + Ok(()) } pub async fn lock(&self) -> Result<(), LockError> { @@ -266,6 +271,9 @@ impl AppState { let app_handle = app::APP.get().unwrap(); app_handle.emit("locked", None::)?; + let menu = app_handle.state::(); + let _ = menu.after_lock(); + Ok(()) } } diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 4458ef0..7ad7cb3 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -7,27 +7,74 @@ use tauri::{ use tauri::menu::{ MenuBuilder, MenuEvent, + MenuItem, MenuItemBuilder, + PredefinedMenuItem, }; use crate::app; use crate::state::AppState; +pub struct MenuItems { + pub status: MenuItem, + pub show_hide: MenuItem, +} + +impl MenuItems { + pub fn after_show(&self) -> tauri::Result<()> { + self.show_hide.set_text("Hide") + } + + pub fn after_hide(&self) -> tauri::Result<()> { + self.show_hide.set_text("Show") + } + + pub fn after_lock(&self) -> tauri::Result<()> { + if cfg!(debug_assertions) { + self.status.set_text("Creddy (dev): Locked") + } + else { + self.status.set_text("Creddy: Locked") + } + } + + pub fn after_unlock(&self) -> tauri::Result<()> { + if cfg!(debug_assertions) { + self.status.set_text("Creddy (dev): Unlocked") + } + else { + self.status.set_text("Creddy: Unlocked") + } + } +} + + pub fn setup(app: &App) -> tauri::Result<()> { + let status_text = + if cfg!(debug_assertions) { + "Creddy (dev): Locked" + } + else { + "Creddy: Locked" + }; + + let status = MenuItemBuilder::with_id("status", status_text) + .enabled(false) + .build(app)?; + let sep = PredefinedMenuItem::separator(app)?; let show_hide = MenuItemBuilder::with_id("show_hide", "Show").build(app)?; let exit = MenuItemBuilder::with_id("exit", "Exit").build(app)?; let menu = MenuBuilder::new(app) - .items(&[&show_hide, &exit]) - .build()?; + .items(&[&status, &sep, &show_hide, &exit]); let tray = app.tray_by_id("main").unwrap(); - tray.set_menu(Some(menu))?; + tray.set_menu(Some(menu.build()?))?; tray.on_menu_event(handle_event); - // stash this so we can find it later to change the text - app.manage(show_hide); + // stash these so we can find them later to change the text + app.manage(MenuItems { status, show_hide }); Ok(()) } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f37903c..15b33cc 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -50,7 +50,7 @@ } }, "productName": "creddy", - "version": "0.6.0", + "version": "0.6.1", "identifier": "creddy", "plugins": {}, "app": { diff --git a/src/App.svelte b/src/App.svelte index f87e364..c14e2b7 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -14,6 +14,7 @@ import Unlock from './views/Unlock.svelte'; // set up app state invoke('get_config').then(config => $appState.config = config); invoke('get_session_status').then(status => $appState.sessionStatus = status); +invoke('get_devmode').then(dm => $appState.devmode = dm) getVersion().then(version => $appState.appVersion = version); invoke('get_setup_errors') .then(errs => { @@ -51,7 +52,7 @@ acceptRequest(); - invoke('signal_activity')} on:keydown={() => invoke('signal_activity')} /> @@ -70,3 +71,9 @@ acceptRequest(); {/if} + +{#if $appState.devmode } +
+ This is a development build of Creddy. +
+{/if}