aboutsummaryrefslogtreecommitdiff
path: root/src/components/global_keys.rs
blob: 67b1b6a0005d479203008c34aabbe9a19606fe88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
use ratatui::prelude::*;
use ratatui::widgets::*;

use crate::app_action::AppAction;
use crate::component::Component;
use crate::keys::key_commands::*;

#[derive(Default)]
pub struct GlobalKeys {
    pub key_commands: Vec<KeyCommand>,

    pub should_show: bool,
    pub scroll: u16,
}

impl Component for GlobalKeys {
    fn init(&mut self) -> eyre::Result<()> {
        self.key_commands.push(KeyCommand {
            key_code: "?".to_string(),
            description: "Show help menu".to_string(),
            action: None,
        });

        Ok(())
    }

    fn handle_key_event(
        &mut self,
        key: KeyEvent,
    ) -> eyre::Result<Option<AppAction>> {
        if key.kind == KeyEventKind::Press {
            for key_command in self.key_commands.iter_mut() {
                if key_command.key_code == serialize_key_event(key) {
                    if serialize_key_event(key) == "?" {
                        self.should_show = !self.should_show;
                    }

                    return Ok(key_command.action);
                }
            }
        }

        Ok(None)
    }

    fn render(&mut self, frame: &mut Frame, rect: Rect) -> eyre::Result<()> {
        let block = Block::default()
            .title("Keyboard shortcuts")
            .borders(Borders::ALL);

        let mut lines: Vec<Line> = vec![];
        for key_command in self.key_commands.iter_mut() {
            let command = Span::from(key_command.key_code.clone());
            let description =
                Span::from(key_command.description.clone()).italic();
            let spacer = Span::from("  ");

            let line = Line::from(vec![command, spacer, description]);
            lines.push(line);
        }

        let commands = Paragraph::new(lines)
            .block(block)
            .wrap(Wrap { trim: true })
            .scroll((self.scroll, 0));

        if self.should_show {
            frame.render_widget(commands, rect);
        }

        Ok(())
    }
}