trnovel 0.14.0

Terminal reader for novel
Documentation
use crossterm::event::{Event, KeyCode, KeyEventKind};
use ratatui::layout::Direction;
use ratatui_kit::{
    AnyElement, EventPriority, EventResult, EventScope, Hooks, State, UseContext, UseEventHandler,
    UseState, component, element, prelude::View,
};

mod import_book_source;
mod select_book_source;
use import_book_source::ImportBookSource;
use select_book_source::SelectBookSource;

use crate::book_source::BookSourceCache;
use crate::components::modal::shortcut_info_modal::ShortcutInfoModal;

#[component]
pub fn BookSourceManager(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
    let book_source_cache = *hooks.use_context::<State<Option<BookSourceCache>>>();

    let mut only_select = hooks.use_state(|| {
        book_source_cache
            .read()
            .as_ref()
            .is_some_and(|c| !c.book_sources.is_empty())
    });
    let mut info_modal_open = hooks.use_state(|| false);

    hooks.use_event_handler(EventScope::Current, EventPriority::Normal, move |event| {
        let Event::Key(key) = event else {
            return EventResult::Ignored;
        };
        if key.kind != KeyEventKind::Press {
            return EventResult::Ignored;
        }
        match key.code {
            KeyCode::Char('i') | KeyCode::Char('I') => {
                info_modal_open.set(!info_modal_open.get());
                EventResult::Consumed
            }
            KeyCode::Tab => {
                only_select.set(!only_select.get());
                EventResult::Consumed
            }
            // 反爬:开/关「浏览器辅助验证」总是允许(读 flag 翻转并持久化)。
            KeyCode::Char('b') | KeyCode::Char('B') => {
                let on = crate::browser_assist::always_allowed();
                let _ = crate::browser_assist::set_always_allowed(!on);
                EventResult::Consumed
            }
            _ => EventResult::Ignored,
        }
    });

    if only_select.get() {
        element!(View(
            flex_direction:Direction::Horizontal
        ){
            SelectBookSource(
                is_editing: !info_modal_open.get(),
            )
            ShortcutInfoModal(
                key_shortcut_info: vec![
                    ("切换导入书源模式", "Tab"),
                    ("删除书源", "D"),
                    ("书源登录(需登录的源)", "L"),
                    ("上下移动", "J / K / ↑ / ↓"),
                    ("选择书源", "Enter"),
                    ("浏览器辅助验证 开/关", "B"),
                ],
                open: info_modal_open.get(),
            )
        })
    } else {
        element!(View(
            flex_direction:Direction::Horizontal
        ){
            ImportBookSource(
                is_editing: !info_modal_open.get(),
            )
            SelectBookSource(
                is_editing: false,
            )
            ShortcutInfoModal(
                key_shortcut_info: vec![
                    ("切换仅选择模式", "Tab"),
                    ("输入书源地址", "S"),
                    ("选择/取消条目", "空格"),
                    ("确认导入/选择", "Enter"),
                    ("上下移动", "J / K / ↑ / ↓"),
                    ("浏览器辅助验证 开/关", "B"),
                ],
                open: info_modal_open.get(),
            )
        })
    }
}