mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: throw catchable errors instead of crashing when publishing a message containing invalid UTF-8 over DDS (#2893)
This commit is contained in:
parent
a0ce7c0ae7
commit
750ca0c0d4
18 changed files with 145 additions and 97 deletions
|
|
@ -7,6 +7,7 @@ use tokio::{fs::{self, OpenOptions}, io::AsyncWriteExt};
|
|||
use yazi_config::YAZI;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, FilesOp, max_common_root, maybe_exists, paths_to_same_file};
|
||||
use yazi_macro::err;
|
||||
use yazi_proxy::{AppProxy, HIDER, TasksProxy, WATCHER};
|
||||
use yazi_shared::{terminal_clear, url::Url};
|
||||
use yazi_term::tty::TTY;
|
||||
|
|
@ -102,7 +103,8 @@ impl Mgr {
|
|||
}
|
||||
|
||||
if !succeeded.is_empty() {
|
||||
Pubsub::pub_from_bulk(succeeded.iter().map(|(o, n)| (o, &n.url)).collect());
|
||||
let map = succeeded.iter().map(|(o, n)| (o, &n.url)).collect();
|
||||
err!(Pubsub::pub_from_bulk(map));
|
||||
FilesOp::rename(succeeded);
|
||||
}
|
||||
drop(permit);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use tokio::fs;
|
|||
use yazi_config::popup::{ConfirmCfg, InputCfg};
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, FilesOp, maybe_exists, ok_or_not_found, paths_to_same_file, realname};
|
||||
use yazi_macro::err;
|
||||
use yazi_proxy::{ConfirmProxy, InputProxy, TabProxy, WATCHER};
|
||||
use yazi_shared::{Id, event::CmdCow, url::{Url, UrnBuf}};
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ impl Mgr {
|
|||
}
|
||||
|
||||
TabProxy::reveal(&new);
|
||||
Pubsub::pub_from_rename(tab, &old, &new);
|
||||
err!(Pubsub::pub_from_rename(tab, &old, &new));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::ops::{Deref, DerefMut};
|
|||
use yazi_boot::BOOT;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::File;
|
||||
use yazi_macro::err;
|
||||
use yazi_proxy::MgrProxy;
|
||||
use yazi_shared::{Id, url::Url};
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ impl Tabs {
|
|||
self.cursor = idx;
|
||||
MgrProxy::refresh();
|
||||
MgrProxy::peek(true);
|
||||
Pubsub::pub_from_tab(self.active().id);
|
||||
err!(Pubsub::pub_from_tab(self.active().id));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,9 @@ impl Watcher {
|
|||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
yazi_fs::mounts::Partitions::monitor(
|
||||
yazi_fs::mounts::PARTITIONS.clone(),
|
||||
yazi_dds::Pubsub::pub_from_mount,
|
||||
);
|
||||
yazi_fs::mounts::Partitions::monitor(yazi_fs::mounts::PARTITIONS.clone(), || {
|
||||
yazi_macro::err!(yazi_dds::Pubsub::pub_from_mount())
|
||||
});
|
||||
|
||||
tokio::spawn(Self::fan_out(out_rx));
|
||||
Self { in_tx, out_tx }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::{collections::HashSet, ops::Deref};
|
|||
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::FilesOp;
|
||||
use yazi_macro::err;
|
||||
use yazi_shared::url::Url;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
|
@ -65,7 +66,7 @@ impl Yanked {
|
|||
}
|
||||
|
||||
self.version = self.revision;
|
||||
Pubsub::pub_from_yank(self.cut, &self.urls);
|
||||
err!(Pubsub::pub_from_yank(self.cut, &self.urls));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
|||
use yazi_config::popup::InputCfg;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, FilesOp, expand_path};
|
||||
use yazi_macro::render;
|
||||
use yazi_macro::{err, render};
|
||||
use yazi_proxy::{CmpProxy, InputProxy, MgrProxy, TabProxy};
|
||||
use yazi_shared::{Debounce, errors::InputError, event::CmdCow, url::Url};
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ impl Tab {
|
|||
self.parent = Some(self.history.remove_or(&parent));
|
||||
}
|
||||
|
||||
Pubsub::pub_from_cd(self.id, self.cwd());
|
||||
err!(Pubsub::pub_from_cd(self.id, self.cwd()));
|
||||
self.hover(None);
|
||||
|
||||
MgrProxy::refresh();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use yazi_dds::Pubsub;
|
||||
use yazi_macro::render;
|
||||
use yazi_macro::{err, render};
|
||||
use yazi_shared::{event::CmdCow, url::{Url, Urn}};
|
||||
|
||||
use crate::tab::Tab;
|
||||
|
|
@ -25,7 +25,7 @@ impl Tab {
|
|||
}
|
||||
|
||||
// Publish through DDS
|
||||
Pubsub::pub_from_hover(self.id, self.hovered().map(|h| &h.url));
|
||||
err!(Pubsub::pub_from_hover(self.id, self.hovered().map(|h| &h.url)));
|
||||
}
|
||||
|
||||
fn hover_do(&mut self, url: Url) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::mem;
|
|||
use yazi_config::{LAYOUT, YAZI};
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, Files, FilesOp, FolderStage, Step, cha::Cha};
|
||||
use yazi_macro::err;
|
||||
use yazi_proxy::MgrProxy;
|
||||
use yazi_shared::{Id, url::{Url, Urn, UrnBuf}};
|
||||
|
||||
|
|
@ -88,7 +89,7 @@ impl Folder {
|
|||
if !self.update(op) {
|
||||
return false;
|
||||
} else if self.stage != old {
|
||||
Pubsub::pub_from_load(tab, &self.url, self.stage);
|
||||
err!(Pubsub::pub_from_load(tab, &self.url, self.stage));
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use parking_lot::RwLock;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tokio::{io::AsyncWriteExt, select, sync::mpsc, task::JoinHandle, time};
|
||||
use tracing::error;
|
||||
use yazi_macro::try_format;
|
||||
use yazi_shared::{Id, RoCell};
|
||||
|
||||
use crate::{ClientReader, ClientWriter, Payload, Pubsub, Server, Stream, body::{Body, BodyBye, BodyHi}};
|
||||
|
|
@ -55,7 +56,7 @@ impl Client {
|
|||
continue;
|
||||
} else if line.starts_with("hey,") {
|
||||
Self::handle_hey(&line);
|
||||
} else if let Err(e) = Payload::from_str(&line).map(|p| p.emit()) {
|
||||
} else if let Err(e) = Payload::from_str(&line).and_then(|p| p.emit()) {
|
||||
error!("Could not parse payload:\n{line}\n\nError:\n{e}");
|
||||
}
|
||||
}
|
||||
|
|
@ -68,11 +69,11 @@ impl Client {
|
|||
pub async fn shot(kind: &str, receiver: Id, body: &str) -> Result<()> {
|
||||
Body::validate(kind)?;
|
||||
|
||||
let payload = format!(
|
||||
let payload = try_format!(
|
||||
"{}\n{kind},{receiver},{ID},{body}\n{}\n",
|
||||
Payload::new(BodyHi::borrowed(Default::default())),
|
||||
Payload::new(BodyBye::owned())
|
||||
);
|
||||
)?;
|
||||
|
||||
let (mut lines, mut writer) = Stream::connect().await?;
|
||||
writer.write_all(payload.as_bytes()).await?;
|
||||
|
|
@ -129,7 +130,7 @@ impl Client {
|
|||
async fn make(kinds: &HashSet<&str>) -> Result<ClientReader> {
|
||||
let (lines, mut writer) = Stream::connect().await?;
|
||||
let hi = Payload::new(BodyHi::borrowed(kinds.clone()));
|
||||
writer.write_all(format!("{hi}\n").as_bytes()).await?;
|
||||
writer.write_all(try_format!("{hi}\n")?.as_bytes()).await?;
|
||||
writer.flush().await?;
|
||||
Ok(lines)
|
||||
}
|
||||
|
|
@ -155,8 +156,8 @@ impl Client {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn push<'a>(payload: impl Into<Payload<'a>>) {
|
||||
QUEUE_TX.send(format!("{}\n", payload.into())).ok();
|
||||
pub(super) fn push<'a>(payload: impl Into<Payload<'a>>) -> Result<()> {
|
||||
Ok(QUEUE_TX.send(try_format!("{}\n", payload.into())?)?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -17,9 +17,12 @@ pub struct Payload<'a> {
|
|||
impl<'a> Payload<'a> {
|
||||
pub(super) fn new(body: Body<'a>) -> Self { Self { receiver: Id(0), sender: *ID, body } }
|
||||
|
||||
pub(super) fn flush(&self) { writeln!(std::io::stdout(), "{self}").ok(); }
|
||||
pub(super) fn flush(&self) -> Result<()> {
|
||||
writeln!(std::io::stdout(), "{self}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn try_flush(&self) {
|
||||
pub(super) fn try_flush(&self) -> Result<()> {
|
||||
let b = if self.receiver == 0 {
|
||||
BOOT.remote_events.contains(self.body.kind())
|
||||
} else if let Body::Custom(b) = &self.body {
|
||||
|
|
@ -27,10 +30,7 @@ impl<'a> Payload<'a> {
|
|||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if b {
|
||||
self.flush();
|
||||
}
|
||||
if b { self.flush() } else { Ok(()) }
|
||||
}
|
||||
|
||||
pub(super) fn with_receiver(mut self, receiver: Id) -> Self {
|
||||
|
|
@ -45,9 +45,10 @@ impl<'a> Payload<'a> {
|
|||
}
|
||||
|
||||
impl Payload<'static> {
|
||||
pub(super) fn emit(self) {
|
||||
self.try_flush();
|
||||
pub(super) fn emit(self) -> Result<()> {
|
||||
self.try_flush()?;
|
||||
emit!(Call(Cmd::new("app:accept_payload").with_any("payload", self)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use anyhow::Result;
|
||||
use mlua::Function;
|
||||
use parking_lot::RwLock;
|
||||
use yazi_boot::BOOT;
|
||||
|
|
@ -62,159 +63,172 @@ impl Pubsub {
|
|||
unsub!(REMOTE)(plugin, kind) && Self::pub_from_hi()
|
||||
}
|
||||
|
||||
pub fn r#pub(body: Body<'static>) { body.with_receiver(*ID).emit(); }
|
||||
pub fn r#pub(body: Body<'static>) -> Result<()> { body.with_receiver(*ID).emit() }
|
||||
|
||||
pub fn pub_to(receiver: Id, body: Body<'static>) {
|
||||
pub fn pub_to(receiver: Id, body: Body<'static>) -> Result<()> {
|
||||
if receiver == *ID {
|
||||
return Self::r#pub(body);
|
||||
}
|
||||
|
||||
let kind = body.kind();
|
||||
if receiver == 0 && Self::any_remote_own(kind) {
|
||||
Client::push(body);
|
||||
Client::push(body)?;
|
||||
} else if PEERS.read().get(&receiver).is_some_and(|c| c.able(kind)) {
|
||||
Client::push(body.with_receiver(receiver));
|
||||
Client::push(body.with_receiver(receiver))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_hi() -> bool {
|
||||
let abilities = REMOTE.read().keys().cloned().collect();
|
||||
let abilities = BOOT.remote_events.union(&abilities).map(|s| s.as_str()).collect();
|
||||
|
||||
Client::push(BodyHi::borrowed(abilities));
|
||||
// FIXME: handle error
|
||||
Client::push(BodyHi::borrowed(abilities)).ok();
|
||||
true
|
||||
}
|
||||
|
||||
pub fn pub_from_tab(idx: Id) {
|
||||
pub fn pub_from_tab(idx: Id) -> Result<()> {
|
||||
if LOCAL.read().contains_key("tab") {
|
||||
Self::r#pub(BodyTab::owned(idx));
|
||||
Self::r#pub(BodyTab::owned(idx))?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("tab")) {
|
||||
Client::push(BodyTab::owned(idx));
|
||||
Client::push(BodyTab::owned(idx))?;
|
||||
}
|
||||
if BOOT.local_events.contains("tab") {
|
||||
BodyTab::owned(idx).with_receiver(*ID).flush();
|
||||
BodyTab::owned(idx).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_cd(tab: Id, url: &Url) {
|
||||
pub fn pub_from_cd(tab: Id, url: &Url) -> Result<()> {
|
||||
if LOCAL.read().contains_key("cd") {
|
||||
Self::r#pub(BodyCd::dummy(tab));
|
||||
Self::r#pub(BodyCd::dummy(tab))?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("cd")) {
|
||||
Client::push(BodyCd::borrowed(tab, url));
|
||||
Client::push(BodyCd::borrowed(tab, url))?;
|
||||
}
|
||||
if BOOT.local_events.contains("cd") {
|
||||
BodyCd::borrowed(tab, url).with_receiver(*ID).flush();
|
||||
BodyCd::borrowed(tab, url).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_load(tab: Id, url: &Url, stage: FolderStage) {
|
||||
pub fn pub_from_load(tab: Id, url: &Url, stage: FolderStage) -> Result<()> {
|
||||
if LOCAL.read().contains_key("load") {
|
||||
Self::r#pub(BodyLoad::dummy(tab, url, stage));
|
||||
Self::r#pub(BodyLoad::dummy(tab, url, stage))?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("load")) {
|
||||
Client::push(BodyLoad::borrowed(tab, url, stage));
|
||||
Client::push(BodyLoad::borrowed(tab, url, stage))?;
|
||||
}
|
||||
if BOOT.local_events.contains("load") {
|
||||
BodyLoad::borrowed(tab, url, stage).with_receiver(*ID).flush();
|
||||
BodyLoad::borrowed(tab, url, stage).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_hover(tab: Id, url: Option<&Url>) {
|
||||
pub fn pub_from_hover(tab: Id, url: Option<&Url>) -> Result<()> {
|
||||
if LOCAL.read().contains_key("hover") {
|
||||
Self::r#pub(BodyHover::dummy(tab));
|
||||
Self::r#pub(BodyHover::dummy(tab))?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("hover")) {
|
||||
Client::push(BodyHover::borrowed(tab, url));
|
||||
Client::push(BodyHover::borrowed(tab, url))?;
|
||||
}
|
||||
if BOOT.local_events.contains("hover") {
|
||||
BodyHover::borrowed(tab, url).with_receiver(*ID).flush();
|
||||
BodyHover::borrowed(tab, url).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_rename(tab: Id, from: &Url, to: &Url) {
|
||||
pub fn pub_from_rename(tab: Id, from: &Url, to: &Url) -> Result<()> {
|
||||
if LOCAL.read().contains_key("rename") {
|
||||
Self::r#pub(BodyRename::dummy(tab, from, to));
|
||||
Self::r#pub(BodyRename::dummy(tab, from, to))?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("rename")) {
|
||||
Client::push(BodyRename::borrowed(tab, from, to));
|
||||
Client::push(BodyRename::borrowed(tab, from, to))?;
|
||||
}
|
||||
if BOOT.local_events.contains("rename") {
|
||||
BodyRename::borrowed(tab, from, to).with_receiver(*ID).flush();
|
||||
BodyRename::borrowed(tab, from, to).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_bulk(changes: HashMap<&Url, &Url>) {
|
||||
pub fn pub_from_bulk(changes: HashMap<&Url, &Url>) -> Result<()> {
|
||||
if LOCAL.read().contains_key("bulk") {
|
||||
Self::r#pub(BodyBulk::owned(&changes));
|
||||
Self::r#pub(BodyBulk::owned(&changes))?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("bulk")) {
|
||||
Client::push(BodyBulk::borrowed(&changes));
|
||||
Client::push(BodyBulk::borrowed(&changes))?;
|
||||
}
|
||||
if BOOT.local_events.contains("bulk") {
|
||||
BodyBulk::borrowed(&changes).with_receiver(*ID).flush();
|
||||
BodyBulk::borrowed(&changes).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_yank(cut: bool, urls: &HashSet<Url>) {
|
||||
pub fn pub_from_yank(cut: bool, urls: &HashSet<Url>) -> Result<()> {
|
||||
if LOCAL.read().contains_key("@yank") {
|
||||
Self::r#pub(BodyYank::dummy());
|
||||
Self::r#pub(BodyYank::dummy())?;
|
||||
}
|
||||
if Self::any_remote_own("@yank") {
|
||||
Client::push(BodyYank::borrowed(cut, urls));
|
||||
Client::push(BodyYank::borrowed(cut, urls))?;
|
||||
}
|
||||
if BOOT.local_events.contains("@yank") {
|
||||
BodyYank::borrowed(cut, urls).with_receiver(*ID).flush();
|
||||
BodyYank::borrowed(cut, urls).with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn pub_from_move(items: Vec<BodyMoveItem>) {
|
||||
pub(super) fn pub_from_move(items: Vec<BodyMoveItem>) -> Result<()> {
|
||||
if PEERS.read().values().any(|p| p.able("move")) {
|
||||
Client::push(BodyMove::borrowed(&items));
|
||||
Client::push(BodyMove::borrowed(&items))?;
|
||||
}
|
||||
if BOOT.local_events.contains("move") {
|
||||
BodyMove::borrowed(&items).with_receiver(*ID).flush();
|
||||
BodyMove::borrowed(&items).with_receiver(*ID).flush()?;
|
||||
}
|
||||
if LOCAL.read().contains_key("move") {
|
||||
Self::r#pub(BodyMove::owned(items));
|
||||
Self::r#pub(BodyMove::owned(items))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn pub_from_trash(urls: Vec<Url>) {
|
||||
pub(super) fn pub_from_trash(urls: Vec<Url>) -> Result<()> {
|
||||
if PEERS.read().values().any(|p| p.able("trash")) {
|
||||
Client::push(BodyTrash::borrowed(&urls));
|
||||
Client::push(BodyTrash::borrowed(&urls))?;
|
||||
}
|
||||
if BOOT.local_events.contains("trash") {
|
||||
BodyTrash::borrowed(&urls).with_receiver(*ID).flush();
|
||||
BodyTrash::borrowed(&urls).with_receiver(*ID).flush()?;
|
||||
}
|
||||
if LOCAL.read().contains_key("trash") {
|
||||
Self::r#pub(BodyTrash::owned(urls));
|
||||
Self::r#pub(BodyTrash::owned(urls))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn pub_from_delete(urls: Vec<Url>) {
|
||||
pub(super) fn pub_from_delete(urls: Vec<Url>) -> Result<()> {
|
||||
if PEERS.read().values().any(|p| p.able("delete")) {
|
||||
Client::push(BodyDelete::borrowed(&urls));
|
||||
Client::push(BodyDelete::borrowed(&urls))?;
|
||||
}
|
||||
if BOOT.local_events.contains("delete") {
|
||||
BodyDelete::borrowed(&urls).with_receiver(*ID).flush();
|
||||
BodyDelete::borrowed(&urls).with_receiver(*ID).flush()?;
|
||||
}
|
||||
if LOCAL.read().contains_key("delete") {
|
||||
Self::r#pub(BodyDelete::owned(urls));
|
||||
Self::r#pub(BodyDelete::owned(urls))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pub_from_mount() {
|
||||
pub fn pub_from_mount() -> Result<()> {
|
||||
if LOCAL.read().contains_key("mount") {
|
||||
Self::r#pub(BodyMount::owned());
|
||||
Self::r#pub(BodyMount::owned())?;
|
||||
}
|
||||
if PEERS.read().values().any(|p| p.able("mount")) {
|
||||
Client::push(BodyMount::owned());
|
||||
Client::push(BodyMount::owned())?;
|
||||
}
|
||||
if BOOT.local_events.contains("mount") {
|
||||
BodyMount::owned().with_receiver(*ID).flush();
|
||||
BodyMount::owned().with_receiver(*ID).flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use parking_lot::Mutex;
|
|||
use tokio::{pin, select, sync::mpsc};
|
||||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use yazi_macro::err;
|
||||
use yazi_shared::{RoCell, url::Url};
|
||||
|
||||
use crate::{Pubsub, body::BodyMoveItem};
|
||||
|
|
@ -61,9 +62,9 @@ impl Pump {
|
|||
|
||||
loop {
|
||||
select! {
|
||||
Some(items) = move_rx.next() => Pubsub::pub_from_move(items),
|
||||
Some(urls) = trash_rx.next() => Pubsub::pub_from_trash(urls),
|
||||
Some(urls) = delete_rx.next() => Pubsub::pub_from_delete(urls),
|
||||
Some(items) = move_rx.next() => err!(Pubsub::pub_from_move(items)),
|
||||
Some(urls) = trash_rx.next() => err!(Pubsub::pub_from_trash(urls)),
|
||||
Some(urls) = delete_rx.next() => err!(Pubsub::pub_from_delete(urls)),
|
||||
else => {
|
||||
CT.cancel();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::{collections::HashMap, str::FromStr, time::Duration};
|
|||
use anyhow::Result;
|
||||
use parking_lot::RwLock;
|
||||
use tokio::{io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, select, sync::mpsc::{self, UnboundedReceiver}, task::JoinHandle, time};
|
||||
use yazi_macro::try_format;
|
||||
use yazi_shared::{Id, RoCell};
|
||||
|
||||
use crate::{Client, ClientWriter, Payload, Peer, STATE, Stream, body::{Body, BodyBye, BodyHey}};
|
||||
|
|
@ -109,13 +110,12 @@ impl Server {
|
|||
}
|
||||
|
||||
fn handle_hey(clients: &HashMap<Id, Client>) {
|
||||
let payload = format!(
|
||||
"{}\n",
|
||||
Payload::new(BodyHey::owned(
|
||||
clients.values().map(|c| (c.id, Peer::new(&c.abilities))).collect()
|
||||
))
|
||||
);
|
||||
clients.values().for_each(|c| _ = c.tx.send(payload.clone()));
|
||||
let payload = Payload::new(BodyHey::owned(
|
||||
clients.values().map(|c| (c.id, Peer::new(&c.abilities))).collect(),
|
||||
));
|
||||
if let Ok(s) = try_format!("{payload}\n") {
|
||||
clients.values().for_each(|c| _ = c.tx.send(s.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_bye(id: Id, mut rx: UnboundedReceiver<String>, mut writer: ClientWriter) {
|
||||
|
|
@ -125,10 +125,10 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
_ = writer
|
||||
.write_all(BodyBye::owned().with_receiver(id).with_sender(Id(0)).to_string().as_bytes())
|
||||
.await;
|
||||
|
||||
writer.flush().await.ok();
|
||||
let bye = BodyBye::owned().with_receiver(id).with_sender(Id(0));
|
||||
if let Ok(s) = try_format!("{bye}") {
|
||||
writer.write_all(s.as_bytes()).await.ok();
|
||||
writer.flush().await.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@ use yazi_shared::natsort;
|
|||
use super::{Locked, Partition, Partitions};
|
||||
|
||||
impl Partitions {
|
||||
pub fn monitor(me: Locked, cb: fn()) {
|
||||
pub fn monitor<F>(me: Locked, cb: F)
|
||||
where
|
||||
F: Fn() + Copy + Send + 'static,
|
||||
{
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let session = unsafe { DASessionCreate(kCFAllocatorDefault) };
|
||||
if session.is_null() {
|
||||
|
|
@ -41,7 +44,7 @@ impl Partitions {
|
|||
if mem::replace(&mut me.write().need_update, true) {
|
||||
return;
|
||||
}
|
||||
Self::update(me.clone(), cb);
|
||||
Self::update(me.clone(), move || _ = cb());
|
||||
});
|
||||
Box::into_raw(Box::new(boxed)) as *mut c_void
|
||||
};
|
||||
|
|
|
|||
9
yazi-macro/src/fmt.rs
Normal file
9
yazi-macro/src/fmt.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#[macro_export]
|
||||
macro_rules! try_format {
|
||||
($($arg:tt)*) => {{
|
||||
use std::fmt::Write;
|
||||
|
||||
let mut output = String::new();
|
||||
output.write_fmt(format_args!($($arg)*)).map(|_| output)
|
||||
}}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
mod asset;
|
||||
mod event;
|
||||
mod fmt;
|
||||
mod log;
|
||||
mod module;
|
||||
mod platform;
|
||||
|
|
|
|||
|
|
@ -17,3 +17,18 @@ macro_rules! time {
|
|||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! err {
|
||||
($expr:expr) => {
|
||||
$crate::err!(stringify!($expr), $expr)
|
||||
};
|
||||
($label:expr, $expr:expr) => {
|
||||
$crate::err!($expr, "{}", $label)
|
||||
};
|
||||
($expr:expr, $fmt:expr, $($args:tt)*) => {{
|
||||
if let Err(e) = $expr {
|
||||
tracing::error!("{} failed: {e}", format_args!($fmt, $($args)*));
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,13 @@ pub struct Pubsub;
|
|||
impl Pubsub {
|
||||
pub(super) fn r#pub(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, (kind, value): (mlua::String, Value)| {
|
||||
yazi_dds::Pubsub::r#pub(Body::from_lua(&kind.to_str()?, value)?);
|
||||
Ok(())
|
||||
yazi_dds::Pubsub::r#pub(Body::from_lua(&kind.to_str()?, value)?).into_lua_err()
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn pub_to(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, (receiver, kind, value): (Id, mlua::String, Value)| {
|
||||
yazi_dds::Pubsub::pub_to(*receiver, Body::from_lua(&kind.to_str()?, value)?);
|
||||
Ok(())
|
||||
yazi_dds::Pubsub::pub_to(*receiver, Body::from_lua(&kind.to_str()?, value)?).into_lua_err()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue