diff --git a/Cargo.lock b/Cargo.lock index b5fb2e7..0dcae59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -457,6 +457,18 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "either" version = "1.15.0" @@ -472,6 +484,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "env_filter" version = "0.1.3" @@ -1135,6 +1167,7 @@ dependencies = [ "mime_guess", "network-interface", "ratatui", + "ratatui-explorer", "reqwest", "serde", "serde_json", @@ -1623,6 +1656,16 @@ dependencies = [ "unicode-width 0.2.0", ] +[[package]] +name = "ratatui-explorer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5135951c1bf2ef7ce25b46c53eacf45f1a3e6b283669229008d6744a9ca1332" +dependencies = [ + "educe", + "ratatui", +] + [[package]] name = "redox_syscall" version = "0.5.13" diff --git a/Cargo.toml b/Cargo.toml index 4769820..a32ad3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ mime = "0.3" mime_guess = "2" network-interface = { version = "2", features = ["serde"] } ratatui = "0.29" +ratatui-explorer = "0.2.1" reqwest = { version = "0.12", features = ["json"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/src/app/mod.rs b/src/app/mod.rs index 4a67dc3..e875419 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -2,7 +2,7 @@ use std::{collections::BTreeMap, net::SocketAddr, time::Duration}; use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, KeyEventKind}; use futures::{FutureExt, StreamExt}; -use joecalsend::{JoecalService, JoecalUploadRequest, TransferEvent, UploadDialog, error::Result}; +use joecalsend::{JoecalService, ReceiveDialog, ReceiveRequest, TransferEvent, error::Result}; use julid::Julid; use log::{LevelFilter, debug, error, warn}; use ratatui::{Frame, widgets::TableState}; @@ -18,7 +18,7 @@ pub struct App { pub events: EventStream, // addr -> (alias, fingerprint) pub peers: Peers, - pub uploads: BTreeMap, + pub receive_requests: BTreeMap, upload_state: TableState, // for getting messages back from the web server or web client about things we've done; the // other end is held by the service @@ -42,7 +42,7 @@ impl App { screen: vec![CurrentScreen::Main], events: Default::default(), peers: Default::default(), - uploads: Default::default(), + receive_requests: Default::default(), upload_state: Default::default(), } } @@ -65,11 +65,11 @@ impl App { if let Some(event) = transfer_event { debug!("got transferr event {event:?}"); match event { - TransferEvent::UploadRequest { id, request } => { - self.uploads.insert(id, request); + TransferEvent::ReceiveRequest { id, request } => { + self.receive_requests.insert(id, request); } TransferEvent::Cancelled(id) | TransferEvent::Received(id) => { - self.uploads.remove(&id); + self.receive_requests.remove(&id); } } } @@ -114,15 +114,15 @@ impl App { return; }; // keys are sorted, so we can use the table selection index - let keys: Vec<_> = self.uploads.keys().collect(); + let keys: Vec<_> = self.receive_requests.keys().collect(); let Some(key) = keys.get(idx) else { warn!("could not get id from selection index {idx}"); return; }; - let Some(req) = self.uploads.get(key) else { + let Some(req) = self.receive_requests.get(key) else { return; }; - if let Err(e) = req.tx.send(UploadDialog::UploadConfirm) { + if let Err(e) = req.tx.send(ReceiveDialog::Approve) { error!("got error sending upload confirmation: {e:?}"); }; } @@ -132,18 +132,18 @@ impl App { return; }; // keys are sorted, so we can use the table selection index - let keys: Vec<_> = self.uploads.keys().cloned().collect(); + let keys: Vec<_> = self.receive_requests.keys().cloned().collect(); let Some(key) = keys.get(idx) else { warn!("could not get id from selection index {idx}"); return; }; - let Some(req) = self.uploads.get(key).cloned() else { + let Some(req) = self.receive_requests.get(key).cloned() else { return; }; - if let Err(e) = req.tx.send(UploadDialog::UploadDeny) { + if let Err(e) = req.tx.send(ReceiveDialog::Deny) { error!("got error sending upload confirmation: {e:?}"); }; - self.uploads.remove(key); + self.receive_requests.remove(key); } pub fn draw(&mut self, frame: &mut Frame) { diff --git a/src/app/widgets.rs b/src/app/widgets.rs index c5fe79a..d0c5399 100644 --- a/src/app/widgets.rs +++ b/src/app/widgets.rs @@ -1,6 +1,6 @@ use std::sync::LazyLock; -use joecalsend::JoecalUploadRequest; +use joecalsend::ReceiveRequest; use log::LevelFilter; use ratatui::{ buffer::Buffer, @@ -78,7 +78,7 @@ impl Widget for &mut App { let subscreen_margin = Margin::new(2, 4); let mode = self.screen.last().unwrap(); - let ups: Vec<_> = self.uploads.values().collect(); + let ups: Vec<_> = self.receive_requests.values().collect(); match mode { CurrentScreen::Main => { main_page(*mode, &MAIN_MENU, area, buf); @@ -145,7 +145,7 @@ fn main_page(screen: CurrentScreen, menu: &Line, area: Rect, buf: &mut Buffer) { } fn upload_requests( - requests: &[&JoecalUploadRequest], + requests: &[&ReceiveRequest], state: &mut TableState, area: Rect, buf: &mut Buffer, diff --git a/src/lib.rs b/src/lib.rs index 706f737..c7babdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,26 +39,23 @@ pub enum Listeners { } #[derive(Debug, Clone, PartialEq, Eq)] -pub enum UploadDialog { - UploadDeny, - UploadConfirm, +pub enum ReceiveDialog { + Approve, + Deny, } #[derive(Debug, Clone)] pub enum TransferEvent { Received(Julid), Cancelled(Julid), - UploadRequest { - id: Julid, - request: JoecalUploadRequest, - }, + ReceiveRequest { id: Julid, request: ReceiveRequest }, } #[derive(Clone, Debug)] -pub struct JoecalUploadRequest { +pub struct ReceiveRequest { pub alias: String, pub files: HashMap, - pub tx: UnboundedSender, + pub tx: UnboundedSender, } /// Contains the main network and backend state for an application session. @@ -83,7 +80,7 @@ impl JoecalService { ) -> crate::error::Result { let socket = UdpSocket::bind(LISTENING_SOCKET_ADDR).await?; socket.set_multicast_loop_v4(true)?; - socket.set_multicast_ttl_v4(2)?; // one hop out from localnet + socket.set_multicast_ttl_v4(8)?; // 8 hops out from localnet socket.join_multicast_v4(MULTICAST_IP, Ipv4Addr::from_bits(0))?; Ok(Self { diff --git a/src/main.rs b/src/main.rs index 6b26db0..f239cbc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,15 +62,15 @@ async fn start_and_run( .insert(addr.to_owned(), (alias, fingerprint.to_owned())); }); - let mut stale_uploads = Vec::with_capacity(app.uploads.len()); + let mut stale_uploads = Vec::with_capacity(app.receive_requests.len()); let now = chrono::Utc::now().timestamp_millis() as u64; - for (id, request) in app.uploads.iter() { + for (id, request) in app.receive_requests.iter() { if request.tx.is_closed() || (now - id.timestamp()) > 60_000 { stale_uploads.push(*id); } } for id in stale_uploads { - app.uploads.remove(&id); + app.receive_requests.remove(&id); } } diff --git a/src/transfer.rs b/src/transfer.rs index 9582d05..ca885e9 100644 --- a/src/transfer.rs +++ b/src/transfer.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use tokio::sync::mpsc::unbounded_channel; use crate::{ - JoecalService, JoecalUploadRequest, TransferEvent, UploadDialog, + JoecalService, ReceiveDialog, ReceiveRequest, TransferEvent, error::{LocalSendError, Result}, models::{Device, FileMetadata}, }; @@ -198,7 +198,7 @@ pub async fn register_prepare_upload( let id = Julid::new(); let (tx, mut rx) = unbounded_channel(); - let request = JoecalUploadRequest { + let request = ReceiveRequest { alias: req.info.alias.clone(), files: req.files.clone(), tx, @@ -206,7 +206,7 @@ pub async fn register_prepare_upload( match service .transfer_event_tx - .send(TransferEvent::UploadRequest { id, request }) + .send(TransferEvent::ReceiveRequest { id, request }) { Ok(_) => {} Err(e) => { @@ -222,7 +222,7 @@ pub async fn register_prepare_upload( return StatusCode::INTERNAL_SERVER_ERROR.into_response(); }; - if confirmation != UploadDialog::UploadConfirm { + if confirmation != ReceiveDialog::Approve { return StatusCode::FORBIDDEN.into_response(); }