argv-todo 0.1.0

A Vim-style terminal todo manager with nested tasks, priorities, search, and local SQLite storage
use crate::app::App;
use ratatui::{
    Frame,
    layout::{Constraint, Layout, Margin},
    style::{Modifier, Style},
    widgets::{Block, Borders, Paragraph, Scrollbar, ScrollbarState},
};

use super::{
    super::{
        branding,
        layout::workspace,
        theme::{ACCENT, MUTED},
    },
    chrome::{draw_footer, draw_sections},
    content,
};

pub(in crate::ui) fn draw_help(frame: &mut Frame, app: &mut App) {
    let area = workspace(frame.area());
    let spacious = area.height >= 17;
    let [brand, _, title, _, body, footer] = Layout::vertical([
        Constraint::Length(branding::height(area)),
        Constraint::Length(u16::from(spacious)),
        Constraint::Length(1),
        Constraint::Length(u16::from(spacious)),
        Constraint::Min(0),
        Constraint::Length(2),
    ])
    .areas(area);
    branding::draw(frame, brand);
    frame.render_widget(
        Paragraph::new(if title.width >= 18 {
            "Keyboard shortcuts"
        } else {
            "Help"
        })
        .style(Style::default().add_modifier(Modifier::BOLD)),
        title,
    );
    let (sections, content_area) = if body.width >= 70 && body.height >= 9 {
        let [sections, _, details] = Layout::horizontal([
            Constraint::Length(30),
            Constraint::Length(2),
            Constraint::Min(0),
        ])
        .areas(body);
        let divider = Block::default()
            .borders(Borders::LEFT)
            .border_style(Style::default().fg(MUTED));
        let inner = divider.inner(details).inner(Margin {
            horizontal: 1,
            vertical: 0,
        });
        frame.render_widget(divider, details);
        (Some(sections), inner)
    } else {
        (None, body)
    };
    let [shortcuts, scrollbar_area] = Layout::horizontal([
        Constraint::Min(0),
        Constraint::Length(u16::from(content_area.width > 1)),
    ])
    .areas(content_area);
    let document = content::document(shortcuts.width);
    app.help_view
        .set_sections(sections.map(|_| document.sections.len()));
    let range = if sections.is_some() {
        document.section_range(app.help_view.selected_section())
    } else {
        0..document.lines.len()
    };
    app.help_view.set_viewport(range.len(), shortcuts.height);
    if let Some(area) = sections {
        draw_sections(frame, &document, app, area);
    }
    if !shortcuts.is_empty() {
        frame.render_widget(
            Paragraph::new(
                document
                    .lines
                    .into_iter()
                    .skip(range.start)
                    .take(range.len())
                    .collect::<Vec<_>>(),
            )
            .scroll((app.help_view.offset(), 0)),
            shortcuts,
        );
        let mut scrollbar = ScrollbarState::new(app.help_view.total_rows())
            .position(usize::from(app.help_view.offset()))
            .viewport_content_length(usize::from(shortcuts.height));
        frame.render_stateful_widget(
            Scrollbar::default()
                .begin_symbol(None)
                .end_symbol(None)
                .track_style(Style::default().fg(MUTED))
                .thumb_style(Style::default().fg(ACCENT)),
            scrollbar_area,
            &mut scrollbar,
        );
    }
    draw_footer(frame, app, shortcuts.height, footer);
}