show non-fatal setup errors on home screen instead of in popup

This commit is contained in:
Joseph Montanaro 2023-09-14 15:04:25 -07:00
parent 12f0f187a6
commit 992d2a4d06
11 changed files with 62 additions and 12 deletions

View File

@ -1,6 +1,6 @@
{
"name": "creddy",
"version": "0.3.1",
"version": "0.3.2",
"scripts": {
"dev": "vite",
"build": "vite build",

2
src-tauri/Cargo.lock generated
View File

@ -1035,7 +1035,7 @@ dependencies = [
[[package]]
name = "creddy"
version = "0.3.1"
version = "0.3.2"
dependencies = [
"argon2",
"auto-launch",

View File

@ -1,6 +1,6 @@
[package]
name = "creddy"
version = "0.3.1"
version = "0.3.2"
description = "A friendly AWS credentials manager"
authors = ["Joseph Montanaro"]
license = ""

View File

@ -43,6 +43,7 @@ pub fn run() -> tauri::Result<()> {
ipc::get_config,
ipc::save_config,
ipc::launch_terminal,
ipc::get_setup_errors,
])
.setup(|app| rt::block_on(setup(app)))
.build(tauri::generate_context!())?
@ -77,14 +78,15 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
// 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 pool = connect_db().await?;
let mut setup_errors: Vec<String> = vec![];
let conf = match AppConfig::load(&pool).await {
Ok(c) => c,
Err(SetupError::ConfigParseError(_)) => {
Err("Could not load configuration from database. Reverting to defaults.")
.error_popup("Setup error");
setup_errors.push(
"Could not load configuration from database. Reverting to defaults.".into()
);
AppConfig::default()
},
err => err?,
@ -94,7 +96,12 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
let srv = Server::new(conf.listen_addr, conf.listen_port, app.handle()).await?;
config::set_auto_launch(conf.start_on_login)?;
config::register_hotkeys(&conf.hotkeys).error_popup("Setup error");
if let Err(_e) = config::set_auto_launch(conf.start_on_login) {
setup_errors.push("Error: Failed to manage autolaunch.".into());
}
if let Err(e) = config::register_hotkeys(&conf.hotkeys) {
setup_errors.push(format!("{e}"));
}
// if session is empty, this is probably the first launch, so don't autohide
if !conf.start_minimized || is_first_launch {
@ -103,7 +110,7 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
.show()?;
}
let state = AppState::new(conf, session, srv, pool);
let state = AppState::new(conf, session, srv, pool, setup_errors);
app.manage(state);
Ok(())
}

View File

@ -22,6 +22,7 @@ use serde::{Serialize, Serializer, ser::SerializeMap};
pub trait ErrorPopup {
fn error_popup(self, title: &str);
fn error_popup_nowait(self, title: &str);
}
impl<E: std::fmt::Display> ErrorPopup for Result<(), E> {
@ -35,6 +36,14 @@ impl<E: std::fmt::Display> ErrorPopup for Result<(), E> {
rx.recv().unwrap();
}
}
fn error_popup_nowait(self, title: &str) {
if let Err(e) = self {
MessageDialogBuilder::new(title, format!("{e}"))
.kind(MessageDialogKind::Error)
.show(|_| {})
}
}
}

View File

@ -85,3 +85,9 @@ pub async fn save_config(config: AppConfig, app_state: State<'_, AppState>) -> R
pub async fn launch_terminal(base: bool) -> Result<(), LaunchTerminalError> {
terminal::launch(base).await
}
#[tauri::command]
pub async fn get_setup_errors(app_state: State<'_, AppState>) -> Result<Vec<String>, ()> {
Ok(app_state.setup_errors.clone())
}

View File

@ -30,12 +30,20 @@ pub struct AppState {
pub waiting_requests: RwLock<HashMap<u64, RequestWaiter>>,
pub pending_terminal_request: RwLock<bool>,
pub bans: RwLock<std::collections::HashSet<Option<Client>>>,
// setup_errors is never modified and so doesn't need to be wrapped in RwLock
pub setup_errors: Vec<String>,
server: RwLock<Server>,
pool: sqlx::SqlitePool,
}
impl AppState {
pub fn new(config: AppConfig, session: Session, server: Server, pool: SqlitePool) -> AppState {
pub fn new(
config: AppConfig,
session: Session,
server: Server,
pool: SqlitePool,
setup_errors: Vec<String>,
) -> AppState {
AppState {
config: RwLock::new(config),
session: RwLock::new(session),
@ -43,6 +51,7 @@ impl AppState {
waiting_requests: RwLock::new(HashMap::new()),
pending_terminal_request: RwLock::new(false),
bans: RwLock::new(HashSet::new()),
setup_errors,
server: RwLock::new(server),
pool,
}

View File

@ -8,7 +8,7 @@
},
"package": {
"productName": "creddy",
"version": "0.3.1"
"version": "0.3.2"
},
"tauri": {
"allowlist": {

View File

@ -28,7 +28,12 @@ listen('launch-terminal-request', async (tauriEvent) => {
// else, session is unlocked, so do nothing
// (although we shouldn't even get the event in that case)
}
})
});
invoke('get_setup_errors')
.then(errs => {
$appState.setupErrors = errs.map(e => ({msg: e, show: true}));
});
acceptRequest();
</script>

View File

@ -8,6 +8,7 @@ export let appState = writable({
currentRequest: null,
pendingRequests: queue(),
credentialStatus: 'locked',
setupErrors: [],
});

View File

@ -52,3 +52,16 @@
{/await}
</div>
</div>
{#if $appState.setupErrors.some(e => e.show)}
<div class="toast">
{#each $appState.setupErrors as error}
{#if error.show}
<div class="alert alert-error shadow-lg">
{error.msg}
<button class="btn btn-sm btn-alert-error" on:click={() => error.show = false}>Ok</button>
</div>
{/if}
{/each}
</div>
{/if}