feat(tui): update keyring initialization and enhance token handling in main function

This commit is contained in:
2026-05-07 21:24:01 +02:00
parent 9a84fcf061
commit 46bd416410
4 changed files with 574 additions and 50 deletions

View File

@@ -5,22 +5,24 @@ edition = "2024"
[features]
default = []
macos = ["dep:apple-native-keyring-store"]
linux-zbus = ["dep:zbus-secret-service-keyring-store", "zbus-secret-service-keyring-store/rt-tokio-crypto-rust"]
windows = ["dep:windows-native-keyring-store"]
sqlite = ["dep:db-keystore"]
macos = ["dep:apple-native-keyring-store"]
linux-zbus = [
"dep:zbus-secret-service-keyring-store",
"zbus-secret-service-keyring-store/rt-tokio-crypto-rust",
]
windows = ["dep:windows-native-keyring-store"]
[dependencies]
ratatui = "0.30.0"
keyring-core = "1.0.0"
directories = "6"
csv = "1"
apple-native-keyring-store = { version = "1.0.0", optional = true, features = ["keychain"] }
apple-native-keyring-store = { version = "1.0.0", optional = true, features = [
"keychain",
] }
zbus-secret-service-keyring-store = { version = "1.0.0", optional = true }
windows-native-keyring-store = { version = "1.0.0", optional = true }
db-keystore = { version = "0.4.2-pre.2", optional = true }
windows-native-keyring-store = { version = "1.0.0", optional = true }
reqwest = { workspace = true }
serde = { workspace = true }

View File

@@ -32,6 +32,7 @@ impl Config {
Ok(())
}
#[allow(unreachable_code)]
pub fn init_keyring() -> Result<()> {
#[cfg(feature = "macos")]
{
@@ -52,21 +53,8 @@ impl Config {
return Ok(());
}
#[cfg(feature = "sqlite")]
{
let path = ProjectDirs::from("com", "movies", "movie-tui")
.ok_or_else(|| anyhow::anyhow!("cannot find data dir for sqlite keystore"))?
.data_dir()
.join("keystore.db");
std::fs::create_dir_all(path.parent().unwrap())?;
let config = db_keystore::DbKeyStoreConfig { path, ..Default::default() };
keyring_core::set_default_store(db_keystore::DbKeyStore::new(config)?);
return Ok(());
}
#[allow(unreachable_code)]
anyhow::bail!(
"no keyring backend compiled in — build with --features macos|linux-zbus|windows|sqlite"
"no keyring backend compiled in — build with --features macos|linux-zbus|windows"
)
}

View File

@@ -10,8 +10,15 @@ use tui::app::{
use tui::client::ApiClient;
use tui::config::Config;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
fn main() -> anyhow::Result<()> {
Config::init_keyring()?;
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?
.block_on(run())
}
async fn run() -> anyhow::Result<()> {
let mut config = Config::load();
// env var override
@@ -24,8 +31,7 @@ async fn main() -> anyhow::Result<()> {
let initial_url = config.as_ref().map(|c| c.api_url.as_str()).unwrap_or("http://localhost:3000");
let client = Arc::new(ApiClient::new(initial_url));
Config::init_keyring()?;
let saved_token = Config::load_token();
let saved_token = tokio::task::spawn_blocking(Config::load_token).await.unwrap_or(None);
let mut app = App::new(config, saved_token.clone());
let (tx, mut rx) = mpsc::channel::<Action>(64);
@@ -99,15 +105,22 @@ fn handle_command(cmd: Command, app: &App, client: &Arc<ApiClient>, tx: &mpsc::S
}
Command::SaveToken(token) => {
if let Err(e) = Config::save_token(&token) {
let tx2 = tx.clone();
let msg = format!("Token not saved to keychain: {e}");
tokio::spawn(async move { let _ = tx2.send(Action::DiaryLoadFailed(msg)).await; });
}
let tx2 = tx.clone();
tokio::spawn(async move {
if let Err(e) = tokio::task::spawn_blocking(move || Config::save_token(&token))
.await
.unwrap_or_else(|e| Err(anyhow::anyhow!(e)))
{
let msg = format!("Token not saved to keychain: {e}");
let _ = tx2.send(Action::DiaryLoadFailed(msg)).await;
}
});
}
Command::ClearToken => {
let _ = Config::clear_token(); // ignore NotFound errors on logout
tokio::spawn(async {
let _ = tokio::task::spawn_blocking(Config::clear_token).await;
});
}
Command::Login { email, password } => {