Skip to main content

kimun_notes/components/settings/
display_section.rs

1use ratatui::Frame;
2use ratatui::layout::Rect;
3use ratatui::style::Style;
4use ratatui::widgets::{Block, Borders, List, ListItem, ListState};
5
6use crate::components::Component;
7use crate::components::event_state::EventState;
8use crate::components::events::{AppTx, InputEvent};
9use crate::settings::themes::Theme;
10
11pub struct DisplaySection {
12    pub use_nerd_fonts: bool,
13    list_state: ListState,
14}
15
16impl DisplaySection {
17    pub fn new(use_nerd_fonts: bool) -> Self {
18        let mut list_state = ListState::default();
19        list_state.select(Some(0));
20        Self {
21            use_nerd_fonts,
22            list_state,
23        }
24    }
25}
26
27impl Component for DisplaySection {
28    fn handle_input(&mut self, event: &InputEvent, _tx: &AppTx) -> EventState {
29        let InputEvent::Key(key) = event else {
30            return EventState::NotConsumed;
31        };
32        match key.code {
33            ratatui::crossterm::event::KeyCode::Enter
34            | ratatui::crossterm::event::KeyCode::Char(' ') => {
35                self.use_nerd_fonts = !self.use_nerd_fonts;
36                EventState::Consumed
37            }
38            _ => EventState::NotConsumed,
39        }
40    }
41
42    fn render(&mut self, f: &mut Frame, rect: Rect, theme: &Theme, focused: bool) {
43        let border_style = theme.border_style(focused);
44        let block = Block::default()
45            .title("Display")
46            .borders(Borders::ALL)
47            .border_style(border_style)
48            .style(theme.base_style());
49
50        let check = if self.use_nerd_fonts { "[x]" } else { "[ ]" };
51        let items = vec![
52            ListItem::new(format!("  Use Nerd Fonts  {}", check))
53                .style(Style::default().fg(theme.fg.to_ratatui())),
54        ];
55
56        let list = List::new(items)
57            .block(block)
58            .style(theme.base_style())
59            .highlight_style(
60                Style::default()
61                    .fg(theme.fg_selected.to_ratatui())
62                    .bg(theme.bg_selected.to_ratatui()),
63            );
64        f.render_stateful_widget(list, rect, &mut self.list_state);
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::components::events::InputEvent;
72    use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
73
74    fn key(code: KeyCode) -> InputEvent {
75        InputEvent::Key(KeyEvent {
76            code,
77            modifiers: KeyModifiers::NONE,
78            kind: KeyEventKind::Press,
79            state: KeyEventState::NONE,
80        })
81    }
82
83    #[test]
84    fn enter_toggles_nerd_fonts() {
85        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
86        let mut section = DisplaySection::new(true);
87        section.handle_input(&key(KeyCode::Enter), &tx);
88        assert!(!section.use_nerd_fonts);
89        section.handle_input(&key(KeyCode::Enter), &tx);
90        assert!(section.use_nerd_fonts);
91    }
92
93    #[test]
94    fn space_toggles_nerd_fonts() {
95        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
96        let mut section = DisplaySection::new(false);
97        section.handle_input(&key(KeyCode::Char(' ')), &tx);
98        assert!(section.use_nerd_fonts);
99    }
100
101    #[test]
102    fn renders_checked_when_enabled() {
103        use ratatui::Terminal;
104        use ratatui::backend::TestBackend;
105        let backend = TestBackend::new(40, 10);
106        let mut terminal = Terminal::new(backend).unwrap();
107        let mut section = DisplaySection::new(true);
108        let theme = Theme::gruvbox_dark();
109        terminal
110            .draw(|f| section.render(f, f.area(), &theme, false))
111            .unwrap();
112        let buf = terminal.backend().buffer().clone();
113        let flat: String = buf.content.iter().map(|c| c.symbol()).collect();
114        assert!(flat.contains("[x]"), "expected [x] when nerd fonts enabled");
115    }
116
117    #[test]
118    fn renders_unchecked_when_disabled() {
119        use ratatui::Terminal;
120        use ratatui::backend::TestBackend;
121        let backend = TestBackend::new(40, 10);
122        let mut terminal = Terminal::new(backend).unwrap();
123        let mut section = DisplaySection::new(false);
124        let theme = Theme::gruvbox_dark();
125        terminal
126            .draw(|f| section.render(f, f.area(), &theme, false))
127            .unwrap();
128        let buf = terminal.backend().buffer().clone();
129        let flat: String = buf.content.iter().map(|c| c.symbol()).collect();
130        assert!(
131            flat.contains("[ ]"),
132            "expected [ ] when nerd fonts disabled"
133        );
134    }
135}