adds preliminary sending, but seems to hang
This commit is contained in:
parent
6d21fa908c
commit
58fca36bd8
3 changed files with 76 additions and 53 deletions
105
src/app/mod.rs
105
src/app/mod.rs
|
@ -67,7 +67,7 @@ impl App {
|
||||||
match evt {
|
match evt {
|
||||||
Event::Key(key)
|
Event::Key(key)
|
||||||
if key.kind == KeyEventKind::Press
|
if key.kind == KeyEventKind::Press
|
||||||
=> self.handle_key_event(key, evt),
|
=> self.handle_key_event(key, evt).await,
|
||||||
Event::Mouse(_) => {}
|
Event::Mouse(_) => {}
|
||||||
Event::Resize(_, _) => {}
|
Event::Resize(_, _) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -93,7 +93,7 @@ impl App {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_key_event(&mut self, key_event: KeyEvent, event: crossterm::event::Event) {
|
pub async fn handle_key_event(&mut self, key_event: KeyEvent, event: crossterm::event::Event) {
|
||||||
match self.screen.last_mut().unwrap() {
|
match self.screen.last_mut().unwrap() {
|
||||||
CurrentScreen::Logging => match key_event.code {
|
CurrentScreen::Logging => match key_event.code {
|
||||||
KeyCode::Esc => self.pop(),
|
KeyCode::Esc => self.pop(),
|
||||||
|
@ -116,14 +116,14 @@ impl App {
|
||||||
KeyCode::Esc => self.pop(),
|
KeyCode::Esc => self.pop(),
|
||||||
KeyCode::Char('q') => self.exit(),
|
KeyCode::Char('q') => self.exit(),
|
||||||
KeyCode::Tab => *s = SendingScreen::Peers,
|
KeyCode::Tab => *s = SendingScreen::Peers,
|
||||||
KeyCode::Enter => todo!("send the selected file or enter directory"),
|
KeyCode::Enter => self.send_content().await,
|
||||||
_ => self.file_picker.handle(&event).unwrap_or_default(),
|
_ => self.file_picker.handle(&event).unwrap_or_default(),
|
||||||
},
|
},
|
||||||
SendingScreen::Peers => match key_event.code {
|
SendingScreen::Peers => match key_event.code {
|
||||||
KeyCode::Esc => self.pop(),
|
KeyCode::Esc => self.pop(),
|
||||||
KeyCode::Char('q') => self.exit(),
|
KeyCode::Char('q') => self.exit(),
|
||||||
KeyCode::Tab => *s = SendingScreen::Files,
|
KeyCode::Tab => *s = SendingScreen::Files,
|
||||||
KeyCode::Enter => todo!("send to the selected peer"),
|
KeyCode::Enter => self.send_content().await,
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
SendingScreen::Text => {}
|
SendingScreen::Text => {}
|
||||||
|
@ -139,43 +139,6 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn accept(&mut self) {
|
|
||||||
let Some(idx) = self.receiving_state.selected() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
// keys are sorted, so we can use the table selection index
|
|
||||||
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.receive_requests.get(key) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let Err(e) = req.tx.send(ReceiveDialog::Approve) {
|
|
||||||
error!("got error sending upload confirmation: {e:?}");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deny(&mut self) {
|
|
||||||
let Some(idx) = self.receiving_state.selected() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
// keys are sorted, so we can use the table selection index
|
|
||||||
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.receive_requests.get(key).cloned() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let Err(e) = req.tx.send(ReceiveDialog::Deny) {
|
|
||||||
error!("got error sending upload confirmation: {e:?}");
|
|
||||||
};
|
|
||||||
self.receive_requests.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw(&mut self, frame: &mut Frame) {
|
pub fn draw(&mut self, frame: &mut Frame) {
|
||||||
frame.render_widget(self, frame.area());
|
frame.render_widget(self, frame.area());
|
||||||
}
|
}
|
||||||
|
@ -216,6 +179,66 @@ impl App {
|
||||||
self.screen.push(CurrentScreen::Main);
|
self.screen.push(CurrentScreen::Main);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accept a content receive request
|
||||||
|
fn accept(&mut self) {
|
||||||
|
let Some(idx) = self.receiving_state.selected() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
// keys are sorted, so we can use the table selection index
|
||||||
|
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.receive_requests.get(key) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let Err(e) = req.tx.send(ReceiveDialog::Approve) {
|
||||||
|
error!("got error sending upload confirmation: {e:?}");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// reject an content receive request
|
||||||
|
fn deny(&mut self) {
|
||||||
|
let Some(idx) = self.receiving_state.selected() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
// keys are sorted, so we can use the table selection index
|
||||||
|
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.receive_requests.get(key).cloned() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let Err(e) = req.tx.send(ReceiveDialog::Deny) {
|
||||||
|
error!("got error sending upload confirmation: {e:?}");
|
||||||
|
};
|
||||||
|
self.receive_requests.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send content to selected peer, or change directories in the file explorer
|
||||||
|
async fn send_content(&mut self) {
|
||||||
|
if let Some(_bytes) = self.content.iter().next().cloned() {
|
||||||
|
// self.service.send_bytes(session_id, content_id, token, body)
|
||||||
|
warn!("entering text is not yet supported");
|
||||||
|
} else {
|
||||||
|
let file = self.file_picker.current().path().clone();
|
||||||
|
|
||||||
|
if file.is_dir()
|
||||||
|
&& let Err(e) = self.file_picker.set_cwd(&file)
|
||||||
|
{
|
||||||
|
error!("could not list directory {file:?}: {e}");
|
||||||
|
} else if let Some((peer, _)) = self.service.peers.lock().await.first_key_value()
|
||||||
|
&& file.is_file()
|
||||||
|
&& let Err(e) = self.service.send_file(peer.to_owned(), file.clone()).await
|
||||||
|
{
|
||||||
|
error!("got error sending content: {e:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_log_level(delta: isize) {
|
fn change_log_level(delta: isize) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub mod models;
|
||||||
pub mod transfer;
|
pub mod transfer;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::BTreeMap,
|
||||||
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||||
sync::{Arc, OnceLock},
|
sync::{Arc, OnceLock},
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ pub enum TransferEvent {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ReceiveRequest {
|
pub struct ReceiveRequest {
|
||||||
pub alias: String,
|
pub alias: String,
|
||||||
pub files: HashMap<String, FileMetadata>,
|
pub files: BTreeMap<String, FileMetadata>,
|
||||||
pub tx: UnboundedSender<ReceiveDialog>,
|
pub tx: UnboundedSender<ReceiveDialog>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ pub struct ReceiveRequest {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct JoecalService {
|
pub struct JoecalService {
|
||||||
pub device: Device,
|
pub device: Device,
|
||||||
pub peers: Arc<Mutex<HashMap<String, (SocketAddr, Device)>>>,
|
pub peers: Arc<Mutex<BTreeMap<String, (SocketAddr, Device)>>>,
|
||||||
pub sessions: Arc<Mutex<HashMap<String, Session>>>, // Session ID to Session
|
pub sessions: Arc<Mutex<BTreeMap<String, Session>>>, // Session ID to Session
|
||||||
pub running_state: Arc<Mutex<RunningState>>,
|
pub running_state: Arc<Mutex<RunningState>>,
|
||||||
pub socket: Arc<UdpSocket>,
|
pub socket: Arc<UdpSocket>,
|
||||||
pub client: reqwest::Client,
|
pub client: reqwest::Client,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::HashMap, net::SocketAddr, path::PathBuf};
|
use std::{collections::BTreeMap, net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
Json,
|
Json,
|
||||||
|
@ -21,8 +21,8 @@ use crate::{
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub session_id: String,
|
pub session_id: String,
|
||||||
pub files: HashMap<String, FileMetadata>,
|
pub files: BTreeMap<String, FileMetadata>,
|
||||||
pub file_tokens: HashMap<String, String>,
|
pub file_tokens: BTreeMap<String, String>,
|
||||||
pub receiver: Device,
|
pub receiver: Device,
|
||||||
pub sender: Device,
|
pub sender: Device,
|
||||||
pub status: SessionStatus,
|
pub status: SessionStatus,
|
||||||
|
@ -42,21 +42,21 @@ pub enum SessionStatus {
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PrepareUploadResponse {
|
pub struct PrepareUploadResponse {
|
||||||
pub session_id: String,
|
pub session_id: String,
|
||||||
pub files: HashMap<String, String>,
|
pub files: BTreeMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PrepareUploadRequest {
|
pub struct PrepareUploadRequest {
|
||||||
pub info: Device,
|
pub info: Device,
|
||||||
pub files: HashMap<String, FileMetadata>,
|
pub files: BTreeMap<String, FileMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JoecalService {
|
impl JoecalService {
|
||||||
pub async fn prepare_upload(
|
pub async fn prepare_upload(
|
||||||
&self,
|
&self,
|
||||||
peer: String,
|
peer: String,
|
||||||
files: HashMap<String, FileMetadata>,
|
files: BTreeMap<String, FileMetadata>,
|
||||||
) -> Result<PrepareUploadResponse> {
|
) -> Result<PrepareUploadResponse> {
|
||||||
if !self.peers.lock().await.contains_key(&peer) {
|
if !self.peers.lock().await.contains_key(&peer) {
|
||||||
return Err(LocalSendError::PeerNotFound);
|
return Err(LocalSendError::PeerNotFound);
|
||||||
|
@ -140,7 +140,7 @@ impl JoecalService {
|
||||||
let file_metadata = FileMetadata::from_path(&file_path)?;
|
let file_metadata = FileMetadata::from_path(&file_path)?;
|
||||||
|
|
||||||
// Prepare files map
|
// Prepare files map
|
||||||
let mut files = HashMap::new();
|
let mut files = BTreeMap::new();
|
||||||
files.insert(file_metadata.id.clone(), file_metadata.clone());
|
files.insert(file_metadata.id.clone(), file_metadata.clone());
|
||||||
|
|
||||||
// Prepare upload
|
// Prepare upload
|
||||||
|
@ -227,7 +227,7 @@ pub async fn prepare_upload(
|
||||||
|
|
||||||
let session_id = id.as_string();
|
let session_id = id.as_string();
|
||||||
|
|
||||||
let file_tokens: HashMap<String, String> = req
|
let file_tokens: BTreeMap<String, String> = req
|
||||||
.files
|
.files
|
||||||
.keys()
|
.keys()
|
||||||
.map(|id| (id.clone(), Julid::new().to_string())) // Replace with actual token logic
|
.map(|id| (id.clone(), Julid::new().to_string())) // Replace with actual token logic
|
||||||
|
|
Loading…
Reference in a new issue