use anyhow::Result;
use ratatui::{Frame, layout::Rect, style::Style};
use crate::{
app_state::AppState,
utils::{AppMode, FileItem},
};
pub mod history;
pub mod normal;
pub mod preview;
pub trait Renderer {
fn render(&self, f: &mut Frame, area: Rect, state: &AppState);
}
#[derive(Debug, Clone, PartialEq)]
pub enum ModeAction {
Stay,
Switch(AppMode),
Exit(Option<FileItem>),
}
pub trait ModeHandler {
fn render_left_panel(&self, f: &mut Frame, area: Rect, state: &AppState);
fn render_right_panel(&self, f: &mut Frame, area: Rect, state: &AppState);
fn get_search_box_config(&self, state: &AppState) -> (String, String, Style);
fn should_show_help(&self, state: &AppState) -> bool;
fn on_enter(&mut self, _state: &mut AppState) -> Result<()> {
Ok(())
}
fn handle_key_event(&mut self, state: &mut AppState, key: crossterm::event::KeyEvent) -> Result<ModeAction>;
fn handle_mouse_event(&mut self, state: &mut AppState, mouse: crossterm::event::MouseEvent) -> Result<ModeAction>;
fn on_exit(&mut self, _state: &mut AppState) -> Result<()> {
Ok(())
}
}
pub fn create_mode_handler(mode: &AppMode) -> Box<dyn ModeHandler> {
match mode {
AppMode::Normal => Box::new(normal::NormalModeHandler::new()),
AppMode::History => Box::new(history::HistoryModeHandler::new()),
}
}
pub struct ModeManager {
pub current_handler: Box<dyn ModeHandler>,
pub current_mode: AppMode,
}
impl ModeManager {
pub fn new(initial_mode: &AppMode) -> Self {
Self {
current_handler: create_mode_handler(initial_mode),
current_mode: *initial_mode,
}
}
pub fn switch_mode(&mut self, state: &mut AppState, new_mode: &AppMode) -> Result<()> {
self.current_handler.on_exit(state)?;
state.search_input.clear();
state.is_searching = false;
let data_provider = crate::services::create_data_provider(new_mode);
data_provider.load_data(state)?;
self.current_handler = create_mode_handler(new_mode);
self.current_mode = *new_mode;
self.current_handler.on_enter(state)?;
Ok(())
}
pub fn render_left_panel(&self, f: &mut Frame, area: Rect, state: &AppState) {
self.current_handler.render_left_panel(f, area, state);
}
pub fn render_right_panel(&self, f: &mut Frame, area: Rect, state: &AppState) {
self.current_handler.render_right_panel(f, area, state);
}
pub fn get_search_box_config(&self, state: &AppState) -> (String, String, Style) {
self.current_handler.get_search_box_config(state)
}
pub fn get_current_mode(&self) -> &AppMode {
&self.current_mode
}
pub fn is_mode(&self, mode: &AppMode) -> bool {
self.current_mode == *mode
}
}