feat(tui): folder jumps, open-all and a path filter in the browse popup

A browsed share only moved a row at a time, so a folder of a few
hundred files stood between the user and the next folder. J and K now
jump between folder rows, H and L close or open every folder, and /
filters the whole tree by path the way the results and the room list
filter: type to narrow, Enter keeps it, Esc clears it, then hides. A
folder under a filter shows the paths that match and d downloads just
those. The keys popup gains a browse section and the bar lists them.
This commit is contained in:
Michel de Graaf
2026-09-08 11:24:41 +02:00
parent 0931bb01b4
commit b8da8668b4
7 changed files with 430 additions and 65 deletions
+22 -1
View File
@@ -62,8 +62,20 @@ fn render_browse_one(
spinner_state: usize,
) {
let title = match browse.status {
BrowseStatus::Loaded
if browse.filtering || !browse.filter().is_empty() =>
{
format!(
" Browse {} — {} files, {} folders · filter: {}{} (Enter: keep, Esc: clear) ",
browse.username,
browse.file_count,
browse.folder_count,
browse.filter(),
if browse.filtering { "_" } else { "" }
)
}
BrowseStatus::Loaded => format!(
" Browse {} — {} files, {} folders (Enter/d: download, Tab: user, w: close, Esc: hide) ",
" Browse {} — {} files, {} folders (Enter/d: download, /: filter, Tab: user, w: close, Esc: hide) ",
browse.username, browse.file_count, browse.folder_count
),
_ => format!(" Browse {} ", browse.username),
@@ -105,6 +117,15 @@ fn render_browse_one(
];
frame.render_widget(Paragraph::new(text).block(block), area);
}
BrowseStatus::Loaded
if browse.rows().is_empty() && !browse.filter().is_empty() =>
{
let text = format!("Nothing here matches '{}'.", browse.filter());
frame.render_widget(
Paragraph::new(text).style(dimmed_style()).block(block),
area,
);
}
BrowseStatus::Loaded => {
let all = browse.rows();
let window = visible_range(