use crate::app::{App, ViewMode};
use crate::progress::ProgressStore;
use crossterm::event::{KeyCode, KeyEvent};
use ratatui_image::picker::Picker;
use std::error::Error;
pub enum Action {
None,
Exit,
SwitchBook(String),
}
pub fn handle_key_event(
app: &mut App,
key: KeyEvent,
picker: &mut Picker,
) -> Result<Action, Box<dyn Error>> {
match app.mode {
ViewMode::Library => match key.code {
KeyCode::Char('q') => return Ok(Action::Exit),
KeyCode::Esc | KeyCode::Char('l') => app.mode = ViewMode::Reading,
KeyCode::Enter => {
if let Some(path) = app.select_book() {
return Ok(Action::SwitchBook(path));
}
}
KeyCode::Down | KeyCode::Char('j') if !app.library_books.is_empty() => {
let i = app.library_state.selected().unwrap_or(0);
let new_index = (i + 1) % app.library_books.len();
app.library_state.select(Some(new_index));
app.update_library_cover(picker);
}
KeyCode::PageDown if !app.library_books.is_empty() => {
let i = app.library_state.selected().unwrap_or(0);
let new_index = (i + 5) % app.library_books.len();
app.library_state.select(Some(new_index));
app.update_library_cover(picker);
}
KeyCode::Up | KeyCode::Char('k') if !app.library_books.is_empty() => {
let i = app.library_state.selected().unwrap_or(0);
let new_index = (i + app.library_books.len() - 1) % app.library_books.len();
app.library_state.select(Some(new_index));
app.update_library_cover(picker);
}
KeyCode::PageUp if !app.library_books.is_empty() => {
let i = app.library_state.selected().unwrap_or(0);
let new_index = (i + app.library_books.len() - 5) % app.library_books.len();
app.library_state.select(Some(new_index));
app.update_library_cover(picker);
}
KeyCode::Char('d') => {
let i = app.library_state.selected().unwrap_or(0);
let mut store = ProgressStore::load(app.profile_dir.as_ref().map(|p| {
let mut p = p.clone();
p.push("progress.json");
p
}));
app.delete_book(i, &mut store);
if !app.library_books.is_empty() {
if i < app.library_books.len() {
app.library_state.select(Some(i));
app.update_library_cover(picker);
} else {
app.library_state.select(Some(0));
app.update_library_cover(picker);
}
}
}
KeyCode::Char('s') => app.next_sort_criteria(picker),
KeyCode::Char('S') => app.toggle_sort(picker),
_ => {}
},
ViewMode::BookmarkBrowser => match key.code {
KeyCode::Char('q') => return Ok(Action::Exit),
KeyCode::Esc | KeyCode::Char('b') => app.mode = ViewMode::Reading,
KeyCode::Enter => app.jump_to_bookmark(),
KeyCode::Down | KeyCode::Char('j') => {
if !app.bookmarks.is_empty() {
let i = app.bookmark_list_state.selected().unwrap_or(0);
let new_index = (i + 1) % app.bookmarks.len();
app.bookmark_list_state.select(Some(new_index));
}
}
KeyCode::Up | KeyCode::Char('k') => {
if !app.bookmarks.is_empty() {
let i = app.bookmark_list_state.selected().unwrap_or(0);
let new_index = (i + app.bookmarks.len() - 1) % app.bookmarks.len();
app.bookmark_list_state.select(Some(new_index));
}
}
KeyCode::Char('d') => app.remove_bookmark(),
KeyCode::Char('r') => app.start_renaming_bookmark(),
_ => {}
},
ViewMode::BookmarkRenaming => match key.code {
KeyCode::Enter => app.finish_renaming_bookmark(),
KeyCode::Esc => app.mode = ViewMode::BookmarkBrowser,
KeyCode::Char(c) => {
app.bookmark_rename_input
.insert(app.bookmark_rename_cursor_position, c);
app.bookmark_rename_cursor_position += 1;
}
KeyCode::Backspace => {
if app.bookmark_rename_cursor_position > 0 {
app.bookmark_rename_input
.remove(app.bookmark_rename_cursor_position - 1);
app.bookmark_rename_cursor_position -= 1;
}
}
KeyCode::Delete => {
if app.bookmark_rename_cursor_position < app.bookmark_rename_input.len() {
app.bookmark_rename_input
.remove(app.bookmark_rename_cursor_position);
}
}
KeyCode::Left => {
app.bookmark_rename_cursor_position =
app.bookmark_rename_cursor_position.saturating_sub(1);
}
KeyCode::Right => {
app.bookmark_rename_cursor_position = (app.bookmark_rename_cursor_position + 1)
.min(app.bookmark_rename_input.len());
}
KeyCode::Home => app.bookmark_rename_cursor_position = 0,
KeyCode::End => app.bookmark_rename_cursor_position = app.bookmark_rename_input.len(),
_ => {}
},
ViewMode::ChapterBrowser => match key.code {
KeyCode::Char('q') => return Ok(Action::Exit),
KeyCode::Esc | KeyCode::Tab => app.mode = ViewMode::Reading,
KeyCode::Enter => {
if let Some(selected) = app.chapter_list_state.selected() {
let visible_indices = app.get_visible_chapter_indices();
if let Some(&real_index) = visible_indices.get(selected) {
app.jump_to_chapter(real_index);
}
}
}
KeyCode::Down | KeyCode::Char('j') => {
let i = app.chapter_list_state.selected().unwrap_or(0);
let visible_indices = app.get_visible_chapter_indices();
if i + 1 < visible_indices.len() {
app.chapter_list_state.select(Some(i + 1));
}
}
KeyCode::PageDown => {
let i = app.chapter_list_state.selected().unwrap_or(0);
let visible_indices = app.get_visible_chapter_indices();
if i + 5 < visible_indices.len() {
app.chapter_list_state.select(Some(i + 5));
} else {
app.chapter_list_state
.select(Some(visible_indices.len().saturating_sub(1)));
}
}
KeyCode::Up | KeyCode::Char('k') => {
let i = app.chapter_list_state.selected().unwrap_or(0);
if i > 0 {
app.chapter_list_state.select(Some(i - 1));
}
}
KeyCode::PageUp => {
let i = app.chapter_list_state.selected().unwrap_or(0);
if i > 5 {
app.chapter_list_state.select(Some(i - 5));
} else {
app.chapter_list_state.select(Some(0));
}
}
KeyCode::Right | KeyCode::Char('l') => {
app.expand_chapter();
}
KeyCode::Left | KeyCode::Char('h') => {
app.collapse_chapter();
}
_ => {}
},
_ => match key.code {
KeyCode::Char('q') => return Ok(Action::Exit),
KeyCode::Right | KeyCode::Char('n') => {
if app.config.view_type == "book" {
app.next_page(2);
} else {
app.next_chapter();
}
}
KeyCode::Left | KeyCode::Char('p') => {
if app.config.view_type == "book" {
app.prev_page(2);
} else {
app.previous_chapter();
}
}
KeyCode::Home => app.go_to_start(),
KeyCode::End => app.go_to_end(),
KeyCode::Down | KeyCode::Char('j') => {
if app.config.view_type != "book" {
app.scroll_down(1);
}
if app.config.view_type == "book" {
app.next_page(1);
}
}
KeyCode::PageDown => app.next_page(2),
KeyCode::Up | KeyCode::Char('k') => {
if app.config.view_type != "book" {
app.scroll_up(1);
}
if app.config.view_type == "book" {
app.prev_page(1);
}
}
KeyCode::PageUp => app.prev_page(1),
KeyCode::Char('c') => app.toggle_mode(),
KeyCode::Char('v') => {
app.config.view_type = match app.config.view_type.as_str() {
"default" => "book".to_string(),
"book" => "continuous".to_string(),
_ => "default".to_string(),
};
}
KeyCode::Char('l') => app.open_library(picker),
KeyCode::Char('b') => app.open_bookmark_browser(),
KeyCode::Char('m') => app.add_bookmark(),
KeyCode::Tab => app.open_chapter_browser(),
_ => {}
},
}
Ok(Action::None)
}