New users with no peer/group set automatically join #ops so they have someone to talk to. Saved peer overrides this on subsequent visits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
91 lines
2.6 KiB
Rust
91 lines
2.6 KiB
Rust
mod types;
|
|
mod draw;
|
|
mod commands;
|
|
mod file_transfer;
|
|
mod input;
|
|
mod network;
|
|
|
|
pub use types::App;
|
|
|
|
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
|
|
use anyhow::Result;
|
|
use crossterm::event::{self, Event, KeyCode};
|
|
|
|
use warzone_protocol::identity::{IdentityKeyPair, Seed};
|
|
|
|
use crate::net::ServerClient;
|
|
use crate::storage::LocalDb;
|
|
|
|
/// Run the TUI event loop.
|
|
pub async fn run_tui(
|
|
our_fp: String,
|
|
peer_fp: Option<String>,
|
|
server_url: String,
|
|
identity: IdentityKeyPair,
|
|
poll_seed: Seed,
|
|
db: LocalDb,
|
|
) -> Result<()> {
|
|
let mut terminal = ratatui::init();
|
|
let client = ServerClient::new(&server_url);
|
|
let db = Arc::new(db);
|
|
|
|
let mut app = App::new(our_fp.clone(), peer_fp, server_url);
|
|
|
|
// Derive a second identity for the poll loop (can't clone IdentityKeyPair)
|
|
let poll_identity = poll_seed.derive_identity();
|
|
let poll_messages = app.messages.clone();
|
|
let poll_receipts = app.receipts.clone();
|
|
let poll_pending_files = app.pending_files.clone();
|
|
let poll_last_dm = app.last_dm_peer.clone();
|
|
let poll_connected = app.connected.clone();
|
|
let poll_client = client.clone();
|
|
let poll_db = db.clone();
|
|
let poll_fp = our_fp.clone();
|
|
|
|
tokio::spawn(async move {
|
|
network::poll_loop(poll_messages, poll_receipts, poll_pending_files, poll_fp, poll_identity, poll_db, poll_client, poll_last_dm, poll_connected).await;
|
|
});
|
|
|
|
// Auto-join #ops if no peer set
|
|
if app.peer_fp.is_none() {
|
|
let join_url = format!("{}/v1/groups/ops/join", client.base_url);
|
|
let fp_clean: String = our_fp.chars().filter(|c| c.is_ascii_hexdigit()).collect::<String>().to_lowercase();
|
|
let _ = client.client.post(&join_url)
|
|
.json(&serde_json::json!({"fingerprint": fp_clean}))
|
|
.send().await;
|
|
app.peer_fp = Some("#ops".to_string());
|
|
app.add_message(types::ChatLine {
|
|
sender: "system".into(),
|
|
text: "Welcome! You have been added to #ops".into(),
|
|
is_system: true,
|
|
is_self: false,
|
|
message_id: None,
|
|
timestamp: chrono::Local::now(),
|
|
});
|
|
}
|
|
|
|
loop {
|
|
terminal.draw(|frame| app.draw(frame))?;
|
|
|
|
if event::poll(Duration::from_millis(100))? {
|
|
if let Event::Key(key) = event::read()? {
|
|
if key.code == KeyCode::Enter {
|
|
app.handle_send(&identity, &db, &client).await;
|
|
app.scroll_offset = 0;
|
|
} else {
|
|
app.handle_key_event(key);
|
|
}
|
|
}
|
|
}
|
|
|
|
if app.should_quit {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ratatui::restore();
|
|
Ok(())
|
|
}
|