perf(tui): flatten a browsed share once and draw one page of it
Moving through a browsed share felt laggy for the same reason the results did: the popup re-flattened the whole expanded tree on every frame, cloning every row's name and path, then built a table row for each, and every keypress flattened it twice more. A heavy sharer's tree runs to tens of thousands of rows once a few folders are open. The flattened rows now live on the browse state and are rebuilt only when a folder opens or closes, and the popup draws the visible page alone. In the harness a 30,000-row tree went from 11ms to 0.35ms a frame and a keypress from 2.7ms to under a microsecond. The downloads pane had the same shape (every transfer became a row each frame, and a select-all can queue ten thousand), so it takes the same page window, which now lives beside page_of for every pane to share.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use crate::models::{BrowseState, BrowseStatus, BrowseTabs};
|
||||
use crate::ui::{
|
||||
HIGHLIGHT_SYMBOL, body_style, dimmed_style, error_style, format_bytes,
|
||||
get_spinner_char, highlight_style, pane_block, primary_style,
|
||||
row_highlight_style, warning_style,
|
||||
get_spinner_char, highlight_style, page_of, pane_block, primary_style,
|
||||
row_highlight_style, visible_range, warning_style,
|
||||
};
|
||||
use ratatui::{
|
||||
Frame,
|
||||
@@ -106,8 +106,15 @@ fn render_browse_one(
|
||||
frame.render_widget(Paragraph::new(text).block(block), area);
|
||||
}
|
||||
BrowseStatus::Loaded => {
|
||||
let rows: Vec<Row> = browse
|
||||
.rows()
|
||||
let all = browse.rows();
|
||||
let window = visible_range(
|
||||
table_state.offset(),
|
||||
Some(browse.selected_row),
|
||||
all.len(),
|
||||
page_of(Some(area), 0),
|
||||
);
|
||||
let start = window.start;
|
||||
let rows: Vec<Row> = all[window]
|
||||
.iter()
|
||||
.map(|row| {
|
||||
let indent = " ".repeat(row.depth);
|
||||
@@ -142,8 +149,13 @@ fn render_browse_one(
|
||||
.highlight_spacing(HighlightSpacing::Always)
|
||||
.block(block);
|
||||
|
||||
table_state.select(Some(browse.selected_row));
|
||||
frame.render_stateful_widget(table, area, table_state);
|
||||
// The table holds one page, so the state it gets is shifted
|
||||
// onto it.
|
||||
let mut page_state = TableState::default().with_selected(Some(
|
||||
browse.selected_row.min(all.len().saturating_sub(1)) - start,
|
||||
));
|
||||
frame.render_stateful_widget(table, area, &mut page_state);
|
||||
*table_state.offset_mut() = start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user