tabiew 0.13.1

A lightweight TUI application to view and query tabular data files, such as CSV, TSV, and parquet.
use std::ops::Deref;

use crossterm::event::KeyCode;
use strum::IntoEnumIterator;

use crate::{
    handler::message::Message,
    misc::{
        config::{config, theme},
        type_ext::UnwrapOrEnqueueError,
    },
    tui::{
        component::Component,
        pickers::search_picker::SearchPicker,
        themes::theme::{LoadedTheme, Theme},
    },
};

#[derive(Debug)]
pub struct ThemeSelector {
    search_picker: SearchPicker<Theme>,
    rollback: LoadedTheme,
}

impl ThemeSelector {
    pub fn into_rollback_theme(self) -> LoadedTheme {
        self.rollback
    }

    pub fn selected(&self) -> Option<Theme> {
        self.search_picker.selected_item().cloned()
    }

    pub fn search_picker(&self) -> &SearchPicker<Theme> {
        &self.search_picker
    }

    pub fn search_picker_mut(&mut self) -> &mut SearchPicker<Theme> {
        &mut self.search_picker
    }
}

impl Component for ThemeSelector {
    fn render(
        &mut self,
        area: ratatui::prelude::Rect,
        buf: &mut ratatui::prelude::Buffer,
        focus_state: crate::tui::component::FocusState,
    ) {
        self.search_picker.render(area, buf, focus_state);
        if let Some(t) = self.search_picker.selected_item()
            && t != theme().app_theme()
        {
            config().set_theme(*t);
        }
    }

    fn handle(&mut self, event: crossterm::event::KeyEvent) -> bool {
        self.search_picker.handle(event)
            || match event.code {
                KeyCode::Esc => {
                    Message::AppDismissOverlay.enqueue();
                    config().set_theme(self.rollback.clone());
                    true
                }
                KeyCode::Enter => {
                    Message::AppDismissOverlay.enqueue();
                    config().store().unwrap_or_enqueue_error();
                    true
                }
                _ => false,
            }
    }
}

impl Default for ThemeSelector {
    fn default() -> Self {
        let mut search_picker = SearchPicker::new(Theme::iter().collect());
        let rollback = config().theme().deref().clone();
        let idx = Theme::iter()
            .enumerate()
            .find_map(|(i, t)| rollback.app_theme().eq(&t).then_some(i))
            .unwrap_or_default();
        search_picker.select(Some(idx));

        Self {
            search_picker,
            rollback,
        }
    }
}