changxi 0.3.0

TUI EPUB Reader
use crate::app::{App, SortCriteria};
use crate::ui::{Component, centered_rect, get_border_type};
use ratatui::style::{Color, Style};
use ratatui::{
    Frame,
    layout::{Constraint, Direction, Layout, Margin, Rect},
    text::Text,
    widgets::{Block, Borders, List, ListItem, Paragraph},
};
use ratatui_image::{StatefulImage, picker::Picker};

pub struct LibraryView;

impl Component for LibraryView {
    fn render(&self, f: &mut Frame, area: Rect, app: &mut App, _picker: &mut Picker) {
        let area = centered_rect(80, 80, area);
        let layout = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
            .split(area);

        let border_type = get_border_type(&app.config);

        let mut list_items = Vec::new();
        for book in &app.library_books {
            let is_current = book.path == app.book_path;
            let prefix = if is_current { "" } else { "  " };
            let display_title = if book.title.is_empty() {
                "Unknown Title"
            } else {
                &book.title
            };
            let content = format!("{}{}", prefix, display_title);
            let mut text = Text::from(content);
            if is_current {
                text = text.style(Style::default().fg(Color::Green));
            }
            list_items.push(ListItem::new(text));
        }

        let sort_text = match app.sort_criteria {
            SortCriteria::Recent => "Recent",
            SortCriteria::Title => "Title",
            SortCriteria::Author => "Author",
        };

        let list = List::new(list_items)
            .block(
                Block::default()
                    .borders(Borders::ALL)
                    .border_type(border_type)
                    .title(format!(" Library (Sort: {}) ", sort_text)),
            )
            .highlight_style(Style::default().bg(Color::DarkGray))
            .highlight_symbol("> ");

        f.render_stateful_widget(list, layout[0], &mut app.library_state);

        let cover_block = Block::default()
            .borders(Borders::ALL)
            .border_type(border_type);
        let cover_area = layout[1];
        f.render_widget(cover_block.clone(), cover_area);

        if let Some(ref mut protocol) = app.library_cover_protocol {
            f.render_stateful_widget(
                StatefulImage::default(),
                cover_area.inner(Margin {
                    vertical: 1,
                    horizontal: 1,
                }),
                protocol,
            );
        } else {
            f.render_widget(
                Paragraph::new("No cover available"),
                cover_area.inner(Margin {
                    vertical: 1,
                    horizontal: 1,
                }),
            );
        }
    }
}