feat: browse the highlighted transfer's user with b
In the Downloads / Uploads pane, b now opens the share of whoever owns the selected download or upload, the way it already browses the owner of a highlighted result. With no row selected it still prompts.
This commit is contained in:
@@ -206,6 +206,21 @@ impl MainTui {
|
|||||||
self.state.results_selected_indices.clear();
|
self.state.results_selected_indices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The user behind the highlighted transfer, download or upload.
|
||||||
|
pub(super) fn selected_transfer_user(&self) -> Option<String> {
|
||||||
|
match selected_transfer(
|
||||||
|
self.state.downloads_table_state.selected(),
|
||||||
|
&self.state.downloads,
|
||||||
|
&self.state.uploads,
|
||||||
|
) {
|
||||||
|
Some(InfoSubject::Download(entry)) => {
|
||||||
|
Some(entry.download.username.clone())
|
||||||
|
}
|
||||||
|
Some(InfoSubject::Upload(upload)) => Some(upload.username.clone()),
|
||||||
|
Some(InfoSubject::Result(_)) | None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn cancel_selected_transfer(&self) {
|
pub(super) fn cancel_selected_transfer(&self) {
|
||||||
let selected = selected_transfer(
|
let selected = selected_transfer(
|
||||||
self.state.downloads_table_state.selected(),
|
self.state.downloads_table_state.selected(),
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ impl MainTui {
|
|||||||
&& let Some(owner) = self.highlighted_result_owner()
|
&& let Some(owner) = self.highlighted_result_owner()
|
||||||
{
|
{
|
||||||
self.start_browse(owner);
|
self.start_browse(owner);
|
||||||
|
} else if self.state.focused_pane == FocusedPane::Downloads
|
||||||
|
&& let Some(user) = self.selected_transfer_user()
|
||||||
|
{
|
||||||
|
self.start_browse(user);
|
||||||
} else {
|
} else {
|
||||||
self.state.command_bar_active = true;
|
self.state.command_bar_active = true;
|
||||||
self.state.command_bar_mode = CommandBarMode::Browse;
|
self.state.command_bar_mode = CommandBarMode::Browse;
|
||||||
|
|||||||
@@ -310,6 +310,20 @@ mod tests {
|
|||||||
at_status(username, filename, soulseek_rs::DownloadStatus::Completed)
|
at_status(username, filename, soulseek_rs::DownloadStatus::Completed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn uploading(
|
||||||
|
username: &str,
|
||||||
|
filename: &str,
|
||||||
|
) -> soulseek_rs::types::UploadInfo {
|
||||||
|
soulseek_rs::types::UploadInfo {
|
||||||
|
username: username.to_string(),
|
||||||
|
filename: filename.to_string(),
|
||||||
|
size: 10,
|
||||||
|
bytes_sent: 1,
|
||||||
|
speed_bytes_per_sec: 1.0,
|
||||||
|
status: soulseek_rs::types::UploadStatus::InProgress,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn at_status(
|
fn at_status(
|
||||||
username: &str,
|
username: &str,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
@@ -654,14 +668,7 @@ mod tests {
|
|||||||
download: queued("bob", "song.mp3"),
|
download: queued("bob", "song.mp3"),
|
||||||
receiver: None,
|
receiver: None,
|
||||||
});
|
});
|
||||||
tui.state.uploads.push(soulseek_rs::types::UploadInfo {
|
tui.state.uploads.push(uploading("alice", "served.mp3"));
|
||||||
username: "alice".to_string(),
|
|
||||||
filename: "served.mp3".to_string(),
|
|
||||||
size: 10,
|
|
||||||
bytes_sent: 1,
|
|
||||||
speed_bytes_per_sec: 1.0,
|
|
||||||
status: soulseek_rs::types::UploadStatus::InProgress,
|
|
||||||
});
|
|
||||||
tui.state.downloads_table_state.select(Some(1));
|
tui.state.downloads_table_state.select(Some(1));
|
||||||
tui.state.focused_pane = FocusedPane::Downloads;
|
tui.state.focused_pane = FocusedPane::Downloads;
|
||||||
|
|
||||||
@@ -677,6 +684,45 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn b_browses_the_user_of_the_highlighted_download() {
|
||||||
|
let mut tui = with_session(TalkativeSession::default());
|
||||||
|
tui.state.downloads.push(crate::models::DownloadEntry {
|
||||||
|
download: queued("bob", "song.mp3"),
|
||||||
|
receiver: None,
|
||||||
|
});
|
||||||
|
tui.state.downloads_table_state.select(Some(0));
|
||||||
|
tui.state.focused_pane = FocusedPane::Downloads;
|
||||||
|
|
||||||
|
tui.handle_key_event(key('b'));
|
||||||
|
|
||||||
|
assert!(tui.state.show_browse, "the browse popup opens");
|
||||||
|
assert_eq!(
|
||||||
|
tui.state.browse.active_tab().map(|b| b.username.as_str()),
|
||||||
|
Some("bob"),
|
||||||
|
"the download's user is the one browsed"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!tui.state.command_bar_active,
|
||||||
|
"b on a transfer goes straight to the user, not the prompt"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn b_on_an_upload_row_browses_that_user() {
|
||||||
|
let mut tui = with_session(TalkativeSession::default());
|
||||||
|
tui.state.uploads.push(uploading("alice", "served.mp3"));
|
||||||
|
tui.state.downloads_table_state.select(Some(0));
|
||||||
|
tui.state.focused_pane = FocusedPane::Downloads;
|
||||||
|
|
||||||
|
tui.handle_key_event(key('b'));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
tui.state.browse.active_tab().map(|b| b.username.as_str()),
|
||||||
|
Some("alice")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn with_session(session: TalkativeSession) -> MainTui {
|
fn with_session(session: TalkativeSession) -> MainTui {
|
||||||
attach(Arc::new(session))
|
attach(Arc::new(session))
|
||||||
}
|
}
|
||||||
@@ -1591,9 +1637,11 @@ mod tests {
|
|||||||
let screen = screen_sized(&mut tui, 80, 24);
|
let screen = screen_sized(&mut tui, 80, 24);
|
||||||
assert!(screen.contains("Tab / Shift-Tab"), "{screen}");
|
assert!(screen.contains("Tab / Shift-Tab"), "{screen}");
|
||||||
|
|
||||||
// A wide window shows both columns at once, nothing to scroll.
|
// A wide window shows both columns at once, nothing to scroll. It
|
||||||
|
// has to be tall enough to hold the taller column outright; in a
|
||||||
|
// shorter one End follows the tail and the headings scroll off.
|
||||||
press(&mut tui, KeyCode::End);
|
press(&mut tui, KeyCode::End);
|
||||||
let screen = screen_of(&mut tui);
|
let screen = screen_sized(&mut tui, 160, 44);
|
||||||
let panes = row_with(&screen, "Panes");
|
let panes = row_with(&screen, "Panes");
|
||||||
assert!(panes.contains("Searches"), "two columns: {panes}");
|
assert!(panes.contains("Searches"), "two columns: {panes}");
|
||||||
assert!(screen.contains("Tab / Shift-Tab"), "{screen}");
|
assert!(screen.contains("Tab / Shift-Tab"), "{screen}");
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ const HELP_RIGHT: &[(&str, &[(&str, &str)])] = &[
|
|||||||
("r", "retry a failed one"),
|
("r", "retry a failed one"),
|
||||||
("d", "delete a queued or finished one"),
|
("d", "delete a queued or finished one"),
|
||||||
("c", "clear every finished one"),
|
("c", "clear every finished one"),
|
||||||
|
("b", "browse that user"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|||||||
Reference in New Issue
Block a user