pub mod code_viewer;
pub mod diff_viewer;
pub mod file_dialog;
pub mod help_modal;
pub mod line_prompt;
pub mod render_options_dialog;
pub mod review_dialog;
pub mod search_modal;
pub mod theme_dialog;
use anyhow::Result;
use crossterm::event::{KeyEvent, MouseEvent};
use ratatui::{
Frame,
layout::{Constraint, Direction, Layout, Rect},
prelude::Stylize,
style::{Color, Style},
symbols::border,
text::Line,
widgets::{Block, Borders, List, ListItem, ListState},
};
use tokio::sync::mpsc::UnboundedSender;
use crate::tui::actions::Action;
use crate::tui::events::Event;
pub fn move_selection(selected: &mut usize, delta: i32, len: usize) {
if delta < 0 {
*selected = selected.saturating_sub(1);
} else if *selected + 1 < len {
*selected += 1;
}
}
pub fn render_list_dialog(
frame: &mut Frame,
area: Rect,
title: Line<'static>,
items: Vec<ListItem<'static>>,
selected: usize,
hint: &'static str,
) {
let layout = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(1), Constraint::Length(1)])
.split(area);
let block = Block::default()
.title(title)
.borders(Borders::ALL)
.border_set(border::ROUNDED)
.border_style(Style::new().fg(Color::Cyan));
let mut list_state = ListState::default().with_selected(Some(selected));
let list = List::new(items)
.block(block)
.highlight_style(Style::new().bg(Color::Blue).bold());
frame.render_stateful_widget(list, layout[0], &mut list_state);
frame.render_widget(Line::from(hint).dim(), layout[1]);
}
pub trait Component {
fn register_action_handler(&mut self, _tx: UnboundedSender<Action>) -> Result<()> {
Ok(())
}
fn init(&mut self, _area: Rect) -> Result<()> {
Ok(())
}
fn handle_events(&mut self, event: Option<Event>) -> Result<Option<Action>> {
let Some(event) = event else {
return Ok(None);
};
let action = match event {
Event::Key(key_event) => self.handle_key_event(key_event)?,
Event::Mouse(mouse_event) => self.handle_mouse_event(mouse_event)?,
_ => None,
};
Ok(action)
}
fn handle_key_event(&mut self, _key: KeyEvent) -> Result<Option<Action>> {
Ok(None)
}
fn handle_mouse_event(&mut self, _mouse: MouseEvent) -> Result<Option<Action>> {
Ok(None)
}
fn update(&mut self, _action: Action) -> Result<Option<Action>> {
Ok(None)
}
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()>;
}