diff --git a/src/ui/activities/auth_activity/view.rs b/src/ui/activities/auth_activity/view.rs index 51d28ed..89ea500 100644 --- a/src/ui/activities/auth_activity/view.rs +++ b/src/ui/activities/auth_activity/view.rs @@ -26,7 +26,7 @@ // Locals use super::{AuthActivity, Context, FileTransferProtocol}; use crate::ui::layout::components::{ - bookmark_list::BookmarkList, ctext::CText, input::Input, radio_group::RadioGroup, table::Table, + bookmark_list::BookmarkList, msgbox::MsgBox, input::Input, radio_group::RadioGroup, table::Table, text::Text, title::Title, }; use crate::ui::layout::props::{ @@ -436,7 +436,7 @@ impl AuthActivity { // Mount self.view.mount( super::COMPONENT_TEXT_ERROR, - Box::new(CText::new( + Box::new(MsgBox::new( PropsBuilder::default() .with_foreground(Color::Red) .bold() diff --git a/src/ui/activities/filetransfer_activity/actions.rs b/src/ui/activities/filetransfer_activity/actions.rs index af36ad3..2fac2ff 100644 --- a/src/ui/activities/filetransfer_activity/actions.rs +++ b/src/ui/activities/filetransfer_activity/actions.rs @@ -331,7 +331,7 @@ impl FileTransferActivity { pub(super) fn action_remote_saveas(&mut self, input: String) { if let Some(idx) = self.get_remote_file_idx() { // Get pwd - let wrkdir: PathBuf = self.remote.wrkdir.clone(); + let wrkdir: PathBuf = self.local.wrkdir.clone(); if self.remote.get(idx).is_some() { let file: FsEntry = self.remote.get(idx).unwrap().clone(); // Call upload; pass realfile, keep link name diff --git a/src/ui/activities/filetransfer_activity/update.rs b/src/ui/activities/filetransfer_activity/update.rs index d51efd7..fc944a5 100644 --- a/src/ui/activities/filetransfer_activity/update.rs +++ b/src/ui/activities/filetransfer_activity/update.rs @@ -37,7 +37,7 @@ use super::{ use crate::fs::explorer::FileSorting; use crate::fs::FsEntry; use crate::ui::activities::keymap::*; -use crate::ui::layout::props::{TableBuilder, TextParts, TextSpan, TextSpanBuilder}; +use crate::ui::layout::props::{PropValue, TableBuilder, TextParts, TextSpan, TextSpanBuilder}; use crate::ui::layout::{Msg, Payload}; // externals use bytesize::ByteSize; @@ -470,9 +470,9 @@ impl FileTransferActivity { } self.umount_saveas(); // Reload files - match self.tab { - FileExplorerTab::Local => self.update_local_filelist(), - FileExplorerTab::Remote => self.update_remote_filelist(), + match self.tab { // NOTE: Swapped is intentional + FileExplorerTab::Local => self.update_remote_filelist(), + FileExplorerTab::Remote => self.update_local_filelist(), } } // -- fileinfo @@ -769,6 +769,7 @@ impl FileTransferActivity { Some(text), Some(vec![TextSpan::from(label)]), )) + .with_value(PropValue::Float(self.transfer.progress / 100.0)) .build(); self.view.update(COMPONENT_PROGRESS_BAR, props) } diff --git a/src/ui/activities/filetransfer_activity/view.rs b/src/ui/activities/filetransfer_activity/view.rs index 5754a5a..34215a2 100644 --- a/src/ui/activities/filetransfer_activity/view.rs +++ b/src/ui/activities/filetransfer_activity/view.rs @@ -33,7 +33,7 @@ use super::{Context, FileExplorerTab, FileTransferActivity}; use crate::fs::explorer::FileSorting; use crate::fs::FsEntry; use crate::ui::layout::components::{ - ctext::CText, file_list::FileList, input::Input, logbox::LogBox, progress_bar::ProgressBar, + msgbox::MsgBox, file_list::FileList, input::Input, logbox::LogBox, progress_bar::ProgressBar, radio_group::RadioGroup, table::Table, }; use crate::ui::layout::props::{ @@ -280,7 +280,7 @@ impl FileTransferActivity { // Mount self.view.mount( super::COMPONENT_TEXT_ERROR, - Box::new(CText::new( + Box::new(MsgBox::new( PropsBuilder::default() .with_foreground(Color::Red) .bold() @@ -303,7 +303,7 @@ impl FileTransferActivity { // Mount self.view.mount( super::COMPONENT_TEXT_FATAL, - Box::new(CText::new( + Box::new(MsgBox::new( PropsBuilder::default() .with_foreground(Color::Red) .bold() @@ -319,7 +319,7 @@ impl FileTransferActivity { // Mount self.view.mount( super::COMPONENT_TEXT_WAIT, - Box::new(CText::new( + Box::new(MsgBox::new( PropsBuilder::default() .with_foreground(Color::White) .bold() @@ -501,8 +501,8 @@ impl FileTransferActivity { super::COMPONENT_PROGRESS_BAR, Box::new(ProgressBar::new( PropsBuilder::default() - .with_foreground(Color::Black) - .with_background(Color::LightGreen) + .with_foreground(Color::LightGreen) + .with_background(Color::Black) .with_texts(TextParts::new(Some(String::from("Please wait")), None)) .build(), )), diff --git a/src/ui/activities/setup_activity/view.rs b/src/ui/activities/setup_activity/view.rs index 90b3af1..92211bd 100644 --- a/src/ui/activities/setup_activity/view.rs +++ b/src/ui/activities/setup_activity/view.rs @@ -29,7 +29,7 @@ use super::{Context, SetupActivity, ViewLayout}; use crate::filetransfer::FileTransferProtocol; use crate::fs::explorer::GroupDirs; use crate::ui::layout::components::{ - bookmark_list::BookmarkList, ctext::CText, input::Input, radio_group::RadioGroup, table::Table, + bookmark_list::BookmarkList, msgbox::MsgBox, input::Input, radio_group::RadioGroup, table::Table, text::Text, }; use crate::ui::layout::props::{ @@ -386,7 +386,7 @@ impl SetupActivity { // Mount self.view.mount( super::COMPONENT_TEXT_ERROR, - Box::new(CText::new( + Box::new(MsgBox::new( PropsBuilder::default() .with_foreground(Color::Red) .bold() diff --git a/src/ui/layout/components/mod.rs b/src/ui/layout/components/mod.rs index 3b52855..c265964 100644 --- a/src/ui/layout/components/mod.rs +++ b/src/ui/layout/components/mod.rs @@ -28,10 +28,10 @@ use super::{Canvas, Component, InputEvent, Msg, Payload, PropValue, Props, Props // exports pub mod bookmark_list; -pub mod ctext; pub mod file_list; pub mod input; pub mod logbox; +pub mod msgbox; pub mod progress_bar; pub mod radio_group; pub mod table; diff --git a/src/ui/layout/components/ctext.rs b/src/ui/layout/components/msgbox.rs similarity index 62% rename from src/ui/layout/components/ctext.rs rename to src/ui/layout/components/msgbox.rs index 803f1e2..e35bf46 100644 --- a/src/ui/layout/components/ctext.rs +++ b/src/ui/layout/components/msgbox.rs @@ -1,6 +1,6 @@ -//! ## CText +//! ## MsgBox //! -//! `CText` component renders a simple readonly no event associated centered text +//! `MsgBox` component renders a simple readonly no event associated centered text /* * @@ -23,15 +23,17 @@ * */ +// deps +extern crate textwrap; // locals use super::{Canvas, Component, InputEvent, Msg, Payload, Props, PropsBuilder}; use crate::utils::fmt::align_text_center; // ext use tui::{ - layout::Rect, - style::Style, - text::{Span, Spans, Text as TuiText}, - widgets::{Block, BorderType, Paragraph}, + layout::{Corner, Rect}, + style::{Color, Style}, + text::{Span, Spans}, + widgets::{Block, BorderType, List, ListItem}, }; // -- state @@ -48,24 +50,24 @@ impl Default for OwnStates { // -- component -pub struct CText { +pub struct MsgBox { props: Props, states: OwnStates, } -impl CText { +impl MsgBox { /// ### new /// /// Instantiate a new Text component pub fn new(props: Props) -> Self { - CText { + MsgBox { props, states: OwnStates::default(), } } } -impl Component for CText { +impl Component for MsgBox { /// ### render /// /// Based on the current properties and states, renders a widget using the provided render engine in the provided Area @@ -74,37 +76,56 @@ impl Component for CText { fn render(&self, render: &mut Canvas, area: Rect) { // Make a Span if self.props.visible { - let spans: Vec = match self.props.texts.rows.as_ref() { + let lines: Vec = match self.props.texts.rows.as_ref() { None => Vec::new(), - Some(rows) => rows - .iter() - .map(|x| { - Span::styled( - align_text_center(x.content.as_str(), area.width), - Style::default() - .add_modifier(x.get_modifiers()) - .fg(x.fg) - .bg(x.bg), - ) - }) - .collect(), + Some(rows) => { + let mut lines: Vec = Vec::new(); + for line in rows.iter() { + // Keep line color, or use default + let line_fg: Color = match line.fg { + Color::Reset => self.props.foreground, + _ => line.fg, + }; + let line_bg: Color = match line.bg { + Color::Reset => self.props.background, + _ => line.bg, + }; + let mut spans: Vec = Vec::new(); + let message_row = + textwrap::wrap(line.content.as_str(), area.width as usize); + for msg in message_row.iter() { + spans.push(Span::styled( + align_text_center(msg, area.width), + Style::default() + .add_modifier(line.get_modifiers()) + .fg(line_fg) + .bg(line_bg), + )); + } + lines.push(ListItem::new(Spans::from(spans))); + } + lines + } + }; + let title: String = match self.props.texts.title.as_ref() { + Some(t) => t.clone(), + None => String::new(), }; - // Make text - let mut text: TuiText = TuiText::from(Spans::from(spans)); - // Apply style - text.patch_style( - Style::default() - .add_modifier(self.props.get_modifiers()) - .fg(self.props.foreground) - .bg(self.props.background), - ); render.render_widget( - Paragraph::new(text).block( - Block::default() - .borders(self.props.borders) - .border_style(Style::default().fg(self.props.foreground)) - .border_type(BorderType::Rounded), - ), + List::new(lines) + .block( + Block::default() + .borders(self.props.borders) + .border_style(Style::default().fg(self.props.foreground)) + .border_type(BorderType::Rounded) + .title(title), + ) + .start_corner(Corner::TopLeft) + .style( + Style::default() + .fg(self.props.foreground) + .bg(self.props.background), + ), area, ); } @@ -180,8 +201,8 @@ mod tests { use tui::style::Color; #[test] - fn test_ui_layout_components_ctext() { - let mut component: CText = CText::new( + fn test_ui_layout_components_msgbox() { + let mut component: MsgBox = MsgBox::new( PropsBuilder::default() .with_texts(TextParts::new( None,