From cd470b0124e1ab40195b8b0ee9357d599aeff6c5 Mon Sep 17 00:00:00 2001 From: Phil Kulak Date: Sat, 22 Apr 2023 08:10:38 -0700 Subject: [PATCH] Support multiple file uploads. --- src/handler.rs | 17 +++++++----- src/matrix/matrix.rs | 61 +++++++++++++++++++++++------------------ src/spawn.rs | 4 +-- src/widgets/chat.rs | 8 +++--- src/widgets/progress.rs | 8 ++++-- 5 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/handler.rs b/src/handler.rs index 5323d65..2a14ee4 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -19,7 +19,7 @@ pub enum MatuiEvent { LoginComplete, LoginRequired, LoginStarted, - ProgressStarted(String), + ProgressStarted(String, u64), ProgressComplete, RoomMember(Joined, RoomMember), RoomSelected(Joined), @@ -53,7 +53,7 @@ pub fn handle_app_event(event: MatuiEvent, app: &mut App) { app.set_popup(Popup::Signin(Signin::default())); } MatuiEvent::LoginStarted => { - app.set_popup(Popup::Progress(Progress::new("Logging in"))); + app.set_popup(Popup::Progress(Progress::new("Logging in", 0))); } MatuiEvent::LoginComplete => { app.popup = None; @@ -65,15 +65,18 @@ pub fn handle_app_event(event: MatuiEvent, app: &mut App) { c.room_member_event(room, member); } } - MatuiEvent::ProgressStarted(msg) => app.set_popup(Popup::Progress(Progress::new(&msg))), + MatuiEvent::ProgressStarted(msg, delay) => { + app.set_popup(Popup::Progress(Progress::new(&msg, delay))) + } MatuiEvent::ProgressComplete => app.popup = None, MatuiEvent::RoomSelected(room) => app.select_room(room), MatuiEvent::SyncStarted(st) => { match st { - SyncType::Initial => { - app.set_popup(Popup::Progress(Progress::new("Performing initial sync."))) - } - SyncType::Latest => app.set_popup(Popup::Progress(Progress::new("Syncing"))), + SyncType::Initial => app.set_popup(Popup::Progress(Progress::new( + "Performing initial sync.", + 0, + ))), + SyncType::Latest => app.set_popup(Popup::Progress(Progress::new("Syncing", 0))), }; } MatuiEvent::SyncComplete => { diff --git a/src/matrix/matrix.rs b/src/matrix/matrix.rs index d2c55ca..b74aed4 100644 --- a/src/matrix/matrix.rs +++ b/src/matrix/matrix.rs @@ -301,7 +301,7 @@ impl Matrix { let matrix = self.clone(); self.rt.spawn(async move { - Matrix::send(ProgressStarted("Downloading file.".to_string())); + Matrix::send(ProgressStarted("Downloading file.".to_string(), 250)); let (content_type, request) = match message { Image(content) => ( @@ -345,7 +345,7 @@ impl Matrix { pub fn send_text_message(&self, room: Joined, message: String) { self.rt.spawn(async move { - Matrix::send(ProgressStarted("Sending message.".to_string())); + Matrix::send(ProgressStarted("Sending message.".to_string(), 500)); if let Err(err) = room .send(RoomMessageEventContent::text_plain(message), None) @@ -358,41 +358,48 @@ impl Matrix { }); } - pub fn send_attachement(&self, room: Joined, path: PathBuf) { - let content_type = mime_from_path(&path); - - let name = path - .file_name() - .unwrap_or_default() - .to_str() - .unwrap_or_default() - .to_string(); + pub fn send_attachements(&self, room: Joined, paths: Vec) { + let total = paths.len(); self.rt.spawn(async move { - Matrix::send(ProgressStarted("Uploading".to_string())); + for (i, path) in paths.into_iter().enumerate() { + Matrix::send(ProgressStarted( + format!("Uploading {} of {}.", i + 1, total), + 0, + )); + + let content_type = mime_from_path(&path); + + let name = path + .file_name() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + .to_string(); + + let data = match fs::read(path.to_str().unwrap()) { + Ok(d) => d, + Err(err) => { + Matrix::send(Error(err.to_string())); + return; + } + }; - let data = match fs::read(path.to_str().unwrap()) { - Ok(d) => d, - Err(err) => { + if let Err(err) = room + .send_attachment(&name, &content_type, data, AttachmentConfig::new()) + .await + { Matrix::send(Error(err.to_string())); - return; } - }; - if let Err(err) = room - .send_attachment(&name, &content_type, data, AttachmentConfig::new()) - .await - { - Matrix::send(Error(err.to_string())); + Matrix::send(ProgressComplete); } - - Matrix::send(ProgressComplete); }); } pub fn send_reaction(&self, room: Joined, event_id: OwnedEventId, key: String) { self.rt.spawn(async move { - Matrix::send(ProgressStarted("Sending reaction.".to_string())); + Matrix::send(ProgressStarted("Sending reaction.".to_string(), 500)); if let Err(err) = room .send( @@ -410,7 +417,7 @@ impl Matrix { pub fn redact_event(&self, room: Joined, event_id: OwnedEventId) { self.rt.spawn(async move { - Matrix::send(ProgressStarted("Removing.".to_string())); + Matrix::send(ProgressStarted("Removing.".to_string(), 500)); if let Err(err) = room.redact(&event_id, None, None).await { Matrix::send(Error(err.to_string())); @@ -422,7 +429,7 @@ impl Matrix { pub fn replace_event(&self, room: Joined, id: OwnedEventId, message: String) { self.rt.spawn(async move { - Matrix::send(ProgressStarted("Editing message.".to_string())); + Matrix::send(ProgressStarted("Editing message.".to_string(), 500)); if let Err(err) = room .send( diff --git a/src/spawn.rs b/src/spawn.rs index 5a26297..2394543 100644 --- a/src/spawn.rs +++ b/src/spawn.rs @@ -11,12 +11,12 @@ use std::path::PathBuf; use std::process::{Command, Stdio}; use tempfile::Builder; -pub fn get_file_path() -> anyhow::Result> { +pub fn get_file_paths() -> anyhow::Result> { let home = dirs::home_dir().context("no home directory")?; let path = FileDialog::new() .set_location(home.as_path()) - .show_open_single_file()?; + .show_open_multiple_file()?; Ok(path) } diff --git a/src/widgets/chat.rs b/src/widgets/chat.rs index 1b3a9fd..1ef64a0 100644 --- a/src/widgets/chat.rs +++ b/src/widgets/chat.rs @@ -4,7 +4,7 @@ use crate::handler::Batch; use crate::matrix::matrix::Matrix; use crate::matrix::roomcache::DecoratedRoom; use crate::settings::is_muted; -use crate::spawn::{get_file_path, get_text}; +use crate::spawn::{get_file_paths, get_text}; use crate::widgets::message::{Message, Reaction, ReactionEvent}; use crate::widgets::react::React; use crate::widgets::react::ReactResult; @@ -259,15 +259,15 @@ impl Chat { Ok(consumed!()) } KeyCode::Char('u') => { - let path = get_file_path()?; + let paths = get_file_paths()?; App::get_sender().send(Event::Redraw)?; - if path.is_none() { + if paths.is_empty() { return Ok(EventResult::Ignored); } - self.matrix.send_attachement(self.room(), path.unwrap()); + self.matrix.send_attachements(self.room(), paths); Ok(consumed!()) } diff --git a/src/widgets/progress.rs b/src/widgets/progress.rs index 2a2c8d6..ae9a1da 100644 --- a/src/widgets/progress.rs +++ b/src/widgets/progress.rs @@ -16,14 +16,16 @@ pub struct Progress { text: String, tail: String, created: Instant, + delay: u64, } impl Progress { - pub fn new(text: &str) -> Progress { + pub fn new(text: &str, delay: u64) -> Progress { Progress { text: text.to_string(), tail: "".to_string(), created: Instant::now(), + delay, } } @@ -42,8 +44,8 @@ pub struct ProgressWidget<'a> { impl Widget for ProgressWidget<'_> { fn render(self, area: Rect, buf: &mut Buffer) { - // don't even render until it's been half a second - if self.progress.created.elapsed() < Duration::from_millis(500) { + // don't render until it's been past the delay + if self.progress.created.elapsed() < Duration::from_millis(self.progress.delay) { return; }