From e3ff8c81d8e9647ceb7baad2fa9dcd99cf437868 Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Sat, 22 Feb 2025 11:05:21 +0100 Subject: [PATCH 1/2] default xdcc save path --- Cargo.lock | 1 + Cargo.toml | 1 + book/src/configuration/file_transfer.md | 6 +-- data/src/config/file_transfer.rs | 8 ++-- src/buffer/file_transfers.rs | 57 ++++++++++++++++++------- src/screen/dashboard.rs | 16 +++---- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb4d0c7dc..4645dbb7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2619,6 +2619,7 @@ dependencies = [ "emojis", "fern", "futures", + "humantime", "iced", "image 0.24.9", "ipc", diff --git a/Cargo.toml b/Cargo.toml index 8d9de23c4..71a048ecf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ rodio = "0.19.0" strum = { version = "0.26.3", features = ["derive"] } tokio-stream = { version = "0.1.16", features = ["fs"] } url = "2.5.0" +humantime = "2.1.0" # change to 1.2.0 when it is released https://github.com/frewsxcv/rust-dark-light/issues/38 dark-light = { git = "https://github.com/frewsxcv/rust-dark-light", rev = "3eb3e93dd0fa30733c3e93082dd9517fb580ae95" } diff --git a/book/src/configuration/file_transfer.md b/book/src/configuration/file_transfer.md index fea2e8316..69618b597 100644 --- a/book/src/configuration/file_transfer.md +++ b/book/src/configuration/file_transfer.md @@ -4,15 +4,15 @@ File transfer configuration options. ## `save_directory` -Default directory to open when prompted to save a file. +Default directory to save files in. If not set, user will see a file dialog. ```toml # Type: string # Values: any string -# Default: "$HOME/Downloads" +# Default: not set [file_transfer] -save_directory = "$HOME/Downloads" +save_directory = "/Users/halloy/Downloads" ``` ## `passive` diff --git a/data/src/config/file_transfer.rs b/data/src/config/file_transfer.rs index 72d51a079..6a97527a4 100644 --- a/data/src/config/file_transfer.rs +++ b/data/src/config/file_transfer.rs @@ -4,9 +4,9 @@ use serde::Deserialize; #[derive(Debug, Clone, Deserialize)] pub struct FileTransfer { - /// Directory opened when prompted to save a file - #[serde(default = "default_save_directory")] - pub save_directory: PathBuf, + /// Default directory to save files in. If not set, user will see a file dialog. + #[serde(default)] + pub save_directory: Option, /// If true, act as the "client" for the transfer. Requires the remote user act as the server. #[serde(default = "default_passive")] pub passive: bool, @@ -19,7 +19,7 @@ pub struct FileTransfer { impl Default for FileTransfer { fn default() -> Self { Self { - save_directory: default_save_directory(), + save_directory: None, passive: default_passive(), timeout: default_timeout(), server: None, diff --git a/src/buffer/file_transfers.rs b/src/buffer/file_transfers.rs index aa71a8dce..72a8fdde2 100644 --- a/src/buffer/file_transfers.rs +++ b/src/buffer/file_transfers.rs @@ -70,18 +70,27 @@ impl FileTransfers { match message { Message::Approve(id) => { if let Some(transfer) = file_transfers.get(&id).cloned() { - let save_directory = config.file_transfer.save_directory.clone(); - return Task::perform( - async move { - rfd::AsyncFileDialog::new() - .set_directory(save_directory) - .set_file_name(transfer.filename) - .save_file() - .await - .map(|handle| handle.path().to_path_buf()) - }, - move |path| Message::SavePathSelected(id, path), - ); + match &config.file_transfer.save_directory { + Some(save_directory) => { + let file_save_directory = save_directory.join(transfer.filename); + return Task::done(Message::SavePathSelected( + id, + Some(file_save_directory), + )); + } + None => { + return Task::perform( + async move { + rfd::AsyncFileDialog::new() + .set_file_name(transfer.filename) + .save_file() + .await + .map(|handle| handle.path().to_path_buf()) + }, + move |path| Message::SavePathSelected(id, path), + ) + } + } } } Message::SavePathSelected(id, path) => { @@ -99,6 +108,8 @@ impl FileTransfers { } mod transfer_row { + use std::time::Duration; + use super::Message; use bytesize::ByteSize; use data::file_transfer::{self, FileTransfer}; @@ -160,13 +171,25 @@ mod transfer_row { transferred, elapsed, } => { - let transfer_speed = if elapsed.as_secs() == 0 { + let transfer_speed_and_remaining_time = if elapsed.as_secs() == 0 { String::default() } else { let bytes_per_second = *transferred / elapsed.as_secs(); let transfer_speed = ByteSize::b(bytes_per_second); - format!("({transfer_speed}/s)") + let remaining_bytes = transfer.size.saturating_sub(*transferred); + let remaining_time = if bytes_per_second > 0 { + let estimated_seconds = remaining_bytes / bytes_per_second; + let readable_time_left = + humantime::format_duration(Duration::from_secs(estimated_seconds)) + .to_string(); + + format!("| {readable_time_left}") + } else { + String::default() + }; + + format!("({transfer_speed}/s) {remaining_time}") }; let transferred = ByteSize::b(*transferred); @@ -178,8 +201,10 @@ mod transfer_row { container( column![ - text(format!("{transferred} of {file_size} {transfer_speed}")) - .style(theme::text::secondary), + text(format!( + "{transferred} of {file_size} {transfer_speed_and_remaining_time}" + )) + .style(theme::text::secondary), progress_bar ] .spacing(0), diff --git a/src/screen/dashboard.rs b/src/screen/dashboard.rs index e4c410622..f477fd883 100644 --- a/src/screen/dashboard.rs +++ b/src/screen/dashboard.rs @@ -302,16 +302,12 @@ impl Dashboard { ); } buffer::user_context::Event::SendFile(server, nick) => { - let starting_directory = - config.file_transfer.save_directory.clone(); - return ( Task::batch(vec![ task, Task::perform( async move { rfd::AsyncFileDialog::new() - .set_directory(starting_directory) .pick_file() .await .map(|handle| { @@ -737,11 +733,11 @@ impl Dashboard { command_bar::Configuration::OpenCacheDirectory => { let _ = open::that_detached(environment::cache_dir()); (Task::none(), None) - }, + } command_bar::Configuration::OpenDataDirectory => { let _ = open::that_detached(environment::data_dir()); (Task::none(), None) - }, + } command_bar::Configuration::OpenWebsite => { let _ = open::that_detached(environment::WIKI_WEBSITE); (Task::none(), None) @@ -774,7 +770,9 @@ impl Dashboard { } }, command_bar::Command::Window(command) => match command { - command_bar::Window::ToggleFullscreen => (window::toggle_fullscreen(), None), + command_bar::Window::ToggleFullscreen => { + (window::toggle_fullscreen(), None) + } }, }; @@ -951,9 +949,7 @@ impl Dashboard { None, ); } - ToggleFullscreen => { - return (window::toggle_fullscreen(), None) - }, + ToggleFullscreen => return (window::toggle_fullscreen(), None), } } Message::FileTransfer(update) => { From aa02b9c24862198b6bfa6345959c3b66cd1d699a Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Sat, 22 Feb 2025 11:34:32 +0100 Subject: [PATCH 2/2] clippy --- CHANGELOG.md | 8 ++++++++ data/src/config/file_transfer.rs | 4 ---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 429870306..2055f3fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Unreleased +Added: + +- Time remaining is now displayed during file transfers + +Changed: + +- [file_transfer.save_directory] is now default download path for transfers. If set, files will be downloaded there by default. Otherwise, you'll be prompted to choose a location. + # 2025.2 (2025-02-20) Added: diff --git a/data/src/config/file_transfer.rs b/data/src/config/file_transfer.rs index 6a97527a4..310dce9f0 100644 --- a/data/src/config/file_transfer.rs +++ b/data/src/config/file_transfer.rs @@ -35,10 +35,6 @@ fn default_timeout() -> u64 { 60 * 5 } -fn default_save_directory() -> PathBuf { - dirs_next::download_dir().unwrap_or(PathBuf::from("/tmp/")) -} - #[derive(Debug, Clone)] pub struct Server { /// Address advertised to the remote user to connect to