fix: interoperability between number, integer, and id (#2883)

This commit is contained in:
三咲雅 misaki masa 2025-06-16 13:18:07 +08:00 committed by GitHub
parent a076ff8c82
commit 56a4e87d7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 27 additions and 46 deletions

View file

@ -1,7 +1,6 @@
use std::time::Instant; use std::time::{Duration, Instant};
use yazi_macro::emit; use yazi_proxy::AppProxy;
use yazi_shared::event::Cmd;
use crate::notify::{Message, Notify}; use crate::notify::{Message, Notify};
@ -14,7 +13,7 @@ impl Notify {
if self.messages.iter().all(|m| m != &msg) { if self.messages.iter().all(|m| m != &msg) {
self.messages.push(msg); self.messages.push(msg);
emit!(Call(Cmd::args("app:update_notify", [0]))); AppProxy::update_notify(Duration::ZERO);
} }
} }
} }

View file

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use ratatui::layout::Rect; use ratatui::layout::Rect;
use yazi_macro::emit; use yazi_proxy::AppProxy;
use yazi_shared::event::{Cmd, CmdCow, Data}; use yazi_shared::event::{Cmd, CmdCow, Data};
use crate::notify::Notify; use crate::notify::Notify;
@ -69,7 +69,7 @@ impl Notify {
self.tick_handle = Some(tokio::spawn(async move { self.tick_handle = Some(tokio::spawn(async move {
tokio::time::sleep(interval).await; tokio::time::sleep(interval).await;
emit!(Call(Cmd::args("app:update_notify", [interval.as_secs_f64()]))); AppProxy::update_notify(interval);
})); }));
} }
} }

View file

@ -9,24 +9,24 @@ use crate::options::{NotifyLevel, NotifyOpt, PluginOpt};
pub struct AppProxy; pub struct AppProxy;
impl AppProxy { impl AppProxy {
#[inline]
pub async fn stop() { pub async fn stop() {
let (tx, rx) = oneshot::channel::<()>(); let (tx, rx) = oneshot::channel::<()>();
emit!(Call(Cmd::new("app:stop").with_any("tx", tx))); emit!(Call(Cmd::new("app:stop").with_any("tx", tx)));
rx.await.ok(); rx.await.ok();
} }
#[inline]
pub fn resume() { pub fn resume() {
emit!(Call(Cmd::new("app:resume"))); emit!(Call(Cmd::new("app:resume")));
} }
#[inline]
pub fn notify(opt: NotifyOpt) { pub fn notify(opt: NotifyOpt) {
emit!(Call(Cmd::new("app:notify").with_any("option", opt))); emit!(Call(Cmd::new("app:notify").with_any("option", opt)));
} }
#[inline] pub fn update_notify(dur: Duration) {
emit!(Call(Cmd::args("app:update_notify", [dur.as_secs_f64()])));
}
pub fn notify_warn(title: &str, content: impl ToString) { pub fn notify_warn(title: &str, content: impl ToString) {
Self::notify(NotifyOpt { Self::notify(NotifyOpt {
title: title.to_owned(), title: title.to_owned(),
@ -36,7 +36,6 @@ impl AppProxy {
}); });
} }
#[inline]
pub fn notify_error(title: &str, content: impl ToString) { pub fn notify_error(title: &str, content: impl ToString) {
Self::notify(NotifyOpt { Self::notify(NotifyOpt {
title: title.to_owned(), title: title.to_owned(),
@ -46,12 +45,10 @@ impl AppProxy {
}); });
} }
#[inline]
pub fn plugin(opt: PluginOpt) { pub fn plugin(opt: PluginOpt) {
emit!(Call(Cmd::new("app:plugin").with_any("opt", opt))); emit!(Call(Cmd::new("app:plugin").with_any("opt", opt)));
} }
#[inline]
pub fn plugin_do(opt: PluginOpt) { pub fn plugin_do(opt: PluginOpt) {
emit!(Call(Cmd::new("app:plugin_do").with_any("opt", opt))); emit!(Call(Cmd::new("app:plugin_do").with_any("opt", opt)));
} }

View file

@ -4,12 +4,10 @@ use yazi_shared::{Id, event::Cmd};
pub struct CmpProxy; pub struct CmpProxy;
impl CmpProxy { impl CmpProxy {
#[inline]
pub fn close() { pub fn close() {
emit!(Call(Cmd::new("cmp:close"))); emit!(Call(Cmd::new("cmp:close")));
} }
#[inline]
pub fn trigger(word: &str, ticket: Id) { pub fn trigger(word: &str, ticket: Id) {
emit!(Call(Cmd::args("cmp:trigger", [word]).with("ticket", ticket))); emit!(Call(Cmd::args("cmp:trigger", [word]).with("ticket", ticket)));
} }

View file

@ -6,10 +6,8 @@ use yazi_shared::event::Cmd;
pub struct ConfirmProxy; pub struct ConfirmProxy;
impl ConfirmProxy { impl ConfirmProxy {
#[inline]
pub async fn show(cfg: ConfirmCfg) -> bool { Self::show_rx(cfg).await.unwrap_or(false) } pub async fn show(cfg: ConfirmCfg) -> bool { Self::show_rx(cfg).await.unwrap_or(false) }
#[inline]
pub fn show_rx(cfg: ConfirmCfg) -> oneshot::Receiver<bool> { pub fn show_rx(cfg: ConfirmCfg) -> oneshot::Receiver<bool> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("confirm:show").with_any("tx", tx).with_any("cfg", cfg))); emit!(Call(Cmd::new("confirm:show").with_any("tx", tx).with_any("cfg", cfg)));

View file

@ -8,14 +8,12 @@ use crate::options::CmpItem;
pub struct InputProxy; pub struct InputProxy;
impl InputProxy { impl InputProxy {
#[inline]
pub fn show(cfg: InputCfg) -> mpsc::UnboundedReceiver<Result<String, InputError>> { pub fn show(cfg: InputCfg) -> mpsc::UnboundedReceiver<Result<String, InputError>> {
let (tx, rx) = mpsc::unbounded_channel(); let (tx, rx) = mpsc::unbounded_channel();
emit!(Call(Cmd::new("input:show").with_any("tx", tx).with_any("cfg", cfg))); emit!(Call(Cmd::new("input:show").with_any("tx", tx).with_any("cfg", cfg)));
rx rx
} }
#[inline]
pub fn complete(item: &CmpItem, ticket: Id) { pub fn complete(item: &CmpItem, ticket: Id) {
emit!(Call(Cmd::new("input:complete").with_any("item", item.clone()).with("ticket", ticket))); emit!(Call(Cmd::new("input:complete").with_any("item", item.clone()).with("ticket", ticket)));
} }

View file

@ -6,49 +6,40 @@ use crate::options::OpenDoOpt;
pub struct MgrProxy; pub struct MgrProxy;
impl MgrProxy { impl MgrProxy {
#[inline]
pub fn spot(skip: Option<usize>) { pub fn spot(skip: Option<usize>) {
emit!(Call(Cmd::new("mgr:spot").with_opt("skip", skip))); emit!(Call(Cmd::new("mgr:spot").with_opt("skip", skip)));
} }
#[inline]
pub fn peek(force: bool) { pub fn peek(force: bool) {
emit!(Call(Cmd::new("mgr:peek").with("force", force))); emit!(Call(Cmd::new("mgr:peek").with("force", force)));
} }
#[inline]
pub fn watch() { pub fn watch() {
emit!(Call(Cmd::new("mgr:watch"))); emit!(Call(Cmd::new("mgr:watch")));
} }
#[inline]
pub fn refresh() { pub fn refresh() {
emit!(Call(Cmd::new("mgr:refresh"))); emit!(Call(Cmd::new("mgr:refresh")));
} }
#[inline]
pub fn open_do(opt: OpenDoOpt) { pub fn open_do(opt: OpenDoOpt) {
emit!(Call(Cmd::new("mgr:open_do").with_any("option", opt))); emit!(Call(Cmd::new("mgr:open_do").with_any("option", opt)));
} }
#[inline]
pub fn remove_do(targets: Vec<Url>, permanently: bool) { pub fn remove_do(targets: Vec<Url>, permanently: bool) {
emit!(Call( emit!(Call(
Cmd::new("mgr:remove_do").with("permanently", permanently).with_any("targets", targets) Cmd::new("mgr:remove_do").with("permanently", permanently).with_any("targets", targets)
)); ));
} }
#[inline]
pub fn update_tasks(url: &Url) { pub fn update_tasks(url: &Url) {
emit!(Call(Cmd::new("mgr:update_tasks").with_any("urls", vec![url.clone()]))); emit!(Call(Cmd::new("mgr:update_tasks").with_any("urls", vec![url.clone()])));
} }
#[inline]
pub fn update_paged() { pub fn update_paged() {
emit!(Call(Cmd::new("mgr:update_paged"))); emit!(Call(Cmd::new("mgr:update_paged")));
} }
#[inline]
pub fn update_paged_by(page: usize, only_if: &Url) { pub fn update_paged_by(page: usize, only_if: &Url) {
emit!(Call(Cmd::args("mgr:update_paged", [page]).with_any("only-if", only_if.clone()))); emit!(Call(Cmd::args("mgr:update_paged", [page]).with_any("only-if", only_if.clone())));
} }

View file

@ -52,7 +52,6 @@ pub enum NotifyLevel {
} }
impl NotifyLevel { impl NotifyLevel {
#[inline]
pub fn icon(self) -> &'static str { pub fn icon(self) -> &'static str {
match self { match self {
Self::Info => &THEME.notify.icon_info, Self::Info => &THEME.notify.icon_info,
@ -61,7 +60,6 @@ impl NotifyLevel {
} }
} }
#[inline]
pub fn style(self) -> &'static Style { pub fn style(self) -> &'static Style {
match self { match self {
Self::Info => &THEME.notify.title_info, Self::Info => &THEME.notify.title_info,

View file

@ -6,7 +6,6 @@ use yazi_shared::event::Cmd;
pub struct PickProxy; pub struct PickProxy;
impl PickProxy { impl PickProxy {
#[inline]
pub async fn show(cfg: PickCfg) -> anyhow::Result<usize> { pub async fn show(cfg: PickCfg) -> anyhow::Result<usize> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("pick:show").with_any("tx", tx).with_any("cfg", cfg))); emit!(Call(Cmd::new("pick:show").with_any("tx", tx).with_any("cfg", cfg)));

View file

@ -8,22 +8,18 @@ use crate::options::SearchOpt;
pub struct TabProxy; pub struct TabProxy;
impl TabProxy { impl TabProxy {
#[inline]
pub fn cd(target: &Url) { pub fn cd(target: &Url) {
emit!(Call(Cmd::args("mgr:cd", [target]))); emit!(Call(Cmd::args("mgr:cd", [target])));
} }
#[inline]
pub fn reveal(target: &Url) { pub fn reveal(target: &Url) {
emit!(Call(Cmd::args("mgr:reveal", [target]).with("no-dummy", true))); emit!(Call(Cmd::args("mgr:reveal", [target]).with("no-dummy", true)));
} }
#[inline]
pub fn arrow(step: impl Into<Cow<'static, str>>) { pub fn arrow(step: impl Into<Cow<'static, str>>) {
emit!(Call(Cmd::args("mgr:arrow", [step.into()]))); emit!(Call(Cmd::args("mgr:arrow", [step.into()])));
} }
#[inline]
pub fn search_do(opt: SearchOpt) { pub fn search_do(opt: SearchOpt) {
emit!(Call( emit!(Call(
// TODO: use second positional argument instead of `args` parameter // TODO: use second positional argument instead of `args` parameter

View file

@ -10,7 +10,6 @@ use crate::options::{OpenWithOpt, ProcessExecOpt};
pub struct TasksProxy; pub struct TasksProxy;
impl TasksProxy { impl TasksProxy {
#[inline]
pub fn open_with(opener: Cow<'static, OpenerRule>, cwd: Url, targets: Vec<Url>) { pub fn open_with(opener: Cow<'static, OpenerRule>, cwd: Url, targets: Vec<Url>) {
emit!(Call(Cmd::new("tasks:open_with").with_any("option", OpenWithOpt { emit!(Call(Cmd::new("tasks:open_with").with_any("option", OpenWithOpt {
opener, opener,
@ -19,7 +18,6 @@ impl TasksProxy {
}))); })));
} }
#[inline]
pub async fn process_exec(opener: Cow<'static, OpenerRule>, cwd: Url, args: Vec<OsString>) { pub async fn process_exec(opener: Cow<'static, OpenerRule>, cwd: Url, args: Vec<OsString>) {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("tasks:process_exec").with_any("option", ProcessExecOpt { emit!(Call(Cmd::new("tasks:process_exec").with_any("option", ProcessExecOpt {

View file

@ -90,6 +90,14 @@ impl From<bool> for Data {
fn from(value: bool) -> Self { Self::Boolean(value) } fn from(value: bool) -> Self { Self::Boolean(value) }
} }
impl From<i32> for Data {
fn from(value: i32) -> Self { Self::Integer(value as i64) }
}
impl From<i64> for Data {
fn from(value: i64) -> Self { Self::Integer(value) }
}
impl From<f64> for Data { impl From<f64> for Data {
fn from(value: f64) -> Self { Self::Number(value) } fn from(value: f64) -> Self { Self::Number(value) }
} }
@ -187,7 +195,7 @@ impl From<String> for DataKey {
} }
// --- Macros // --- Macros
macro_rules! impl_integer_as { macro_rules! impl_as_integer {
($t:ty, $name:ident) => { ($t:ty, $name:ident) => {
impl Data { impl Data {
#[inline] #[inline]
@ -203,14 +211,16 @@ macro_rules! impl_integer_as {
}; };
} }
macro_rules! impl_number_as { macro_rules! impl_as_number {
($t:ty, $name:ident) => { ($t:ty, $name:ident) => {
impl Data { impl Data {
#[inline] #[inline]
pub fn $name(&self) -> Option<$t> { pub fn $name(&self) -> Option<$t> {
match self { match self {
Data::Integer(i) if *i == (*i as $t as _) => Some(*i as $t),
Data::Number(n) => <$t>::try_from(*n).ok(), Data::Number(n) => <$t>::try_from(*n).ok(),
Data::String(s) => s.parse().ok(), Data::String(s) => s.parse().ok(),
Data::Id(i) if i.0 == (i.0 as $t as _) => Some(i.0 as $t),
_ => None, _ => None,
} }
} }
@ -218,11 +228,10 @@ macro_rules! impl_number_as {
}; };
} }
impl_integer_as!(usize, as_usize); impl_as_integer!(usize, as_usize);
impl_integer_as!(isize, as_isize); impl_as_integer!(isize, as_isize);
impl_integer_as!(i16, as_i16); impl_as_integer!(i16, as_i16);
impl_integer_as!(i32, as_i32); impl_as_integer!(i32, as_i32);
impl_as_integer!(crate::Id, as_id);
impl_number_as!(f64, as_f64); impl_as_number!(f64, as_f64);
impl_integer_as!(crate::Id, as_id);