tano-tui 0.1.1

Tano terminal user interface
Documentation
use ratatui::{
    Frame,
    layout::Alignment,
    widgets::{Block, BorderType, List, Paragraph},
};
use tano_config::pages::album::AlbumPage;
use tano_database::{album::Album, artist::Artist, song::Song};

use crate::utils::{layout_cache::update_list_area, list_state::ListState, load_state::LoadState};

#[derive(Debug, Clone)]
pub struct AlbumProps {
    pub album_id: i64,
    pub config: AlbumPage,
    pub data: LoadState<(Album, Vec<Artist>, ListState<Song>)>,
}

pub struct AlbumComponent {}

impl AlbumComponent {
    pub fn render(frame: &mut Frame, props: &AlbumProps) {
        let block = Block::bordered().border_type(BorderType::Rounded);

        let (album, artists, songs) = match &props.data {
            LoadState::Loaded((album, artists, songs)) => (album, artists, songs),
            LoadState::Loading => {
                let loading_widget = Paragraph::new("Loading...")
                    .alignment(Alignment::Center)
                    .block(block);

                frame.render_widget(loading_widget, frame.area());
                return;
            }
        };

        let artist_names: Vec<_> = artists.iter().map(|artist| artist.name.clone()).collect();
        let artist_str = match (props.config.hide_artists, artist_names.is_empty()) {
            (false, false) => format!(" by {}", artist_names.join(", ")),
            _ => String::new(),
        };

        let title = format!("{}{}", album.title.as_str(), artist_str);

        let block = block.title(title.as_str());

        update_list_area(block.inner(frame.area()));

        let items = songs.to_list_items(|song| {
            let track_prefix = if props.config.hide_track_numbers {
                String::new()
            } else {
                match song.track_number {
                    Some(track_number) => format!("{:02} - ", track_number),
                    None => String::new(),
                }
            };

            format!("{}{}", track_prefix, song.title)
        });

        let list = List::new(items).block(block);

        frame.render_widget(list, frame.area());
    }
}