From 5eb1ace9589c36dbb81ba7b58d341e393949e476 Mon Sep 17 00:00:00 2001 From: ChristianVisintin Date: Sat, 21 Nov 2020 21:26:27 +0100 Subject: [PATCH] Working on AuthActivity --- docs/drawio/UI.drawio | 1 + src/ui/activities/auth_activity.rs | 208 +++++++++++++++++++++++++++++ src/ui/activities/mod.rs | 2 + src/ui/input.rs | 4 +- 4 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 docs/drawio/UI.drawio create mode 100644 src/ui/activities/auth_activity.rs diff --git a/docs/drawio/UI.drawio b/docs/drawio/UI.drawio new file mode 100644 index 0000000..229052f --- /dev/null +++ b/docs/drawio/UI.drawio @@ -0,0 +1 @@ +7ZlRk5owEMc/DY/HABGEx2rv2pnWmXaczj3nJEKmgdAQD+yn7wJBoOhUrbbcTHwx2SSb5L+/4EoMtEzKDwJn8YqHhBmOFZYGem84ju26FnxVln1j8QO3MUSChqpTZ1jTn0QZ1bhoR0OSDzpKzpmk2dC44WlKNnJgw0LwYthty9lw1gxHZGRYbzAbW59pKGO1C2fe2T8SGsXtzLYXNC0JbjurneQxDnnRM6FHAy0F57IpJeWSsEq8Vpdm3NOJ1sPCBEnlOQOyRbEsv31ixSv+vi6c588r9vXBaby8YrZTG1aLlftWAcF3aUgqJ5aBFkVMJVlneFO1FhBzsMUyYVCzobiljC054wLqKU+h00LNQIQk5cml2wdBgCTCEyLFHrqoAchEqBmzH9JRdCFBgWd6KipxLyJopvpiRUJ0cN+JBQWl1wXaoTeh3azl77R0M8s6pptj+t6dpJsdkc5jMPPiBQqRrLfeGLYc9tkX1fux423DQ14/MN5BB9Ck7BpbL1+qU6g8wUobZ8MJwNyb9MYBxIxGKVQZ2crbxBMo9/58Fo4E1L3XOXB1MK8/nO60YumNYvlEGUlxQkBVnFQapS95Vu/e+semGo8b+seS3nZbGREJzXPK0/w6H7xIiahTIb7L3gC+o2fR/Bi/8Os9GyPs3QvhuUZYI3x1ejQFgn1NsCb4fILNwA96H3+YUaAJAB1ooDXQl2QVbh/o+RDoYAJAt3m6JloT/ddEH/7N/VeibU20JvqStNm0+p/f3klNIeuwxy+3NdIa6bNflE8i0RhfMmiGNcOnGbaHqcYUM43x5c+K5Hl1D+tYL7y8m8wbEBGi2Vw2rJV/u603N8+Oe6NAmEEwkB55Y+l92zUteyz94clzgfZQ7a6S67behTx6/AU=5ZfRbpswFIafhstIAQNtL1OarlI1qUq6RdrNZLADnowPs00ge/qZYCA0ldZOSiqVK+z/2Mec/zuWwEFRXn+RuMi+AqHc8eakdtCd43luEMzNo1H2rXJ9E7RCKhmxiwZhzf5QK9p9ackIVaOFGoBrVozFBISgiR5pWEqoxsu2wMenFjilJ8I6wfxU3TCiM1uFdzXoD5SlWXeyG960kRx3i20lKsMEqiMJLR0USQDdjvI6orwxr/Pl8ennZvUQzVZ3uwXDz8pfPaNZm+z+PVv6EiQV+r9Tb/ax+q59lCz5D/5rN4sf0z71DvPS+mVr1fvOQAmlILRJMnfQbZUxTdcFTppoZVrGaJnOuZm5ZrhlnEfAQZq5AEEbCYS2beEFZo45S4WZcLo1xdzaF6BS0/oFsX+U6/YMTPNSyKmWe7PP9qlvqVXH0K2WHQFHXaNi22hpn2ow0wysn+/w1jvxdlHqzNTEEqwZiKk5HZ7LaPRKE4dcW0dGHoe/S+gCM3XwamEWuH5RD0EzSu3zkCXuhAUhkip12NOGzPvGL5cbrT23kz8HZnf+Rs7+uTj7l+L8BFJPFPJbL/PZIAcXgyxBQwK83aQob74+Jkj8+qOJh5ci/k1RKXBOp3m1++/YDwN9dbGrjZWqQJIWNM4bJiJWxRjyZMCH5wNvpsMP0CF29BuJln8B \ No newline at end of file diff --git a/src/ui/activities/auth_activity.rs b/src/ui/activities/auth_activity.rs new file mode 100644 index 0000000..9b2a18c --- /dev/null +++ b/src/ui/activities/auth_activity.rs @@ -0,0 +1,208 @@ +//! ## AuthActivity +//! +//! `auth_activity` is the module which implements the authentication activity + +/* +* +* Copyright (C) 2020 Christian Visintin - christian.visintin1997@gmail.com +* +* This file is part of "TermSCP" +* +* TermSCP is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* TermSCP is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with TermSCP. If not, see . +* +*/ + +// Dependencies +extern crate crossterm; +extern crate tui; + +// locals +use super::{Activity, Context}; + +// Includes +use crossterm::event::Event as InputEvent; +use crossterm::event::{KeyCode, KeyEvent}; +use tui::layout; +use tui::style; +use tui::widgets; + +/// ### InputField +/// +/// InputField describes the current input field to edit +#[derive(std::cmp::PartialEq)] +enum InputField { + Address, + Port, + Protocol, + Username, + Password, +} + +/// ### ScpProtocol +/// +/// ScpProtocol describes the communication protocol selected by the user to communicate with the remote +pub enum ScpProtocol { + Sftp, + Ftp, +} + +/// ### AuthActivity +/// +/// AuthActivity is the data holder for the authentication activity +pub struct AuthActivity { + pub address: String, + pub port: String, + pub protocol: ScpProtocol, + pub username: String, + pub password: String, + pub form_submit: bool, // becomes true after user has submitted fields + pub esc_called: bool, // Becomes true if user has pressed esc + selected_field: InputField, +} + +impl AuthActivity { + /// ### new + /// + /// Instantiates a new AuthActivity + pub fn new() -> AuthActivity { + AuthActivity { + address: String::new(), + port: String::from("22"), + protocol: ScpProtocol::Sftp, + username: String::new(), + password: String::new(), + form_submit: false, + esc_called: false, + selected_field: InputField::Address, + } + } +} + +impl Activity for AuthActivity { + /// ### on_create + /// + /// `on_create` is the function which must be called to initialize the activity. + /// `on_create` must initialize all the data structures used by the activity + fn on_create(&mut self, context: &mut Context) { + // Mhm, nothing to do here I guess... + } + + /// ### on_draw + /// + /// `on_draw` is the function which draws the graphical interface. + /// This function must be called at each tick to refresh the interface + fn on_draw(&mut self, context: &mut Context) { + // Start catching Input Events + let mut popup: Option = None; + if let Ok(input_events) = context.input_hnd.fetch_events() { + // Iterate over input events + for event in input_events.iter() { + match event { + InputEvent::Key(key) => { + match key.code { + KeyCode::Esc => { + self.esc_called = true; + break + }, + KeyCode::Enter => { + // TODO: handle submit (check form) + }, + KeyCode::Backspace => { + // Pop last char + match self.selected_field { + InputField::Address => { + let _ = self.address.pop(); + }, + InputField::Password => { + let _ = self.password.pop(); + }, + InputField::Username => { + let _ = self.username.pop(); + }, + InputField::Port => { + let _ = self.port.pop(); + }, + _ => { /* Nothing to do */ } + }; + }, + KeyCode::Up => { + // Move item up + self.selected_field = match self.selected_field { + InputField::Address => InputField::Address, // End of list + InputField::Port => InputField::Address, + InputField::Protocol => InputField::Port, + InputField::Username => InputField::Protocol, + InputField::Password => InputField::Username, + } + }, + KeyCode::Down => { + // Move item down + self.selected_field = match self.selected_field { + InputField::Address => InputField::Port, + InputField::Port => InputField::Protocol, + InputField::Protocol => InputField::Username, + InputField::Username => InputField::Password, + InputField::Password => InputField::Password, // End of list + } + }, + KeyCode::Char(ch) => { + match self.selected_field { + InputField::Address => self.address.push(ch), + InputField::Password => self.password.push(ch), + InputField::Username => self.username.push(ch), + InputField::Port => { + // Value must be numeric + if ch.is_numeric() { + self.port.push(ch); + } + }, + _ => { /* Nothing to do */ } + } + }, + KeyCode::Left => { + // If current field is Protocol handle event... (move element left) + if self.selected_field == InputField::Protocol { + self.protocol = match self.protocol { + ScpProtocol::Sftp => ScpProtocol::Sftp, + ScpProtocol::Ftp => ScpProtocol::Sftp, // End of list + } + } + }, + KeyCode::Right => { + // If current field is Protocol handle event... ( move element right ) + if self.selected_field == InputField::Protocol { + self.protocol = match self.protocol { + ScpProtocol::Sftp => ScpProtocol::Ftp, + ScpProtocol::Ftp => ScpProtocol::Ftp, // End of list + } + } + }, + _ => { /* Nothing to do */ } + } + } + _ => { /* Nothing to do */ } + } + } + } + // TODO: draw interface + } + + /// ### on_destroy + /// + /// `on_destroy` is the function which cleans up runtime variables and data before terminating the activity. + /// This function must be called once before terminating the activity. + fn on_destroy(&mut self, context: &mut Context) { + // Mhm, nothing to do here I guess... + } +} diff --git a/src/ui/activities/mod.rs b/src/ui/activities/mod.rs index 64717ef..77476be 100644 --- a/src/ui/activities/mod.rs +++ b/src/ui/activities/mod.rs @@ -24,9 +24,11 @@ * */ +// Locals use super::context::Context; // Activities +pub mod auth_activity; // Activity trait diff --git a/src/ui/input.rs b/src/ui/input.rs index a19a256..2801c46 100644 --- a/src/ui/input.rs +++ b/src/ui/input.rs @@ -42,10 +42,10 @@ impl InputHandler { InputHandler {} } - /// ### fetch_messages + /// ### fetch_events /// /// Check if new events have been received from handler - pub(crate) fn fetch_messages(&self) -> Result, ()> { + pub(crate) fn fetch_events(&self) -> Result, ()> { let mut inbox: Vec = Vec::new(); loop { if let Ok(available) = poll(Duration::from_millis(10)) {