pinakes: import in parallel; various UI improvements

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I1eb47cd79cd4145c56af966f6756fe1d6a6a6964
This commit is contained in:
raf 2026-02-03 10:31:20 +03:00
commit 116fe7b059
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
42 changed files with 4316 additions and 316 deletions

View file

@ -8,7 +8,7 @@ use super::{format_duration, format_size, media_type_color};
use crate::app::AppState;
pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
let header = Row::new(vec!["Title / Name", "Type", "Duration", "Year", "Size"]).style(
let header = Row::new(vec!["", "Title / Name", "Type", "Duration", "Year", "Size"]).style(
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
@ -19,12 +19,27 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
.iter()
.enumerate()
.map(|(i, item)| {
let style = if Some(i) == state.selected_index {
let is_cursor = Some(i) == state.selected_index;
let is_selected = state.selected_items.contains(&item.id);
let style = if is_cursor {
Style::default().fg(Color::Black).bg(Color::Cyan)
} else if is_selected {
Style::default().fg(Color::Black).bg(Color::Green)
} else {
Style::default()
};
// Selection marker
let marker = if is_selected { "[*]" } else { "[ ]" };
let marker_style = if is_selected {
Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::DarkGray)
};
let display_name = item.title.as_deref().unwrap_or(&item.file_name).to_string();
let type_color = media_type_color(&item.media_type);
@ -44,6 +59,7 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
.unwrap_or_else(|| "-".to_string());
Row::new(vec![
Cell::from(Span::styled(marker, marker_style)),
Cell::from(display_name),
type_cell,
Cell::from(duration),
@ -56,16 +72,22 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
let page = (state.page_offset / state.page_size) + 1;
let item_count = state.media_list.len();
let title = format!(" Library (page {page}, {item_count} items) ");
let selected_count = state.selected_items.len();
let title = if selected_count > 0 {
format!(" Library (page {page}, {item_count} items, {selected_count} selected) ")
} else {
format!(" Library (page {page}, {item_count} items) ")
};
let table = Table::new(
rows,
[
Constraint::Percentage(35),
Constraint::Percentage(20),
Constraint::Percentage(15),
Constraint::Percentage(10),
Constraint::Percentage(20),
Constraint::Length(3), // Selection marker
Constraint::Percentage(33), // Title
Constraint::Percentage(18), // Type
Constraint::Percentage(13), // Duration
Constraint::Percentage(8), // Year
Constraint::Percentage(18), // Size
],
)
.header(header)

View file

@ -28,7 +28,7 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
f.render_widget(input, chunks[0]);
// Results
let header = Row::new(vec!["Name", "Type", "Artist", "Size"]).style(
let header = Row::new(vec!["", "Name", "Type", "Artist", "Size"]).style(
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
@ -39,12 +39,27 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
.iter()
.enumerate()
.map(|(i, item)| {
let style = if Some(i) == state.search_selected {
let is_cursor = Some(i) == state.search_selected;
let is_selected = state.selected_items.contains(&item.id);
let style = if is_cursor {
Style::default().fg(Color::Black).bg(Color::Cyan)
} else if is_selected {
Style::default().fg(Color::Black).bg(Color::Green)
} else {
Style::default()
};
// Selection marker
let marker = if is_selected { "[*]" } else { "[ ]" };
let marker_style = if is_selected {
Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::DarkGray)
};
let type_color = media_type_color(&item.media_type);
let type_cell = Cell::from(Span::styled(
item.media_type.clone(),
@ -52,6 +67,7 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
));
Row::new(vec![
Cell::from(Span::styled(marker, marker_style)),
Cell::from(item.file_name.clone()),
type_cell,
Cell::from(item.artist.clone().unwrap_or_default()),
@ -63,15 +79,21 @@ pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
let shown = state.search_results.len();
let total = state.search_total_count;
let results_title = format!(" Results: {shown} shown, {total} total ");
let selected_count = state.selected_items.len();
let results_title = if selected_count > 0 {
format!(" Results: {shown} shown, {total} total, {selected_count} selected ")
} else {
format!(" Results: {shown} shown, {total} total ")
};
let table = Table::new(
rows,
[
Constraint::Percentage(35),
Constraint::Percentage(20),
Constraint::Percentage(25),
Constraint::Percentage(20),
Constraint::Length(3), // Selection marker
Constraint::Percentage(33), // Name
Constraint::Percentage(18), // Type
Constraint::Percentage(23), // Artist
Constraint::Percentage(18), // Size
],
)
.header(header)