diff --git a/crates/nip4e/src/lib.rs b/crates/nip4e/src/lib.rs index bb1dbbea..2aa90c2b 100644 --- a/crates/nip4e/src/lib.rs +++ b/crates/nip4e/src/lib.rs @@ -18,7 +18,7 @@ use nostr_sdk::prelude::*; use person::Directory; use settings::AppSettings; use smallvec::{SmallVec, smallvec}; -use state::{Announcement, CLIENT_NAME, NostrRegistry, UniversalSigner}; +use state::{Announcement, NostrRegistry, UniversalSigner, credentials}; use ui::Avatar; const IDENTIFIER: &str = "coop:device"; @@ -840,10 +840,10 @@ fn authorization_code(public_key: &PublicKey) -> SharedString { /// Get or create new app keys (async, returns a task) fn get_or_init_app_keys(cx: &App) -> Task> { - let read = cx.read_credentials(CLIENT_NAME); + let read = credentials::read_app_keys(cx); cx.spawn(async move |cx| { - if let Ok(Some((_, secret))) = read.await + if let Ok(Some(secret)) = read.await && let Ok(keys) = SecretKey::from_slice(&secret).map(Keys::new) { return Ok(keys); @@ -851,14 +851,13 @@ fn get_or_init_app_keys(cx: &App) -> Task> { // No stored keys found or invalid — generate new ones let keys = Keys::generate(); - let user = keys.public_key().to_hex(); let secret = keys.secret_key().to_secret_bytes(); cx.update(|cx| { - let write = cx.write_credentials(CLIENT_NAME, &user, &secret); + let write = credentials::write_app_keys(cx, &secret); cx.background_spawn(async move { if let Err(e) = write.await { - log::error!("Keyring not available or panic: {e}") + log::error!("Failed to persist app keys: {e}") } }) .detach(); diff --git a/crates/state/src/credentials.rs b/crates/state/src/credentials.rs index f7b93a2e..d9fade1f 100644 --- a/crates/state/src/credentials.rs +++ b/crates/state/src/credentials.rs @@ -1,10 +1,13 @@ use anyhow::Result; #[cfg(target_arch = "wasm32")] use common::web_store; -use gpui::{App, Task}; +use gpui::{App, AppContext as _, Task}; use crate::USER_KEYRING; +/// The storage key for the NIP-4e app keys +const APP_KEYS_KEY: &str = "coop/nip4e/app-keys"; + /// Read the stored credential as `(username, secret)` #[allow(clippy::type_complexity)] pub(crate) fn read(cx: &App) -> Task)>>> { @@ -49,3 +52,54 @@ pub(crate) fn delete(cx: &App) -> Task> { Task::ready(web_store::remove(USER_KEYRING)) } } + +/// Read named bytes from the platform keyring, +/// falling back to browser storage on web where no keyring exists +fn read_named(cx: &App, key: &str) -> Task>>> { + #[cfg(not(target_arch = "wasm32"))] + { + let key = key.to_owned(); + let read = cx.read_credentials(&key); + cx.background_spawn(async move { Ok(read.await?.map(|(_, secret)| secret)) }) + } + + #[cfg(target_arch = "wasm32")] + { + let _ = cx; + let stored = web_store::get(key).map(|content| content.map(|s| s.into_bytes())); + Task::ready(stored) + } +} + +/// Write named bytes to the platform keyring, +/// falling back to browser storage on web where no keyring exists +fn write_named(cx: &App, key: &str, secret: &[u8]) -> Task> { + #[cfg(not(target_arch = "wasm32"))] + { + let key = key.to_owned(); + let secret = secret.to_vec(); + let write = cx.write_credentials(&key, "", &secret); + cx.background_spawn(write) + } + + #[cfg(target_arch = "wasm32")] + { + let _ = cx; + let content = match std::str::from_utf8(secret) { + Ok(content) => content, + Err(e) => return Task::ready(Err(anyhow::anyhow!("secret is not UTF-8: {e}"))), + }; + + Task::ready(web_store::set(key, content)) + } +} + +/// Load the NIP-4e app keys from storage, as raw secret bytes +pub fn read_app_keys(cx: &App) -> Task>>> { + read_named(cx, APP_KEYS_KEY) +} + +/// Persist the NIP-4e app keys, as raw secret bytes +pub fn write_app_keys(cx: &App, secret: &[u8]) -> Task> { + write_named(cx, APP_KEYS_KEY, secret) +} diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 512110b4..e79f058f 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -22,7 +22,7 @@ use nostr_sdk::prelude::*; mod blossom; mod constants; -mod credentials; +pub mod credentials; mod file; mod nip05; mod nip4e; diff --git a/crates/workspace/src/dock/tab_panel.rs b/crates/workspace/src/dock/tab_panel.rs index 678b8d63..c92101b4 100644 --- a/crates/workspace/src/dock/tab_panel.rs +++ b/crates/workspace/src/dock/tab_panel.rs @@ -54,6 +54,7 @@ impl Render for DragPanelPreview { .cursor_grab() .p_1() .whitespace_nowrap() + .font_family(cx.theme().font_family.clone()) .border_1() .border_color(cx.theme().border) .rounded(cx.theme().radius_lg)