From 0a93a4e9a4ff750ad56923fb3f23a5245866a087 Mon Sep 17 00:00:00 2001 From: Mika Vilpas Date: Wed, 10 Apr 2024 19:25:24 +0300 Subject: [PATCH] feat: add "trash" event for trashing files --- yazi-dds/src/body/body.rs | 6 +++++- yazi-dds/src/body/mod.rs | 2 ++ yazi-dds/src/body/trash.rs | 36 +++++++++++++++++++++++++++++++++ yazi-dds/src/payload.rs | 1 + yazi-dds/src/pubsub.rs | 14 ++++++++++++- yazi-dds/src/pump.rs | 15 ++++++++++++++ yazi-scheduler/src/scheduler.rs | 2 +- 7 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 yazi-dds/src/body/trash.rs diff --git a/yazi-dds/src/body/body.rs b/yazi-dds/src/body/body.rs index 21549fd2..159cb5d1 100644 --- a/yazi-dds/src/body/body.rs +++ b/yazi-dds/src/body/body.rs @@ -2,7 +2,7 @@ use anyhow::Result; use mlua::{ExternalResult, IntoLua, Lua, Value}; use serde::Serialize; -use super::{BodyBulk, BodyCd, BodyCustom, BodyDelete, BodyHey, BodyHi, BodyHover, BodyMove, BodyRename, BodyYank}; +use super::{BodyBulk, BodyCd, BodyCustom, BodyDelete, BodyHey, BodyHi, BodyHover, BodyMove, BodyRename, BodyTrash, BodyYank}; use crate::Payload; #[derive(Debug, Serialize)] @@ -17,6 +17,7 @@ pub enum Body<'a> { Yank(BodyYank<'a>), Move(BodyMove<'a>), Delete(BodyDelete<'a>), + Trash(BodyTrash<'a>), Custom(BodyCustom), } @@ -32,6 +33,7 @@ impl<'a> Body<'a> { "yank" => Body::Yank(serde_json::from_str(body)?), "move" => Body::Move(serde_json::from_str(body)?), "delete" => Body::Delete(serde_json::from_str(body)?), + "trash" => Body::Trash(serde_json::from_str(body)?), _ => BodyCustom::from_str(kind, body)?, }) } @@ -60,6 +62,7 @@ impl<'a> Body<'a> { Self::Yank(_) => "yank", Body::Move(_) => "move", Body::Delete(_) => "delete", + Body::Trash(_) => "trash", Self::Custom(b) => b.kind.as_str(), } } @@ -102,6 +105,7 @@ impl IntoLua<'_> for Body<'static> { Body::Yank(b) => b.into_lua(lua), Body::Move(b) => b.into_lua(lua), Body::Delete(b) => b.into_lua(lua), + Body::Trash(b) => b.into_lua(lua), Body::Custom(b) => b.into_lua(lua), } } diff --git a/yazi-dds/src/body/mod.rs b/yazi-dds/src/body/mod.rs index ade26d21..1c60c6ce 100644 --- a/yazi-dds/src/body/mod.rs +++ b/yazi-dds/src/body/mod.rs @@ -10,6 +10,7 @@ mod hi; mod hover; mod move_; mod rename; +mod trash; mod yank; pub use body::*; @@ -22,4 +23,5 @@ pub use hi::*; pub use hover::*; pub use move_::*; pub use rename::*; +pub use trash::*; pub use yank::*; diff --git a/yazi-dds/src/body/trash.rs b/yazi-dds/src/body/trash.rs new file mode 100644 index 00000000..88a2242b --- /dev/null +++ b/yazi-dds/src/body/trash.rs @@ -0,0 +1,36 @@ +use std::borrow::Cow; + +use mlua::{IntoLua, Lua, Value}; +use serde::{Deserialize, Serialize}; +use yazi_shared::fs::Url; + +use super::Body; + +#[derive(Debug, Serialize, Deserialize)] +pub struct BodyTrash<'a> { + pub urls: Cow<'a, Vec>, +} + +impl<'a> BodyTrash<'a> { + #[inline] + pub fn borrowed(urls: &'a Vec) -> Body<'a> { Self { urls: Cow::Borrowed(urls) }.into() } +} + +impl BodyTrash<'static> { + #[inline] + pub fn owned(urls: Vec) -> Body<'static> { Self { urls: Cow::Owned(urls) }.into() } +} + +impl<'a> From> for Body<'a> { + fn from(value: BodyTrash<'a>) -> Self { Self::Trash(value) } +} + +impl IntoLua<'_> for BodyTrash<'static> { + fn into_lua(self, lua: &Lua) -> mlua::Result> { + let t = lua.create_table_with_capacity(self.urls.len(), 0)?; + for (i, url) in self.urls.into_owned().into_iter().enumerate() { + t.raw_set(i + 1, lua.create_any_userdata(url)?)?; + } + t.into_lua(lua) + } +} diff --git a/yazi-dds/src/payload.rs b/yazi-dds/src/payload.rs index 7deb80d5..881fa972 100644 --- a/yazi-dds/src/payload.rs +++ b/yazi-dds/src/payload.rs @@ -86,6 +86,7 @@ impl Display for Payload<'_> { Body::Yank(b) => serde_json::to_string(b), Body::Move(b) => serde_json::to_string(b), Body::Delete(b) => serde_json::to_string(b), + Body::Trash(b) => serde_json::to_string(b), Body::Custom(b) => serde_json::to_string(b), }; diff --git a/yazi-dds/src/pubsub.rs b/yazi-dds/src/pubsub.rs index 0120a1e9..482413a1 100644 --- a/yazi-dds/src/pubsub.rs +++ b/yazi-dds/src/pubsub.rs @@ -5,7 +5,7 @@ use parking_lot::RwLock; use yazi_boot::BOOT; use yazi_shared::{fs::Url, RoCell}; -use crate::{body::{Body, BodyCd, BodyDelete, BodyHi, BodyHover, BodyMove, BodyMoveItem, BodyRename, BodyYank}, Client, ID, PEERS}; +use crate::{body::{Body, BodyCd, BodyDelete, BodyHi, BodyHover, BodyMove, BodyMoveItem, BodyRename, BodyTrash, BodyYank}, Client, ID, PEERS}; pub static LOCAL: RoCell>>>> = RoCell::new(); @@ -166,4 +166,16 @@ impl Pubsub { Self::pub_(BodyDelete::owned(urls)); } } + + pub(super) fn pub_from_trash(urls: Vec) { + if PEERS.read().values().any(|p| p.able("trash")) { + Client::push(BodyTrash::borrowed(&urls)); + } + if BOOT.local_events.contains("trash") { + BodyTrash::borrowed(&urls).with_receiver(*ID).flush(); + } + if LOCAL.read().contains_key("trash") { + Self::pub_(BodyTrash::owned(urls)); + } + } } diff --git a/yazi-dds/src/pump.rs b/yazi-dds/src/pump.rs index 740c9e1a..a5e58117 100644 --- a/yazi-dds/src/pump.rs +++ b/yazi-dds/src/pump.rs @@ -11,6 +11,7 @@ use crate::{body::BodyMoveItem, Pubsub}; static CT: RoCell = RoCell::new(); static MOVE_TX: Mutex>> = Mutex::new(None); static DELETE_TX: Mutex>> = Mutex::new(None); +static TRASH_TX: Mutex>> = Mutex::new(None); pub struct Pump; @@ -29,27 +30,40 @@ impl Pump { } } + #[inline] + pub fn push_trash(target: Url) { + if let Some(tx) = &*TRASH_TX.lock() { + tx.send(target).ok(); + } + } + pub(super) fn serve() { let (move_tx, move_rx) = mpsc::unbounded_channel(); let (delete_tx, delete_rx) = mpsc::unbounded_channel(); + let (trash_tx, trash_rx) = mpsc::unbounded_channel(); CT.with(Default::default); MOVE_TX.lock().replace(move_tx); DELETE_TX.lock().replace(delete_tx); + TRASH_TX.lock().replace(trash_tx); tokio::spawn(async move { let move_rx = UnboundedReceiverStream::new(move_rx).chunks_timeout(1000, Duration::from_millis(500)); let delete_rx = UnboundedReceiverStream::new(delete_rx).chunks_timeout(1000, Duration::from_millis(500)); + let trash_rx = + UnboundedReceiverStream::new(trash_rx).chunks_timeout(1000, Duration::from_millis(500)); pin!(move_rx); pin!(delete_rx); + pin!(trash_rx); loop { select! { Some(items) = move_rx.next() => Pubsub::pub_from_move(items), Some(urls) = delete_rx.next() => Pubsub::pub_from_delete(urls), + Some(urls) = trash_rx.next() => Pubsub::pub_from_trash(urls), else => { CT.cancel(); break; @@ -62,6 +76,7 @@ impl Pump { pub(super) async fn shutdown() { drop(MOVE_TX.lock().take()); drop(DELETE_TX.lock().take()); + drop(TRASH_TX.lock().take()); CT.cancelled().await; } } diff --git a/yazi-scheduler/src/scheduler.rs b/yazi-scheduler/src/scheduler.rs index da9fbc4b..8b66556f 100644 --- a/yazi-scheduler/src/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -175,7 +175,7 @@ impl Scheduler { _ = self.micro.try_send( async move { file.trash(FileOpTrash { id, target: target.clone(), length: 0 }).await.ok(); - Pump::push_delete(target); + Pump::push_trash(target); } .boxed(), LOW,