mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Removed tui; added tuirealm
This commit is contained in:
@@ -32,11 +32,11 @@ extern crate dirs;
|
||||
use super::{AuthActivity, FileTransferProtocol};
|
||||
use crate::system::bookmarks_client::BookmarksClient;
|
||||
use crate::system::environment;
|
||||
use crate::ui::layout::props::PropValue;
|
||||
use crate::ui::layout::Payload;
|
||||
|
||||
// Ext
|
||||
use std::path::PathBuf;
|
||||
use tuirealm::components::{input::InputPropsBuilder, radio::RadioPropsBuilder};
|
||||
use tuirealm::{Payload, PropsBuilder};
|
||||
|
||||
impl AuthActivity {
|
||||
/// ### del_bookmark
|
||||
@@ -83,7 +83,7 @@ impl AuthActivity {
|
||||
let password: Option<String> = match save_password {
|
||||
true => match self
|
||||
.view
|
||||
.get_value(super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD)
|
||||
.get_state(super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD)
|
||||
{
|
||||
Some(Payload::Unsigned(0)) => Some(password), // Yes
|
||||
_ => None, // No such component / No
|
||||
@@ -246,32 +246,34 @@ impl AuthActivity {
|
||||
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();
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_ADDR) {
|
||||
let props = InputPropsBuilder::from(props).with_value(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::Str(port.to_string())).build();
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_PORT) {
|
||||
let props = InputPropsBuilder::from(props)
|
||||
.with_value(port.to_string())
|
||||
.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 {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_PROTOCOL) {
|
||||
let props = RadioPropsBuilder::from(props)
|
||||
.with_value(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();
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_USERNAME) {
|
||||
let props = InputPropsBuilder::from(props).with_value(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();
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_PASSWORD) {
|
||||
let props = InputPropsBuilder::from(props).with_value(password).build();
|
||||
self.view.update(super::COMPONENT_INPUT_PASSWORD, props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,18 +32,18 @@ mod view;
|
||||
|
||||
// Dependencies
|
||||
extern crate crossterm;
|
||||
extern crate tui;
|
||||
extern crate tuirealm;
|
||||
|
||||
// locals
|
||||
use super::{Activity, Context, ExitReason};
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
use crate::system::bookmarks_client::BookmarksClient;
|
||||
use crate::ui::context::FileTransferParams;
|
||||
use crate::ui::layout::view::View;
|
||||
use crate::utils::git;
|
||||
|
||||
// Includes
|
||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||
use tuirealm::View;
|
||||
|
||||
// -- components
|
||||
const COMPONENT_TEXT_HEADER: &str = "TEXT_HEADER";
|
||||
|
||||
@@ -35,7 +35,7 @@ use super::{
|
||||
COMPONENT_TEXT_HELP,
|
||||
};
|
||||
use crate::ui::activities::keymap::*;
|
||||
use crate::ui::layout::{Msg, Payload};
|
||||
use tuirealm::{Msg, Payload};
|
||||
|
||||
// -- update
|
||||
|
||||
@@ -164,7 +164,7 @@ impl AuthActivity {
|
||||
match *index {
|
||||
0 => {
|
||||
// Get selected bookmark
|
||||
match self.view.get_value(COMPONENT_BOOKMARKS_LIST) {
|
||||
match self.view.get_state(COMPONENT_BOOKMARKS_LIST) {
|
||||
Some(Payload::Unsigned(index)) => {
|
||||
// Delete bookmark
|
||||
self.del_bookmark(index);
|
||||
@@ -184,7 +184,7 @@ impl AuthActivity {
|
||||
match *index {
|
||||
0 => {
|
||||
// Get selected bookmark
|
||||
match self.view.get_value(COMPONENT_RECENTS_LIST) {
|
||||
match self.view.get_state(COMPONENT_RECENTS_LIST) {
|
||||
Some(Payload::Unsigned(index)) => {
|
||||
// Delete recent
|
||||
self.del_recent(index);
|
||||
@@ -199,36 +199,12 @@ impl AuthActivity {
|
||||
}
|
||||
// <ESC> hide tab
|
||||
(COMPONENT_RADIO_BOOKMARK_DEL_RECENT, &MSG_KEY_ESC) => {
|
||||
match self
|
||||
.view
|
||||
.get_props(COMPONENT_RADIO_BOOKMARK_DEL_RECENT)
|
||||
.as_mut()
|
||||
{
|
||||
Some(props) => {
|
||||
let msg = self.view.update(
|
||||
COMPONENT_RADIO_BOOKMARK_DEL_RECENT,
|
||||
props.hidden().build(),
|
||||
);
|
||||
self.update(msg)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
self.umount_recent_del_dialog();
|
||||
None
|
||||
}
|
||||
(COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, &MSG_KEY_ESC) => {
|
||||
match self
|
||||
.view
|
||||
.get_props(COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK)
|
||||
.as_mut()
|
||||
{
|
||||
Some(props) => {
|
||||
let msg = self.view.update(
|
||||
COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK,
|
||||
props.hidden().build(),
|
||||
);
|
||||
self.update(msg)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
self.umount_bookmark_del_dialog();
|
||||
None
|
||||
}
|
||||
// Help
|
||||
(_, &MSG_KEY_CTRL_H) => {
|
||||
@@ -269,12 +245,12 @@ impl AuthActivity {
|
||||
| (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, Msg::OnSubmit(_)) => {
|
||||
// Get values
|
||||
let bookmark_name: String =
|
||||
match self.view.get_value(COMPONENT_INPUT_BOOKMARK_NAME) {
|
||||
match self.view.get_state(COMPONENT_INPUT_BOOKMARK_NAME) {
|
||||
Some(Payload::Text(s)) => s,
|
||||
_ => String::new(),
|
||||
};
|
||||
let save_pwd: bool = matches!(
|
||||
self.view.get_value(COMPONENT_RADIO_BOOKMARK_SAVE_PWD),
|
||||
self.view.get_state(COMPONENT_RADIO_BOOKMARK_SAVE_PWD),
|
||||
Some(Payload::Unsigned(0))
|
||||
);
|
||||
// Save bookmark
|
||||
|
||||
@@ -27,20 +27,27 @@
|
||||
*/
|
||||
// Locals
|
||||
use super::{AuthActivity, Context, FileTransferProtocol};
|
||||
use crate::ui::layout::components::{
|
||||
bookmark_list::BookmarkList, input::Input, msgbox::MsgBox, radio_group::RadioGroup,
|
||||
table::Table, text::Text, title::Title,
|
||||
use crate::ui::components::{
|
||||
bookmark_list::{BookmarkList, BookmarkListPropsBuilder},
|
||||
msgbox::{MsgBox, MsgBoxPropsBuilder},
|
||||
};
|
||||
use crate::ui::layout::props::{
|
||||
InputType, PropValue, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
||||
};
|
||||
use crate::ui::layout::utils::draw_area_in;
|
||||
use crate::ui::layout::{Msg, Payload};
|
||||
use crate::utils::ui::draw_area_in;
|
||||
// Ext
|
||||
use tui::{
|
||||
use tuirealm::components::{
|
||||
input::{Input, InputPropsBuilder},
|
||||
label::{Label, LabelPropsBuilder},
|
||||
radio::{Radio, RadioPropsBuilder},
|
||||
span::{Span, SpanPropsBuilder},
|
||||
table::{Table, TablePropsBuilder},
|
||||
};
|
||||
use tuirealm::tui::{
|
||||
layout::{Constraint, Direction, Layout},
|
||||
style::Color,
|
||||
widgets::Clear,
|
||||
widgets::{BorderType, Borders, Clear},
|
||||
};
|
||||
use tuirealm::{
|
||||
props::{InputType, PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder},
|
||||
Msg, Payload,
|
||||
};
|
||||
|
||||
impl AuthActivity {
|
||||
@@ -50,35 +57,32 @@ impl AuthActivity {
|
||||
pub(super) fn init(&mut self) {
|
||||
// Header
|
||||
self.view.mount(super::COMPONENT_TEXT_HEADER, Box::new(
|
||||
Title::new(
|
||||
PropsBuilder::default().with_foreground(Color::White).with_texts(
|
||||
TextParts::new(Some(String::from(" _____ ____ ____ ____ \n|_ _|__ _ __ _ __ ___ / ___| / ___| _ \\ \n | |/ _ \\ '__| '_ ` _ \\\\___ \\| | | |_) |\n | | __/ | | | | | | |___) | |___| __/ \n |_|\\___|_| |_| |_| |_|____/ \\____|_| \n")), None)
|
||||
Label::new(
|
||||
LabelPropsBuilder::default().with_foreground(Color::White).with_text(
|
||||
String::from(" _____ ____ ____ ____ \n|_ _|__ _ __ _ __ ___ / ___| / ___| _ \\ \n | |/ _ \\ '__| '_ ` _ \\\\___ \\| | | |_) |\n | | __/ | | | | | | |___) | |___| __/ \n |_|\\___|_| |_| |_| |_|____/ \\____|_| \n")
|
||||
).bold().build()
|
||||
)
|
||||
));
|
||||
// Footer
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_FOOTER,
|
||||
Box::new(Text::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
None,
|
||||
Some(vec![
|
||||
TextSpanBuilder::new("Press ").bold().build(),
|
||||
TextSpanBuilder::new("<CTRL+H>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to show keybindings; ")
|
||||
.bold()
|
||||
.build(),
|
||||
TextSpanBuilder::new("<CTRL+C>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to enter setup").bold().build(),
|
||||
]),
|
||||
))
|
||||
Box::new(Span::new(
|
||||
SpanPropsBuilder::default()
|
||||
.with_spans(vec![
|
||||
TextSpanBuilder::new("Press ").bold().build(),
|
||||
TextSpanBuilder::new("<CTRL+H>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to show keybindings; ")
|
||||
.bold()
|
||||
.build(),
|
||||
TextSpanBuilder::new("<CTRL+C>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to enter setup").bold().build(),
|
||||
])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -86,9 +90,10 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_ADDR,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_texts(TextParts::new(Some(String::from("Remote address")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
|
||||
.with_label(String::from("Remote address"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -96,31 +101,33 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_PORT,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::LightCyan)
|
||||
.with_texts(TextParts::new(Some(String::from("Port number")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightCyan)
|
||||
.with_label(String::from("Port number"))
|
||||
.with_input(InputType::Number)
|
||||
.with_input_len(5)
|
||||
.with_value(PropValue::Str(String::from("22")))
|
||||
.with_value(String::from("22"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Protocol
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_PROTOCOL,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightGreen)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightGreen)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen)
|
||||
.with_options(
|
||||
Some(String::from("Protocol")),
|
||||
Some(vec![
|
||||
TextSpan::from("SFTP"),
|
||||
TextSpan::from("SCP"),
|
||||
TextSpan::from("FTP"),
|
||||
TextSpan::from("FTPS"),
|
||||
]),
|
||||
))
|
||||
vec![
|
||||
String::from("SFTP"),
|
||||
String::from("SCP"),
|
||||
String::from("FTP"),
|
||||
String::from("FTPS"),
|
||||
],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -128,9 +135,10 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_USERNAME,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::LightMagenta)
|
||||
.with_texts(TextParts::new(Some(String::from("Username")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightMagenta)
|
||||
.with_label(String::from("Username"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -138,9 +146,10 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_PASSWORD,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::LightBlue)
|
||||
.with_texts(TextParts::new(Some(String::from("Password")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightBlue)
|
||||
.with_label(String::from("Password"))
|
||||
.with_input(InputType::Password)
|
||||
.build(),
|
||||
)),
|
||||
@@ -155,10 +164,16 @@ impl AuthActivity {
|
||||
{
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_NEW_VERSION,
|
||||
Box::new(Text::new(
|
||||
PropsBuilder::default()
|
||||
Box::new(Span::new(
|
||||
SpanPropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_texts(TextParts::new(None, Some(vec![TextSpan::from(format!("TermSCP {} is now available! Download it from <https://github.com/veeso/termscp/releases/latest>", version))])))
|
||||
.with_spans(
|
||||
vec![
|
||||
TextSpan::from("TermSCP "),
|
||||
TextSpanBuilder::new(version).underlined().bold().build(),
|
||||
TextSpan::from(" is now available! Download it from <https://github.com/veeso/termscp/releases/latest>")
|
||||
]
|
||||
)
|
||||
.build()
|
||||
))
|
||||
);
|
||||
@@ -167,10 +182,11 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_BOOKMARKS_LIST,
|
||||
Box::new(BookmarkList::new(
|
||||
PropsBuilder::default()
|
||||
BookmarkListPropsBuilder::default()
|
||||
.with_background(Color::LightGreen)
|
||||
.with_foreground(Color::Black)
|
||||
.with_texts(TextParts::new(Some(String::from("Bookmarks")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::LightGreen)
|
||||
.with_bookmarks(Some(String::from("Bookmarks")), vec![])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -179,13 +195,11 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RECENTS_LIST,
|
||||
Box::new(BookmarkList::new(
|
||||
PropsBuilder::default()
|
||||
BookmarkListPropsBuilder::default()
|
||||
.with_background(Color::LightBlue)
|
||||
.with_foreground(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Recent connections")),
|
||||
None,
|
||||
))
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::LightBlue)
|
||||
.with_bookmarks(Some(String::from("Recent connections")), vec![])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -258,27 +272,27 @@ impl AuthActivity {
|
||||
self.view
|
||||
.render(super::COMPONENT_RECENTS_LIST, f, bookmark_chunks[1]);
|
||||
// Popups
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_ERROR, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_QUIT) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_QUIT) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
self.view.render(super::COMPONENT_RADIO_QUIT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK)
|
||||
{
|
||||
if props.build().visible {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
@@ -286,11 +300,11 @@ impl AuthActivity {
|
||||
.render(super::COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_RADIO_BOOKMARK_DEL_RECENT)
|
||||
{
|
||||
if props.build().visible {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
@@ -298,19 +312,19 @@ impl AuthActivity {
|
||||
.render(super::COMPONENT_RADIO_BOOKMARK_DEL_RECENT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 50, 70);
|
||||
f.render_widget(Clear, popup);
|
||||
self.view.render(super::COMPONENT_TEXT_HELP, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD)
|
||||
{
|
||||
if props.build().visible {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 20, 20);
|
||||
f.render_widget(Clear, popup);
|
||||
@@ -340,7 +354,7 @@ impl AuthActivity {
|
||||
///
|
||||
/// Make text span from bookmarks
|
||||
pub(super) fn view_bookmarks(&mut self) -> Option<(String, Msg)> {
|
||||
let bookmarks: Vec<TextSpan> = self
|
||||
let bookmarks: Vec<String> = self
|
||||
.bookmarks_list
|
||||
.iter()
|
||||
.map(|x| {
|
||||
@@ -350,33 +364,23 @@ impl AuthActivity {
|
||||
.unwrap()
|
||||
.get_bookmark(x)
|
||||
.unwrap();
|
||||
TextSpan::from(
|
||||
format!(
|
||||
"{} ({}://{}@{}:{})",
|
||||
x,
|
||||
entry.2.to_string().to_lowercase(),
|
||||
entry.3,
|
||||
entry.0,
|
||||
entry.1
|
||||
)
|
||||
.as_str(),
|
||||
format!(
|
||||
"{} ({}://{}@{}:{})",
|
||||
x,
|
||||
entry.2.to_string().to_lowercase(),
|
||||
entry.3,
|
||||
entry.0,
|
||||
entry.1
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
match self
|
||||
.view
|
||||
.get_props(super::COMPONENT_BOOKMARKS_LIST)
|
||||
.as_mut()
|
||||
{
|
||||
match self.view.get_props(super::COMPONENT_BOOKMARKS_LIST) {
|
||||
None => None,
|
||||
Some(props) => {
|
||||
let msg = self.view.update(
|
||||
super::COMPONENT_BOOKMARKS_LIST,
|
||||
props
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Bookmarks")),
|
||||
Some(bookmarks),
|
||||
))
|
||||
BookmarkListPropsBuilder::from(props)
|
||||
.with_bookmarks(Some(String::from("Bookmarks")), bookmarks)
|
||||
.build(),
|
||||
);
|
||||
msg
|
||||
@@ -388,7 +392,7 @@ impl AuthActivity {
|
||||
///
|
||||
/// View recent connections
|
||||
pub(super) fn view_recent_connections(&mut self) -> Option<(String, Msg)> {
|
||||
let bookmarks: Vec<TextSpan> = self
|
||||
let bookmarks: Vec<String> = self
|
||||
.recents_list
|
||||
.iter()
|
||||
.map(|x| {
|
||||
@@ -398,28 +402,23 @@ impl AuthActivity {
|
||||
.unwrap()
|
||||
.get_recent(x)
|
||||
.unwrap();
|
||||
TextSpan::from(
|
||||
format!(
|
||||
"{}://{}@{}:{}",
|
||||
entry.2.to_string().to_lowercase(),
|
||||
entry.3,
|
||||
entry.0,
|
||||
entry.1
|
||||
)
|
||||
.as_str(),
|
||||
|
||||
format!(
|
||||
"{}://{}@{}:{}",
|
||||
entry.2.to_string().to_lowercase(),
|
||||
entry.3,
|
||||
entry.0,
|
||||
entry.1
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
match self.view.get_props(super::COMPONENT_RECENTS_LIST).as_mut() {
|
||||
match self.view.get_props(super::COMPONENT_RECENTS_LIST) {
|
||||
None => None,
|
||||
Some(props) => {
|
||||
let msg = self.view.update(
|
||||
super::COMPONENT_RECENTS_LIST,
|
||||
props
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Recent connections")),
|
||||
Some(bookmarks),
|
||||
))
|
||||
BookmarkListPropsBuilder::from(props)
|
||||
.with_bookmarks(Some(String::from("Recent connections")), bookmarks)
|
||||
.build(),
|
||||
);
|
||||
msg
|
||||
@@ -437,10 +436,11 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_ERROR,
|
||||
Box::new(MsgBox::new(
|
||||
PropsBuilder::default()
|
||||
MsgBoxPropsBuilder::default()
|
||||
.with_foreground(Color::Red)
|
||||
.with_borders(Borders::ALL, BorderType::Thick, Color::Red)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(None, Some(vec![TextSpan::from(text)])))
|
||||
.with_texts(None, vec![TextSpan::from(text)])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -462,14 +462,15 @@ impl AuthActivity {
|
||||
// Protocol
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_QUIT,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Yellow)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Yellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_options(
|
||||
Some(String::from("Quit TermSCP?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -489,15 +490,16 @@ impl AuthActivity {
|
||||
pub(super) fn mount_bookmark_del_dialog(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Yellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Yellow)
|
||||
.with_options(
|
||||
Some(String::from("Delete bookmark?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(1))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.with_value(1)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -520,15 +522,16 @@ impl AuthActivity {
|
||||
pub(super) fn mount_recent_del_dialog(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_BOOKMARK_DEL_RECENT,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Yellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Yellow)
|
||||
.with_options(
|
||||
Some(String::from("Delete bookmark?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(1))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.with_value(1)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -550,27 +553,31 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_BOOKMARK_NAME,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::LightCyan)
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Save bookmark as...")),
|
||||
None,
|
||||
))
|
||||
//.with_borders(Borders::TOP | Borders::RIGHT | Borders::LEFT)
|
||||
.with_label(String::from("Save bookmark as..."))
|
||||
.with_borders(
|
||||
Borders::TOP | Borders::RIGHT | Borders::LEFT,
|
||||
BorderType::Rounded,
|
||||
Color::Reset,
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_BOOKMARK_SAVE_PWD,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Red)
|
||||
//.with_borders(Borders::BOTTOM | Borders::RIGHT | Borders::LEFT)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Red)
|
||||
.with_borders(
|
||||
Borders::BOTTOM | Borders::RIGHT | Borders::LEFT,
|
||||
BorderType::Rounded,
|
||||
Color::Reset,
|
||||
)
|
||||
.with_options(
|
||||
Some(String::from("Save password?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
//.with_value(PropValue::Unsigned(1))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -593,8 +600,9 @@ impl AuthActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_HELP,
|
||||
Box::new(Table::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::table(
|
||||
TablePropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_table(
|
||||
Some(String::from("Help")),
|
||||
TableBuilder::default()
|
||||
.add_col(
|
||||
@@ -661,7 +669,7 @@ impl AuthActivity {
|
||||
)
|
||||
.add_col(TextSpan::from(" Save bookmark"))
|
||||
.build(),
|
||||
))
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -680,16 +688,16 @@ impl AuthActivity {
|
||||
///
|
||||
/// 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) {
|
||||
let addr: String = match self.view.get_state(super::COMPONENT_INPUT_ADDR) {
|
||||
Some(Payload::Text(a)) => a,
|
||||
_ => String::new(),
|
||||
};
|
||||
let port: u16 = match self.view.get_value(super::COMPONENT_INPUT_PORT) {
|
||||
let port: u16 = match self.view.get_state(super::COMPONENT_INPUT_PORT) {
|
||||
Some(Payload::Unsigned(p)) => p as u16,
|
||||
_ => 0,
|
||||
};
|
||||
let protocol: FileTransferProtocol =
|
||||
match self.view.get_value(super::COMPONENT_RADIO_PROTOCOL) {
|
||||
match self.view.get_state(super::COMPONENT_RADIO_PROTOCOL) {
|
||||
Some(Payload::Unsigned(p)) => match p {
|
||||
1 => FileTransferProtocol::Scp,
|
||||
2 => FileTransferProtocol::Ftp(false),
|
||||
@@ -698,11 +706,11 @@ impl AuthActivity {
|
||||
},
|
||||
_ => FileTransferProtocol::Sftp,
|
||||
};
|
||||
let username: String = match self.view.get_value(super::COMPONENT_INPUT_USERNAME) {
|
||||
let username: String = match self.view.get_state(super::COMPONENT_INPUT_USERNAME) {
|
||||
Some(Payload::Text(a)) => a,
|
||||
_ => String::new(),
|
||||
};
|
||||
let password: String = match self.view.get_value(super::COMPONENT_INPUT_PASSWORD) {
|
||||
let password: String = match self.view.get_state(super::COMPONENT_INPUT_PASSWORD) {
|
||||
Some(Payload::Text(a)) => a,
|
||||
_ => String::new(),
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
*/
|
||||
// locals
|
||||
use super::{FileExplorerTab, FileTransferActivity, FsEntry, LogLevel};
|
||||
use crate::ui::layout::Payload;
|
||||
use tuirealm::Payload;
|
||||
// externals
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -622,7 +622,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Get index of selected file in the local tab
|
||||
fn get_local_file_idx(&self) -> Option<usize> {
|
||||
match self.view.get_value(super::COMPONENT_EXPLORER_LOCAL) {
|
||||
match self.view.get_state(super::COMPONENT_EXPLORER_LOCAL) {
|
||||
Some(Payload::Unsigned(idx)) => Some(idx),
|
||||
_ => None,
|
||||
}
|
||||
@@ -632,7 +632,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Get index of selected file in the remote file
|
||||
fn get_remote_file_idx(&self) -> Option<usize> {
|
||||
match self.view.get_value(super::COMPONENT_EXPLORER_REMOTE) {
|
||||
match self.view.get_state(super::COMPONENT_EXPLORER_REMOTE) {
|
||||
Some(Payload::Unsigned(idx)) => Some(idx),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ mod view;
|
||||
extern crate chrono;
|
||||
extern crate crossterm;
|
||||
extern crate textwrap;
|
||||
extern crate tui;
|
||||
extern crate tuirealm;
|
||||
|
||||
// locals
|
||||
use super::{Activity, Context, ExitReason};
|
||||
@@ -47,7 +47,6 @@ use crate::filetransfer::{FileTransfer, FileTransferProtocol};
|
||||
use crate::fs::explorer::FileExplorer;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::system::config_client::ConfigClient;
|
||||
use crate::ui::layout::view::View;
|
||||
|
||||
// Includes
|
||||
use chrono::{DateTime, Local};
|
||||
@@ -55,6 +54,7 @@ use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||
use std::collections::VecDeque;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use tuirealm::View;
|
||||
|
||||
// -- Storage keys
|
||||
|
||||
|
||||
@@ -40,14 +40,16 @@ use super::{
|
||||
use crate::fs::explorer::FileSorting;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::ui::activities::keymap::*;
|
||||
use crate::ui::layout::props::{
|
||||
PropValue, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
||||
};
|
||||
use crate::ui::layout::{Msg, Payload};
|
||||
use crate::ui::components::{file_list::FileListPropsBuilder, logbox::LogboxPropsBuilder};
|
||||
// externals
|
||||
use bytesize::ByteSize;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tui::style::Color;
|
||||
use tuirealm::{
|
||||
components::progress_bar::ProgressBarPropsBuilder,
|
||||
props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder},
|
||||
tui::style::Color,
|
||||
Msg, Payload,
|
||||
};
|
||||
|
||||
impl FileTransferActivity {
|
||||
// -- update
|
||||
@@ -394,7 +396,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
(COMPONENT_EXPLORER_FIND, &MSG_KEY_SPACE) => {
|
||||
// Get entry
|
||||
match self.view.get_value(COMPONENT_EXPLORER_FIND) {
|
||||
match self.view.get_state(COMPONENT_EXPLORER_FIND) {
|
||||
Some(Payload::Unsigned(idx)) => {
|
||||
self.action_find_transfer(idx, None);
|
||||
// Reload files
|
||||
@@ -585,7 +587,7 @@ impl FileTransferActivity {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::FindRemote => {
|
||||
// Get entry
|
||||
if let Some(Payload::Unsigned(idx)) =
|
||||
self.view.get_value(COMPONENT_EXPLORER_FIND)
|
||||
self.view.get_state(COMPONENT_EXPLORER_FIND)
|
||||
{
|
||||
self.action_find_transfer(idx, Some(input.to_string()));
|
||||
}
|
||||
@@ -621,7 +623,7 @@ impl FileTransferActivity {
|
||||
FileExplorerTab::FindLocal | FileExplorerTab::FindRemote => {
|
||||
// Get entry
|
||||
if let Some(Payload::Unsigned(idx)) =
|
||||
self.view.get_value(COMPONENT_EXPLORER_FIND)
|
||||
self.view.get_state(COMPONENT_EXPLORER_FIND)
|
||||
{
|
||||
self.action_find_delete(idx);
|
||||
// Reload entries
|
||||
@@ -662,11 +664,12 @@ impl FileTransferActivity {
|
||||
None
|
||||
}
|
||||
// -- sorting
|
||||
(COMPONENT_RADIO_SORTING, &MSG_KEY_ESC) => {
|
||||
(COMPONENT_RADIO_SORTING, &MSG_KEY_ESC)
|
||||
| (COMPONENT_RADIO_SORTING, Msg::OnSubmit(_)) => {
|
||||
self.umount_file_sorting();
|
||||
None
|
||||
}
|
||||
(COMPONENT_RADIO_SORTING, Msg::OnSubmit(Payload::Unsigned(mode))) => {
|
||||
(COMPONENT_RADIO_SORTING, Msg::OnChange(Payload::Unsigned(mode))) => {
|
||||
// Get sorting mode
|
||||
let sorting: FileSorting = match mode {
|
||||
1 => FileSorting::ByModifyTime,
|
||||
@@ -679,7 +682,6 @@ impl FileTransferActivity {
|
||||
FileExplorerTab::Remote => self.remote.sort_by(sorting),
|
||||
_ => panic!("Found result doesn't support SORTING"),
|
||||
}
|
||||
self.umount_file_sorting();
|
||||
// Reload files
|
||||
match self.tab {
|
||||
FileExplorerTab::Local => self.update_local_filelist(),
|
||||
@@ -718,11 +720,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Update local file list
|
||||
pub(super) fn update_local_filelist(&mut self) -> Option<(String, Msg)> {
|
||||
match self
|
||||
.view
|
||||
.get_props(super::COMPONENT_EXPLORER_LOCAL)
|
||||
.as_mut()
|
||||
{
|
||||
match self.view.get_props(super::COMPONENT_EXPLORER_LOCAL) {
|
||||
Some(props) => {
|
||||
// Get width
|
||||
let width: usize = self
|
||||
@@ -750,14 +748,14 @@ impl FileTransferActivity {
|
||||
)
|
||||
.display()
|
||||
);
|
||||
let files: Vec<TextSpan> = self
|
||||
let files: Vec<String> = self
|
||||
.local
|
||||
.iter_files()
|
||||
.map(|x: &FsEntry| TextSpan::from(self.local.fmt_file(x)))
|
||||
.map(|x: &FsEntry| self.local.fmt_file(x))
|
||||
.collect();
|
||||
// Update
|
||||
let props = props
|
||||
.with_texts(TextParts::new(Some(hostname), Some(files)))
|
||||
let props = FileListPropsBuilder::from(props)
|
||||
.with_files(Some(hostname), files)
|
||||
.build();
|
||||
// Update
|
||||
self.view.update(super::COMPONENT_EXPLORER_LOCAL, props)
|
||||
@@ -770,11 +768,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Update remote file list
|
||||
pub(super) fn update_remote_filelist(&mut self) -> Option<(String, Msg)> {
|
||||
match self
|
||||
.view
|
||||
.get_props(super::COMPONENT_EXPLORER_REMOTE)
|
||||
.as_mut()
|
||||
{
|
||||
match self.view.get_props(super::COMPONENT_EXPLORER_REMOTE) {
|
||||
Some(props) => {
|
||||
// Get width
|
||||
let width: usize = self
|
||||
@@ -795,14 +789,14 @@ impl FileTransferActivity {
|
||||
)
|
||||
.display()
|
||||
);
|
||||
let files: Vec<TextSpan> = self
|
||||
let files: Vec<String> = self
|
||||
.remote
|
||||
.iter_files()
|
||||
.map(|x: &FsEntry| TextSpan::from(self.remote.fmt_file(x)))
|
||||
.map(|x: &FsEntry| self.remote.fmt_file(x))
|
||||
.collect();
|
||||
// Update
|
||||
let props = props
|
||||
.with_texts(TextParts::new(Some(hostname), Some(files)))
|
||||
let props = FileListPropsBuilder::from(props)
|
||||
.with_files(Some(hostname), files)
|
||||
.build();
|
||||
self.view.update(super::COMPONENT_EXPLORER_REMOTE, props)
|
||||
}
|
||||
@@ -814,7 +808,7 @@ impl FileTransferActivity {
|
||||
///
|
||||
/// Update log box
|
||||
pub(super) fn update_logbox(&mut self) -> Option<(String, Msg)> {
|
||||
match self.view.get_props(super::COMPONENT_LOG_BOX).as_mut() {
|
||||
match self.view.get_props(super::COMPONENT_LOG_BOX) {
|
||||
Some(props) => {
|
||||
// Get width
|
||||
let width: usize = self
|
||||
@@ -876,8 +870,8 @@ impl FileTransferActivity {
|
||||
}
|
||||
}
|
||||
let table = table.build();
|
||||
let props = props
|
||||
.with_texts(TextParts::table(Some(String::from("Log")), table))
|
||||
let props = LogboxPropsBuilder::from(props)
|
||||
.with_log(Some(String::from("Log")), table)
|
||||
.build();
|
||||
self.view.update(super::COMPONENT_LOG_BOX, props)
|
||||
}
|
||||
@@ -886,7 +880,7 @@ impl FileTransferActivity {
|
||||
}
|
||||
|
||||
pub(super) fn update_progress_bar(&mut self, text: String) -> Option<(String, Msg)> {
|
||||
match self.view.get_props(COMPONENT_PROGRESS_BAR).as_mut() {
|
||||
match self.view.get_props(COMPONENT_PROGRESS_BAR) {
|
||||
Some(props) => {
|
||||
// Calculate ETA
|
||||
let elapsed_secs: u64 = self.transfer.started.elapsed().as_secs();
|
||||
@@ -905,12 +899,9 @@ impl FileTransferActivity {
|
||||
eta,
|
||||
ByteSize(self.transfer.bytes_per_second())
|
||||
);
|
||||
let props = props
|
||||
.with_texts(TextParts::new(
|
||||
Some(text),
|
||||
Some(vec![TextSpan::from(label)]),
|
||||
))
|
||||
.with_value(PropValue::Float(self.transfer.progress / 100.0))
|
||||
let props = ProgressBarPropsBuilder::from(props)
|
||||
.with_texts(Some(text), label)
|
||||
.with_progress(self.transfer.progress / 100.0)
|
||||
.build();
|
||||
self.view.update(COMPONENT_PROGRESS_BAR, props)
|
||||
}
|
||||
@@ -933,22 +924,20 @@ impl FileTransferActivity {
|
||||
}
|
||||
|
||||
fn update_find_list(&mut self) -> Option<(String, Msg)> {
|
||||
match self.view.get_props(COMPONENT_EXPLORER_FIND).as_mut() {
|
||||
match self.view.get_props(COMPONENT_EXPLORER_FIND) {
|
||||
None => None,
|
||||
Some(props) => {
|
||||
let props = props.build();
|
||||
let title: String = props.texts.title.clone().unwrap_or_default();
|
||||
let mut props = PropsBuilder::from(props);
|
||||
// Prepare files
|
||||
let file_texts: Vec<TextSpan> = self
|
||||
let files: Vec<String> = self
|
||||
.found
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter_files()
|
||||
.map(|x: &FsEntry| TextSpan::from(self.found.as_ref().unwrap().fmt_file(x)))
|
||||
.map(|x: &FsEntry| self.found.as_ref().unwrap().fmt_file(x))
|
||||
.collect();
|
||||
let props = props
|
||||
.with_texts(TextParts::new(Some(title), Some(file_texts)))
|
||||
let props = FileListPropsBuilder::from(props)
|
||||
.with_files(Some(title), files)
|
||||
.build();
|
||||
self.view.update(COMPONENT_EXPLORER_FIND, props)
|
||||
}
|
||||
|
||||
@@ -34,23 +34,28 @@ extern crate users;
|
||||
use super::{Context, FileExplorerTab, FileTransferActivity};
|
||||
use crate::fs::explorer::FileSorting;
|
||||
use crate::fs::FsEntry;
|
||||
use crate::ui::layout::components::{
|
||||
file_list::FileList, input::Input, logbox::LogBox, msgbox::MsgBox, progress_bar::ProgressBar,
|
||||
radio_group::RadioGroup, table::Table,
|
||||
use crate::ui::components::{
|
||||
file_list::{FileList, FileListPropsBuilder},
|
||||
logbox::{LogBox, LogboxPropsBuilder},
|
||||
msgbox::{MsgBox, MsgBoxPropsBuilder},
|
||||
};
|
||||
use crate::ui::layout::props::{
|
||||
PropValue, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
||||
};
|
||||
use crate::ui::layout::utils::draw_area_in;
|
||||
use crate::ui::store::Store;
|
||||
use crate::utils::fmt::fmt_time;
|
||||
use crate::utils::ui::draw_area_in;
|
||||
// Ext
|
||||
use bytesize::ByteSize;
|
||||
use std::path::PathBuf;
|
||||
use tui::{
|
||||
use tuirealm::components::{
|
||||
input::{Input, InputPropsBuilder},
|
||||
progress_bar::{ProgressBar, ProgressBarPropsBuilder},
|
||||
radio::{Radio, RadioPropsBuilder},
|
||||
table::{Table, TablePropsBuilder},
|
||||
};
|
||||
use tuirealm::props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder};
|
||||
use tuirealm::tui::{
|
||||
layout::{Constraint, Direction, Layout},
|
||||
style::Color,
|
||||
widgets::Clear,
|
||||
widgets::{BorderType, Borders, Clear},
|
||||
};
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
use users::{get_group_by_gid, get_user_by_uid};
|
||||
@@ -66,9 +71,10 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_EXPLORER_LOCAL,
|
||||
Box::new(FileList::new(
|
||||
PropsBuilder::default()
|
||||
FileListPropsBuilder::default()
|
||||
.with_background(Color::Yellow)
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::Yellow)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -76,9 +82,10 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_EXPLORER_REMOTE,
|
||||
Box::new(FileList::new(
|
||||
PropsBuilder::default()
|
||||
FileListPropsBuilder::default()
|
||||
.with_background(Color::LightBlue)
|
||||
.with_foreground(Color::LightBlue)
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::LightBlue)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -86,9 +93,8 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_LOG_BOX,
|
||||
Box::new(LogBox::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightGreen)
|
||||
.bold()
|
||||
LogboxPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::LightGreen)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -156,96 +162,96 @@ impl FileTransferActivity {
|
||||
// Draw log box
|
||||
self.view.render(super::COMPONENT_LOG_BOX, f, chunks[1]);
|
||||
// @! Draw popups
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_COPY) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_COPY) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_COPY, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_FIND) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_FIND) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_FIND, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_GOTO) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_GOTO) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_GOTO, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_MKDIR) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_MKDIR) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_MKDIR, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_NEWFILE) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_NEWFILE) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_NEWFILE, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_RENAME) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_RENAME) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_RENAME, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_SAVEAS) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_SAVEAS) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_SAVEAS, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_EXEC) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_EXEC) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_INPUT_EXEC, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_LIST_FILEINFO) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_LIST_FILEINFO) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 50);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_LIST_FILEINFO, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_PROGRESS_BAR) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_PROGRESS_BAR) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_PROGRESS_BAR, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_DELETE) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_DELETE) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_RADIO_DELETE, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_DISCONNECT) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_DISCONNECT) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
@@ -253,48 +259,48 @@ impl FileTransferActivity {
|
||||
.render(super::COMPONENT_RADIO_DISCONNECT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_QUIT) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_QUIT) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_RADIO_QUIT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_SORTING) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_SORTING) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_RADIO_SORTING, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_ERROR, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_FATAL) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_FATAL) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_FATAL, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_WAIT) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_WAIT) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_WAIT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 80);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
@@ -316,10 +322,11 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_ERROR,
|
||||
Box::new(MsgBox::new(
|
||||
PropsBuilder::default()
|
||||
MsgBoxPropsBuilder::default()
|
||||
.with_foreground(Color::Red)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Red)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(None, Some(vec![TextSpan::from(text)])))
|
||||
.with_texts(None, vec![TextSpan::from(text)])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -339,10 +346,11 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_FATAL,
|
||||
Box::new(MsgBox::new(
|
||||
PropsBuilder::default()
|
||||
MsgBoxPropsBuilder::default()
|
||||
.with_foreground(Color::Red)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Red)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(None, Some(vec![TextSpan::from(text)])))
|
||||
.with_texts(None, vec![TextSpan::from(text)])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -355,10 +363,11 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_WAIT,
|
||||
Box::new(MsgBox::new(
|
||||
PropsBuilder::default()
|
||||
MsgBoxPropsBuilder::default()
|
||||
.with_foreground(Color::White)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(None, Some(vec![TextSpan::from(text)])))
|
||||
.with_texts(None, vec![TextSpan::from(text)])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -377,14 +386,15 @@ impl FileTransferActivity {
|
||||
// Protocol
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_QUIT,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Yellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Yellow)
|
||||
.with_options(
|
||||
Some(String::from("Are you sure you want to quit?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -405,14 +415,15 @@ impl FileTransferActivity {
|
||||
// Protocol
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_DISCONNECT,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Yellow)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Yellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Yellow)
|
||||
.with_options(
|
||||
Some(String::from("Are you sure you want to disconnect?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -430,11 +441,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_COPY,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Insert destination name")),
|
||||
None,
|
||||
))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("Insert destination name"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -449,8 +458,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_EXEC,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(Some(String::from("Execute command")), None))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::White)
|
||||
.with_label(String::from("Execute command"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -471,11 +481,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_EXPLORER_FIND,
|
||||
Box::new(FileList::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(format!("Search results for \"{}\"", search)),
|
||||
Some(vec![]),
|
||||
))
|
||||
FileListPropsBuilder::default()
|
||||
.with_files(Some(format!("Search results for \"{}\"", search)), vec![])
|
||||
.with_borders(Borders::ALL, BorderType::Plain, color)
|
||||
.with_background(color)
|
||||
.with_foreground(color)
|
||||
.build(),
|
||||
@@ -493,11 +501,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_FIND,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Search files by name")),
|
||||
None,
|
||||
))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("Search files by name"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -514,11 +520,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_GOTO,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Change working directory")),
|
||||
None,
|
||||
))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("Change working directory"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -533,11 +537,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_MKDIR,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Insert directory name")),
|
||||
None,
|
||||
))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("Insert directory name"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -552,8 +554,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_NEWFILE,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(Some(String::from("New file name")), None))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("New file name"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -568,8 +571,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_RENAME,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(Some(String::from("Insert new name")), None))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("Insert new name"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -584,8 +588,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_SAVEAS,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(Some(String::from("Save as...")), None))
|
||||
InputPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_label(String::from("Save as..."))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -600,10 +605,11 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_PROGRESS_BAR,
|
||||
Box::new(ProgressBar::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightGreen)
|
||||
ProgressBarPropsBuilder::default()
|
||||
.with_progbar_color(Color::LightGreen)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(Some(String::from("Please wait")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen)
|
||||
.with_texts(Some(String::from("Please wait")), String::new())
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -628,20 +634,21 @@ impl FileTransferActivity {
|
||||
};
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_SORTING,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightMagenta)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightMagenta)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightMagenta)
|
||||
.with_options(
|
||||
Some(String::from("Sort files by")),
|
||||
Some(vec![
|
||||
TextSpan::from("Name"),
|
||||
TextSpan::from("Modify time"),
|
||||
TextSpan::from("Creation time"),
|
||||
TextSpan::from("Size"),
|
||||
]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(index))
|
||||
vec![
|
||||
String::from("Name"),
|
||||
String::from("Modify time"),
|
||||
String::from("Creation time"),
|
||||
String::from("Size"),
|
||||
],
|
||||
)
|
||||
.with_value(index)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -655,15 +662,16 @@ impl FileTransferActivity {
|
||||
pub(super) fn mount_radio_delete(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_DELETE,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::Red)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::Red)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::Red)
|
||||
.with_options(
|
||||
Some(String::from("Delete file")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(1))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.with_value(1)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -772,11 +780,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_LIST_FILEINFO,
|
||||
Box::new(Table::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::table(
|
||||
Some(file.get_name().to_string()),
|
||||
texts.build(),
|
||||
))
|
||||
TablePropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_table(Some(file.get_name().to_string()), texts.build())
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -794,8 +800,9 @@ impl FileTransferActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_HELP,
|
||||
Box::new(Table::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::table(
|
||||
TablePropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_table(
|
||||
Some(String::from("Help")),
|
||||
TableBuilder::default()
|
||||
.add_col(
|
||||
@@ -984,7 +991,7 @@ impl FileTransferActivity {
|
||||
)
|
||||
.add_col(TextSpan::from(" Interrupt file transfer"))
|
||||
.build(),
|
||||
))
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use crate::ui::layout::Msg;
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use tuirealm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use tuirealm::Msg;
|
||||
|
||||
// -- Special keys
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
*/
|
||||
// Locals
|
||||
use super::SetupActivity;
|
||||
use crate::ui::layout::Payload;
|
||||
// Ext
|
||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||
use std::env;
|
||||
use tuirealm::Payload;
|
||||
|
||||
impl SetupActivity {
|
||||
/// ### action_save_config
|
||||
@@ -63,7 +63,7 @@ impl SetupActivity {
|
||||
// Get key
|
||||
if let Some(config_cli) = self.context.as_mut().unwrap().config_client.as_mut() {
|
||||
// get index
|
||||
let idx: Option<usize> = match self.view.get_value(super::COMPONENT_LIST_SSH_KEYS) {
|
||||
let idx: Option<usize> = match self.view.get_state(super::COMPONENT_LIST_SSH_KEYS) {
|
||||
Some(Payload::Unsigned(idx)) => Some(idx),
|
||||
_ => None,
|
||||
};
|
||||
@@ -99,11 +99,11 @@ impl SetupActivity {
|
||||
pub(super) fn action_new_ssh_key(&mut self) {
|
||||
if let Some(cli) = self.context.as_mut().unwrap().config_client.as_mut() {
|
||||
// get parameters
|
||||
let host: String = match self.view.get_value(super::COMPONENT_INPUT_SSH_HOST) {
|
||||
let host: String = match self.view.get_state(super::COMPONENT_INPUT_SSH_HOST) {
|
||||
Some(Payload::Text(host)) => host,
|
||||
_ => String::new(),
|
||||
};
|
||||
let username: String = match self.view.get_value(super::COMPONENT_INPUT_SSH_USERNAME) {
|
||||
let username: String = match self.view.get_state(super::COMPONENT_INPUT_SSH_USERNAME) {
|
||||
Some(Payload::Text(user)) => user,
|
||||
_ => String::new(),
|
||||
};
|
||||
|
||||
@@ -34,13 +34,13 @@ mod view;
|
||||
|
||||
// Deps
|
||||
extern crate crossterm;
|
||||
extern crate tui;
|
||||
extern crate tuirealm;
|
||||
|
||||
// Locals
|
||||
use super::{Activity, Context, ExitReason};
|
||||
use crate::ui::layout::view::View;
|
||||
// Ext
|
||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||
use tuirealm::View;
|
||||
|
||||
// -- components
|
||||
const COMPONENT_TEXT_HELP: &str = "TEXT_HELP";
|
||||
|
||||
@@ -35,7 +35,9 @@ use super::{
|
||||
COMPONENT_RADIO_UPDATES, COMPONENT_TEXT_ERROR, COMPONENT_TEXT_HELP,
|
||||
};
|
||||
use crate::ui::activities::keymap::*;
|
||||
use crate::ui::layout::{Msg, Payload};
|
||||
|
||||
// ext
|
||||
use tuirealm::{Msg, Payload};
|
||||
|
||||
impl SetupActivity {
|
||||
/// ### update
|
||||
|
||||
@@ -30,22 +30,27 @@
|
||||
use super::{Context, SetupActivity, ViewLayout};
|
||||
use crate::filetransfer::FileTransferProtocol;
|
||||
use crate::fs::explorer::GroupDirs;
|
||||
use crate::ui::layout::components::{
|
||||
bookmark_list::BookmarkList, input::Input, msgbox::MsgBox, radio_group::RadioGroup,
|
||||
table::Table, text::Text,
|
||||
use crate::ui::components::{
|
||||
bookmark_list::{BookmarkList, BookmarkListPropsBuilder},
|
||||
msgbox::{MsgBox, MsgBoxPropsBuilder},
|
||||
};
|
||||
use crate::ui::layout::props::{
|
||||
PropValue, PropsBuilder, TableBuilder, TextParts, TextSpan, TextSpanBuilder,
|
||||
};
|
||||
use crate::ui::layout::utils::draw_area_in;
|
||||
use crate::ui::layout::view::View;
|
||||
use crate::ui::layout::Payload;
|
||||
use crate::utils::ui::draw_area_in;
|
||||
// Ext
|
||||
use std::path::PathBuf;
|
||||
use tui::{
|
||||
use tuirealm::components::{
|
||||
input::{Input, InputPropsBuilder},
|
||||
radio::{Radio, RadioPropsBuilder},
|
||||
span::{Span, SpanPropsBuilder},
|
||||
table::{Table, TablePropsBuilder},
|
||||
};
|
||||
use tuirealm::tui::{
|
||||
layout::{Constraint, Direction, Layout},
|
||||
style::Color,
|
||||
widgets::{Borders, Clear},
|
||||
widgets::{BorderType, Borders, Clear},
|
||||
};
|
||||
use tuirealm::{
|
||||
props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder},
|
||||
Payload, View,
|
||||
};
|
||||
|
||||
impl SetupActivity {
|
||||
@@ -61,38 +66,32 @@ impl SetupActivity {
|
||||
// Radio tab
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_TAB,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightYellow)
|
||||
.with_background(Color::Black)
|
||||
.with_borders(Borders::BOTTOM)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightYellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::BOTTOM, BorderType::Thick, Color::White)
|
||||
.with_options(
|
||||
None,
|
||||
Some(vec![
|
||||
TextSpan::from("User Interface"),
|
||||
TextSpan::from("SSH Keys"),
|
||||
]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(0))
|
||||
vec![String::from("User Interface"), String::from("SSH Keys")],
|
||||
)
|
||||
.with_value(0)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Footer
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_FOOTER,
|
||||
Box::new(Text::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
None,
|
||||
Some(vec![
|
||||
TextSpanBuilder::new("Press ").bold().build(),
|
||||
TextSpanBuilder::new("<CTRL+H>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to show keybindings").bold().build(),
|
||||
]),
|
||||
))
|
||||
Box::new(Span::new(
|
||||
SpanPropsBuilder::default()
|
||||
.with_spans(vec![
|
||||
TextSpanBuilder::new("Press ").bold().build(),
|
||||
TextSpanBuilder::new("<CTRL+H>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to show keybindings").bold().build(),
|
||||
])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -100,83 +99,86 @@ impl SetupActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_TEXT_EDITOR,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::LightGreen)
|
||||
.with_texts(TextParts::new(Some(String::from("Text editor")), None))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen)
|
||||
.with_label(String::from("Text editor"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.active(super::COMPONENT_INPUT_TEXT_EDITOR); // <-- Focus
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_DEFAULT_PROTOCOL,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightCyan)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightCyan)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightCyan)
|
||||
.with_options(
|
||||
Some(String::from("Default file transfer protocol")),
|
||||
Some(vec![
|
||||
TextSpan::from("SFTP"),
|
||||
TextSpan::from("SCP"),
|
||||
TextSpan::from("FTP"),
|
||||
TextSpan::from("FTPS"),
|
||||
]),
|
||||
))
|
||||
vec![
|
||||
String::from("SFTP"),
|
||||
String::from("SCP"),
|
||||
String::from("FTP"),
|
||||
String::from("FTPS"),
|
||||
],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_HIDDEN_FILES,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightRed)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightRed)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed)
|
||||
.with_options(
|
||||
Some(String::from("Show hidden files (by default)")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_UPDATES,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightYellow)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightYellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
|
||||
.with_options(
|
||||
Some(String::from("Check for updates?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_GROUP_DIRS,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightMagenta)
|
||||
.with_background(Color::Black)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightMagenta)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightMagenta)
|
||||
.with_options(
|
||||
Some(String::from("Group directories")),
|
||||
Some(vec![
|
||||
TextSpan::from("Display first"),
|
||||
TextSpan::from("Display Last"),
|
||||
TextSpan::from("No"),
|
||||
]),
|
||||
))
|
||||
vec![
|
||||
String::from("Display first"),
|
||||
String::from("Display Last"),
|
||||
String::from("No"),
|
||||
],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_FILE_FMT,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
InputPropsBuilder::default()
|
||||
.with_foreground(Color::LightBlue)
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("File formatter syntax")),
|
||||
None,
|
||||
))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightBlue)
|
||||
.with_label(String::from("File formatter syntax"))
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -196,46 +198,41 @@ impl SetupActivity {
|
||||
// Radio tab
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_TAB,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightYellow)
|
||||
.with_background(Color::Black)
|
||||
.with_borders(Borders::BOTTOM)
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightYellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::BOTTOM, BorderType::Thick, Color::LightYellow)
|
||||
.with_options(
|
||||
None,
|
||||
Some(vec![
|
||||
TextSpan::from("User Interface"),
|
||||
TextSpan::from("SSH Keys"),
|
||||
]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(1))
|
||||
vec![String::from("User Interface"), String::from("SSH Keys")],
|
||||
)
|
||||
.with_value(1)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Footer
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_FOOTER,
|
||||
Box::new(Text::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
None,
|
||||
Some(vec![
|
||||
TextSpanBuilder::new("Press ").bold().build(),
|
||||
TextSpanBuilder::new("<CTRL+H>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to show keybindings").bold().build(),
|
||||
]),
|
||||
))
|
||||
Box::new(Span::new(
|
||||
SpanPropsBuilder::default()
|
||||
.with_spans(vec![
|
||||
TextSpanBuilder::new("Press ").bold().build(),
|
||||
TextSpanBuilder::new("<CTRL+H>")
|
||||
.bold()
|
||||
.with_foreground(Color::Cyan)
|
||||
.build(),
|
||||
TextSpanBuilder::new(" to show keybindings").bold().build(),
|
||||
])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_LIST_SSH_KEYS,
|
||||
Box::new(BookmarkList::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(Some(String::from("SSH Keys")), Some(vec![])))
|
||||
BookmarkListPropsBuilder::default()
|
||||
.with_bookmarks(Some(String::from("SSH Keys")), vec![])
|
||||
.with_borders(Borders::ALL, BorderType::Plain, Color::LightGreen)
|
||||
.with_background(Color::LightGreen)
|
||||
.with_foreground(Color::Black)
|
||||
.build(),
|
||||
@@ -312,40 +309,40 @@ impl SetupActivity {
|
||||
}
|
||||
}
|
||||
// Popups
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_ERROR) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_ERROR, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_QUIT) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_QUIT) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 40, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
self.view.render(super::COMPONENT_RADIO_QUIT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 50, 70);
|
||||
f.render_widget(Clear, popup);
|
||||
self.view.render(super::COMPONENT_TEXT_HELP, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_SAVE) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_SAVE) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
self.view.render(super::COMPONENT_RADIO_SAVE, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_RADIO_DEL_SSH_KEY) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_DEL_SSH_KEY) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 30, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
@@ -353,8 +350,8 @@ impl SetupActivity {
|
||||
.render(super::COMPONENT_RADIO_DEL_SSH_KEY, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(mut props) = self.view.get_props(super::COMPONENT_INPUT_SSH_HOST) {
|
||||
if props.build().visible {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_SSH_HOST) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 50, 20);
|
||||
f.render_widget(Clear, popup);
|
||||
@@ -389,10 +386,11 @@ impl SetupActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_ERROR,
|
||||
Box::new(MsgBox::new(
|
||||
PropsBuilder::default()
|
||||
MsgBoxPropsBuilder::default()
|
||||
.with_foreground(Color::Red)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(None, Some(vec![TextSpan::from(text)])))
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::Red)
|
||||
.with_texts(None, vec![TextSpan::from(text)])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -413,15 +411,16 @@ impl SetupActivity {
|
||||
pub(super) fn mount_del_ssh_key(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_DEL_SSH_KEY,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightRed)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightRed)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed)
|
||||
.with_options(
|
||||
Some(String::from("Delete key?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
.with_value(PropValue::Unsigned(1)) // Default: No
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.with_value(1) // Default: No
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -443,21 +442,26 @@ impl SetupActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_SSH_HOST,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(
|
||||
Some(String::from("Hostname or address")),
|
||||
None,
|
||||
))
|
||||
.with_borders(Borders::TOP | Borders::RIGHT | Borders::LEFT)
|
||||
InputPropsBuilder::default()
|
||||
.with_label(String::from("Hostname or address"))
|
||||
.with_borders(
|
||||
Borders::TOP | Borders::RIGHT | Borders::LEFT,
|
||||
BorderType::Plain,
|
||||
Color::Reset,
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.mount(
|
||||
super::COMPONENT_INPUT_SSH_USERNAME,
|
||||
Box::new(Input::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::new(Some(String::from("Username")), None))
|
||||
.with_borders(Borders::BOTTOM | Borders::RIGHT | Borders::LEFT)
|
||||
InputPropsBuilder::default()
|
||||
.with_label(String::from("Username"))
|
||||
.with_borders(
|
||||
Borders::ALL | Borders::RIGHT | Borders::LEFT,
|
||||
BorderType::Plain,
|
||||
Color::Reset,
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -478,18 +482,19 @@ impl SetupActivity {
|
||||
pub(super) fn mount_quit(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_QUIT,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightRed)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightRed)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed)
|
||||
.with_options(
|
||||
Some(String::from("Exit setup?")),
|
||||
Some(vec![
|
||||
TextSpan::from("Save"),
|
||||
TextSpan::from("Don't save"),
|
||||
TextSpan::from("Cancel"),
|
||||
]),
|
||||
))
|
||||
vec![
|
||||
String::from("Save"),
|
||||
String::from("Don't save"),
|
||||
String::from("Cancel"),
|
||||
],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -510,14 +515,15 @@ impl SetupActivity {
|
||||
pub(super) fn mount_save_popup(&mut self) {
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_SAVE,
|
||||
Box::new(RadioGroup::new(
|
||||
PropsBuilder::default()
|
||||
.with_foreground(Color::LightYellow)
|
||||
.bold()
|
||||
.with_texts(TextParts::new(
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightYellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
|
||||
.with_options(
|
||||
Some(String::from("Save changes?")),
|
||||
Some(vec![TextSpan::from("Yes"), TextSpan::from("No")]),
|
||||
))
|
||||
vec![String::from("Yes"), String::from("No")],
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -539,8 +545,9 @@ impl SetupActivity {
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_HELP,
|
||||
Box::new(Table::new(
|
||||
PropsBuilder::default()
|
||||
.with_texts(TextParts::table(
|
||||
TablePropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::White)
|
||||
.with_table(
|
||||
Some(String::from("Help")),
|
||||
TableBuilder::default()
|
||||
.add_col(
|
||||
@@ -615,7 +622,7 @@ impl SetupActivity {
|
||||
)
|
||||
.add_col(TextSpan::from(" Save configuration"))
|
||||
.build(),
|
||||
))
|
||||
)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -636,77 +643,59 @@ impl SetupActivity {
|
||||
pub(super) fn load_input_values(&mut self) {
|
||||
if let Some(cli) = self.context.as_mut().unwrap().config_client.as_mut() {
|
||||
// Text editor
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_INPUT_TEXT_EDITOR)
|
||||
.as_mut()
|
||||
{
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_TEXT_EDITOR) {
|
||||
let text_editor: String =
|
||||
String::from(cli.get_text_editor().as_path().to_string_lossy());
|
||||
let props = props.with_value(PropValue::Str(text_editor)).build();
|
||||
let props = InputPropsBuilder::from(props)
|
||||
.with_value(text_editor)
|
||||
.build();
|
||||
let _ = self.view.update(super::COMPONENT_INPUT_TEXT_EDITOR, props);
|
||||
}
|
||||
// Protocol
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_RADIO_DEFAULT_PROTOCOL)
|
||||
.as_mut()
|
||||
{
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_DEFAULT_PROTOCOL) {
|
||||
let protocol: usize = match cli.get_default_protocol() {
|
||||
FileTransferProtocol::Sftp => 0,
|
||||
FileTransferProtocol::Scp => 1,
|
||||
FileTransferProtocol::Ftp(false) => 2,
|
||||
FileTransferProtocol::Ftp(true) => 3,
|
||||
};
|
||||
let props = props.with_value(PropValue::Unsigned(protocol)).build();
|
||||
let props = RadioPropsBuilder::from(props).with_value(protocol).build();
|
||||
let _ = self
|
||||
.view
|
||||
.update(super::COMPONENT_RADIO_DEFAULT_PROTOCOL, props);
|
||||
}
|
||||
// Hidden files
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_RADIO_HIDDEN_FILES)
|
||||
.as_mut()
|
||||
{
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_HIDDEN_FILES) {
|
||||
let hidden: usize = match cli.get_show_hidden_files() {
|
||||
true => 0,
|
||||
false => 1,
|
||||
};
|
||||
let props = props.with_value(PropValue::Unsigned(hidden)).build();
|
||||
let props = RadioPropsBuilder::from(props).with_value(hidden).build();
|
||||
let _ = self.view.update(super::COMPONENT_RADIO_HIDDEN_FILES, props);
|
||||
}
|
||||
// Updates
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_UPDATES).as_mut() {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_UPDATES) {
|
||||
let updates: usize = match cli.get_check_for_updates() {
|
||||
true => 0,
|
||||
false => 1,
|
||||
};
|
||||
let props = props.with_value(PropValue::Unsigned(updates)).build();
|
||||
let props = RadioPropsBuilder::from(props).with_value(updates).build();
|
||||
let _ = self.view.update(super::COMPONENT_RADIO_UPDATES, props);
|
||||
}
|
||||
// Group dirs
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_RADIO_GROUP_DIRS)
|
||||
.as_mut()
|
||||
{
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_RADIO_GROUP_DIRS) {
|
||||
let dirs: usize = match cli.get_group_dirs() {
|
||||
Some(GroupDirs::First) => 0,
|
||||
Some(GroupDirs::Last) => 1,
|
||||
None => 2,
|
||||
};
|
||||
let props = props.with_value(PropValue::Unsigned(dirs)).build();
|
||||
let props = RadioPropsBuilder::from(props).with_value(dirs).build();
|
||||
let _ = self.view.update(super::COMPONENT_RADIO_GROUP_DIRS, props);
|
||||
}
|
||||
// File Fmt
|
||||
if let Some(props) = self
|
||||
.view
|
||||
.get_props(super::COMPONENT_INPUT_FILE_FMT)
|
||||
.as_mut()
|
||||
{
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_INPUT_FILE_FMT) {
|
||||
let file_fmt: String = cli.get_file_fmt().unwrap_or_default();
|
||||
let props = props.with_value(PropValue::Str(file_fmt)).build();
|
||||
let props = InputPropsBuilder::from(props).with_value(file_fmt).build();
|
||||
let _ = self.view.update(super::COMPONENT_INPUT_FILE_FMT, props);
|
||||
}
|
||||
}
|
||||
@@ -718,12 +707,12 @@ impl SetupActivity {
|
||||
pub(super) fn collect_input_values(&mut self) {
|
||||
if let Some(cli) = self.context.as_mut().unwrap().config_client.as_mut() {
|
||||
if let Some(Payload::Text(editor)) =
|
||||
self.view.get_value(super::COMPONENT_INPUT_TEXT_EDITOR)
|
||||
self.view.get_state(super::COMPONENT_INPUT_TEXT_EDITOR)
|
||||
{
|
||||
cli.set_text_editor(PathBuf::from(editor.as_str()));
|
||||
}
|
||||
if let Some(Payload::Unsigned(protocol)) =
|
||||
self.view.get_value(super::COMPONENT_RADIO_DEFAULT_PROTOCOL)
|
||||
self.view.get_state(super::COMPONENT_RADIO_DEFAULT_PROTOCOL)
|
||||
{
|
||||
let protocol: FileTransferProtocol = match protocol {
|
||||
1 => FileTransferProtocol::Scp,
|
||||
@@ -734,22 +723,22 @@ impl SetupActivity {
|
||||
cli.set_default_protocol(protocol);
|
||||
}
|
||||
if let Some(Payload::Unsigned(opt)) =
|
||||
self.view.get_value(super::COMPONENT_RADIO_HIDDEN_FILES)
|
||||
self.view.get_state(super::COMPONENT_RADIO_HIDDEN_FILES)
|
||||
{
|
||||
let show: bool = matches!(opt, 0);
|
||||
cli.set_show_hidden_files(show);
|
||||
}
|
||||
if let Some(Payload::Unsigned(opt)) =
|
||||
self.view.get_value(super::COMPONENT_RADIO_UPDATES)
|
||||
self.view.get_state(super::COMPONENT_RADIO_UPDATES)
|
||||
{
|
||||
let check: bool = matches!(opt, 0);
|
||||
cli.set_check_for_updates(check);
|
||||
}
|
||||
if let Some(Payload::Text(fmt)) = self.view.get_value(super::COMPONENT_INPUT_FILE_FMT) {
|
||||
if let Some(Payload::Text(fmt)) = self.view.get_state(super::COMPONENT_INPUT_FILE_FMT) {
|
||||
cli.set_file_fmt(fmt);
|
||||
}
|
||||
if let Some(Payload::Unsigned(opt)) =
|
||||
self.view.get_value(super::COMPONENT_RADIO_GROUP_DIRS)
|
||||
self.view.get_state(super::COMPONENT_RADIO_GROUP_DIRS)
|
||||
{
|
||||
let dirs: Option<GroupDirs> = match opt {
|
||||
0 => Some(GroupDirs::First),
|
||||
@@ -767,17 +756,17 @@ impl SetupActivity {
|
||||
pub(super) fn reload_ssh_keys(&mut self) {
|
||||
if let Some(cli) = self.context.as_ref().unwrap().config_client.as_ref() {
|
||||
// get props
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_LIST_SSH_KEYS).as_mut() {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_LIST_SSH_KEYS) {
|
||||
// Create texts
|
||||
let keys: Vec<TextSpan> = cli
|
||||
let keys: Vec<String> = cli
|
||||
.iter_ssh_keys()
|
||||
.map(|x| {
|
||||
let (addr, username, _) = cli.get_ssh_key(x).ok().unwrap().unwrap();
|
||||
TextSpan::from(format!("{} at {}", addr, username).as_str())
|
||||
format!("{} at {}", addr, username)
|
||||
})
|
||||
.collect();
|
||||
let props = props
|
||||
.with_texts(TextParts::new(Some(String::from("SSH Keys")), Some(keys)))
|
||||
let props = BookmarkListPropsBuilder::from(props)
|
||||
.with_bookmarks(Some(String::from("SSH Keys")), keys)
|
||||
.build();
|
||||
self.view.update(super::COMPONENT_LIST_SSH_KEYS, props);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user