feat: TUI /call, /accept, /reject, /hangup commands (FC-P2-T1+T2+T3)
- /call [fp|@alias|0x...] — send CallSignal::Offer to peer - /accept — answer incoming call (uses last_dm_peer) - /reject — reject incoming call - /hangup — end active call - All four added to /help text Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,10 @@ impl App {
|
||||
" /gkick <fp> Kick member from group",
|
||||
" /gmembers List group members",
|
||||
" /file <path> Send a file (max 10MB)",
|
||||
" /call [fp|@alias] Call current peer (or specified peer)",
|
||||
" /accept Accept incoming call",
|
||||
" /reject Reject incoming call",
|
||||
" /hangup End current call",
|
||||
" /quit, /q Exit",
|
||||
"",
|
||||
"Navigation:",
|
||||
@@ -488,6 +492,147 @@ impl App {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if text == "/call" || text.starts_with("/call ") {
|
||||
let target = if text.starts_with("/call ") {
|
||||
let arg = text[6..].trim();
|
||||
if arg.starts_with('@') {
|
||||
match self.resolve_alias(&arg[1..], client).await {
|
||||
Some(fp) => Some(fp),
|
||||
None => return,
|
||||
}
|
||||
} else if arg.starts_with("0x") || arg.starts_with("0X") {
|
||||
match self.resolve_address(arg, client).await {
|
||||
Some(fp) => Some(fp),
|
||||
None => return,
|
||||
}
|
||||
} else if !arg.is_empty() {
|
||||
Some(arg.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let peer = target.or_else(|| self.peer_fp.clone());
|
||||
let peer = match peer {
|
||||
Some(p) if !p.starts_with('#') => p,
|
||||
_ => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "No peer to call. Use /call <fp> or set a peer first.".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let peer_fp_clean = normfp(&peer);
|
||||
let msg_id = uuid::Uuid::new_v4().to_string();
|
||||
let our_pub = identity.public_identity();
|
||||
|
||||
let wire = warzone_protocol::message::WireMessage::CallSignal {
|
||||
id: msg_id.clone(),
|
||||
sender_fingerprint: our_pub.fingerprint.to_string(),
|
||||
signal_type: warzone_protocol::message::CallSignalType::Offer,
|
||||
payload: String::new(),
|
||||
target: peer_fp_clean.clone(),
|
||||
};
|
||||
let encoded = match bincode::serialize(&wire) {
|
||||
Ok(e) => e,
|
||||
Err(e) => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: format!("Call failed: {}", e), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match client.send_message(&peer_fp_clean, Some(&self.our_fp), &encoded).await {
|
||||
Ok(_) => {
|
||||
let display = self.peer_eth.as_deref()
|
||||
.or(Some(&peer))
|
||||
.map(|s| if s.len() > 16 { format!("{}...", &s[..16]) } else { s.to_string() })
|
||||
.unwrap_or_default();
|
||||
self.add_message(ChatLine { sender: "system".into(), text: format!("📞 Calling {}...", display), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
}
|
||||
Err(e) => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: format!("Call failed: {}", e), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if text == "/accept" {
|
||||
let peer = match self.last_dm_peer.lock().unwrap().clone() {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "No incoming call to accept".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let msg_id = uuid::Uuid::new_v4().to_string();
|
||||
let our_pub = identity.public_identity();
|
||||
let wire = warzone_protocol::message::WireMessage::CallSignal {
|
||||
id: msg_id,
|
||||
sender_fingerprint: our_pub.fingerprint.to_string(),
|
||||
signal_type: warzone_protocol::message::CallSignalType::Answer,
|
||||
payload: String::new(),
|
||||
target: normfp(&peer),
|
||||
};
|
||||
if let Ok(encoded) = bincode::serialize(&wire) {
|
||||
let _ = client.send_message(&normfp(&peer), Some(&self.our_fp), &encoded).await;
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "✓ Call accepted".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if text == "/reject" {
|
||||
let peer = match self.last_dm_peer.lock().unwrap().clone() {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "No incoming call to reject".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let msg_id = uuid::Uuid::new_v4().to_string();
|
||||
let our_pub = identity.public_identity();
|
||||
let wire = warzone_protocol::message::WireMessage::CallSignal {
|
||||
id: msg_id,
|
||||
sender_fingerprint: our_pub.fingerprint.to_string(),
|
||||
signal_type: warzone_protocol::message::CallSignalType::Reject,
|
||||
payload: String::new(),
|
||||
target: normfp(&peer),
|
||||
};
|
||||
if let Ok(encoded) = bincode::serialize(&wire) {
|
||||
let _ = client.send_message(&normfp(&peer), Some(&self.our_fp), &encoded).await;
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "✗ Call rejected".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if text == "/hangup" {
|
||||
let peer = self.peer_fp.clone().or_else(|| self.last_dm_peer.lock().unwrap().clone());
|
||||
let peer = match peer {
|
||||
Some(p) if !p.starts_with('#') => p,
|
||||
_ => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "No active call".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let msg_id = uuid::Uuid::new_v4().to_string();
|
||||
let our_pub = identity.public_identity();
|
||||
let wire = warzone_protocol::message::WireMessage::CallSignal {
|
||||
id: msg_id,
|
||||
sender_fingerprint: our_pub.fingerprint.to_string(),
|
||||
signal_type: warzone_protocol::message::CallSignalType::Hangup,
|
||||
payload: String::new(),
|
||||
target: normfp(&peer),
|
||||
};
|
||||
if let Ok(encoded) = bincode::serialize(&wire) {
|
||||
let _ = client.send_message(&normfp(&peer), Some(&self.our_fp), &encoded).await;
|
||||
self.add_message(ChatLine { sender: "system".into(), text: "Call ended".into(), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if text.starts_with("/file ") {
|
||||
let path_str = text[6..].trim();
|
||||
self.handle_file_send(path_str, identity, db, client).await;
|
||||
|
||||
Reference in New Issue
Block a user