Added filter. Improved UI. Fixed settings window

This commit is contained in:
Ultradesu
2026-07-23 19:43:47 +03:00
parent 6dbfc83bf6
commit 7fe6ddfe05
13 changed files with 397 additions and 33 deletions
+17
View File
@@ -193,6 +193,16 @@ fn status_line(label: &str, value: String) -> Line<'static> {
])
}
fn bytes_label(bytes: u64) -> String {
if bytes >= 1024 * 1024 {
format!("{bytes} B ({:.1} MiB)", bytes as f64 / 1024.0 / 1024.0)
} else if bytes >= 1024 {
format!("{bytes} B ({:.1} KiB)", bytes as f64 / 1024.0)
} else {
format!("{bytes} B")
}
}
fn short_id(id: &str) -> String {
id.chars().take(12).collect::<String>() + ""
}
@@ -240,6 +250,13 @@ fn draw_status(frame: &mut Frame, area: Rect, state: &AppState) {
.map(|count| count.to_string())
.unwrap_or_else(|| "unavailable".to_string()),
));
lines.push(status_line(
"Stored DHT bytes",
status
.stored_dht_bytes
.map(bytes_label)
.unwrap_or_else(|| "unavailable".to_string()),
));
lines.push(status_line(
"Published items",
status.published_items.to_string(),
+15 -9
View File
@@ -36,10 +36,11 @@ fn error_style() -> Style {
}
fn bordered(frame: &mut Frame, area: Rect, title: String) -> Rect {
let block = Block::bordered()
.title(title)
.title_style(theme::header())
.border_style(theme::dim());
bordered_line(frame, area, Line::styled(title, theme::header()))
}
fn bordered_line(frame: &mut Frame, area: Rect, title: Line<'static>) -> Rect {
let block = Block::bordered().title(title).border_style(theme::dim());
let inner = block.inner(area);
frame.render_widget(block, area);
inner
@@ -271,11 +272,16 @@ fn scroll_offset(items: &[PlanItem], cursor_item: Option<usize>, viewport: u16)
fn draw_grid(frame: &mut Frame, area: Rect, state: &AppState) {
let global = &state.global;
let title = if global.total > 0 {
format!(" Global{} artists ", global.total)
format!(" Library{} artists ", global.total)
} else {
" Global ".to_string()
" Library ".to_string()
};
let inner = bordered(frame, area, title);
let mut title_spans = vec![Span::styled(title, theme::tab_active())];
if global.filters.is_active() {
title_spans.push(Span::raw(" "));
title_spans.push(Span::styled(" FILTERED ", theme::tab_active()));
}
let inner = bordered_line(frame, area, Line::from(title_spans));
if global.artists.is_empty() {
let message = if let Some(error) = &global.error {
@@ -373,7 +379,7 @@ fn draw_artist(frame: &mut Frame, area: Rect, state: &AppState, id: i64, cursor:
Some(Loadable::Ready(detail)) => detail.name.clone(),
_ => "Artist".to_string(),
};
let inner = bordered(frame, area, format!(" Global{name} "));
let inner = bordered(frame, area, format!(" Library{name} "));
let detail = match loadable {
Some(Loadable::Ready(detail)) => detail,
@@ -640,7 +646,7 @@ fn draw_release(frame: &mut Frame, area: Rect, state: &AppState, id: i64, cursor
Some(Loadable::Ready(detail)) => detail.title.clone(),
_ => "Release".to_string(),
};
let inner = bordered(frame, area, format!(" Global{title} "));
let inner = bordered(frame, area, format!(" Library{title} "));
let detail = match loadable {
Some(Loadable::Ready(detail)) => detail,
+44
View File
@@ -21,6 +21,7 @@ pub fn draw(frame: &mut Frame, state: &AppState) {
..
}) => draw_edit(frame, title, fields, *focus, error.as_deref()),
Some(Popup::ConfirmDelete { label, .. }) => draw_confirm_delete(frame, label),
Some(Popup::LibraryFilters { cursor }) => draw_library_filters(frame, state, *cursor),
Some(Popup::TrackInfo {
tracks,
cursor,
@@ -39,6 +40,49 @@ pub fn draw(frame: &mut Frame, state: &AppState) {
}
}
fn draw_library_filters(frame: &mut Frame, state: &AppState, cursor: usize) {
let area = centered(frame.area(), 46, 6);
let block = Block::bordered()
.title(" Library filters ")
.title_style(theme::header())
.border_style(theme::accent());
let inner = block.inner(area);
frame.render_widget(Clear, area);
frame.render_widget(block, area);
let [list_area, _, footer] = Layout::vertical([
Constraint::Length(1),
Constraint::Length(1),
Constraint::Length(1),
])
.areas(inner);
let checked = if state.global.filters.hide_featured_only {
"[x]"
} else {
"[ ]"
};
let row = Rect {
height: 1,
..list_area
};
frame.render_widget(
Paragraph::new(Line::from(vec![
Span::styled(format!("{checked} "), theme::accent()),
Span::raw("Hide featured only"),
])),
row,
);
if cursor == 0 {
frame.buffer_mut().set_style(row, theme::tab_active());
}
frame.render_widget(
Paragraph::new(Line::styled("space/enter toggle · esc close", theme::dim()))
.alignment(Alignment::Center),
footer,
);
}
/// One-line text entry on the Federation tab (network id / peer ticket).
fn draw_fed_input(frame: &mut Frame, title: &str, input: &crate::app::input::LineEdit) {
let area = centered(frame.area(), 64, 5);