nyaa 0.9.1

A tui tool for browsing and downloading torrents from nyaa.si
Documentation
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
use ratatui::{
    layout::{Constraint, Direction, Layout, Margin, Rect},
    widgets::StatefulWidget as _,
    Frame,
};
use ratatui_image::{protocol::StatefulProtocol, StatefulImage};

use crate::app::{Context, LoadType, Mode};

use super::{input::InputWidget, Widget};

pub struct CaptchaPopup {
    pub image: Option<Box<dyn StatefulProtocol>>,
    pub input: InputWidget,
}

impl Default for CaptchaPopup {
    fn default() -> Self {
        Self {
            image: None,
            input: InputWidget::new(32, None),
        }
    }
}

impl Widget for CaptchaPopup {
    fn draw(&mut self, f: &mut Frame, ctx: &Context, area: Rect) {
        let center = area.inner(&Margin {
            horizontal: 4,
            vertical: 4,
        });
        super::clear(center, f.buffer_mut(), ctx.theme.bg);
        let layout = Layout::new(
            Direction::Vertical,
            [Constraint::Fill(1), Constraint::Length(3)],
        )
        .split(center);
        if let Some(img) = self.image.as_mut() {
            f.render_widget(
                super::border_block(&ctx.theme, true).title("Captcha"),
                layout[0],
            );
            StatefulImage::new(None).render(
                layout[0].inner(&Margin {
                    horizontal: 1,
                    vertical: 1,
                }),
                f.buffer_mut(),
                img,
            );
        }
        f.render_widget(
            super::border_block(&ctx.theme, true).title("Enter Captcha solution"),
            layout[1],
        );

        let input_area = layout[1].inner(&Margin {
            horizontal: 1,
            vertical: 1,
        });
        self.input.draw(f, ctx, input_area);
        self.input.show_cursor(f, input_area);
    }

    fn handle_event(&mut self, ctx: &mut Context, e: &Event) {
        if let Event::Key(KeyEvent {
            code,
            kind: KeyEventKind::Press,
            ..
        }) = e
        {
            match code {
                KeyCode::Esc => {
                    ctx.mode = Mode::Normal;
                }
                KeyCode::Enter => {
                    ctx.mode = Mode::Loading(LoadType::SolvingCaptcha(self.input.input.clone()));
                }
                _ => {}
            }
        }
        self.input.handle_event(ctx, e);
    }

    fn get_help() -> Option<Vec<(&'static str, &'static str)>> {
        Some(vec![
            ("Enter", "Confirm"),
            ("Esc, f, q", "Close"),
            ("g", "Top"),
            ("G", "Bottom"),
            ("j, ↓", "Down"),
            ("k, ↑", "Up"),
        ])
    }
}