feat: persist API keys across restarts via tauri-plugin-store
All checks were successful
Android Universal Build / build-android (push) Successful in 12m9s
All checks were successful
Android Universal Build / build-android (push) Successful in 12m9s
Keys are saved to keys.json in the app's private data directory on both Linux and Android. load_keys is called on app mount to restore them into NewsState before the first news fetch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ tauri-build = { version = "2", features = [] }
|
||||
[dependencies]
|
||||
tauri = { version = "2", features = [] }
|
||||
tauri-plugin-opener = "2"
|
||||
tauri-plugin-store = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
easy-nostr = { path = "./easy-nostr" }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"opener:default"
|
||||
"opener:default",
|
||||
"store:default"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,16 +5,18 @@ mod news;
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_store::Builder::default().build())
|
||||
// Registriert den Nostr-State
|
||||
.manage(news::NewsState::default())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
home::fetch_nostr_posts,
|
||||
news::save_openrouter_key,
|
||||
news::save_groq_key,
|
||||
news::load_keys,
|
||||
news::load_rss_config,
|
||||
news::save_rss_urls, // Geändert von save_rss_url zu save_rss_urls
|
||||
news::save_rss_urls,
|
||||
news::fetch_ai_news,
|
||||
news::fetch_rss_news,
|
||||
news::save_groq_key,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
use tauri::{AppHandle, Manager, State};
|
||||
use tauri_plugin_store::StoreExt;
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Clone)]
|
||||
pub struct RssConfig {
|
||||
@@ -114,16 +115,46 @@ fn default_feeds() -> Vec<RssFeed> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn save_openrouter_key(key: String, state: State<'_, NewsState>) -> Result<(), String> {
|
||||
let mut lock = state.openrouter_key.lock().map_err(|_| "Lock failed")?;
|
||||
*lock = key.trim().to_string();
|
||||
pub async fn load_keys(app: AppHandle, state: State<'_, NewsState>) -> Result<(), String> {
|
||||
let store = app.store("keys.json").map_err(|e| e.to_string())?;
|
||||
if let Some(v) = store.get("openrouter_key") {
|
||||
if let Some(k) = v.as_str() {
|
||||
*state.openrouter_key.lock().unwrap() = k.to_string();
|
||||
}
|
||||
}
|
||||
if let Some(v) = store.get("groq_key") {
|
||||
if let Some(k) = v.as_str() {
|
||||
*state.groq_key.lock().unwrap() = k.to_string();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn save_groq_key(key: String, state: State<'_, NewsState>) -> Result<(), String> {
|
||||
let mut lock = state.groq_key.lock().map_err(|_| "Lock failed")?;
|
||||
*lock = key.trim().to_string();
|
||||
pub async fn save_openrouter_key(
|
||||
key: String,
|
||||
app: AppHandle,
|
||||
state: State<'_, NewsState>,
|
||||
) -> Result<(), String> {
|
||||
let trimmed = key.trim().to_string();
|
||||
*state.openrouter_key.lock().map_err(|_| "Lock failed")? = trimmed.clone();
|
||||
let store = app.store("keys.json").map_err(|e| e.to_string())?;
|
||||
store.set("openrouter_key", trimmed);
|
||||
store.save().map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn save_groq_key(
|
||||
key: String,
|
||||
app: AppHandle,
|
||||
state: State<'_, NewsState>,
|
||||
) -> Result<(), String> {
|
||||
let trimmed = key.trim().to_string();
|
||||
*state.groq_key.lock().map_err(|_| "Lock failed")? = trimmed.clone();
|
||||
let store = app.store("keys.json").map_err(|e| e.to_string())?;
|
||||
store.set("groq_key", trimmed);
|
||||
store.save().map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -69,11 +69,12 @@ pub fn news() -> Html {
|
||||
let new_url_ref = use_node_ref();
|
||||
let new_cat_ref = use_node_ref();
|
||||
|
||||
// Init: RSS Feeds laden
|
||||
// Init: Keys und RSS Feeds laden
|
||||
{
|
||||
let rss_feeds = rss_feeds.clone();
|
||||
use_effect_with((), move |_| {
|
||||
spawn_local(async move {
|
||||
let _ = invoke("load_keys", JsValue::NULL).await;
|
||||
if let Ok(res) = invoke("load_rss_config", JsValue::NULL).await {
|
||||
if let Ok(feeds) = serde_wasm_bindgen::from_value::<Vec<RssFeed>>(res) {
|
||||
rss_feeds.set(feeds);
|
||||
|
||||
Reference in New Issue
Block a user