fix: TUI shows ETH address, /peer 0x... resolves, Cmd+key on macOS
TUI header: shows ETH address (0x...) instead of fingerprint /peer 0x...: resolves via GET /v1/resolve/:address endpoint Cmd+A/E/U/K/W: macOS SUPER modifier now handled alongside CONTROL Added resolve_address() method for ETH/any address resolution Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -379,6 +379,12 @@ impl App {
|
||||
Some(resolved) => resolved,
|
||||
None => return,
|
||||
}
|
||||
} else if raw.starts_with("0x") || raw.starts_with("0X") {
|
||||
// Resolve ETH address via server
|
||||
match self.resolve_address(&raw, client).await {
|
||||
Some(resolved) => resolved,
|
||||
None => return,
|
||||
}
|
||||
} else {
|
||||
raw
|
||||
};
|
||||
@@ -928,6 +934,29 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve an ETH address (0x...) or any address format via the server.
|
||||
pub(crate) async fn resolve_address(&self, addr: &str, client: &ServerClient) -> Option<String> {
|
||||
let url = format!("{}/v1/resolve/{}", client.base_url, addr);
|
||||
match client.client.get(&url).send().await {
|
||||
Ok(resp) => {
|
||||
if let Ok(data) = resp.json::<serde_json::Value>().await {
|
||||
if let Some(fp) = data.get("fingerprint").and_then(|v| v.as_str()) {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: format!("{} → {}", addr, &fp[..fp.len().min(16)]), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
return Some(fp.to_string());
|
||||
}
|
||||
if let Some(err) = data.get("error") {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: format!("Cannot resolve {}: {}", addr, err), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(e) => {
|
||||
self.add_message(ChatLine { sender: "system".into(), text: format!("Error: {}", e), is_system: true, is_self: false, message_id: None, timestamp: Local::now() });
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_aliases(&self, client: &ServerClient) {
|
||||
let url = format!("{}/v1/alias/list", client.base_url);
|
||||
match client.client.get(&url).send().await {
|
||||
|
||||
@@ -58,9 +58,14 @@ impl App {
|
||||
} else {
|
||||
(" \u{25CF}", Color::Red) // ●
|
||||
};
|
||||
let identity_display = if self.our_eth.is_empty() {
|
||||
self.our_fp.clone()
|
||||
} else {
|
||||
format!("{}", &self.our_eth[..self.our_eth.len().min(12)])
|
||||
};
|
||||
let header = Paragraph::new(Line::from(vec![
|
||||
Span::styled("WZ ", Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)),
|
||||
Span::styled(&self.our_fp, Style::default().fg(Color::Green)),
|
||||
Span::styled(identity_display, Style::default().fg(Color::Green)),
|
||||
Span::raw(" \u{2192} "),
|
||||
Span::styled(peer_str, Style::default().fg(Color::Yellow)),
|
||||
Span::styled(
|
||||
|
||||
@@ -51,9 +51,9 @@ impl App {
|
||||
self.cursor_pos += 1;
|
||||
}
|
||||
}
|
||||
// Home / Ctrl+A
|
||||
// Home / Ctrl+A / Cmd+A (macOS)
|
||||
KeyCode::Home => { self.cursor_pos = 0; }
|
||||
KeyCode::Char('a') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
KeyCode::Char('a') if key.modifiers.contains(KeyModifiers::CONTROL) || key.modifiers.contains(KeyModifiers::SUPER) => {
|
||||
self.cursor_pos = 0;
|
||||
}
|
||||
// End: cursor to end of input when typing, snap to bottom when input is empty.
|
||||
@@ -70,20 +70,20 @@ impl App {
|
||||
self.cursor_pos = self.input.len();
|
||||
}
|
||||
}
|
||||
KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) || key.modifiers.contains(KeyModifiers::SUPER) => {
|
||||
self.cursor_pos = self.input.len();
|
||||
}
|
||||
// Ctrl+U: clear line
|
||||
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
// Ctrl+U / Cmd+U: clear line
|
||||
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) || key.modifiers.contains(KeyModifiers::SUPER) => {
|
||||
self.input.clear();
|
||||
self.cursor_pos = 0;
|
||||
}
|
||||
// Ctrl+K: kill to end of line
|
||||
KeyCode::Char('k') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
// Ctrl+K / Cmd+K: kill to end of line
|
||||
KeyCode::Char('k') if key.modifiers.contains(KeyModifiers::CONTROL) || key.modifiers.contains(KeyModifiers::SUPER) => {
|
||||
self.input.truncate(self.cursor_pos);
|
||||
}
|
||||
// Ctrl+W: delete word back
|
||||
KeyCode::Char('w') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
// Ctrl+W / Cmd+W: delete word back
|
||||
KeyCode::Char('w') if key.modifiers.contains(KeyModifiers::CONTROL) || key.modifiers.contains(KeyModifiers::SUPER) => {
|
||||
let before = &self.input[..self.cursor_pos];
|
||||
let new_pos = before.trim_end().rfind(' ').map(|i| i + 1).unwrap_or(0);
|
||||
self.input.drain(new_pos..self.cursor_pos);
|
||||
|
||||
@@ -41,6 +41,8 @@ pub struct App {
|
||||
pub receipts: Arc<Mutex<HashMap<String, ReceiptStatus>>>,
|
||||
/// Pending incoming file transfers, keyed by file ID.
|
||||
pub pending_files: Arc<Mutex<HashMap<String, PendingFileTransfer>>>,
|
||||
/// Our ETH address (derived from seed).
|
||||
pub our_eth: String,
|
||||
/// Scroll offset from bottom (0 = pinned to newest).
|
||||
pub scroll_offset: usize,
|
||||
/// Whether the WebSocket connection is active.
|
||||
@@ -99,6 +101,14 @@ impl App {
|
||||
timestamp: Local::now(),
|
||||
});
|
||||
|
||||
// Derive ETH address from seed if available
|
||||
let our_eth = crate::keystore::load_seed_raw()
|
||||
.map(|seed| {
|
||||
let eth = warzone_protocol::ethereum::derive_eth_identity(&seed);
|
||||
eth.address.to_checksum()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
App {
|
||||
input: String::new(),
|
||||
messages,
|
||||
@@ -110,6 +120,7 @@ impl App {
|
||||
cursor_pos: 0,
|
||||
receipts: Arc::new(Mutex::new(HashMap::new())),
|
||||
pending_files: Arc::new(Mutex::new(HashMap::new())),
|
||||
our_eth,
|
||||
scroll_offset: 0,
|
||||
connected: Arc::new(AtomicBool::new(false)),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user