Add size field, improve info, fix eject

This commit is contained in:
Lutsai Aleksandr 2025-01-02 02:31:43 +03:00
parent 7746a764f7
commit 69c1ba8dbc
5 changed files with 68 additions and 18 deletions

2
Cargo.lock generated
View file

@ -868,7 +868,7 @@ dependencies = [
[[package]] [[package]]
name = "mmtui" name = "mmtui"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"crossterm", "crossterm",
"ratatui", "ratatui",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "mmtui" name = "mmtui"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
authors = ["Lutsai Aleksandr <s.lyra@ya.ru>"] authors = ["Lutsai Aleksandr <s.lyra@ya.ru>"]
description = "Terminal User Interface disk mount manager for TUI file managers" description = "Terminal User Interface disk mount manager for TUI file managers"

View file

@ -4,11 +4,13 @@ use std::collections::HashMap;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Block { pub struct Block {
pub object_path: String, pub object_path: String,
pub drive_path: String,
pub dev: String, pub dev: String,
pub label: String, pub label: String,
pub mount: Option<String>, pub mount: Option<String>,
pub fstype: String, pub fstype: String,
pub mounted: bool, pub mounted: bool,
pub size: String,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -56,8 +58,14 @@ pub async fn collect_drives_from_udisk() -> udisks2::Result<Vec<Drive>> {
} }
} else if let Ok(blk) = i.block().await { } else if let Ok(blk) = i.block().await {
let drv_path = blk.drive().await?.to_string(); let drv_path = blk.drive().await?.to_string();
let size = if let Ok(size) = blk.size().await {
client.size_for_display(size, true, false)
} else {
String::new()
};
let block = Block { let block = Block {
object_path: path, object_path: path,
drive_path: drv_path.clone(),
dev: String::from_utf8_lossy(&blk.device().await?) dev: String::from_utf8_lossy(&blk.device().await?)
.chars() .chars()
.filter(|c| c != &'\0') .filter(|c| c != &'\0')
@ -66,6 +74,7 @@ pub async fn collect_drives_from_udisk() -> udisks2::Result<Vec<Drive>> {
mount: None, mount: None,
fstype: blk.id_type().await?, fstype: blk.id_type().await?,
mounted: false, mounted: false,
size,
}; };
if let Some(d) = drives.iter_mut().find(|i| i.object_path == drv_path) { if let Some(d) = drives.iter_mut().find(|i| i.object_path == drv_path) {
@ -108,11 +117,13 @@ pub async fn collect_all() -> udisks2::Result<Vec<Drive>> {
} else { } else {
fstab.blocks.push(Block { fstab.blocks.push(Block {
object_path: String::new(), object_path: String::new(),
drive_path: fstab.object_path.clone(),
dev: i.dev, dev: i.dev,
label: String::new(), label: String::new(),
mount: i.path, mount: i.path,
fstype: i.fs, fstype: i.fs,
mounted: i.mounted, mounted: i.mounted,
size: String::new(),
}); });
} }
} }
@ -151,3 +162,16 @@ pub async fn unmount(block: &Block) -> udisks2::Result<()> {
Ok(()) Ok(())
} }
pub async fn eject(block: &Block) -> udisks2::Result<()> {
let client = udisks2::Client::new().await?;
client
.object(block.drive_path.clone())?
.drive()
.await?
.eject(HashMap::new())
.await?;
Ok(())
}

View file

@ -27,8 +27,9 @@ async fn main() -> udisks2::Result<()> {
let s = state.clone(); let s = state.clone();
tokio::spawn(async move { tokio::spawn(async move {
loop { loop {
let drv = drives::collect_all().await.unwrap(); if let Ok(drv) = drives::collect_all().await {
s.lock().await.clone_from(&drv); s.lock().await.clone_from(&drv);
};
tokio::time::sleep(Duration::from_millis(500)).await; tokio::time::sleep(Duration::from_millis(500)).await;
} }
}); });

View file

@ -24,7 +24,16 @@ pub struct Tui {
pub last_status: String, pub last_status: String,
} }
const HELP: &str = "j/▲⋮k/▼⋮l/o/▶ - CD⋮m - Mount⋮u - Unmount⋮e - Eject⋮q - Quit";
impl Tui { impl Tui {
fn set_status(&mut self, res: udisks2::Result<()>) {
self.last_status = match res {
Ok(()) => String::from("Ok"),
Err(e) => format!("Error: {e:?}"),
}
}
pub async fn input(&mut self, key: KeyEvent) -> InputResult { pub async fn input(&mut self, key: KeyEvent) -> InputResult {
match key.code { match key.code {
KeyCode::Up | KeyCode::Char('k') => { KeyCode::Up | KeyCode::Char('k') => {
@ -37,21 +46,31 @@ impl Tui {
} }
KeyCode::Char('m') => { KeyCode::Char('m') => {
if let Some(b) = &self.selected { if let Some(b) = &self.selected {
self.last_status = format!("{:?}", drives::mount(b).await); self.set_status(drives::mount(b).await);
} }
InputResult::None InputResult::None
} }
KeyCode::Char('u') => { KeyCode::Char('u') => {
if let Some(b) = &self.selected { if let Some(b) = &self.selected {
self.last_status = format!("{:?}", drives::unmount(b).await); self.set_status(drives::unmount(b).await);
} }
InputResult::None InputResult::None
} }
KeyCode::Esc | KeyCode::Char('q') => InputResult::Quit, KeyCode::Char('e') => {
KeyCode::Enter => { if let Some(b) = &self.selected {
let output = self.selected.clone().unwrap().mount.unwrap(); self.set_status(drives::eject(b).await);
InputResult::QuitChangeDirectory(output)
} }
InputResult::None
}
KeyCode::Enter | KeyCode::Char('l' | 'o') => {
if let Some(s) = &self.selected {
let output = s.clone().mount.unwrap_or_default();
InputResult::QuitChangeDirectory(output)
} else {
InputResult::Quit
}
}
KeyCode::Esc | KeyCode::Char('q') => InputResult::Quit,
_ => InputResult::None, _ => InputResult::None,
} }
} }
@ -81,11 +100,20 @@ impl Tui {
.and_then(|n| rows.get(n).cloned()) .and_then(|n| rows.get(n).cloned())
.clone_into(&mut self.selected); .clone_into(&mut self.selected);
let max_size_field_length: u16 = rows
.iter()
.map(|r| r.size.len())
.max()
.unwrap_or(0)
.try_into()
.unwrap_or(0);
let rows = rows.iter().map(|i| { let rows = rows.iter().map(|i| {
Row::new(vec![ Row::new(vec![
i.dev.clone(), i.dev.clone(),
i.label.clone(), i.label.clone(),
i.mount.clone().unwrap_or_default(), i.mount.clone().unwrap_or_default(),
i.size.clone(),
if i.mounted { if i.mounted {
"M".to_owned() "M".to_owned()
} else { } else {
@ -97,7 +125,8 @@ impl Tui {
Constraint::Ratio(1, 3), Constraint::Ratio(1, 3),
Constraint::Ratio(1, 3), Constraint::Ratio(1, 3),
Constraint::Ratio(1, 3), Constraint::Ratio(1, 3),
Constraint::Length(3), Constraint::Length(max_size_field_length),
Constraint::Length(1),
]; ];
let table = Table::new(rows, widths) let table = Table::new(rows, widths)
.row_highlight_style(Color::Green) .row_highlight_style(Color::Green)
@ -123,18 +152,14 @@ impl Tui {
}; };
format!( format!(
"dev: {:?} label: {:?} type: {:?} {mounted} ", "dev: {:?} label: {:?} type: {:?} size {} {mounted}",
s.dev, s.label, s.fstype s.dev, s.label, s.fstype, s.size
) )
} }
None => String::new(), None => String::new(),
}; };
let info = format!( let info = format!("{} | {HELP}\n{descr}", self.last_status);
"j - UP, k - DOWN, l - Goto mountpoint, m - Mount, u - Unmount, e - Eject\n{descr} {:?}",
self.last_status
);
let info = Paragraph::new(info).wrap(Wrap { trim: true }); let info = Paragraph::new(info).wrap(Wrap { trim: true });
frame.render_widget(info, layout[1]); frame.render_widget(info, layout[1]);
} }