103 lines
3.4 KiB
Rust
103 lines
3.4 KiB
Rust
//! NIP-78 (kind 30078) settings sync for sovereign_browser
|
|
//!
|
|
//! Port of `settings_sync.c` / `settings_sync.h` from the C project.
|
|
//! Uses `nostr_signer` and `nostr_relay` from `rust_core_lib`.
|
|
|
|
use nostr_signer::traits::NostrSigner;
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
use once_cell::sync::Lazy;
|
|
|
|
use crate::db;
|
|
use crate::settings;
|
|
|
|
/// The d-tag identifier used for the shared kind 30078 user-settings event.
|
|
const SETTINGS_SYNC_D_TAG: &str = "user-settings";
|
|
|
|
/// The Nostr kind for arbitrary custom app data (NIP-78).
|
|
const _SETTINGS_SYNC_KIND: u64 = 30078;
|
|
|
|
/// Global signer state for settings sync.
|
|
static G_SYNC_STATE: Lazy<Mutex<SyncState>> = Lazy::new(|| Mutex::new(SyncState::default()));
|
|
|
|
struct SyncState {
|
|
signer: Option<Arc<dyn NostrSigner>>,
|
|
pubkey_hex: String,
|
|
have_signer: bool,
|
|
}
|
|
|
|
impl Default for SyncState {
|
|
fn default() -> Self {
|
|
SyncState {
|
|
signer: None,
|
|
pubkey_hex: String::new(),
|
|
have_signer: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Initialize the settings sync module.
|
|
pub fn settings_sync_init(signer: Option<Arc<dyn NostrSigner>>, pubkey_hex: &str) {
|
|
let mut state = G_SYNC_STATE.lock().unwrap();
|
|
state.signer = signer;
|
|
state.pubkey_hex = pubkey_hex.to_string();
|
|
state.have_signer = state.signer.is_some() && !state.pubkey_hex.is_empty();
|
|
}
|
|
|
|
/// Update the signer reference.
|
|
pub fn settings_sync_set_signer(signer: Option<Arc<dyn NostrSigner>>, pubkey_hex: &str) {
|
|
settings_sync_init(signer, pubkey_hex);
|
|
}
|
|
|
|
/// Serialize syncable settings, build and sign a kind 30078 event.
|
|
pub fn settings_sync_publish() {
|
|
let state = G_SYNC_STATE.lock().unwrap();
|
|
if !state.have_signer {
|
|
return;
|
|
}
|
|
|
|
let browser_settings = settings::settings_get();
|
|
|
|
let payload = serde_json::json!({
|
|
"v": 2,
|
|
"updatedAt": std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_secs(),
|
|
"sovereign_browser": {
|
|
"new_tab_url": browser_settings.new_tab_url,
|
|
"tab_bar_position": browser_settings.tab_bar_position,
|
|
"show_tab_close_buttons": browser_settings.show_tab_close_buttons,
|
|
"middle_click_close": browser_settings.middle_click_close,
|
|
"ctrl_tab_switch": browser_settings.ctrl_tab_switch,
|
|
"tab_drag_reorder": browser_settings.tab_drag_reorder,
|
|
"max_tabs": browser_settings.max_tabs,
|
|
"bootstrap_relays": browser_settings.bootstrap_relays,
|
|
"search_engine": browser_settings.search_engine,
|
|
}
|
|
});
|
|
|
|
if let Ok(payload_str) = serde_json::to_string(&payload) {
|
|
let _ = db::db_kv_set("settings_sync.last_payload", &payload_str);
|
|
}
|
|
|
|
println!("[settings_sync] Publish requested (NIP-44 encryption not yet implemented)");
|
|
}
|
|
|
|
/// Merge settings from a fetched kind 30078 event.
|
|
pub fn settings_sync_merge_from_nostr(event_json: &serde_json::Value) -> Result<(), Box<dyn std::error::Error>> {
|
|
let content = event_json["content"]
|
|
.as_str()
|
|
.ok_or("Missing content")?;
|
|
|
|
if let Ok(payload) = serde_json::from_str::<serde_json::Value>(content) {
|
|
if let Some(browser) = payload.get("sovereign_browser") {
|
|
settings::settings_update(browser);
|
|
settings::settings_save();
|
|
println!("[settings_sync] Merged settings from Nostr event");
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|