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)) {