From 37acd94345f910040e6233f840765f6494686609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Tue, 5 Mar 2024 16:46:12 +0800 Subject: [PATCH] feat: `ya.notify()` plugin API (#780) --- Cargo.lock | 152 +++++++++++++--------- yazi-core/src/input/commands/show.rs | 2 +- yazi-core/src/manager/commands/open.rs | 2 +- yazi-core/src/notify/commands/push.rs | 6 +- yazi-core/src/notify/level.rs | 20 --- yazi-core/src/notify/message.rs | 34 ++--- yazi-core/src/notify/mod.rs | 2 - yazi-core/src/select/commands/show.rs | 2 +- yazi-core/src/tab/commands/escape.rs | 2 +- yazi-core/src/tab/commands/select.rs | 5 +- yazi-core/src/tab/commands/select_all.rs | 5 +- yazi-core/src/tasks/commands/open_with.rs | 2 +- yazi-fm/src/app/commands/notify.rs | 10 +- yazi-fm/src/notify/layout.rs | 9 +- yazi-plugin/src/utils/layer.rs | 10 +- yazi-proxy/Cargo.toml | 1 + yazi-proxy/src/app.rs | 21 ++- yazi-proxy/src/input.rs | 11 +- yazi-proxy/src/lib.rs | 1 + yazi-proxy/src/manager.rs | 11 +- yazi-proxy/src/options/input.rs | 14 ++ yazi-proxy/src/options/mod.rs | 9 ++ yazi-proxy/src/options/notify.rs | 63 +++++++++ yazi-proxy/src/options/open.rs | 26 ++++ yazi-proxy/src/options/select.rs | 14 ++ yazi-proxy/src/select.rs | 11 +- yazi-proxy/src/tasks.rs | 13 +- 27 files changed, 286 insertions(+), 172 deletions(-) delete mode 100644 yazi-core/src/notify/level.rs create mode 100644 yazi-proxy/src/options/input.rs create mode 100644 yazi-proxy/src/options/mod.rs create mode 100644 yazi-proxy/src/options/notify.rs create mode 100644 yazi-proxy/src/options/open.rs create mode 100644 yazi-proxy/src/options/select.rs diff --git a/Cargo.lock b/Cargo.lock index c1dd3431..28030fd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", @@ -126,9 +126,9 @@ checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" [[package]] name = "async-priority-channel" @@ -166,6 +166,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "better-panic" version = "0.3.0" @@ -263,9 +269,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" [[package]] name = "cfg-if" @@ -304,7 +310,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", ] [[package]] @@ -502,6 +508,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 2.0.52", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.52", +] + [[package]] name = "deranged" version = "0.3.11" @@ -887,14 +928,10 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.4.0" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" @@ -906,12 +943,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - [[package]] name = "image" version = "0.24.9" @@ -998,9 +1029,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1165,9 +1196,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -1431,7 +1462,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ - "base64", + "base64 0.21.7", "indexmap", "line-wrap", "quick-xml", @@ -1592,9 +1623,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1840,6 +1871,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.0" @@ -2240,7 +2277,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", ] @@ -2262,12 +2299,12 @@ dependencies = [ [[package]] name = "validator" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd" +checksum = "da339118f018cc70ebf01fafc103360528aad53717e4bf311db929cb01cb9345" dependencies = [ - "idna 0.4.0", - "lazy_static", + "idna", + "once_cell", "regex", "serde", "serde_derive", @@ -2278,28 +2315,16 @@ dependencies = [ [[package]] name = "validator_derive" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc44ca3088bb3ba384d9aecf40c6a23a676ce23e09bdaca2073d99c207f864af" +checksum = "76e88ea23b8f5e59230bff8a2f03c0ee0054a61d5b8343a38946bcd406fe624c" dependencies = [ - "if_chain", - "lazy_static", + "darling", "proc-macro-error", "proc-macro2", "quote", "regex", - "syn 1.0.109", - "validator_types", -] - -[[package]] -name = "validator_types" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3" -dependencies = [ - "proc-macro2", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -2328,9 +2353,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2344,9 +2369,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2354,9 +2379,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -2369,9 +2394,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2379,9 +2404,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -2392,9 +2417,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "weezl" @@ -2668,7 +2693,7 @@ version = "0.2.3" dependencies = [ "anyhow", "arc-swap", - "base64", + "base64 0.22.0", "color_quant", "crossterm", "image", @@ -2719,7 +2744,7 @@ name = "yazi-core" version = "0.2.3" dependencies = [ "anyhow", - "base64", + "base64 0.22.0", "bitflags 2.4.2", "clipboard-win", "crossterm", @@ -2818,6 +2843,7 @@ name = "yazi-proxy" version = "0.2.3" dependencies = [ "anyhow", + "mlua", "tokio", "yazi-config", "yazi-shared", @@ -2829,7 +2855,7 @@ version = "0.2.3" dependencies = [ "anyhow", "async-priority-channel", - "base64", + "base64 0.22.0", "crossterm", "futures", "parking_lot", diff --git a/yazi-core/src/input/commands/show.rs b/yazi-core/src/input/commands/show.rs index bc35e16e..7abfcafc 100644 --- a/yazi-core/src/input/commands/show.rs +++ b/yazi-core/src/input/commands/show.rs @@ -1,4 +1,4 @@ -use yazi_proxy::InputOpt; +use yazi_proxy::options::InputOpt; use yazi_shared::render; use crate::input::Input; diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index c62b31ba..e4d1862a 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -4,7 +4,7 @@ use tracing::error; use yazi_boot::ARGS; use yazi_config::{popup::SelectCfg, OPEN}; use yazi_plugin::isolate; -use yazi_proxy::{ManagerProxy, OpenDoOpt, TasksProxy}; +use yazi_proxy::{options::OpenDoOpt, ManagerProxy, TasksProxy}; use yazi_shared::{emit, event::{Cmd, EventQuit}, fs::{File, Url}, MIME_DIR}; use crate::{folder::Folder, manager::Manager, tasks::Tasks}; diff --git a/yazi-core/src/notify/commands/push.rs b/yazi-core/src/notify/commands/push.rs index f3f2572b..0851895f 100644 --- a/yazi-core/src/notify/commands/push.rs +++ b/yazi-core/src/notify/commands/push.rs @@ -5,10 +5,8 @@ use yazi_shared::{emit, event::Cmd, Layer}; use crate::notify::{Message, Notify}; impl Notify { - pub fn push(&mut self, msg: impl TryInto) { - let Ok(mut msg) = msg.try_into() else { - return; - }; + pub fn push(&mut self, msg: impl Into) { + let mut msg = msg.into() as Message; let instant = Instant::now(); msg.timeout += instant - self.messages.first().map_or(instant, |m| m.instant); diff --git a/yazi-core/src/notify/level.rs b/yazi-core/src/notify/level.rs deleted file mode 100644 index f1cfa946..00000000 --- a/yazi-core/src/notify/level.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::str::FromStr; - -pub enum Level { - Info, - Warn, - Error, -} - -impl FromStr for Level { - type Err = (); - - fn from_str(s: &str) -> Result { - Ok(match s { - "info" => Self::Info, - "warn" => Self::Warn, - "error" => Self::Error, - _ => return Err(()), - }) - } -} diff --git a/yazi-core/src/notify/message.rs b/yazi-core/src/notify/message.rs index 9faad177..da80c186 100644 --- a/yazi-core/src/notify/message.rs +++ b/yazi-core/src/notify/message.rs @@ -1,41 +1,31 @@ use std::time::{Duration, Instant}; use unicode_width::UnicodeWidthStr; -use yazi_shared::event::Cmd; +use yazi_proxy::options::{NotifyLevel, NotifyOpt}; -use super::{Level, NOTIFY_BORDER}; +use super::NOTIFY_BORDER; pub struct Message { pub title: String, pub content: String, - pub level: Level, - - pub instant: Instant, + pub level: NotifyLevel, pub timeout: Duration, + pub instant: Instant, pub percent: u8, } -impl TryFrom for Message { - type Error = (); - - fn try_from(mut c: Cmd) -> Result { - let timeout = c.take_name("timeout").and_then(|s| s.parse::().ok()).ok_or(())?; - if timeout < 0.0 { - return Err(()); - } - - let content = c.take_name("content").ok_or(())?; - Ok(Self { - title: c.take_name("title").ok_or(())?, - content, - level: c.take_name("level").ok_or(())?.parse()?, +impl From for Message { + fn from(opt: NotifyOpt) -> Self { + Self { + title: opt.title, + content: opt.content, + level: opt.level, + timeout: opt.timeout, instant: Instant::now(), - timeout: Duration::from_secs_f64(timeout), - percent: 0, - }) + } } } diff --git a/yazi-core/src/notify/mod.rs b/yazi-core/src/notify/mod.rs index f54c7704..3d7d03fc 100644 --- a/yazi-core/src/notify/mod.rs +++ b/yazi-core/src/notify/mod.rs @@ -1,9 +1,7 @@ mod commands; -mod level; mod message; mod notify; -pub use level::*; pub use message::*; pub use notify::*; diff --git a/yazi-core/src/select/commands/show.rs b/yazi-core/src/select/commands/show.rs index b43157e1..1b6d6d1f 100644 --- a/yazi-core/src/select/commands/show.rs +++ b/yazi-core/src/select/commands/show.rs @@ -1,4 +1,4 @@ -use yazi_proxy::SelectOpt; +use yazi_proxy::options::SelectOpt; use yazi_shared::render; use crate::select::Select; diff --git a/yazi-core/src/tab/commands/escape.rs b/yazi-core/src/tab/commands/escape.rs index f730e79c..10015872 100644 --- a/yazi-core/src/tab/commands/escape.rs +++ b/yazi-core/src/tab/commands/escape.rs @@ -112,7 +112,7 @@ impl Tab { if !select { self.selected.remove_many(&urls, same); } else if self.selected.add_many(&urls, same) != urls.len() { - AppProxy::warn( + AppProxy::notify_warn( "Escape visual mode", "Some files cannot be selected, due to path nesting conflict.", ); diff --git a/yazi-core/src/tab/commands/select.rs b/yazi-core/src/tab/commands/select.rs index 78fef324..10a9d987 100644 --- a/yazi-core/src/tab/commands/select.rs +++ b/yazi-core/src/tab/commands/select.rs @@ -38,7 +38,10 @@ impl<'a> Tab { }; if !b { - AppProxy::warn("Select one", "This file cannot be selected, due to path nesting conflict."); + AppProxy::notify_warn( + "Select one", + "This file cannot be selected, due to path nesting conflict.", + ); } } } diff --git a/yazi-core/src/tab/commands/select_all.rs b/yazi-core/src/tab/commands/select_all.rs index 99167e3b..7e7399ae 100644 --- a/yazi-core/src/tab/commands/select_all.rs +++ b/yazi-core/src/tab/commands/select_all.rs @@ -38,7 +38,10 @@ impl Tab { render!(added > 0); if added != addition.len() { - AppProxy::warn("Select all", "Some files cannot be selected, due to path nesting conflict."); + AppProxy::notify_warn( + "Select all", + "Some files cannot be selected, due to path nesting conflict.", + ); } } } diff --git a/yazi-core/src/tasks/commands/open_with.rs b/yazi-core/src/tasks/commands/open_with.rs index cbf247fd..ff874532 100644 --- a/yazi-core/src/tasks/commands/open_with.rs +++ b/yazi-core/src/tasks/commands/open_with.rs @@ -1,4 +1,4 @@ -use yazi_proxy::OpenWithOpt; +use yazi_proxy::options::OpenWithOpt; use crate::tasks::Tasks; diff --git a/yazi-fm/src/app/commands/notify.rs b/yazi-fm/src/app/commands/notify.rs index 2222fb76..ab66ec69 100644 --- a/yazi-fm/src/app/commands/notify.rs +++ b/yazi-fm/src/app/commands/notify.rs @@ -1,7 +1,13 @@ -use yazi_core::notify::Message; +use yazi_proxy::options::NotifyOpt; use crate::app::App; impl App { - pub(crate) fn notify(&mut self, msg: impl TryInto) { self.cx.notify.push(msg); } + pub(crate) fn notify(&mut self, opt: impl TryInto) { + let Ok(opt) = opt.try_into() else { + return; + }; + + self.cx.notify.push(opt); + } } diff --git a/yazi-fm/src/notify/layout.rs b/yazi-fm/src/notify/layout.rs index a0bae27b..39fbea87 100644 --- a/yazi-fm/src/notify/layout.rs +++ b/yazi-fm/src/notify/layout.rs @@ -2,7 +2,8 @@ use std::rc::Rc; use ratatui::{buffer::Buffer, layout::{self, Constraint, Offset, Rect}, widgets::{Block, BorderType, Paragraph, Widget, Wrap}}; use yazi_config::THEME; -use yazi_core::notify::{Level, Message}; +use yazi_core::notify::Message; +use yazi_proxy::options::NotifyLevel; use crate::{widgets::Clear, Ctx}; @@ -43,9 +44,9 @@ impl<'a> Widget for Layout<'a> { for (i, m) in notify.messages.iter().enumerate().take(limit) { let (icon, style) = match m.level { - Level::Info => (&THEME.notify.icon_info, THEME.notify.title_info), - Level::Warn => (&THEME.notify.icon_warn, THEME.notify.title_warn), - Level::Error => (&THEME.notify.icon_error, THEME.notify.title_error), + NotifyLevel::Info => (&THEME.notify.icon_info, THEME.notify.title_info), + NotifyLevel::Warn => (&THEME.notify.icon_warn, THEME.notify.title_warn), + NotifyLevel::Error => (&THEME.notify.icon_error, THEME.notify.title_error), }; let mut rect = diff --git a/yazi-plugin/src/utils/layer.rs b/yazi-plugin/src/utils/layer.rs index c84f5d6a..90bff80a 100644 --- a/yazi-plugin/src/utils/layer.rs +++ b/yazi-plugin/src/utils/layer.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use mlua::{ExternalError, ExternalResult, IntoLuaMulti, Lua, Table, Value}; use tokio::sync::mpsc; use yazi_config::{keymap::{Control, Key}, popup::InputCfg}; -use yazi_proxy::InputProxy; +use yazi_proxy::{AppProxy, InputProxy}; use yazi_shared::{emit, event::Cmd, Layer}; use super::Utils; @@ -79,6 +79,14 @@ impl Utils { })?, )?; + ya.raw_set( + "notify", + lua.create_function(|_, t: Table| { + AppProxy::notify(t.try_into()?); + Ok(()) + })?, + )?; + Ok(()) } } diff --git a/yazi-proxy/Cargo.toml b/yazi-proxy/Cargo.toml index fa1211ca..8fbc3400 100644 --- a/yazi-proxy/Cargo.toml +++ b/yazi-proxy/Cargo.toml @@ -14,4 +14,5 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.3" } # External dependencies anyhow = "^1" +mlua = { version = "^0", features = [ "lua54", "vendored" ] } tokio = { version = "^1", features = [ "parking_lot" ] } diff --git a/yazi-proxy/src/app.rs b/yazi-proxy/src/app.rs index dd5ac3d7..144b66d1 100644 --- a/yazi-proxy/src/app.rs +++ b/yazi-proxy/src/app.rs @@ -1,6 +1,10 @@ +use std::time::Duration; + use tokio::sync::oneshot; use yazi_shared::{emit, event::Cmd, Layer}; +use crate::options::{NotifyLevel, NotifyOpt}; + pub struct AppProxy; impl AppProxy { @@ -16,14 +20,19 @@ impl AppProxy { emit!(Call(Cmd::new("resume"), Layer::App)); } + pub fn notify(opt: NotifyOpt) { + emit!(Call(Cmd::new("notify").with_data(opt), Layer::App)); + } + #[inline] - pub fn warn(title: &str, content: &str) { + pub fn notify_warn(title: &str, content: &str) { emit!(Call( - Cmd::new("notify") - .with("title", title) - .with("content", content) - .with("level", "warn") - .with("timeout", 5), + Cmd::new("notify").with_data(NotifyOpt { + title: title.to_owned(), + content: content.to_owned(), + level: NotifyLevel::Warn, + timeout: Duration::from_secs(5), + }), Layer::App )); } diff --git a/yazi-proxy/src/input.rs b/yazi-proxy/src/input.rs index 5a92b452..66a7491d 100644 --- a/yazi-proxy/src/input.rs +++ b/yazi-proxy/src/input.rs @@ -2,16 +2,7 @@ use tokio::sync::mpsc; use yazi_config::popup::InputCfg; use yazi_shared::{emit, event::Cmd, InputError, Layer}; -pub struct InputOpt { - pub cfg: InputCfg, - pub tx: mpsc::UnboundedSender>, -} - -impl TryFrom for InputOpt { - type Error = (); - - fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } -} +use crate::options::InputOpt; pub struct InputProxy; diff --git a/yazi-proxy/src/lib.rs b/yazi-proxy/src/lib.rs index 79993c29..8d60381d 100644 --- a/yazi-proxy/src/lib.rs +++ b/yazi-proxy/src/lib.rs @@ -2,6 +2,7 @@ mod app; mod completion; mod input; mod manager; +pub mod options; mod select; mod tab; mod tasks; diff --git a/yazi-proxy/src/manager.rs b/yazi-proxy/src/manager.rs index 8aa0f561..f690ed6a 100644 --- a/yazi-proxy/src/manager.rs +++ b/yazi-proxy/src/manager.rs @@ -1,15 +1,6 @@ use yazi_shared::{emit, event::Cmd, fs::Url, Layer}; -#[derive(Default)] -pub struct OpenDoOpt { - pub hovered: Url, - pub targets: Vec<(Url, String)>, - pub interactive: bool, -} - -impl From for OpenDoOpt { - fn from(mut c: Cmd) -> Self { c.take_data().unwrap_or_default() } -} +use crate::options::OpenDoOpt; pub struct ManagerProxy; diff --git a/yazi-proxy/src/options/input.rs b/yazi-proxy/src/options/input.rs new file mode 100644 index 00000000..b524a33c --- /dev/null +++ b/yazi-proxy/src/options/input.rs @@ -0,0 +1,14 @@ +use tokio::sync::mpsc; +use yazi_config::popup::InputCfg; +use yazi_shared::{event::Cmd, InputError}; + +pub struct InputOpt { + pub cfg: InputCfg, + pub tx: mpsc::UnboundedSender>, +} + +impl TryFrom for InputOpt { + type Error = (); + + fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } +} diff --git a/yazi-proxy/src/options/mod.rs b/yazi-proxy/src/options/mod.rs new file mode 100644 index 00000000..e787fc53 --- /dev/null +++ b/yazi-proxy/src/options/mod.rs @@ -0,0 +1,9 @@ +mod input; +mod notify; +mod open; +mod select; + +pub use input::*; +pub use notify::*; +pub use open::*; +pub use select::*; diff --git a/yazi-proxy/src/options/notify.rs b/yazi-proxy/src/options/notify.rs new file mode 100644 index 00000000..a8884d66 --- /dev/null +++ b/yazi-proxy/src/options/notify.rs @@ -0,0 +1,63 @@ +use std::{str::FromStr, time::Duration}; + +use anyhow::bail; +use mlua::{ExternalError, ExternalResult}; +use yazi_shared::event::Cmd; + +pub struct NotifyOpt { + pub title: String, + pub content: String, + pub level: NotifyLevel, + pub timeout: Duration, +} + +impl TryFrom for NotifyOpt { + type Error = (); + + fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } +} + +impl<'a> TryFrom> for NotifyOpt { + type Error = mlua::Error; + + fn try_from(t: mlua::Table) -> Result { + let timeout = t.raw_get::<_, f64>("timeout")?; + if timeout < 0.0 { + return Err("timeout must be non-negative".into_lua_err()); + } + + let level = if let Ok(s) = t.raw_get::<_, mlua::String>("level") { + s.to_str()?.parse().into_lua_err()? + } else { + Default::default() + }; + + Ok(Self { + title: t.raw_get("title")?, + content: t.raw_get("content")?, + level, + timeout: Duration::from_secs_f64(timeout), + }) + } +} + +#[derive(Default)] +pub enum NotifyLevel { + #[default] + Info, + Warn, + Error, +} + +impl FromStr for NotifyLevel { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(match s { + "info" => Self::Info, + "warn" => Self::Warn, + "error" => Self::Error, + _ => bail!("Invalid notify level: {s}"), + }) + } +} diff --git a/yazi-proxy/src/options/open.rs b/yazi-proxy/src/options/open.rs new file mode 100644 index 00000000..65a6cd5d --- /dev/null +++ b/yazi-proxy/src/options/open.rs @@ -0,0 +1,26 @@ +use yazi_config::open::Opener; +use yazi_shared::{event::Cmd, fs::Url}; + +// --- Open +#[derive(Default)] +pub struct OpenDoOpt { + pub hovered: Url, + pub targets: Vec<(Url, String)>, + pub interactive: bool, +} + +impl From for OpenDoOpt { + fn from(mut c: Cmd) -> Self { c.take_data().unwrap_or_default() } +} + +// --- Open with +pub struct OpenWithOpt { + pub targets: Vec, + pub opener: Opener, +} + +impl TryFrom for OpenWithOpt { + type Error = (); + + fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } +} diff --git a/yazi-proxy/src/options/select.rs b/yazi-proxy/src/options/select.rs new file mode 100644 index 00000000..0478f4a3 --- /dev/null +++ b/yazi-proxy/src/options/select.rs @@ -0,0 +1,14 @@ +use tokio::sync::oneshot; +use yazi_config::popup::SelectCfg; +use yazi_shared::event::Cmd; + +pub struct SelectOpt { + pub cfg: SelectCfg, + pub tx: oneshot::Sender>, +} + +impl TryFrom for SelectOpt { + type Error = (); + + fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } +} diff --git a/yazi-proxy/src/select.rs b/yazi-proxy/src/select.rs index 518176dd..5629485d 100644 --- a/yazi-proxy/src/select.rs +++ b/yazi-proxy/src/select.rs @@ -2,16 +2,7 @@ use tokio::sync::oneshot; use yazi_config::popup::SelectCfg; use yazi_shared::{emit, event::Cmd, term::Term, Layer}; -pub struct SelectOpt { - pub cfg: SelectCfg, - pub tx: oneshot::Sender>, -} - -impl TryFrom for SelectOpt { - type Error = (); - - fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } -} +use crate::options::SelectOpt; pub struct SelectProxy; diff --git a/yazi-proxy/src/tasks.rs b/yazi-proxy/src/tasks.rs index d60672fc..24ce61f6 100644 --- a/yazi-proxy/src/tasks.rs +++ b/yazi-proxy/src/tasks.rs @@ -1,19 +1,10 @@ use yazi_config::open::Opener; use yazi_shared::{emit, event::Cmd, fs::Url, Layer}; +use crate::options::OpenWithOpt; + pub struct TasksProxy; -pub struct OpenWithOpt { - pub targets: Vec, - pub opener: Opener, -} - -impl TryFrom for OpenWithOpt { - type Error = (); - - fn try_from(mut c: Cmd) -> Result { c.take_data().ok_or(()) } -} - impl TasksProxy { #[inline] pub fn open_with(targets: Vec, opener: Opener) {