v0.0.15: unalias, admin alias removal, /reply, web version fix

Aliases:
- /unalias — remove your own alias
- /admin-unalias <alias> <password> — admin removes any alias
- Admin password via WARZONE_ADMIN_PASSWORD env var (default: "admin")
- POST /v1/alias/unregister + POST /v1/alias/admin-remove

Reply:
- /r or /reply — switches peer to whoever last DM'd you
- lastDmPeer tracked on both web and TUI
- Then type normally to reply

Web:
- Version bumped to 0.0.15 (was stuck at 0.0.10)
- WASM rebuilt with latest protocol

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-03-27 14:12:33 +04:00
parent 608a160614
commit 9c70e02eba
5 changed files with 132 additions and 8 deletions

View File

@@ -52,6 +52,7 @@ pub struct App {
pub peer_fp: Option<String>,
pub server_url: String,
pub should_quit: bool,
pub last_dm_peer: Option<String>,
/// Track receipt status for messages we sent, keyed by message ID.
pub receipts: Arc<Mutex<HashMap<String, ReceiptStatus>>>,
/// Pending incoming file transfers, keyed by file ID.
@@ -111,6 +112,7 @@ impl App {
peer_fp,
server_url,
should_quit: false,
last_dm_peer: None,
receipts: Arc::new(Mutex::new(HashMap::new())),
pending_files: Arc::new(Mutex::new(HashMap::new())),
}
@@ -266,6 +268,33 @@ impl App {
self.list_aliases(client).await;
return;
}
if text == "/unalias" {
let url = format!("{}/v1/alias/unregister", client.base_url);
match client.client.post(&url)
.json(&serde_json::json!({"fingerprint": normfp(&self.our_fp)}))
.send().await
{
Ok(resp) => if let Ok(data) = resp.json::<serde_json::Value>().await {
if let Some(err) = data.get("error") {
self.add_message(ChatLine { sender: "system".into(), text: format!("Error: {}", err), is_system: true, is_self: false, message_id: None });
} else {
self.add_message(ChatLine { sender: "system".into(), text: "Alias removed".into(), is_system: true, is_self: false, message_id: None });
}
},
Err(e) => self.add_message(ChatLine { sender: "system".into(), text: format!("Error: {}", e), is_system: true, is_self: false, message_id: None }),
}
return;
}
if text == "/r" || text == "/reply" {
// Just switch to last DM peer
if let Some(ref peer) = self.last_dm_peer.clone() {
self.peer_fp = Some(peer.clone());
self.add_message(ChatLine { sender: "system".into(), text: format!("→ switched to {}", &peer[..peer.len().min(16)]), is_system: true, is_self: false, message_id: None });
} else {
self.add_message(ChatLine { sender: "system".into(), text: "No one to reply to".into(), is_system: true, is_self: false, message_id: None });
}
return;
}
if text.starts_with("/peer ") {
let raw = text[6..].trim().to_string();
let fp = if raw.starts_with('@') {