use ratatui::layout::{Constraint, Direction, Flex, Layout, Rect};
use ratatui::text::Line;
use rustc_hash::FxHashMap;
use crate::tui::theme::Theme;
use crate::tui::widgets::{ChatState, InputState};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct LayoutKey {
width: u16,
height: u16,
input_height: u16,
status_line_height: u16,
attachment_height: u16,
bottom_height: u16,
}
pub struct LayoutCache {
cached: Option<(LayoutKey, Vec<Rect>)>,
}
impl LayoutCache {
fn new() -> Self {
Self { cached: None }
}
pub fn get_main_layout(
&mut self,
area: Rect,
input_height: u16,
status_line_height: u16,
attachment_height: u16,
bottom_height: u16,
) -> Vec<Rect> {
let key = LayoutKey {
width: area.width,
height: area.height,
input_height,
status_line_height,
attachment_height,
bottom_height,
};
if let Some((cached_key, ref rects)) = self.cached
&& cached_key == key
{
return rects.clone();
}
let layout = Layout::default()
.direction(Direction::Vertical)
.margin(0)
.spacing(0)
.flex(Flex::Start)
.constraints([
Constraint::Min(10),
Constraint::Length(status_line_height),
Constraint::Length(attachment_height),
Constraint::Length(input_height),
Constraint::Length(bottom_height),
])
.split(area);
let layout_vec = layout.to_vec();
self.cached = Some((key, layout_vec.clone()));
layout_vec
}
}
pub struct UIState {
pub chat_state: ChatState,
pub input_state: InputState,
pub theme: Theme,
pub selected_message: Option<usize>,
pub attachment_focused: bool,
pub selected_attachment: usize,
pub attachment_area_y: Option<u16>,
pub palette_selected_index: usize,
pub layout_cache: LayoutCache,
pub markdown_cache: FxHashMap<u64, Vec<Line<'static>>>,
}
impl UIState {
pub fn new() -> Self {
Self {
chat_state: ChatState::default(),
input_state: InputState::default(),
theme: Theme::dark(),
selected_message: None,
attachment_focused: false,
selected_attachment: 0,
attachment_area_y: None,
palette_selected_index: 0,
layout_cache: LayoutCache::new(),
markdown_cache: FxHashMap::default(),
}
}
}
impl Default for UIState {
fn default() -> Self {
Self::new()
}
}