Thanks to latest commit I can finally draw progress bar :D

This commit is contained in:
ChristianVisintin
2020-11-29 20:31:51 +01:00
parent 4430f3133d
commit 9b135200d7

View File

@@ -44,6 +44,7 @@ use crossterm::event::Event as InputEvent;
use crossterm::event::{KeyCode, KeyModifiers}; use crossterm::event::{KeyCode, KeyModifiers};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::io::{Read, Seek, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tui::{ use tui::{
layout::{Constraint, Corner, Direction, Layout, Rect}, layout::{Constraint, Corner, Direction, Layout, Rect},
@@ -209,7 +210,7 @@ pub struct FileTransferActivity {
input_field: InputField, // Current selected input mode input_field: InputField, // Current selected input mode
input_txt: String, // Input text input_txt: String, // Input text
choice_opt: DialogYesNoOption, // Dialog popup selected option choice_opt: DialogYesNoOption, // Dialog popup selected option
transfer_prog: f64, // Current write/read progress (percentage) transfer_progress: f64, // Current write/read progress (percentage)
} }
impl FileTransferActivity { impl FileTransferActivity {
@@ -237,7 +238,7 @@ impl FileTransferActivity {
input_field: InputField::Explorer, input_field: InputField::Explorer,
input_txt: String::new(), input_txt: String::new(),
choice_opt: DialogYesNoOption::Yes, choice_opt: DialogYesNoOption::Yes,
transfer_prog: 0.0, transfer_progress: 0.0,
} }
} }
@@ -302,8 +303,7 @@ impl FileTransferActivity {
FsEntry::Directory(dir) => dir.name.clone(), FsEntry::Directory(dir) => dir.name.clone(),
FsEntry::File(file) => file.name.clone(), FsEntry::File(file) => file.name.clone(),
}; };
self.input_mode = self.input_mode = InputMode::Popup(PopupType::Wait(format!("Uploading \"{}\"", file_name)));
InputMode::Popup(PopupType::Wait(format!("Uploading \"{}\"...", file_name)));
// Draw // Draw
self.draw(); self.draw();
// Get remote path // Get remote path
@@ -323,16 +323,66 @@ impl FileTransferActivity {
.local .local
.open_file_read(file.abs_path.as_path()) .open_file_read(file.abs_path.as_path())
{ {
Ok(mut f) => match self.client.send_file(remote_path.as_path(), &mut f) { Ok(mut fhnd) => match self.client.send_file(remote_path.as_path()) {
Ok(_) => self.log( Ok(mut rhnd) => {
LogLevel::Info, // Write file
format!( let file_size: usize =
"Saved file \"{}\" to \"{}\"", fhnd.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
file.abs_path.display(), // rewind
remote_path.display() if let Err(err) = fhnd.seek(std::io::SeekFrom::Start(0)) {
) self.log(
.as_ref(), LogLevel::Error,
), format!("Could not rewind local file: {}", err).as_ref(),
);
}
// Write remote file
let mut total_bytes_written: usize = 0;
// Set input state to popup progress
self.input_mode = InputMode::Popup(PopupType::Progress(format!(
"Uploading \"{}\"",
file_name
)));
loop {
// Read till you can
let mut buffer: [u8; 8192] = [0; 8192];
match fhnd.read(&mut buffer) {
Ok(bytes_read) => {
total_bytes_written += bytes_read;
if bytes_read == 0 {
break;
} else {
// Write bytes
if let Err(err) = rhnd.write(&buffer[0..bytes_read]) {
self.log(
LogLevel::Error,
format!("Could not write remote file: {}", err)
.as_ref(),
);
}
}
}
Err(err) => {
self.log(
LogLevel::Error,
format!("Could not read local file: {}", err).as_ref(),
);
}
}
// Increase progress
self.set_progress(total_bytes_written, file_size);
// Draw
self.draw();
}
self.log(
LogLevel::Info,
format!(
"Saved file \"{}\" to \"{}\"",
file.abs_path.display(),
remote_path.display()
)
.as_ref(),
);
}
Err(err) => self.log( Err(err) => self.log(
LogLevel::Error, LogLevel::Error,
format!( format!(
@@ -446,19 +496,60 @@ impl FileTransferActivity {
{ {
Ok(mut local_file) => { Ok(mut local_file) => {
// Download file from remote // Download file from remote
match self match self.client.recv_file(file.abs_path.as_path()) {
.client Ok((mut rhnd, file_size)) => {
.recv_file(file.abs_path.as_path(), &mut local_file) // Set popup progress
{ self.input_mode = InputMode::Popup(PopupType::Progress(format!(
Ok(_) => self.log( "Downloading \"{}\"...",
LogLevel::Info, file_name
format!( )));
"Saved file \"{}\" to \"{}\"", let mut total_bytes_written: usize = 0;
file.abs_path.display(), // Write local file
local_file_path.display() loop {
) // Read till you can
.as_ref(), let mut buffer: [u8; 8192] = [0; 8192];
), match rhnd.read(&mut buffer) {
Ok(bytes_read) => {
total_bytes_written += bytes_read;
if bytes_read == 0 {
break;
} else {
// Write bytes
if let Err(err) =
local_file.write(&buffer[0..bytes_read])
{
self.log(
LogLevel::Error,
format!(
"Could not write local file: {}",
err
)
.as_ref(),
);
}
}
}
Err(err) => self.log(
LogLevel::Error,
format!("Could not read remote file: {}", err).as_ref(),
),
}
// Set progress
self.set_progress(total_bytes_written, file_size);
// Draw
self.draw();
}
// Log
self.log(
LogLevel::Info,
format!(
"Saved file \"{}\" to \"{}\"",
file.abs_path.display(),
local_file_path.display()
)
.as_ref(),
);
}
Err(err) => self.log( Err(err) => self.log(
LogLevel::Error, LogLevel::Error,
format!( format!(
@@ -596,7 +687,10 @@ impl FileTransferActivity {
.change_wrkdir(PathBuf::from(path)) .change_wrkdir(PathBuf::from(path))
{ {
Ok(_) => { Ok(_) => {
self.log(LogLevel::Info, format!("Changed directory on local: {}", path.display()).as_str()); self.log(
LogLevel::Info,
format!("Changed directory on local: {}", path.display()).as_str(),
);
// Reload files // Reload files
self.local_scan(path); self.local_scan(path);
// Push prev_dir to stack // Push prev_dir to stack
@@ -621,7 +715,10 @@ impl FileTransferActivity {
// Change directory // Change directory
match self.client.change_dir(path) { match self.client.change_dir(path) {
Ok(_) => { Ok(_) => {
self.log(LogLevel::Info, format!("Changed directory on remote: {}", path.display()).as_str()); self.log(
LogLevel::Info,
format!("Changed directory on remote: {}", path.display()).as_str(),
);
// Update files // Update files
self.remote_scan(path); self.remote_scan(path);
// Push prev_dir to stack // Push prev_dir to stack
@@ -636,7 +733,7 @@ impl FileTransferActivity {
format!("Could not change working directory: {}", err), format!("Could not change working directory: {}", err),
)); ));
} }
} }
} }
Err(err) => { Err(err) => {
// Report err // Report err
@@ -685,6 +782,13 @@ impl FileTransferActivity {
} }
} }
/// ### set_progress
///
/// Calculate progress percentage based on current progress
fn set_progress(&mut self, it: usize, sz: usize) {
self.transfer_progress = ((it as f64) * 100.0) / (sz as f64);
}
// @! input listeners // @! input listeners
/// ### handle_input_event /// ### handle_input_event
@@ -969,12 +1073,13 @@ impl FileTransferActivity {
self.remote_changedir(parent, true); self.remote_changedir(parent, true);
} }
} }
Err(err) => self.input_mode = InputMode::Popup(PopupType::Alert( Err(err) => {
Color::Red, self.input_mode = InputMode::Popup(PopupType::Alert(
format!("Could not change working directory: {}", err), Color::Red,
)) format!("Could not change working directory: {}", err),
))
}
} }
} }
} }
' ' => { ' ' => {
@@ -1567,7 +1672,7 @@ impl FileTransferActivity {
PopupType::Help => (50, 70), PopupType::Help => (50, 70),
PopupType::Input(_, _) => (30, 10), PopupType::Input(_, _) => (30, 10),
PopupType::Progress(_) => (40, 10), PopupType::Progress(_) => (40, 10),
PopupType::Wait(_) => (30, 10), PopupType::Wait(_) => (50, 10),
PopupType::YesNo(_, _, _) => (10, 10), PopupType::YesNo(_, _, _) => (10, 10),
}; };
let popup_area: Rect = self.draw_popup_area(f.size(), width, height); let popup_area: Rect = self.draw_popup_area(f.size(), width, height);
@@ -1580,9 +1685,7 @@ impl FileTransferActivity {
PopupType::Fatal(txt) => { PopupType::Fatal(txt) => {
f.render_widget(self.draw_popup_fatal(txt.clone()), popup_area) f.render_widget(self.draw_popup_fatal(txt.clone()), popup_area)
} }
PopupType::Help => { PopupType::Help => f.render_widget(self.draw_popup_help(), popup_area),
f.render_widget(self.draw_popup_help(), popup_area)
}
PopupType::Input(txt, _) => { PopupType::Input(txt, _) => {
f.render_widget(self.draw_popup_input(txt.clone()), popup_area); f.render_widget(self.draw_popup_input(txt.clone()), popup_area);
// Set cursor // Set cursor
@@ -1781,9 +1884,9 @@ impl FileTransferActivity {
/// ///
/// Draw progress popup /// Draw progress popup
fn draw_popup_progress(&self, text: String) -> Gauge { fn draw_popup_progress(&self, text: String) -> Gauge {
let label = format!("{:.2}%", self.transfer_prog); let label = format!("{:.2}%", self.transfer_progress);
Gauge::default() Gauge::default()
.block(Block::default().title(text)) .block(Block::default().borders(Borders::ALL).title(text))
.gauge_style( .gauge_style(
Style::default() Style::default()
.fg(Color::Magenta) .fg(Color::Magenta)
@@ -1791,7 +1894,7 @@ impl FileTransferActivity {
.add_modifier(Modifier::BOLD), .add_modifier(Modifier::BOLD),
) )
.label(label) .label(label)
.ratio(self.transfer_prog / 100.0) .ratio(self.transfer_progress / 100.0)
} }
/// ### draw_popup_wait /// ### draw_popup_wait
@@ -1800,11 +1903,7 @@ impl FileTransferActivity {
fn draw_popup_wait(&self, text: String) -> Paragraph { fn draw_popup_wait(&self, text: String) -> Paragraph {
Paragraph::new(text) Paragraph::new(text)
.style(Style::default().add_modifier(Modifier::BOLD)) .style(Style::default().add_modifier(Modifier::BOLD))
.block( .block(Block::default().borders(Borders::ALL).title("Please wait"))
Block::default()
.borders(Borders::ALL)
.title("Please wait"),
)
} }
/// ### draw_popup_yesno /// ### draw_popup_yesno
@@ -1833,126 +1932,106 @@ impl FileTransferActivity {
fn draw_popup_help(&self) -> List { fn draw_popup_help(&self) -> List {
// Write header // Write header
let cmds: Vec<ListItem> = vec![ let cmds: Vec<ListItem> = vec![
ListItem::new( ListItem::new(Spans::from(vec![
Spans::from(vec![ Span::styled(
Span::styled( "<ESC> ",
"<ESC> ", Style::default()
Style::default() .bg(Color::Cyan)
.bg(Color::Cyan) .fg(Color::White)
.fg(Color::White) .add_modifier(Modifier::BOLD),
.add_modifier(Modifier::BOLD), ),
), Span::raw("quit"),
Span::raw("quit") ])),
]) ListItem::new(Spans::from(vec![
), Span::styled(
ListItem::new( "<TAB> ",
Spans::from(vec![ Style::default()
Span::styled( .bg(Color::Cyan)
"<TAB> ", .fg(Color::White)
Style::default() .add_modifier(Modifier::BOLD),
.bg(Color::Cyan) ),
.fg(Color::White) Span::raw("change input field"),
.add_modifier(Modifier::BOLD), ])),
), ListItem::new(Spans::from(vec![
Span::raw("change input field") Span::styled(
]) "<RIGHT/LEFT> ",
), Style::default()
ListItem::new( .bg(Color::Cyan)
Spans::from(vec![ .fg(Color::White)
Span::styled( .add_modifier(Modifier::BOLD),
"<RIGHT/LEFT> ", ),
Style::default() Span::raw("change explorer tab"),
.bg(Color::Cyan) ])),
.fg(Color::White) ListItem::new(Spans::from(vec![
.add_modifier(Modifier::BOLD), Span::styled(
), "<ENTER> ",
Span::raw("change explorer tab") Style::default()
]) .bg(Color::Cyan)
), .fg(Color::White)
ListItem::new( .add_modifier(Modifier::BOLD),
Spans::from(vec![ ),
Span::styled( Span::raw("enter directory"),
"<ENTER> ", ])),
Style::default() ListItem::new(Spans::from(vec![
.bg(Color::Cyan) Span::styled(
.fg(Color::White) "<SPACE> ",
.add_modifier(Modifier::BOLD), Style::default()
), .bg(Color::Cyan)
Span::raw("enter directory") .fg(Color::White)
]) .add_modifier(Modifier::BOLD),
), ),
ListItem::new( Span::raw("upload/download file"),
Spans::from(vec![ ])),
Span::styled( ListItem::new(Spans::from(vec![
"<SPACE> ", Span::styled(
Style::default() "<CTRL+D> ",
.bg(Color::Cyan) Style::default()
.fg(Color::White) .bg(Color::Cyan)
.add_modifier(Modifier::BOLD), .fg(Color::White)
), .add_modifier(Modifier::BOLD),
Span::raw("upload/download file") ),
]) Span::raw("make directory"),
), ])),
ListItem::new( ListItem::new(Spans::from(vec![
Spans::from(vec![ Span::styled(
Span::styled( "<CTRL+G> ",
"<CTRL+D> ", Style::default()
Style::default() .bg(Color::Cyan)
.bg(Color::Cyan) .fg(Color::White)
.fg(Color::White) .add_modifier(Modifier::BOLD),
.add_modifier(Modifier::BOLD), ),
), Span::raw("goto path"),
Span::raw("make directory") ])),
]) ListItem::new(Spans::from(vec![
), Span::styled(
ListItem::new( "<CTRL+R> ",
Spans::from(vec![ Style::default()
Span::styled( .bg(Color::Cyan)
"<CTRL+G> ", .fg(Color::White)
Style::default() .add_modifier(Modifier::BOLD),
.bg(Color::Cyan) ),
.fg(Color::White) Span::raw("rename file"),
.add_modifier(Modifier::BOLD), ])),
), ListItem::new(Spans::from(vec![
Span::raw("goto path") Span::styled(
]) "<CTRL+U> ",
), Style::default()
ListItem::new( .bg(Color::Cyan)
Spans::from(vec![ .fg(Color::White)
Span::styled( .add_modifier(Modifier::BOLD),
"<CTRL+R> ", ),
Style::default() Span::raw("go to parent directory"),
.bg(Color::Cyan) ])),
.fg(Color::White) ListItem::new(Spans::from(vec![
.add_modifier(Modifier::BOLD), Span::styled(
), "<CANC> ",
Span::raw("rename file") Style::default()
]) .bg(Color::Cyan)
), .fg(Color::White)
ListItem::new( .add_modifier(Modifier::BOLD),
Spans::from(vec![ ),
Span::styled( Span::raw("delete file"),
"<CTRL+U> ", ])),
Style::default()
.bg(Color::Cyan)
.fg(Color::White)
.add_modifier(Modifier::BOLD),
),
Span::raw("go to parent directory")
])
),
ListItem::new(
Spans::from(vec![
Span::styled(
"<CANC> ",
Style::default()
.bg(Color::Cyan)
.fg(Color::White)
.add_modifier(Modifier::BOLD),
),
Span::raw("delete file")
])
)
]; ];
List::new(cmds) List::new(cmds)
.block( .block(