diff --git a/crates/citadel-opds/src/credential_store.rs b/crates/citadel-opds/src/credential_store.rs index df871879..b1a7b1ed 100644 --- a/crates/citadel-opds/src/credential_store.rs +++ b/crates/citadel-opds/src/credential_store.rs @@ -82,11 +82,7 @@ impl OpdsCredentialStore { /// Disk is the source of truth; memory mirrors the last successful disk /// operation. pub fn status(&self) -> OpdsCredentialStatus { - let credentials = self - .inner - .credentials - .read() - .expect("OPDS credential store poisoned"); + let credentials = self.read(); OpdsCredentialStatus { configured: credentials.is_some(), username: credentials @@ -96,22 +92,14 @@ impl OpdsCredentialStore { } pub fn get(&self) -> Option { - self.inner - .credentials - .read() - .expect("OPDS credential store poisoned") - .clone() + self.read().clone() } pub fn set(&self, credentials: StoredOpdsCredentials) -> io::Result<()> { if let Some(path) = &self.inner.path { persist(path, &credentials)?; } - *self - .inner - .credentials - .write() - .expect("OPDS credential store poisoned") = Some(credentials); + *self.write() = Some(credentials); Ok(()) } @@ -123,11 +111,7 @@ impl OpdsCredentialStore { Err(error) => return Err(error), } } - *self - .inner - .credentials - .write() - .expect("OPDS credential store poisoned") = None; + *self.write() = None; Ok(()) } } diff --git a/crates/citadel-opds/src/password.rs b/crates/citadel-opds/src/password.rs index a953e977..ccbc3e62 100644 --- a/crates/citadel-opds/src/password.rs +++ b/crates/citadel-opds/src/password.rs @@ -1,8 +1,7 @@ //! The generated-password chunk shape and algorithm. use super::words::WORD_POOL; -use rand_core::{OsRng, RngCore}; -use serde::{Deserialize, Serialize}; +use serde::Serialize; /// Returned once when credentials are generated; the plaintext is never /// stored, so this is the only chance to copy it into a reader. diff --git a/src-tauri/src/libs/calibre/mod.rs b/src-tauri/src/libs/calibre/mod.rs index c392fb88..880f81f6 100644 --- a/src-tauri/src/libs/calibre/mod.rs +++ b/src-tauri/src/libs/calibre/mod.rs @@ -26,13 +26,23 @@ pub struct CalibreClientConfig { #[tauri::command] #[specta::specta] -pub fn init_client( +pub async fn init_client( handle: tauri::AppHandle, - state: tauri::State, + state: tauri::State<'_, CitadelState>, library_path: String, ) -> Result { use tauri::Manager; + // Stop BEFORE the swap: the running server reads live state, so draining + // after the swap would serve the new library under the old share. If the + // new library then fails to open, sharing stays off - the right failure + // direction (better a dead share than a wrong one). Re-opening the + // already-active library keeps sharing. + let same_library = state.get_library_path().as_deref() == Some(library_path.as_str()); + if !same_library { + handle.state::().stop().await; + } + state.init_library(library_path.clone())?; // Full-resolution covers are served over the asset protocol straight from