diff --git a/soulseek-rs/src/ui/main_tui/downloads.rs b/soulseek-rs/src/ui/main_tui/downloads.rs
index 63b3239..8e650a0 100644
--- a/soulseek-rs/src/ui/main_tui/downloads.rs
+++ b/soulseek-rs/src/ui/main_tui/downloads.rs
@@ -89,6 +89,31 @@ impl MainTui {
}
}
+ /// Empty the whole transfer list: every live download is cancelled and
+ /// every row — live or finished — is forgotten by the session too, so a
+ /// shared queue empties for every window rather than only this one.
+ /// Uploads still streaming are cancelled; finished ones are the
+ /// session's history and refresh back from it regardless.
+ pub(super) fn clear_all_transfers(&mut self) {
+ for entry in &self.state.downloads {
+ let download = &entry.download;
+ if !download.is_finished() {
+ self.client
+ .cancel_download(&download.username, &download.filename);
+ }
+ self.client
+ .remove_download(&download.username, &download.filename);
+ }
+ for upload in &self.state.uploads {
+ if upload.status == UploadStatus::InProgress {
+ self.client
+ .cancel_upload(&upload.username, &upload.filename);
+ }
+ }
+ self.state.downloads.clear();
+ self.state.downloads_table_state.select(None);
+ }
+
pub(super) fn toggle_selected_download_pause(&self) {
let Some(index) = self.state.downloads_table_state.selected() else {
return;
diff --git a/soulseek-rs/src/ui/main_tui/input.rs b/soulseek-rs/src/ui/main_tui/input.rs
index 0bb26e1..84bdc5b 100644
--- a/soulseek-rs/src/ui/main_tui/input.rs
+++ b/soulseek-rs/src/ui/main_tui/input.rs
@@ -569,6 +569,9 @@ impl MainTui {
KeyCode::Char('c') => {
self.clear_finished_downloads();
}
+ KeyCode::Char('C') => {
+ self.clear_all_transfers();
+ }
_ => {}
}
}
diff --git a/soulseek-rs/src/ui/main_tui/mod.rs b/soulseek-rs/src/ui/main_tui/mod.rs
index f3544f7..5b35068 100644
--- a/soulseek-rs/src/ui/main_tui/mod.rs
+++ b/soulseek-rs/src/ui/main_tui/mod.rs
@@ -295,8 +295,9 @@ mod tests {
download_dir_set: std::sync::Mutex