sara-tasks 2.7.3

Sara — folder-aware task manager
use crossterm::event::KeyCode;
use ratatui::Frame;
use rusqlite::Connection;

use super::{Flow, Screen, cycle, step_direction};
use crate::commands::dream::load::{navigate_back, open};
use crate::commands::dream::render;
use crate::commands::dream::types::DreamData;

pub(in crate::commands::dream) struct MemoryScreen {
    data: DreamData,
    frame: u64,
    selected: usize,
    breadcrumb: Vec<String>,
    show_help: bool,
}

impl MemoryScreen {
    pub(in crate::commands::dream) fn new(data: DreamData) -> Self {
        Self {
            data,
            frame: 0,
            selected: 0,
            breadcrumb: vec![],
            show_help: false,
        }
    }

    fn show(&mut self, data: DreamData) {
        self.data = data;
        self.frame = 0;
        self.selected = 0;
    }

    fn back(&mut self, conn: &Connection) -> bool {
        match navigate_back(conn, &mut self.breadcrumb) {
            Some(d) => {
                self.show(d);
                true
            }
            None => false,
        }
    }
}

impl Screen for MemoryScreen {
    fn draw(&self, f: &mut Frame) {
        render::ui(
            f,
            &self.data,
            self.frame,
            self.selected,
            &self.breadcrumb,
            self.show_help,
        );
    }

    fn tick(&mut self) {
        self.frame += 1;
    }

    fn on_key(&mut self, conn: &Connection, code: KeyCode) -> Flow {
        if let Some(forward) = step_direction(code) {
            self.selected = cycle(self.selected, self.data.neighbors.len(), forward);
            return Flow::Continue;
        }
        match code {
            KeyCode::Char('q') => return Flow::Quit,
            KeyCode::Char('?') => self.show_help = !self.show_help,
            KeyCode::Esc => {
                if self.show_help {
                    self.show_help = false;
                } else if self.breadcrumb.is_empty() || !self.back(conn) {
                    return Flow::Quit;
                }
            }
            KeyCode::Backspace => {
                self.back(conn);
            }
            KeyCode::Enter => {
                if let Some(label) = self.data.memory_label_at(self.selected)
                    && let Ok(d) = open(conn, label)
                {
                    self.breadcrumb.push(self.data.label.clone());
                    self.show(d);
                }
            }
            _ => {}
        }
        Flow::Continue
    }
}