cosmic-files/src/operation.rs

219 lines
7.3 KiB
Rust
Raw Normal View History

use cosmic::iced::futures::{channel::mpsc, executor, SinkExt};
use std::{fs, path::PathBuf, sync::Arc};
2024-01-29 11:58:50 -07:00
2024-02-01 15:14:14 -07:00
use crate::app::Message;
fn err_str<T: ToString>(err: T) -> String {
err.to_string()
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2024-01-29 11:58:50 -07:00
pub enum Operation {
/// Copy items
2024-02-27 13:25:50 -07:00
Copy {
paths: Vec<PathBuf>,
to: PathBuf,
},
/// Move items to the trash
2024-02-27 13:25:50 -07:00
Delete {
paths: Vec<PathBuf>,
},
2024-05-09 13:24:06 -06:00
/// Empty the trash
EmptyTrash,
/// Move items
2024-02-27 13:25:50 -07:00
Move {
paths: Vec<PathBuf>,
to: PathBuf,
},
NewFile {
path: PathBuf,
},
NewFolder {
path: PathBuf,
},
2024-02-28 15:07:50 -07:00
Rename {
from: PathBuf,
to: PathBuf,
},
2024-01-29 11:58:50 -07:00
/// Restore a path from the trash
2024-02-27 13:25:50 -07:00
Restore {
paths: Vec<trash::TrashItem>,
},
2024-01-29 11:58:50 -07:00
}
impl Operation {
/// Perform the operation
pub async fn perform(
self,
id: u64,
msg_tx: &Arc<tokio::sync::Mutex<mpsc::Sender<Message>>>,
) -> Result<(), String> {
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(id, 0.0))
.await;
2024-01-29 11:58:50 -07:00
//TODO: IF ERROR, RETURN AN Operation THAT CAN UNDO THE CURRENT STATE
//TODO: SAFELY HANDLE CANCEL
2024-01-29 11:58:50 -07:00
match self {
Self::Copy { paths, to } => {
let msg_tx = msg_tx.clone();
tokio::task::spawn_blocking(move || {
log::info!("Copy {:?} to {:?}", paths, to);
let options = fs_extra::dir::CopyOptions::default();
//TODO: set options as desired
fs_extra::copy_items_with_progress(&paths, &to, &options, |progress| {
executor::block_on(async {
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(
id,
100.0 * (progress.copied_bytes as f32)
/ (progress.total_bytes as f32),
))
.await;
});
//TODO: handle exceptions
fs_extra::dir::TransitProcessResult::ContinueOrAbort
})
})
.await
.map_err(err_str)?
.map_err(err_str)?;
}
Self::Delete { paths } => {
2024-02-27 09:58:22 -07:00
let total = paths.len();
let mut count = 0;
for path in paths {
tokio::task::spawn_blocking(|| trash::delete(path))
.await
.map_err(err_str)?
.map_err(err_str)?;
count += 1;
2024-02-27 09:58:22 -07:00
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(
id,
100.0 * (count as f32) / (total as f32),
))
.await;
}
}
2024-05-09 13:24:06 -06:00
Self::EmptyTrash => {
#[cfg(any(
target_os = "windows",
all(
unix,
not(target_os = "macos"),
not(target_os = "ios"),
not(target_os = "android")
)
))]
{
tokio::task::spawn_blocking(|| {
let items = trash::os_limited::list()?;
trash::os_limited::purge_all(items)
})
.await
.map_err(err_str)?
.map_err(err_str)?;
}
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(id, 100.0))
.await;
}
Self::Move { paths, to } => {
let msg_tx = msg_tx.clone();
tokio::task::spawn_blocking(move || {
log::info!("Move {:?} to {:?}", paths, to);
let options = fs_extra::dir::CopyOptions::default();
//TODO: set options as desired
fs_extra::move_items_with_progress(&paths, &to, &options, |progress| {
executor::block_on(async {
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(
id,
100.0 * (progress.copied_bytes as f32)
/ (progress.total_bytes as f32),
))
.await;
});
//TODO: handle exceptions
fs_extra::dir::TransitProcessResult::ContinueOrAbort
})
})
.await
.map_err(err_str)?
.map_err(err_str)?;
}
2024-02-27 13:25:50 -07:00
Self::NewFolder { path } => {
tokio::task::spawn_blocking(|| fs::create_dir(path))
.await
.map_err(err_str)?
.map_err(err_str)?;
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(id, 100.0))
.await;
2024-02-27 13:25:50 -07:00
}
Self::NewFile { path } => {
tokio::task::spawn_blocking(|| fs::File::create(path))
.await
.map_err(err_str)?
2024-02-28 15:07:50 -07:00
.map_err(err_str)?;
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(id, 100.0))
.await;
2024-02-28 15:07:50 -07:00
}
Self::Rename { from, to } => {
tokio::task::spawn_blocking(|| fs::rename(from, to))
.await
.map_err(err_str)?
2024-02-27 13:25:50 -07:00
.map_err(err_str)?;
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(id, 100.0))
.await;
2024-02-27 13:25:50 -07:00
}
Self::Restore { paths } => {
2024-02-27 09:58:22 -07:00
let total = paths.len();
let mut count = 0;
for path in paths {
tokio::task::spawn_blocking(|| trash::os_limited::restore_all([path]))
.await
.map_err(err_str)?
.map_err(err_str)?;
count += 1;
2024-02-27 09:58:22 -07:00
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(
id,
100.0 * (count as f32) / (total as f32),
))
.await;
}
}
2024-01-29 11:58:50 -07:00
}
let _ = msg_tx
.lock()
.await
.send(Message::PendingProgress(id, 100.0))
.await;
2024-01-29 11:58:50 -07:00
Ok(())
2024-01-29 11:58:50 -07:00
}
}