use anyhow::Result;
use crossterm::event::{self, Event};
use ratatui::Terminal;
use ratatui::backend::CrosstermBackend;
use std::io::Stdout;
use std::time::Duration;
use crate::app_theme::AppThemeColors;
use crate::content_tree::state::ContentTreeState;
use crate::content_tree::{input, render};
use crate::keybinds::Keybinds;
use crate::storage::Storage;
pub enum ContentTreeResult {
Back,
JumpToLine { note_id: String, line: usize },
HelpRequested,
}
pub fn run_content_tree_view(
terminal: &mut Terminal<CrosstermBackend<Stdout>>,
storage: Storage,
note_id: Option<String>,
keybinds: &Keybinds,
theme: AppThemeColors,
) -> Result<ContentTreeResult> {
let mut state = if let Some(id) = note_id {
match storage.load_note(&id) {
Ok(note) => ContentTreeState::new(id, ¬e.title, ¬e.content),
Err(_) => ContentTreeState::error(id),
}
} else {
ContentTreeState::error(String::new())
};
loop {
terminal.draw(|f| {
let area = f.area();
render::draw_content_tree(f, area, &state, &theme, keybinds);
})?;
if event::poll(Duration::from_millis(100))? {
match event::read()? {
Event::Key(key) => {
if key.kind == crossterm::event::KeyEventKind::Release {
continue;
}
match input::handle_input(&mut state, key, keybinds) {
input::InputResult::Back => return Ok(ContentTreeResult::Back),
input::InputResult::Help => return Ok(ContentTreeResult::HelpRequested),
input::InputResult::Open => {
if !state.load_error && state.selected < state.nodes.len() {
let node = &state.nodes[state.selected];
return Ok(ContentTreeResult::JumpToLine {
note_id: state.note_id.clone(),
line: node.line,
});
} else {
return Ok(ContentTreeResult::Back);
}
}
input::InputResult::None => {}
}
}
Event::Mouse(mouse) => {
let area = terminal.size()?;
match input::handle_content_tree_mouse(&mut state, mouse, area.into()) {
input::InputResult::Back => return Ok(ContentTreeResult::Back),
input::InputResult::Help => return Ok(ContentTreeResult::HelpRequested),
input::InputResult::Open => {
if !state.load_error && state.selected < state.nodes.len() {
let node = &state.nodes[state.selected];
return Ok(ContentTreeResult::JumpToLine {
note_id: state.note_id.clone(),
line: node.line,
});
} else {
return Ok(ContentTreeResult::Back);
}
}
input::InputResult::None => {}
}
}
Event::Resize(_, _) => {
terminal.autoresize()?;
let _ = terminal.clear();
}
_ => {}
}
}
}
}