mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Something is working, but it is still unusable
This commit is contained in:
@@ -27,9 +27,11 @@
|
|||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
|
|
||||||
// Locals
|
// Locals
|
||||||
use super::{AuthActivity, Color, DialogYesNoOption, Popup};
|
use super::{AuthActivity, FileTransferProtocol};
|
||||||
use crate::system::bookmarks_client::BookmarksClient;
|
use crate::system::bookmarks_client::BookmarksClient;
|
||||||
use crate::system::environment;
|
use crate::system::environment;
|
||||||
|
use crate::ui::layout::props::PropValue;
|
||||||
|
use crate::ui::layout::Payload;
|
||||||
|
|
||||||
// Ext
|
// Ext
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -60,14 +62,10 @@ impl AuthActivity {
|
|||||||
// Iterate over bookmarks
|
// Iterate over bookmarks
|
||||||
if let Some(key) = self.bookmarks_list.get(idx) {
|
if let Some(key) = self.bookmarks_list.get(idx) {
|
||||||
if let Some(bookmark) = bookmarks_cli.get_bookmark(&key) {
|
if let Some(bookmark) = bookmarks_cli.get_bookmark(&key) {
|
||||||
// Load parameters
|
// Load parameters into components
|
||||||
self.address = bookmark.0;
|
self.load_bookmark_into_gui(
|
||||||
self.port = bookmark.1.to_string();
|
bookmark.0, bookmark.1, bookmark.2, bookmark.3, bookmark.4,
|
||||||
self.protocol = bookmark.2;
|
);
|
||||||
self.username = bookmark.3;
|
|
||||||
if let Some(password) = bookmark.4 {
|
|
||||||
self.password = password;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,41 +74,24 @@ impl AuthActivity {
|
|||||||
/// ### save_bookmark
|
/// ### save_bookmark
|
||||||
///
|
///
|
||||||
/// Save current input fields as a bookmark
|
/// Save current input fields as a bookmark
|
||||||
pub(super) fn save_bookmark(&mut self, name: String) {
|
pub(super) fn save_bookmark(&mut self, name: String, save_password: bool) {
|
||||||
// Check port
|
let (address, port, protocol, username, password) = self.get_input();
|
||||||
let port: u16 = match self.port.parse::<usize>() {
|
|
||||||
Ok(val) => {
|
|
||||||
if val > 65535 {
|
|
||||||
self.popup = Some(Popup::Alert(
|
|
||||||
Color::Red,
|
|
||||||
String::from("Specified port must be in range 0-65535"),
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
val as u16
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
self.popup = Some(Popup::Alert(
|
|
||||||
Color::Red,
|
|
||||||
String::from("Specified port is not a number"),
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if let Some(bookmarks_cli) = self.bookmarks_client.as_mut() {
|
if let Some(bookmarks_cli) = self.bookmarks_client.as_mut() {
|
||||||
// Check if password must be saved
|
// Check if password must be saved
|
||||||
let password: Option<String> = match self.choice_opt {
|
let password: Option<String> = match save_password {
|
||||||
DialogYesNoOption::Yes => Some(self.password.clone()),
|
true => match self
|
||||||
DialogYesNoOption::No => None,
|
.view
|
||||||
|
.get_value(super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD)
|
||||||
|
{
|
||||||
|
Some(Payload::Unsigned(choice)) => match choice {
|
||||||
|
0 => Some(password), // Yes
|
||||||
|
_ => None, // No
|
||||||
|
},
|
||||||
|
_ => None, // No such component
|
||||||
|
},
|
||||||
|
false => None,
|
||||||
};
|
};
|
||||||
bookmarks_cli.add_bookmark(
|
bookmarks_cli.add_bookmark(name.clone(), address, port, protocol, username, password);
|
||||||
name.clone(),
|
|
||||||
self.address.clone(),
|
|
||||||
port,
|
|
||||||
self.protocol,
|
|
||||||
self.username.clone(),
|
|
||||||
password,
|
|
||||||
);
|
|
||||||
// Save bookmarks
|
// Save bookmarks
|
||||||
self.write_bookmarks();
|
self.write_bookmarks();
|
||||||
// Push bookmark to list and sort
|
// Push bookmark to list and sort
|
||||||
@@ -143,10 +124,9 @@ impl AuthActivity {
|
|||||||
if let Some(key) = self.recents_list.get(idx) {
|
if let Some(key) = self.recents_list.get(idx) {
|
||||||
if let Some(bookmark) = client.get_recent(key) {
|
if let Some(bookmark) = client.get_recent(key) {
|
||||||
// Load parameters
|
// Load parameters
|
||||||
self.address = bookmark.0;
|
self.load_bookmark_into_gui(
|
||||||
self.port = bookmark.1.to_string();
|
bookmark.0, bookmark.1, bookmark.2, bookmark.3, None,
|
||||||
self.protocol = bookmark.2;
|
);
|
||||||
self.username = bookmark.3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,33 +136,9 @@ impl AuthActivity {
|
|||||||
///
|
///
|
||||||
/// Save current input fields as a "recent"
|
/// Save current input fields as a "recent"
|
||||||
pub(super) fn save_recent(&mut self) {
|
pub(super) fn save_recent(&mut self) {
|
||||||
// Check port
|
let (address, port, protocol, username, _password) = self.get_input();
|
||||||
let port: u16 = match self.port.parse::<usize>() {
|
|
||||||
Ok(val) => {
|
|
||||||
if val > 65535 {
|
|
||||||
self.popup = Some(Popup::Alert(
|
|
||||||
Color::Red,
|
|
||||||
String::from("Specified port must be in range 0-65535"),
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
val as u16
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
self.popup = Some(Popup::Alert(
|
|
||||||
Color::Red,
|
|
||||||
String::from("Specified port is not a number"),
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if let Some(bookmarks_cli) = self.bookmarks_client.as_mut() {
|
if let Some(bookmarks_cli) = self.bookmarks_client.as_mut() {
|
||||||
bookmarks_cli.add_recent(
|
bookmarks_cli.add_recent(address, port, protocol, username);
|
||||||
self.address.clone(),
|
|
||||||
port,
|
|
||||||
self.protocol,
|
|
||||||
self.username.clone(),
|
|
||||||
);
|
|
||||||
// Save bookmarks
|
// Save bookmarks
|
||||||
self.write_bookmarks();
|
self.write_bookmarks();
|
||||||
}
|
}
|
||||||
@@ -194,10 +150,7 @@ impl AuthActivity {
|
|||||||
fn write_bookmarks(&mut self) {
|
fn write_bookmarks(&mut self) {
|
||||||
if let Some(bookmarks_cli) = self.bookmarks_client.as_ref() {
|
if let Some(bookmarks_cli) = self.bookmarks_client.as_ref() {
|
||||||
if let Err(err) = bookmarks_cli.write_bookmarks() {
|
if let Err(err) = bookmarks_cli.write_bookmarks() {
|
||||||
self.popup = Some(Popup::Alert(
|
self.mount_error(format!("Could not write bookmarks: {}", err).as_str());
|
||||||
Color::Red,
|
|
||||||
format!("Could not write bookmarks: {}", err),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,28 +193,29 @@ impl AuthActivity {
|
|||||||
self.sort_recents();
|
self.sort_recents();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.popup = Some(Popup::Alert(
|
self.mount_error(
|
||||||
Color::Red,
|
|
||||||
format!(
|
format!(
|
||||||
"Could not initialize bookmarks (at \"{}\", \"{}\"): {}",
|
"Could not initialize bookmarks (at \"{}\", \"{}\"): {}",
|
||||||
bookmarks_file.display(),
|
bookmarks_file.display(),
|
||||||
config_dir_path.display(),
|
config_dir_path.display(),
|
||||||
err
|
err
|
||||||
),
|
)
|
||||||
))
|
.as_str(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.popup = Some(Popup::Alert(
|
self.mount_error(
|
||||||
Color::Red,
|
format!("Could not initialize configuration directory: {}", err).as_str(),
|
||||||
format!("Could not initialize configuration directory: {}", err),
|
);
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- privates
|
||||||
|
|
||||||
/// ### sort_bookmarks
|
/// ### sort_bookmarks
|
||||||
///
|
///
|
||||||
/// Sort bookmarks in list
|
/// Sort bookmarks in list
|
||||||
@@ -278,4 +232,47 @@ impl AuthActivity {
|
|||||||
// Reverse order
|
// Reverse order
|
||||||
self.recents_list.sort_by(|a, b| b.cmp(a));
|
self.recents_list.sort_by(|a, b| b.cmp(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### load_bookmark_into_gui
|
||||||
|
///
|
||||||
|
/// Load bookmark data into the gui components
|
||||||
|
fn load_bookmark_into_gui(
|
||||||
|
&mut self,
|
||||||
|
addr: String,
|
||||||
|
port: u16,
|
||||||
|
protocol: FileTransferProtocol,
|
||||||
|
username: String,
|
||||||
|
password: Option<String>,
|
||||||
|
) {
|
||||||
|
// Load parameters into components
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_ADDR) {
|
||||||
|
let props = props.with_value(PropValue::Str(addr)).build();
|
||||||
|
self.view.update(super::COMPONENT_INPUT_ADDR, props);
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_PORT) {
|
||||||
|
let props = props.with_value(PropValue::Unsigned(port as usize)).build();
|
||||||
|
self.view.update(super::COMPONENT_INPUT_PORT, props);
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_PROTOCOL) {
|
||||||
|
let props = props
|
||||||
|
.with_value(PropValue::Unsigned(match protocol {
|
||||||
|
FileTransferProtocol::Sftp => 0,
|
||||||
|
FileTransferProtocol::Scp => 1,
|
||||||
|
FileTransferProtocol::Ftp(false) => 2,
|
||||||
|
FileTransferProtocol::Ftp(true) => 3,
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
self.view.update(super::COMPONENT_RADIO_PROTOCOL, props);
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_USERNAME) {
|
||||||
|
let props = props.with_value(PropValue::Str(username)).build();
|
||||||
|
self.view.update(super::COMPONENT_INPUT_USERNAME, props);
|
||||||
|
}
|
||||||
|
if let Some(password) = password {
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_PASSWORD) {
|
||||||
|
let props = props.with_value(PropValue::Str(password)).build();
|
||||||
|
self.view.update(super::COMPONENT_INPUT_PASSWORD, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,6 @@ use crate::utils::git;
|
|||||||
// Includes
|
// Includes
|
||||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tui::style::Color;
|
|
||||||
|
|
||||||
// Types
|
|
||||||
type DialogCallback = fn(&mut AuthActivity);
|
|
||||||
|
|
||||||
// -- components
|
// -- components
|
||||||
const COMPONENT_TEXT_HEADER: &str = "TEXT_HEADER";
|
const COMPONENT_TEXT_HEADER: &str = "TEXT_HEADER";
|
||||||
@@ -68,48 +64,6 @@ const COMPONENT_RADIO_BOOKMARK_SAVE_PWD: &str = "RADIO_SAVE_PASSWORD";
|
|||||||
const COMPONENT_BOOKMARKS_LIST: &str = "BOOKMARKS_LIST";
|
const COMPONENT_BOOKMARKS_LIST: &str = "BOOKMARKS_LIST";
|
||||||
const COMPONENT_RECENTS_LIST: &str = "RECENTS_LIST";
|
const COMPONENT_RECENTS_LIST: &str = "RECENTS_LIST";
|
||||||
|
|
||||||
/// ### InputField
|
|
||||||
///
|
|
||||||
/// InputField describes the current input field to edit
|
|
||||||
#[derive(std::cmp::PartialEq)]
|
|
||||||
enum InputField {
|
|
||||||
Address,
|
|
||||||
Port,
|
|
||||||
Protocol,
|
|
||||||
Username,
|
|
||||||
Password,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ### DialogYesNoOption
|
|
||||||
///
|
|
||||||
/// Current yes/no dialog option
|
|
||||||
#[derive(std::cmp::PartialEq, Clone)]
|
|
||||||
enum DialogYesNoOption {
|
|
||||||
Yes,
|
|
||||||
No,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ### Popup
|
|
||||||
///
|
|
||||||
/// Popup describes the type of the popup displayed
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum Popup {
|
|
||||||
Alert(Color, String), // Show a message displaying text with the provided color
|
|
||||||
Help, // Help page
|
|
||||||
SaveBookmark,
|
|
||||||
YesNo(String, DialogCallback, DialogCallback), // Yes, no callback
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(std::cmp::PartialEq)]
|
|
||||||
/// ### InputForm
|
|
||||||
///
|
|
||||||
/// InputForm describes the selected input form
|
|
||||||
enum InputForm {
|
|
||||||
AuthCredentials,
|
|
||||||
Bookmarks,
|
|
||||||
Recents,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ### AuthActivity
|
/// ### AuthActivity
|
||||||
///
|
///
|
||||||
/// AuthActivity is the data holder for the authentication activity
|
/// AuthActivity is the data holder for the authentication activity
|
||||||
@@ -126,17 +80,9 @@ pub struct AuthActivity {
|
|||||||
view: View,
|
view: View,
|
||||||
bookmarks_client: Option<BookmarksClient>,
|
bookmarks_client: Option<BookmarksClient>,
|
||||||
config_client: Option<ConfigClient>,
|
config_client: Option<ConfigClient>,
|
||||||
selected_field: InputField, // Selected field in AuthCredentials Form
|
redraw: bool, // Should ui actually be redrawned?
|
||||||
popup: Option<Popup>,
|
bookmarks_list: Vec<String>, // List of bookmarks
|
||||||
input_form: InputForm,
|
recents_list: Vec<String>, // list of recents
|
||||||
password_placeholder: String,
|
|
||||||
redraw: bool, // Should ui actually be redrawned?
|
|
||||||
input_txt: String, // Input text
|
|
||||||
choice_opt: DialogYesNoOption, // Dialog popup selected option
|
|
||||||
bookmarks_idx: usize, // Index of selected bookmark
|
|
||||||
bookmarks_list: Vec<String>, // List of bookmarks
|
|
||||||
recents_idx: usize, // Index of selected recent
|
|
||||||
recents_list: Vec<String>, // list of recents
|
|
||||||
// misc
|
// misc
|
||||||
new_version: Option<String>, // Contains new version of termscp
|
new_version: Option<String>, // Contains new version of termscp
|
||||||
}
|
}
|
||||||
@@ -165,16 +111,8 @@ impl AuthActivity {
|
|||||||
view: View::init(),
|
view: View::init(),
|
||||||
bookmarks_client: None,
|
bookmarks_client: None,
|
||||||
config_client: None,
|
config_client: None,
|
||||||
selected_field: InputField::Address,
|
|
||||||
popup: None,
|
|
||||||
input_form: InputForm::AuthCredentials,
|
|
||||||
password_placeholder: String::new(),
|
|
||||||
redraw: true, // True at startup
|
redraw: true, // True at startup
|
||||||
input_txt: String::new(),
|
|
||||||
choice_opt: DialogYesNoOption::Yes,
|
|
||||||
bookmarks_idx: 0,
|
|
||||||
bookmarks_list: Vec::new(),
|
bookmarks_list: Vec::new(),
|
||||||
recents_idx: 0,
|
|
||||||
recents_list: Vec::new(),
|
recents_list: Vec::new(),
|
||||||
new_version: None,
|
new_version: None,
|
||||||
}
|
}
|
||||||
@@ -199,19 +137,18 @@ impl AuthActivity {
|
|||||||
self.config_client = Some(cli);
|
self.config_client = Some(cli);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.popup = Some(Popup::Alert(
|
self.mount_error(
|
||||||
Color::Red,
|
format!("Could not initialize user configuration: {}", err)
|
||||||
format!("Could not initialize user configuration: {}", err),
|
.as_str(),
|
||||||
))
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.popup = Some(Popup::Alert(
|
self.mount_error(
|
||||||
Color::Red,
|
format!("Could not initialize configuration directory: {}", err).as_str(),
|
||||||
format!("Could not initialize configuration directory: {}", err),
|
);
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,10 +164,9 @@ impl AuthActivity {
|
|||||||
Ok(version) => self.new_version = version,
|
Ok(version) => self.new_version = version,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// Report error
|
// Report error
|
||||||
self.popup = Some(Popup::Alert(
|
self.mount_error(
|
||||||
Color::Red,
|
format!("Could not check for new updates: {}", err).as_str(),
|
||||||
format!("Could not check for new updates: {}", err),
|
);
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,7 +187,6 @@ impl Activity for AuthActivity {
|
|||||||
self.context.as_mut().unwrap().clear_screen();
|
self.context.as_mut().unwrap().clear_screen();
|
||||||
// Put raw mode on enabled
|
// Put raw mode on enabled
|
||||||
let _ = enable_raw_mode();
|
let _ = enable_raw_mode();
|
||||||
self.popup = None;
|
|
||||||
// Init bookmarks client
|
// Init bookmarks client
|
||||||
if self.bookmarks_client.is_none() {
|
if self.bookmarks_client.is_none() {
|
||||||
self.init_bookmarks_client();
|
self.init_bookmarks_client();
|
||||||
|
|||||||
@@ -25,16 +25,13 @@
|
|||||||
|
|
||||||
// locals
|
// locals
|
||||||
use super::{
|
use super::{
|
||||||
AuthActivity, FileTransferProtocol, COMPONENT_BOOKMARKS_LIST, COMPONENT_INPUT_ADDR,
|
AuthActivity, COMPONENT_BOOKMARKS_LIST, COMPONENT_INPUT_ADDR, COMPONENT_INPUT_BOOKMARK_NAME,
|
||||||
COMPONENT_INPUT_BOOKMARK_NAME, COMPONENT_INPUT_PASSWORD, COMPONENT_INPUT_PORT,
|
COMPONENT_INPUT_PASSWORD, COMPONENT_INPUT_PORT, COMPONENT_INPUT_USERNAME,
|
||||||
COMPONENT_INPUT_USERNAME, COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK,
|
COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, COMPONENT_RADIO_BOOKMARK_DEL_RECENT,
|
||||||
COMPONENT_RADIO_BOOKMARK_DEL_RECENT, COMPONENT_RADIO_BOOKMARK_SAVE_PWD,
|
COMPONENT_RADIO_BOOKMARK_SAVE_PWD, COMPONENT_RADIO_PROTOCOL, COMPONENT_RECENTS_LIST,
|
||||||
COMPONENT_RADIO_PROTOCOL, COMPONENT_RECENTS_LIST, COMPONENT_TEXT_ERROR, COMPONENT_TEXT_HELP,
|
COMPONENT_TEXT_ERROR, COMPONENT_TEXT_HELP,
|
||||||
};
|
|
||||||
use crate::ui::layout::{
|
|
||||||
props::{TextParts, TextSpan},
|
|
||||||
Msg, Payload,
|
|
||||||
};
|
};
|
||||||
|
use crate::ui::layout::{props::TextParts, Msg, Payload};
|
||||||
// ext
|
// ext
|
||||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
|
||||||
@@ -193,6 +190,15 @@ impl AuthActivity {
|
|||||||
self.mount_recent_del_dialog();
|
self.mount_recent_del_dialog();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
// Enter
|
||||||
|
(COMPONENT_BOOKMARKS_LIST, Msg::OnSubmit(Payload::Unsigned(idx))) => {
|
||||||
|
self.load_bookmark(*idx);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
(COMPONENT_RECENTS_LIST, Msg::OnSubmit(Payload::Unsigned(idx))) => {
|
||||||
|
self.load_recent(*idx);
|
||||||
|
None
|
||||||
|
}
|
||||||
// Bookmark radio
|
// Bookmark radio
|
||||||
// Del bookmarks
|
// Del bookmarks
|
||||||
(
|
(
|
||||||
@@ -209,16 +215,19 @@ impl AuthActivity {
|
|||||||
Some(Payload::Unsigned(index)) => {
|
Some(Payload::Unsigned(index)) => {
|
||||||
// Delete bookmark
|
// Delete bookmark
|
||||||
self.del_bookmark(index);
|
self.del_bookmark(index);
|
||||||
// TODO: view bookmarks
|
|
||||||
// Update bookmarks
|
// Update bookmarks
|
||||||
match self.view.get_props(COMPONENT_BOOKMARKS_LIST).as_mut() {
|
match self.view.get_props(COMPONENT_BOOKMARKS_LIST).as_mut() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(props) => {
|
Some(props) => {
|
||||||
let msg = self
|
let msg = self.view.update(
|
||||||
.view
|
COMPONENT_BOOKMARKS_LIST,
|
||||||
.update(COMPONENT_BOOKMARKS_LIST, props.with_texts(
|
props
|
||||||
TextParts::new(Some(String::from("Bookmarks")), Some(self.view_bookmarks()))
|
.with_texts(TextParts::new(
|
||||||
).build()); // TODO: set rows
|
Some(String::from("Bookmarks")),
|
||||||
|
Some(self.view_bookmarks()),
|
||||||
|
))
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
self.update(msg)
|
self.update(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,16 +249,19 @@ impl AuthActivity {
|
|||||||
Some(Payload::Unsigned(index)) => {
|
Some(Payload::Unsigned(index)) => {
|
||||||
// Delete recent
|
// Delete recent
|
||||||
self.del_recent(index);
|
self.del_recent(index);
|
||||||
// TODO: view recents
|
|
||||||
// Update bookmarks
|
// Update bookmarks
|
||||||
match self.view.get_props(COMPONENT_RECENTS_LIST).as_mut() {
|
match self.view.get_props(COMPONENT_RECENTS_LIST).as_mut() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(props) => {
|
Some(props) => {
|
||||||
let msg = self
|
let msg = self.view.update(
|
||||||
.view
|
COMPONENT_RECENTS_LIST,
|
||||||
.update(COMPONENT_RECENTS_LIST, props.with_texts(
|
props
|
||||||
TextParts::new(Some(String::from("Recent connections")), Some(self.view_recent_connections()))
|
.with_texts(TextParts::new(
|
||||||
).build()); // TODO: set rows
|
Some(String::from("Recent connections")),
|
||||||
|
Some(self.view_recent_connections()),
|
||||||
|
))
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
self.update(msg)
|
self.update(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +356,8 @@ impl AuthActivity {
|
|||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
// TODO: save bookmark
|
// Save bookmark
|
||||||
|
self.save_bookmark(bookmark_name, save_pwd);
|
||||||
// Umount popup
|
// Umount popup
|
||||||
self.umount_bookmark_save_dialog();
|
self.umount_bookmark_save_dialog();
|
||||||
None
|
None
|
||||||
@@ -365,44 +378,8 @@ impl AuthActivity {
|
|||||||
// On submit on any unhandled (connect)
|
// On submit on any unhandled (connect)
|
||||||
(_, Msg::OnSubmit(_)) | (_, &MSG_KEY_ENTER) => {
|
(_, Msg::OnSubmit(_)) | (_, &MSG_KEY_ENTER) => {
|
||||||
// Match <ENTER> key for all other components
|
// Match <ENTER> key for all other components
|
||||||
// Collect values from inputs
|
|
||||||
let address: String = match self.view.get_value(COMPONENT_INPUT_ADDR) {
|
|
||||||
Some(Payload::Text(addr)) => addr,
|
|
||||||
_ => {
|
|
||||||
// Show error
|
|
||||||
self.mount_error("Invalid address!");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let port: u16 = match self.view.get_value(COMPONENT_INPUT_PORT) {
|
|
||||||
Some(Payload::Unsigned(p)) => p as u16,
|
|
||||||
_ => {
|
|
||||||
// Show error
|
|
||||||
self.mount_error("Invalid port number!");
|
|
||||||
// Return None
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let username: String = match self.view.get_value(COMPONENT_INPUT_USERNAME) {
|
|
||||||
Some(Payload::Text(u)) => u,
|
|
||||||
_ => String::new(),
|
|
||||||
};
|
|
||||||
let password: String = match self.view.get_value(COMPONENT_INPUT_PASSWORD) {
|
|
||||||
Some(Payload::Text(p)) => p,
|
|
||||||
_ => String::new(),
|
|
||||||
};
|
|
||||||
let protocol: FileTransferProtocol =
|
|
||||||
match self.view.get_value(COMPONENT_RADIO_PROTOCOL) {
|
|
||||||
Some(Payload::Unsigned(choice)) => match choice {
|
|
||||||
1 => FileTransferProtocol::Scp,
|
|
||||||
2 => FileTransferProtocol::Ftp(false),
|
|
||||||
3 => FileTransferProtocol::Ftp(true),
|
|
||||||
_ => FileTransferProtocol::Sftp,
|
|
||||||
},
|
|
||||||
_ => FileTransferProtocol::Sftp,
|
|
||||||
};
|
|
||||||
// FIXME: save recent, pass attributes
|
|
||||||
self.save_recent();
|
self.save_recent();
|
||||||
|
let (address, port, protocol, username, password) = self.get_input();
|
||||||
// TOREM: remove this after removing states
|
// TOREM: remove this after removing states
|
||||||
self.address = address;
|
self.address = address;
|
||||||
self.port = port.to_string();
|
self.port = port.to_string();
|
||||||
|
|||||||
@@ -24,17 +24,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Locals
|
// Locals
|
||||||
use super::{AuthActivity, Context};
|
use super::{AuthActivity, Context, FileTransferProtocol};
|
||||||
use crate::ui::layout::components::{
|
use crate::ui::layout::components::{
|
||||||
bookmark_list::BookmarkList, input::Input, radio_group::RadioGroup, table::Table, text::Text,
|
bookmark_list::BookmarkList, ctext::CText, input::Input, radio_group::RadioGroup, table::Table,
|
||||||
|
text::Text,
|
||||||
};
|
};
|
||||||
use crate::ui::layout::props::{
|
use crate::ui::layout::props::{
|
||||||
InputType, PropValue, Props, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
InputType, PropValue, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
||||||
};
|
};
|
||||||
use crate::utils::fmt::align_text_center;
|
use crate::ui::layout::utils::draw_area_in;
|
||||||
|
use crate::ui::layout::Payload;
|
||||||
// Ext
|
// Ext
|
||||||
use tui::{
|
use tui::{
|
||||||
layout::{Constraint, Corner, Direction, Layout},
|
layout::{Constraint, Direction, Layout},
|
||||||
style::Color,
|
style::Color,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,6 +155,34 @@ impl AuthActivity {
|
|||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Bookmarks
|
||||||
|
self.view.mount(
|
||||||
|
super::COMPONENT_BOOKMARKS_LIST,
|
||||||
|
Box::new(BookmarkList::new(
|
||||||
|
PropsBuilder::default()
|
||||||
|
.with_foreground(Color::LightGreen)
|
||||||
|
.with_texts(TextParts::new(
|
||||||
|
Some(String::from("Bookmarks")),
|
||||||
|
Some(self.view_bookmarks()),
|
||||||
|
))
|
||||||
|
.build(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
// Recents
|
||||||
|
self.view.mount(
|
||||||
|
super::COMPONENT_RECENTS_LIST,
|
||||||
|
Box::new(BookmarkList::new(
|
||||||
|
PropsBuilder::default()
|
||||||
|
.with_foreground(Color::LightBlue)
|
||||||
|
.with_texts(TextParts::new(
|
||||||
|
Some(String::from("Recent connections")),
|
||||||
|
Some(self.view_recent_connections()),
|
||||||
|
))
|
||||||
|
.build(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
// Active address
|
||||||
|
self.view.active(super::COMPONENT_INPUT_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### view
|
/// ### view
|
||||||
@@ -218,8 +248,68 @@ impl AuthActivity {
|
|||||||
.render(super::COMPONENT_BOOKMARKS_LIST, f, bookmark_chunks[0]);
|
.render(super::COMPONENT_BOOKMARKS_LIST, f, bookmark_chunks[0]);
|
||||||
self.view
|
self.view
|
||||||
.render(super::COMPONENT_RECENTS_LIST, f, bookmark_chunks[1]);
|
.render(super::COMPONENT_RECENTS_LIST, f, bookmark_chunks[1]);
|
||||||
// Popup
|
// Popups
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||||
|
if props.build().visible {
|
||||||
|
// make popup
|
||||||
|
self.view.render(
|
||||||
|
super::COMPONENT_TEXT_ERROR,
|
||||||
|
f,
|
||||||
|
draw_area_in(f.size(), 50, 10),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self
|
||||||
|
.view
|
||||||
|
.get_props(super::COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK)
|
||||||
|
{
|
||||||
|
if props.build().visible {
|
||||||
|
// make popup
|
||||||
|
self.view.render(
|
||||||
|
super::COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK,
|
||||||
|
f,
|
||||||
|
draw_area_in(f.size(), 30, 10),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self
|
||||||
|
.view
|
||||||
|
.get_props(super::COMPONENT_RADIO_BOOKMARK_DEL_RECENT)
|
||||||
|
{
|
||||||
|
if props.build().visible {
|
||||||
|
// make popup
|
||||||
|
self.view.render(
|
||||||
|
super::COMPONENT_RADIO_BOOKMARK_DEL_RECENT,
|
||||||
|
f,
|
||||||
|
draw_area_in(f.size(), 30, 10),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||||
|
if props.build().visible {
|
||||||
|
// make popup
|
||||||
|
self.view.render(
|
||||||
|
super::COMPONENT_TEXT_HELP,
|
||||||
|
f,
|
||||||
|
draw_area_in(f.size(), 50, 70),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mut props) = self
|
||||||
|
.view
|
||||||
|
.get_props(super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD)
|
||||||
|
{
|
||||||
|
if props.build().visible {
|
||||||
|
// make popup
|
||||||
|
let popup = draw_area_in(f.size(), 20, 20);
|
||||||
|
self.view
|
||||||
|
.render(super::COMPONENT_INPUT_BOOKMARK_NAME, f, popup);
|
||||||
|
self.view
|
||||||
|
.render(super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD, f, popup);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
self.context = Some(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- partials
|
// -- partials
|
||||||
@@ -253,7 +343,7 @@ impl AuthActivity {
|
|||||||
// Mount
|
// Mount
|
||||||
self.view.mount(
|
self.view.mount(
|
||||||
super::COMPONENT_TEXT_ERROR,
|
super::COMPONENT_TEXT_ERROR,
|
||||||
Box::new(Text::new(
|
Box::new(CText::new(
|
||||||
PropsBuilder::default()
|
PropsBuilder::default()
|
||||||
.with_foreground(Color::Red)
|
.with_foreground(Color::Red)
|
||||||
.bold()
|
.bold()
|
||||||
@@ -459,4 +549,37 @@ impl AuthActivity {
|
|||||||
pub(super) fn umount_help(&mut self) {
|
pub(super) fn umount_help(&mut self) {
|
||||||
self.view.umount(super::COMPONENT_TEXT_HELP);
|
self.view.umount(super::COMPONENT_TEXT_HELP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### get_input
|
||||||
|
///
|
||||||
|
/// Collect input values from view
|
||||||
|
pub(super) fn get_input(&self) -> (String, u16, FileTransferProtocol, String, String) {
|
||||||
|
let addr: String = match self.view.get_value(super::COMPONENT_INPUT_ADDR) {
|
||||||
|
Some(Payload::Text(a)) => a,
|
||||||
|
_ => String::new(),
|
||||||
|
};
|
||||||
|
let port: u16 = match self.view.get_value(super::COMPONENT_INPUT_PORT) {
|
||||||
|
Some(Payload::Unsigned(p)) => p as u16,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
let protocol: FileTransferProtocol =
|
||||||
|
match self.view.get_value(super::COMPONENT_RADIO_PROTOCOL) {
|
||||||
|
Some(Payload::Unsigned(p)) => match p {
|
||||||
|
1 => FileTransferProtocol::Scp,
|
||||||
|
2 => FileTransferProtocol::Ftp(false),
|
||||||
|
3 => FileTransferProtocol::Ftp(true),
|
||||||
|
_ => FileTransferProtocol::Sftp,
|
||||||
|
},
|
||||||
|
_ => FileTransferProtocol::Sftp,
|
||||||
|
};
|
||||||
|
let username: String = match self.view.get_value(super::COMPONENT_INPUT_USERNAME) {
|
||||||
|
Some(Payload::Text(a)) => a,
|
||||||
|
_ => String::new(),
|
||||||
|
};
|
||||||
|
let password: String = match self.view.get_value(super::COMPONENT_INPUT_PASSWORD) {
|
||||||
|
Some(Payload::Text(a)) => a,
|
||||||
|
_ => String::new(),
|
||||||
|
};
|
||||||
|
(addr, port, protocol, username, password)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ pub struct PropsBuilder {
|
|||||||
props: Option<Props>,
|
props: Option<Props>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl PropsBuilder {
|
impl PropsBuilder {
|
||||||
/// ### build
|
/// ### build
|
||||||
///
|
///
|
||||||
@@ -382,6 +383,7 @@ pub struct TextSpanBuilder {
|
|||||||
text: Option<TextSpan>,
|
text: Option<TextSpan>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl TextSpanBuilder {
|
impl TextSpanBuilder {
|
||||||
/// ### new
|
/// ### new
|
||||||
///
|
///
|
||||||
@@ -456,6 +458,7 @@ impl TextSpanBuilder {
|
|||||||
///
|
///
|
||||||
/// PropValue describes a property initial value
|
/// PropValue describes a property initial value
|
||||||
#[derive(Clone, PartialEq, std::fmt::Debug)]
|
#[derive(Clone, PartialEq, std::fmt::Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub enum PropValue {
|
pub enum PropValue {
|
||||||
Str(String),
|
Str(String),
|
||||||
Unsigned(usize),
|
Unsigned(usize),
|
||||||
|
|||||||
Reference in New Issue
Block a user