voynich 0.1.1

Library for creating anonymous, end-to-end encrypted and authenticated chat applications
Documentation
use crate::{
    app::InputHandler,
    app_context::AppContext,
    commands::Command,
    input::{CursorMovement, Input},
};
use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
use std::str::FromStr;
use voynich::{
    engine::Engine,
    logger::{Logger, StandardLogger},
};

#[derive(Debug)]
pub struct CommandInput {
    input: Input,
}

impl CommandInput {
    pub fn new() -> Self {
        Self {
            input: Input::new(Some(":> ")),
        }
    }

    pub fn get_input(&self) -> String {
        self.input.get_input()
    }

    pub fn cursor_location(&self, width: usize) -> (u16, u16) {
        self.input.cursor_location(width)
    }

    pub async fn handle_command(
        &mut self,
        context: &mut AppContext,
        logger: &mut StandardLogger,
        command: Command,
        engine: &mut Engine,
    ) {
        match command {
            Command::Connect { address } => {
                if let Err(error) = engine.connect(&address).await {
                    logger.log_error(&format!("Connect error: {}", error));
                }
            }
            Command::Quit => {
                context.should_quit = true;
            }
        }
    }
}

impl InputHandler for CommandInput {
    async fn handle_input_event(
        &mut self,
        event: Event,
        context: &mut AppContext,
        engine: &mut Engine,
        logger: &mut StandardLogger,
    ) {
        if let Event::Key(KeyEvent {
            code,
            modifiers,
            kind: _,
            state: _,
        }) = event
        {
            match code {
                KeyCode::Char(character) => {
                    if character == 'c' && modifiers.contains(KeyModifiers::CONTROL) {
                        context.should_quit = true;
                    } else if character == 'k' && modifiers.contains(KeyModifiers::CONTROL) {
                        context.toggle_command_popup();
                        if context.show_command_popup {
                            context.show_welcome_popup = false;
                        }
                    } else if character == 'u' && modifiers.contains(KeyModifiers::CONTROL) {
                        self.input.clear_input_to_cursor();
                    } else if character == 'h' && modifiers.contains(KeyModifiers::CONTROL) {
                        context.toggle_welcome_popup();
                        if context.show_welcome_popup {
                            context.show_command_popup = false;
                        }
                    } else {
                        self.input.write(character);
                    }
                }
                KeyCode::Esc => {
                    context.show_command_popup = false;
                }
                KeyCode::Enter => {
                    if let Some(input) = self.input.reset_input() {
                        context.toggle_command_popup();
                        match Command::from_str(&input) {
                            Ok(command) => {
                                self.handle_command(context, logger, command, engine).await;
                            }
                            Err(error) => {
                                logger.log_error(&format!("Error parsing command: {}", error));
                            }
                        }
                    }
                }
                KeyCode::Delete => {
                    self.input.remove();
                }
                KeyCode::Backspace => {
                    self.input.remove_previous();
                }
                KeyCode::Left => {
                    self.input.move_cursor(CursorMovement::Left);
                }
                KeyCode::Right => {
                    self.input.move_cursor(CursorMovement::Right);
                }
                KeyCode::Home => {
                    self.input.move_cursor(CursorMovement::Start);
                }
                KeyCode::End => {
                    self.input.move_cursor(CursorMovement::End);
                }
                _ => {}
            }
        }
    }
}