mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Added FileInfo popup ('I')
This commit is contained in:
@@ -215,10 +215,11 @@ impl FileTransferActivity {
|
|||||||
}
|
}
|
||||||
'h' | 'H' => {
|
'h' | 'H' => {
|
||||||
// Show help
|
// Show help
|
||||||
// If ctrl is enabled...
|
self.input_mode = InputMode::Popup(PopupType::Help);
|
||||||
if key.modifiers.intersects(KeyModifiers::CONTROL) {
|
}
|
||||||
self.input_mode = InputMode::Popup(PopupType::Help);
|
'i' | 'I' => {
|
||||||
}
|
// Show file info
|
||||||
|
self.input_mode = InputMode::Popup(PopupType::FileInfo);
|
||||||
}
|
}
|
||||||
'r' | 'R' => {
|
'r' | 'R' => {
|
||||||
// Rename
|
// Rename
|
||||||
@@ -431,10 +432,11 @@ impl FileTransferActivity {
|
|||||||
}
|
}
|
||||||
'h' | 'H' => {
|
'h' | 'H' => {
|
||||||
// Show help
|
// Show help
|
||||||
// If ctrl is enabled...
|
self.input_mode = InputMode::Popup(PopupType::Help);
|
||||||
if key.modifiers.intersects(KeyModifiers::CONTROL) {
|
}
|
||||||
self.input_mode = InputMode::Popup(PopupType::Help);
|
'i' | 'I' => {
|
||||||
}
|
// Show file info
|
||||||
|
self.input_mode = InputMode::Popup(PopupType::FileInfo);
|
||||||
}
|
}
|
||||||
'r' | 'R' => {
|
'r' | 'R' => {
|
||||||
// Rename
|
// Rename
|
||||||
@@ -569,6 +571,7 @@ impl FileTransferActivity {
|
|||||||
pub(super) fn handle_input_event_mode_popup(&mut self, ev: &InputEvent, popup: PopupType) {
|
pub(super) fn handle_input_event_mode_popup(&mut self, ev: &InputEvent, popup: PopupType) {
|
||||||
match popup {
|
match popup {
|
||||||
PopupType::Alert(_, _) => self.handle_input_event_mode_popup_alert(ev),
|
PopupType::Alert(_, _) => self.handle_input_event_mode_popup_alert(ev),
|
||||||
|
PopupType::FileInfo => self.handle_input_event_mode_popup_fileinfo(ev),
|
||||||
PopupType::Help => self.handle_input_event_mode_popup_help(ev),
|
PopupType::Help => self.handle_input_event_mode_popup_help(ev),
|
||||||
PopupType::Fatal(_) => self.handle_input_event_mode_popup_fatal(ev),
|
PopupType::Fatal(_) => self.handle_input_event_mode_popup_fatal(ev),
|
||||||
PopupType::Input(_, cb) => self.handle_input_event_mode_popup_input(ev, cb),
|
PopupType::Input(_, cb) => self.handle_input_event_mode_popup_input(ev, cb),
|
||||||
@@ -599,6 +602,25 @@ impl FileTransferActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### handle_input_event_mode_popup_fileinfo
|
||||||
|
///
|
||||||
|
/// Input event handler for popup fileinfo
|
||||||
|
pub(super) fn handle_input_event_mode_popup_fileinfo(&mut self, ev: &InputEvent) {
|
||||||
|
// If enter, close popup
|
||||||
|
match ev {
|
||||||
|
InputEvent::Key(key) => {
|
||||||
|
match key.code {
|
||||||
|
KeyCode::Enter | KeyCode::Esc => {
|
||||||
|
// Set input mode back to explorer
|
||||||
|
self.input_mode = InputMode::Explorer;
|
||||||
|
}
|
||||||
|
_ => { /* Nothing to do */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => { /* Nothing to do */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ### handle_input_event_mode_popup_help
|
/// ### handle_input_event_mode_popup_help
|
||||||
///
|
///
|
||||||
/// Input event handler for popup help
|
/// Input event handler for popup help
|
||||||
|
|||||||
@@ -19,12 +19,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern crate bytesize;
|
||||||
extern crate hostname;
|
extern crate hostname;
|
||||||
|
#[cfg(any(unix, macos, linux))]
|
||||||
|
extern crate users;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Context, DialogYesNoOption, FileExplorerTab, FileTransferActivity, FsEntry, InputField,
|
Context, DialogYesNoOption, FileExplorerTab, FileTransferActivity, FsEntry, InputField,
|
||||||
InputMode, LogLevel, LogRecord, PopupType,
|
InputMode, LogLevel, LogRecord, PopupType,
|
||||||
};
|
};
|
||||||
|
use crate::utils::time_to_str;
|
||||||
|
|
||||||
|
use bytesize::ByteSize;
|
||||||
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},
|
||||||
@@ -33,6 +39,8 @@ use tui::{
|
|||||||
widgets::{Block, Borders, Clear, Gauge, List, ListItem, ListState, Paragraph, Tabs},
|
widgets::{Block, Borders, Clear, Gauge, List, ListItem, ListState, Paragraph, Tabs},
|
||||||
};
|
};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
#[cfg(any(unix, macos, linux))]
|
||||||
|
use users::{get_group_by_gid, get_user_by_uid};
|
||||||
|
|
||||||
impl FileTransferActivity {
|
impl FileTransferActivity {
|
||||||
/// ### draw
|
/// ### draw
|
||||||
@@ -96,8 +104,9 @@ impl FileTransferActivity {
|
|||||||
let (width, height): (u16, u16) = match popup {
|
let (width, height): (u16, u16) = match popup {
|
||||||
PopupType::Alert(_, _) => (50, 10),
|
PopupType::Alert(_, _) => (50, 10),
|
||||||
PopupType::Fatal(_) => (50, 10),
|
PopupType::Fatal(_) => (50, 10),
|
||||||
|
PopupType::FileInfo => (50, 50),
|
||||||
PopupType::Help => (50, 70),
|
PopupType::Help => (50, 70),
|
||||||
PopupType::Input(_, _) => (30, 10),
|
PopupType::Input(_, _) => (40, 10),
|
||||||
PopupType::Progress(_) => (40, 10),
|
PopupType::Progress(_) => (40, 10),
|
||||||
PopupType::Wait(_) => (50, 10),
|
PopupType::Wait(_) => (50, 10),
|
||||||
PopupType::YesNo(_, _, _) => (30, 10),
|
PopupType::YesNo(_, _, _) => (30, 10),
|
||||||
@@ -113,6 +122,7 @@ impl FileTransferActivity {
|
|||||||
self.draw_popup_fatal(txt.clone(), popup_area.width),
|
self.draw_popup_fatal(txt.clone(), popup_area.width),
|
||||||
popup_area,
|
popup_area,
|
||||||
),
|
),
|
||||||
|
PopupType::FileInfo => f.render_widget(self.draw_popup_fileinfo(), popup_area),
|
||||||
PopupType::Help => f.render_widget(self.draw_popup_help(), popup_area),
|
PopupType::Help => 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);
|
||||||
@@ -434,6 +444,225 @@ impl FileTransferActivity {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### draw_popup_fileinfo
|
||||||
|
///
|
||||||
|
/// Draw popup containing info about selected fsentry
|
||||||
|
pub(super) fn draw_popup_fileinfo(&self) -> List {
|
||||||
|
let mut info: Vec<ListItem> = Vec::new();
|
||||||
|
// Get current fsentry
|
||||||
|
let fsentry: Option<&FsEntry> = match self.tab {
|
||||||
|
FileExplorerTab::Local => {
|
||||||
|
// Get selected file
|
||||||
|
match self.local.files.get(self.local.index) {
|
||||||
|
Some(entry) => Some(entry),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileExplorerTab::Remote => match self.remote.files.get(self.remote.index) {
|
||||||
|
Some(entry) => Some(entry),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Get file_name and fill info list
|
||||||
|
let file_name: String = match fsentry {
|
||||||
|
Some(fsentry) => match fsentry {
|
||||||
|
FsEntry::Directory(dir) => {
|
||||||
|
// Push path
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Path: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
match &dir.symlink {
|
||||||
|
Some(symlink) => {
|
||||||
|
format!("{} => {}", dir.abs_path.display(), symlink.display())
|
||||||
|
}
|
||||||
|
None => dir.abs_path.to_string_lossy().to_string(),
|
||||||
|
},
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightYellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push creation time
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Creation time: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
time_to_str(dir.creation_time, "%b %d %Y %H:%M:%S"),
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightGreen)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push Last change
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Last change time: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
time_to_str(dir.last_change_time, "%b %d %Y %H:%M:%S"),
|
||||||
|
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push Last access
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Last access time: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
time_to_str(dir.last_access_time, "%b %d %Y %H:%M:%S"),
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightMagenta)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// User
|
||||||
|
#[cfg(any(unix, macos, linux))]
|
||||||
|
let username: String = match dir.user {
|
||||||
|
Some(uid) => match get_user_by_uid(uid) {
|
||||||
|
Some(user) => user.name().to_string_lossy().to_string(),
|
||||||
|
None => uid.to_string(),
|
||||||
|
},
|
||||||
|
None => String::from("0"),
|
||||||
|
};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let username: format!("{}", dir.user.unwrap_or(0));
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("User: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
username,
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightRed)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Group
|
||||||
|
#[cfg(any(unix, macos, linux))]
|
||||||
|
let group: String = match dir.group {
|
||||||
|
Some(gid) => match get_group_by_gid(gid) {
|
||||||
|
Some(group) => group.name().to_string_lossy().to_string(),
|
||||||
|
None => gid.to_string(),
|
||||||
|
},
|
||||||
|
None => String::from("0"),
|
||||||
|
};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let group: String = format!("{}", dir.group.unwrap_or(0));
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Group: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
group,
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightBlue)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Finally return file name
|
||||||
|
dir.name.clone()
|
||||||
|
}
|
||||||
|
FsEntry::File(file) => {
|
||||||
|
// Push path
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Path: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
match &file.symlink {
|
||||||
|
Some(symlink) => {
|
||||||
|
format!("{} => {}", file.abs_path.display(), symlink.display())
|
||||||
|
}
|
||||||
|
None => file.abs_path.to_string_lossy().to_string(),
|
||||||
|
},
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightYellow)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push size
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Size: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
format!("{} ({})", ByteSize(file.size as u64), file.size),
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightBlue)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push creation time
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Creation time: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
time_to_str(file.creation_time, "%b %d %Y %H:%M:%S"),
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightGreen)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push Last change
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Last change time: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
time_to_str(file.last_change_time, "%b %d %Y %H:%M:%S"),
|
||||||
|
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Push Last access
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Last access time: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
time_to_str(file.last_access_time, "%b %d %Y %H:%M:%S"),
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightMagenta)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// User
|
||||||
|
#[cfg(any(unix, macos, linux))]
|
||||||
|
let username: String = match file.user {
|
||||||
|
Some(uid) => match get_user_by_uid(uid) {
|
||||||
|
Some(user) => user.name().to_string_lossy().to_string(),
|
||||||
|
None => uid.to_string(),
|
||||||
|
},
|
||||||
|
None => String::from("0"),
|
||||||
|
};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let username: format!("{}", file.user.unwrap_or(0));
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("User: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
username,
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightRed)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Group
|
||||||
|
#[cfg(any(unix, macos, linux))]
|
||||||
|
let group: String = match file.group {
|
||||||
|
Some(gid) => match get_group_by_gid(gid) {
|
||||||
|
Some(group) => group.name().to_string_lossy().to_string(),
|
||||||
|
None => gid.to_string(),
|
||||||
|
},
|
||||||
|
None => String::from("0"),
|
||||||
|
};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let group: String = format!("{}", file.group.unwrap_or(0));
|
||||||
|
info.push(ListItem::new(Spans::from(vec![
|
||||||
|
Span::styled("Group: ", Style::default()),
|
||||||
|
Span::styled(
|
||||||
|
group,
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::LightBlue)
|
||||||
|
.add_modifier(Modifier::BOLD),
|
||||||
|
),
|
||||||
|
])));
|
||||||
|
// Finally return file name
|
||||||
|
file.name.clone()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => String::from(""),
|
||||||
|
};
|
||||||
|
List::new(info)
|
||||||
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(Style::default())
|
||||||
|
.title(file_name),
|
||||||
|
)
|
||||||
|
.start_corner(Corner::TopLeft)
|
||||||
|
}
|
||||||
|
|
||||||
/// ### draw_footer
|
/// ### draw_footer
|
||||||
///
|
///
|
||||||
/// Draw authentication page footer
|
/// Draw authentication page footer
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ enum DialogYesNoOption {
|
|||||||
enum PopupType {
|
enum PopupType {
|
||||||
Alert(Color, String), // Block color; Block text
|
Alert(Color, String), // Block color; Block text
|
||||||
Fatal(String), // Must quit after being hidden
|
Fatal(String), // Must quit after being hidden
|
||||||
|
FileInfo, // Show info about current file
|
||||||
Help, // Show Help
|
Help, // Show Help
|
||||||
Input(String, OnInputSubmitCallback), // Input description; Callback for submit
|
Input(String, OnInputSubmitCallback), // Input description; Callback for submit
|
||||||
Progress(String), // Progress block text
|
Progress(String), // Progress block text
|
||||||
|
|||||||
Reference in New Issue
Block a user