mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
feat: port task manager to Lua (#3134)
This commit is contained in:
parent
d670da80d3
commit
cfc7238638
41 changed files with 283 additions and 174 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -3510,6 +3510,7 @@ dependencies = [
|
|||
"yazi-parser",
|
||||
"yazi-plugin",
|
||||
"yazi-proxy",
|
||||
"yazi-scheduler",
|
||||
"yazi-shared",
|
||||
"yazi-term",
|
||||
"yazi-watcher",
|
||||
|
|
@ -3870,6 +3871,7 @@ dependencies = [
|
|||
"ordered-float 5.0.0",
|
||||
"parking_lot",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ objc = "0.2.7"
|
|||
ordered-float = { version = "5.0.0", features = [ "serde" ] }
|
||||
parking_lot = "0.12.4"
|
||||
paste = "1.0.15"
|
||||
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] }
|
||||
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info", "unstable-widget-ref" ] }
|
||||
regex = "1.11.2"
|
||||
scopeguard = "1.2.0"
|
||||
serde = { version = "1.0.219", features = [ "derive" ] }
|
||||
|
|
|
|||
|
|
@ -13,20 +13,21 @@ default = [ "vendored-lua" ]
|
|||
vendored-lua = [ "mlua/vendored" ]
|
||||
|
||||
[dependencies]
|
||||
yazi-binding = { path = "../yazi-binding", version = "25.6.11" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.6.11" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.6.11" }
|
||||
yazi-core = { path = "../yazi-core", version = "25.6.11" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.6.11" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.6.11" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.6.11" }
|
||||
yazi-parser = { path = "../yazi-parser", version = "25.6.11" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.6.11" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.6.11" }
|
||||
yazi-term = { path = "../yazi-term", version = "25.6.11" }
|
||||
yazi-watcher = { path = "../yazi-watcher", version = "25.6.11" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "25.6.11" }
|
||||
yazi-binding = { path = "../yazi-binding", version = "25.6.11" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "25.6.11" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.6.11" }
|
||||
yazi-core = { path = "../yazi-core", version = "25.6.11" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.6.11" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.6.11" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.6.11" }
|
||||
yazi-parser = { path = "../yazi-parser", version = "25.6.11" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.6.11" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.6.11" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "25.6.11" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.6.11" }
|
||||
yazi-term = { path = "../yazi-term", version = "25.6.11" }
|
||||
yazi-watcher = { path = "../yazi-watcher", version = "25.6.11" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "25.6.11" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(core file files filter finder folder lives mode preference preview ptr selected tab tabs tasks yanked);
|
||||
yazi_macro::mod_flat!(core file files filter finder folder lives mode preference preview ptr selected tab tabs task tasks yanked);
|
||||
|
|
|
|||
37
yazi-actor/src/lives/task.rs
Normal file
37
yazi-actor/src/lives/task.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, LuaSerdeExt, UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
use yazi_plugin::runtime::SER_OPT;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct TaskSnap {
|
||||
inner: PtrCell<yazi_scheduler::TaskSnap>,
|
||||
|
||||
v_name: Option<Value>,
|
||||
v_prog: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for TaskSnap {
|
||||
type Target = yazi_scheduler::TaskSnap;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl TaskSnap {
|
||||
pub(super) fn make(inner: &yazi_scheduler::TaskSnap) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into(), v_name: None, v_prog: None })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for TaskSnap {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
cached_field!(fields, name, |lua, me| lua.create_string(&me.name));
|
||||
cached_field!(fields, prog, |lua, me| lua.to_value_with(&me.prog, SER_OPT));
|
||||
|
||||
fields.add_field_method_get("running", |_, me| Ok(me.prog.running()));
|
||||
fields.add_field_method_get("success", |_, me| Ok(me.prog.success()));
|
||||
fields.add_field_method_get("percent", |_, me| Ok(me.prog.percent()));
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,12 @@ use yazi_binding::{cached_field, deprecate};
|
|||
use yazi_plugin::runtime::SER_OPT;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
use crate::lives::TaskSnap;
|
||||
|
||||
pub(super) struct Tasks {
|
||||
inner: PtrCell<yazi_core::tasks::Tasks>,
|
||||
|
||||
v_snaps: Option<Value>,
|
||||
v_summary: Option<Value>,
|
||||
v_progress: Option<Value>,
|
||||
}
|
||||
|
|
@ -21,12 +23,28 @@ impl Deref for Tasks {
|
|||
|
||||
impl Tasks {
|
||||
pub(super) fn make(inner: &yazi_core::tasks::Tasks) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into(), v_summary: None, v_progress: None })
|
||||
Lives::scoped_userdata(Self {
|
||||
inner: inner.into(),
|
||||
|
||||
v_snaps: None,
|
||||
v_summary: None,
|
||||
v_progress: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Tasks {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
|
||||
|
||||
cached_field!(fields, snaps, |lua, me| {
|
||||
let tbl = lua.create_table_with_capacity(me.snaps.len(), 0)?;
|
||||
for snap in &me.snaps {
|
||||
tbl.raw_push(TaskSnap::make(snap)?)?;
|
||||
}
|
||||
Ok(tbl)
|
||||
});
|
||||
|
||||
cached_field!(fields, summary, |lua, me| lua.to_value_with(&me.summary, SER_OPT));
|
||||
|
||||
cached_field!(fields, progress, |lua, me| {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ yazi_macro::mod_flat!(
|
|||
update_paged
|
||||
update_peeked
|
||||
update_spotted
|
||||
update_tasks
|
||||
update_yanked
|
||||
visual_mode
|
||||
watch
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(arrow cancel close inspect open_with process_exec show);
|
||||
yazi_macro::mod_flat!(arrow cancel close inspect open_with process_exec show update_succeed);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::mgr::UpdateTasksOpt;
|
||||
use yazi_parser::tasks::UpdateSucceedOpt;
|
||||
use yazi_shared::event::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct UpdateTasks;
|
||||
pub struct UpdateSucceed;
|
||||
|
||||
impl Actor for UpdateTasks {
|
||||
type Options = UpdateTasksOpt;
|
||||
impl Actor for UpdateSucceed {
|
||||
type Options = UpdateSucceedOpt;
|
||||
|
||||
const NAME: &str = "update_tasks";
|
||||
const NAME: &str = "update_succeed";
|
||||
|
||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
cx.mgr.watcher.push_files(opt.urls);
|
||||
|
|
@ -25,8 +25,9 @@ pub struct Border {
|
|||
|
||||
impl Border {
|
||||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
let new = lua
|
||||
.create_function(|_, (_, edge): (Table, Edge)| Ok(Border { edge, ..Default::default() }))?;
|
||||
let new = lua.create_function(|_, (_, edge): (Table, Edge)| {
|
||||
Ok(Border { edge, r#type: ratatui::widgets::BorderType::Rounded, ..Default::default() })
|
||||
})?;
|
||||
|
||||
let border = lua.create_table_from([
|
||||
// Type
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ perm_exec = { fg = "cyan" }
|
|||
# Progress
|
||||
progress_label = { bold = true }
|
||||
progress_normal = { fg = "blue", bg = "black" }
|
||||
progress_error = { fg = "red", bg = "black" }
|
||||
progress_error = { fg = "blue", bg = "red" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ perm_exec = { fg = "cyan" }
|
|||
# Progress
|
||||
progress_label = { bold = true }
|
||||
progress_normal = { fg = "blue", bg = "black" }
|
||||
progress_error = { fg = "red", bg = "black" }
|
||||
progress_error = { fg = "blue", bg = "red" }
|
||||
|
||||
# : }}}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ impl Layout {
|
|||
Self { current: Rect::ZERO, preview: Rect::ZERO, progress: Rect::ZERO }
|
||||
}
|
||||
|
||||
pub const fn limit(&self) -> usize { self.current.height as _ }
|
||||
pub const fn folder_limit(self) -> usize { self.current.height as _ }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ impl Folder {
|
|||
}
|
||||
|
||||
pub fn sync_page(&mut self, force: bool) {
|
||||
let limit = LAYOUT.get().limit();
|
||||
let limit = LAYOUT.get().folder_limit();
|
||||
if limit == 0 {
|
||||
return;
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ impl Folder {
|
|||
let old = self.offset;
|
||||
let len = self.files.len();
|
||||
|
||||
let limit = LAYOUT.get().limit();
|
||||
let limit = LAYOUT.get().folder_limit();
|
||||
let scrolloff = (limit / 2).min(YAZI.mgr.scrolloff.get() as usize);
|
||||
|
||||
self.offset = if self.cursor < (self.offset + limit).min(len).saturating_sub(scrolloff) {
|
||||
|
|
@ -167,7 +167,7 @@ impl Folder {
|
|||
|
||||
pub fn paginate(&self, page: usize) -> &[File] {
|
||||
let len = self.files.len();
|
||||
let limit = LAYOUT.get().limit();
|
||||
let limit = LAYOUT.get().folder_limit();
|
||||
|
||||
let start = (page.saturating_sub(1) * limit).min(len.saturating_sub(1));
|
||||
let end = ((page + 2) * limit).min(len);
|
||||
|
|
@ -178,7 +178,7 @@ impl Folder {
|
|||
impl Scrollable for Folder {
|
||||
fn total(&self) -> usize { self.files.len() }
|
||||
|
||||
fn limit(&self) -> usize { LAYOUT.get().limit() }
|
||||
fn limit(&self) -> usize { LAYOUT.get().folder_limit() }
|
||||
|
||||
fn scrolloff(&self) -> usize { (self.limit() / 2).min(YAZI.mgr.scrolloff.get() as usize) }
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ impl Tasks {
|
|||
let new = ongoing.lock().summary();
|
||||
if last != new {
|
||||
last = new;
|
||||
AppProxy::update_summary(new);
|
||||
AppProxy::update_progress(new);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ pub enum Spark<'a> {
|
|||
UpdatePaged(yazi_parser::mgr::UpdatePagedOpt),
|
||||
UpdatePeeked(yazi_parser::mgr::UpdatePeekedOpt),
|
||||
UpdateSpotted(yazi_parser::mgr::UpdateSpottedOpt),
|
||||
UpdateTasks(yazi_parser::mgr::UpdateTasksOpt),
|
||||
UpdateYanked(yazi_parser::mgr::UpdateYankedOpt<'a>),
|
||||
VisualMode(yazi_parser::mgr::VisualModeOpt),
|
||||
Watch(yazi_parser::VoidOpt),
|
||||
|
|
@ -109,6 +108,7 @@ pub enum Spark<'a> {
|
|||
|
||||
// Tasks
|
||||
TasksProcessExec(yazi_parser::tasks::ProcessExecOpt),
|
||||
TasksUpdateSucceed(yazi_parser::tasks::UpdateSucceedOpt),
|
||||
|
||||
// Which
|
||||
WhichCallback(yazi_parser::which::CallbackOpt),
|
||||
|
|
@ -188,7 +188,6 @@ impl<'a> IntoLua for Spark<'a> {
|
|||
Self::UpdatePaged(b) => b.into_lua(lua),
|
||||
Self::UpdatePeeked(b) => b.into_lua(lua),
|
||||
Self::UpdateSpotted(b) => b.into_lua(lua),
|
||||
Self::UpdateTasks(b) => b.into_lua(lua),
|
||||
Self::UpdateYanked(b) => b.into_lua(lua),
|
||||
Self::VisualMode(b) => b.into_lua(lua),
|
||||
Self::Watch(b) => b.into_lua(lua),
|
||||
|
|
@ -231,6 +230,7 @@ impl<'a> IntoLua for Spark<'a> {
|
|||
|
||||
// Tasks
|
||||
Self::TasksProcessExec(b) => b.into_lua(lua),
|
||||
Self::TasksUpdateSucceed(b) => b.into_lua(lua),
|
||||
|
||||
// Which
|
||||
Self::WhichCallback(b) => b.into_lua(lua),
|
||||
|
|
@ -314,7 +314,6 @@ try_from_spark!(mgr::UpdateMimesOpt, mgr:update_mimes);
|
|||
try_from_spark!(mgr::UpdatePagedOpt, mgr:update_paged);
|
||||
try_from_spark!(mgr::UpdatePeekedOpt, mgr:update_peeked);
|
||||
try_from_spark!(mgr::UpdateSpottedOpt, mgr:update_spotted);
|
||||
try_from_spark!(mgr::UpdateTasksOpt, mgr:update_tasks);
|
||||
try_from_spark!(mgr::UpdateYankedOpt<'a>, mgr:update_yanked);
|
||||
try_from_spark!(mgr::VisualModeOpt, mgr:visual_mode);
|
||||
try_from_spark!(mgr::YankOpt, mgr:yank);
|
||||
|
|
@ -323,5 +322,6 @@ try_from_spark!(pick::CloseOpt, pick:close);
|
|||
try_from_spark!(pick::ShowOpt, pick:show);
|
||||
try_from_spark!(spot::CopyOpt, spot:copy);
|
||||
try_from_spark!(tasks::ProcessExecOpt, tasks:process_exec);
|
||||
try_from_spark!(tasks::UpdateSucceedOpt, tasks:update_succeed);
|
||||
try_from_spark!(which::CallbackOpt, which:callback);
|
||||
try_from_spark!(which::ShowOpt, which:show);
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ yazi_macro::mod_flat!(
|
|||
resume
|
||||
stop
|
||||
update_notify
|
||||
update_summary
|
||||
update_progress
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::app::UpdateSummaryOpt;
|
||||
use yazi_parser::app::UpdateProgressOpt;
|
||||
use yazi_shared::event::Data;
|
||||
|
||||
use crate::app::App;
|
||||
|
||||
impl App {
|
||||
pub(crate) fn update_summary(&mut self, opt: UpdateSummaryOpt) -> Result<Data> {
|
||||
pub(crate) fn update_progress(&mut self, opt: UpdateProgressOpt) -> Result<Data> {
|
||||
// Update the progress of all tasks.
|
||||
let tasks = &mut self.core.tasks;
|
||||
let progressed = tasks.summary != opt.summary;
|
||||
|
|
@ -44,7 +44,7 @@ impl<'a> Executor<'a> {
|
|||
on!(plugin);
|
||||
on!(plugin_do);
|
||||
on!(update_notify);
|
||||
on!(update_summary);
|
||||
on!(update_progress);
|
||||
on!(resize);
|
||||
on!(stop);
|
||||
on!(resume);
|
||||
|
|
@ -65,7 +65,6 @@ impl<'a> Executor<'a> {
|
|||
}
|
||||
|
||||
on!(cd);
|
||||
on!(update_tasks);
|
||||
on!(update_yanked);
|
||||
|
||||
on!(update_files);
|
||||
|
|
@ -155,6 +154,8 @@ impl<'a> Executor<'a> {
|
|||
};
|
||||
}
|
||||
|
||||
on!(update_succeed);
|
||||
|
||||
on!(show);
|
||||
on!(close);
|
||||
on!(arrow);
|
||||
|
|
|
|||
30
yazi-fm/src/tasks/list.rs
Normal file
30
yazi-fm/src/tasks/list.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
use mlua::{ObjectLike, Table};
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||
use tracing::error;
|
||||
use yazi_binding::elements::render_once;
|
||||
use yazi_core::Core;
|
||||
use yazi_plugin::LUA;
|
||||
|
||||
pub(crate) struct List<'a> {
|
||||
core: &'a Core,
|
||||
}
|
||||
|
||||
impl<'a> List<'a> {
|
||||
#[inline]
|
||||
pub(crate) fn new(core: &'a Core) -> Self { Self { core } }
|
||||
}
|
||||
|
||||
impl Widget for List<'_> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let mut f = || {
|
||||
let area = yazi_binding::elements::Rect::from(area);
|
||||
let root = LUA.globals().raw_get::<Table>("Tasks")?.call_method::<Table>("new", area)?;
|
||||
|
||||
render_once(root.call_method("redraw", ())?, buf, |p| self.core.mgr.area(p));
|
||||
Ok::<_, mlua::Error>(())
|
||||
};
|
||||
if let Err(e) = f() {
|
||||
error!("Failed to redraw the `Tasks` component:\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(progress tasks);
|
||||
yazi_macro::mod_flat!(list progress tasks);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Rect}, text::{Line, Text}, widgets::{Block, BorderType, List, Padding, Widget}};
|
||||
use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Rect}, text::Line, widgets::{Block, BorderType, Widget, WidgetRef}};
|
||||
use yazi_config::THEME;
|
||||
use yazi_core::{Core, tasks::TASKS_PERCENT};
|
||||
|
||||
use crate::tasks::List;
|
||||
|
||||
pub(crate) struct Tasks<'a> {
|
||||
core: &'a Core,
|
||||
}
|
||||
|
|
@ -31,26 +33,14 @@ impl Widget for Tasks<'_> {
|
|||
let area = Self::area(area);
|
||||
|
||||
yazi_binding::elements::Clear::default().render(area, buf);
|
||||
|
||||
let block = Block::bordered()
|
||||
.title(Line::styled("Tasks", THEME.tasks.title))
|
||||
.title_alignment(Alignment::Center)
|
||||
.padding(Padding::symmetric(1, 1))
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(THEME.tasks.border);
|
||||
block.render_ref(area, buf);
|
||||
|
||||
let inner = block.inner(area);
|
||||
block.render(area, buf);
|
||||
|
||||
let tasks = &self.core.tasks;
|
||||
let items = tasks.snaps.iter().take(inner.height as usize).enumerate().map(|(i, v)| {
|
||||
let mut item =
|
||||
Text::from_iter(textwrap::wrap(&v.name, inner.width as usize).into_iter().map(Line::from));
|
||||
if i == tasks.cursor {
|
||||
item = item.style(THEME.tasks.hovered);
|
||||
}
|
||||
item
|
||||
});
|
||||
|
||||
List::new(items).render(inner, buf);
|
||||
List::new(self.core).render(block.inner(area), buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(deprecate mouse notify plugin stop update_summary);
|
||||
yazi_macro::mod_flat!(deprecate mouse notify plugin stop update_progress);
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ use ordered_float::OrderedFloat;
|
|||
use serde::Serialize;
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
pub struct UpdateSummaryOpt {
|
||||
pub struct UpdateProgressOpt {
|
||||
pub summary: TaskSummary,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for UpdateSummaryOpt {
|
||||
impl TryFrom<CmdCow> for UpdateProgressOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
|
|
@ -37,7 +37,6 @@ yazi_macro::mod_flat!(
|
|||
update_paged
|
||||
update_peeked
|
||||
update_spotted
|
||||
update_tasks
|
||||
update_yanked
|
||||
visual_mode
|
||||
yank
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(process_exec);
|
||||
yazi_macro::mod_flat!(process_exec update_succeed);
|
||||
|
|
|
|||
|
|
@ -3,26 +3,26 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
|||
use yazi_shared::{event::CmdCow, url::UrlBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UpdateTasksOpt {
|
||||
pub struct UpdateSucceedOpt {
|
||||
pub urls: Vec<UrlBuf>,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for UpdateTasksOpt {
|
||||
impl TryFrom<CmdCow> for UpdateSucceedOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
let Some(urls) = c.take_any("urls") else {
|
||||
bail!("Invalid 'urls' argument in UpdateTasksOpt");
|
||||
bail!("Invalid 'urls' argument in UpdateSucceedOpt");
|
||||
};
|
||||
|
||||
Ok(Self { urls })
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for UpdateTasksOpt {
|
||||
impl FromLua for UpdateSucceedOpt {
|
||||
fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
||||
impl IntoLua for UpdateTasksOpt {
|
||||
impl IntoLua for UpdateSucceedOpt {
|
||||
fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ function Progress:redraw()
|
|||
if percent then
|
||||
label = string.format("%3d%%, ", math.floor(percent))
|
||||
else
|
||||
percent = 99
|
||||
percent = 0
|
||||
end
|
||||
|
||||
label = label .. string.format("%d left", summary.total - summary.success)
|
||||
|
|
|
|||
22
yazi-plugin/preset/components/tasks.lua
Normal file
22
yazi-plugin/preset/components/tasks.lua
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Tasks = {
|
||||
_id = "tasks",
|
||||
}
|
||||
|
||||
function Tasks:new(area) return setmetatable({ _area = area }, { __index = self }) end
|
||||
|
||||
function Tasks:reflow() return { self } end
|
||||
|
||||
function Tasks:redraw()
|
||||
local rows = {}
|
||||
for _, snap in ipairs(cx.tasks.snaps) do
|
||||
rows[#rows + 1] = ui.Row { snap.name }
|
||||
end
|
||||
|
||||
local tbl = ui.Table(rows)
|
||||
:area(self._area:pad(ui.Pad.x(1)))
|
||||
:row(cx.tasks.cursor)
|
||||
:row_style(th.tasks.hovered)
|
||||
:widths { ui.Constraint.Fill(1) }
|
||||
|
||||
return { tbl }
|
||||
end
|
||||
|
|
@ -52,6 +52,7 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
|
|||
lua.load(preset!("components/status")).set_name("status.lua").exec()?;
|
||||
lua.load(preset!("components/tab")).set_name("tab.lua").exec()?;
|
||||
lua.load(preset!("components/tabs")).set_name("tabs.lua").exec()?;
|
||||
lua.load(preset!("components/tasks")).set_name("tasks.lua").exec()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ impl AppProxy {
|
|||
emit!(Call(relay!(app:plugin_do).with_any("opt", opt)));
|
||||
}
|
||||
|
||||
pub fn update_summary(summary: TaskSummary) {
|
||||
emit!(Call(relay!(app:update_summary).with_any("summary", summary)));
|
||||
pub fn update_progress(summary: TaskSummary) {
|
||||
emit!(Call(relay!(app:update_progress).with_any("summary", summary)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,10 +54,6 @@ impl MgrProxy {
|
|||
emit!(Call(relay!(mgr:update_spotted).with_any("opt", opt)));
|
||||
}
|
||||
|
||||
pub fn update_tasks(url: &UrlBuf) {
|
||||
emit!(Call(relay!(mgr:update_tasks).with_any("urls", vec![url.clone()])));
|
||||
}
|
||||
|
||||
pub fn update_paged_by(page: usize, only_if: &UrlBuf) {
|
||||
emit!(Call(relay!(mgr:update_paged, [page]).with_any("only-if", only_if.clone())));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,4 +23,8 @@ impl TasksProxy {
|
|||
})));
|
||||
rx.await.ok();
|
||||
}
|
||||
|
||||
pub fn update_succeed(url: impl Into<UrlBuf>) {
|
||||
emit!(Call(relay!(tasks:update_succeed).with_any("urls", vec![url.into()])));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ mlua = { workspace = true }
|
|||
ordered-float = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-util = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
use serde::Serialize;
|
||||
use yazi_parser::app::TaskSummary;
|
||||
|
||||
// --- Paste
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct FileProgPaste {
|
||||
pub(crate) total_files: u32,
|
||||
pub(crate) success_files: u32,
|
||||
pub(crate) failed_files: u32,
|
||||
pub(crate) total_bytes: u64,
|
||||
pub(crate) processed_bytes: u64,
|
||||
pub(crate) collected: bool,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct FileProgPaste {
|
||||
pub total_files: u32,
|
||||
pub success_files: u32,
|
||||
pub failed_files: u32,
|
||||
pub total_bytes: u64,
|
||||
pub processed_bytes: u64,
|
||||
pub collected: bool,
|
||||
}
|
||||
|
||||
impl From<FileProgPaste> for TaskSummary {
|
||||
|
|
@ -23,13 +24,13 @@ impl From<FileProgPaste> for TaskSummary {
|
|||
}
|
||||
|
||||
impl FileProgPaste {
|
||||
pub(crate) fn running(self) -> bool {
|
||||
pub fn running(self) -> bool {
|
||||
!self.collected || self.success_files + self.failed_files != self.total_files
|
||||
}
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.collected && self.success_files == self.total_files }
|
||||
pub fn success(self) -> bool { self.collected && self.success_files == self.total_files }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> {
|
||||
pub fn percent(self) -> Option<f32> {
|
||||
Some(if self.success() {
|
||||
100.0
|
||||
} else if self.total_bytes == 0 {
|
||||
|
|
@ -41,9 +42,9 @@ impl FileProgPaste {
|
|||
}
|
||||
|
||||
// --- Link
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct FileProgLink {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct FileProgLink {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<FileProgLink> for TaskSummary {
|
||||
|
|
@ -58,20 +59,20 @@ impl From<FileProgLink> for TaskSummary {
|
|||
}
|
||||
|
||||
impl FileProgLink {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
||||
// --- Hardlink
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct FileProgHardlink {
|
||||
pub(crate) total: u32,
|
||||
pub(crate) success: u32,
|
||||
pub(crate) failed: u32,
|
||||
pub(crate) collected: bool,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct FileProgHardlink {
|
||||
pub total: u32,
|
||||
pub success: u32,
|
||||
pub failed: u32,
|
||||
pub collected: bool,
|
||||
}
|
||||
|
||||
impl From<FileProgHardlink> for TaskSummary {
|
||||
|
|
@ -86,24 +87,22 @@ impl From<FileProgHardlink> for TaskSummary {
|
|||
}
|
||||
|
||||
impl FileProgHardlink {
|
||||
pub(crate) fn running(self) -> bool {
|
||||
!self.collected || self.success + self.failed != self.total
|
||||
}
|
||||
pub fn running(self) -> bool { !self.collected || self.success + self.failed != self.total }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.collected && self.success == self.total }
|
||||
pub fn success(self) -> bool { self.collected && self.success == self.total }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
||||
// --- Delete
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct FileProgDelete {
|
||||
pub(crate) total_files: u32,
|
||||
pub(crate) success_files: u32,
|
||||
pub(crate) failed_files: u32,
|
||||
pub(crate) total_bytes: u64,
|
||||
pub(crate) processed_bytes: u64,
|
||||
pub(crate) collected: bool,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct FileProgDelete {
|
||||
pub total_files: u32,
|
||||
pub success_files: u32,
|
||||
pub failed_files: u32,
|
||||
pub total_bytes: u64,
|
||||
pub processed_bytes: u64,
|
||||
pub collected: bool,
|
||||
}
|
||||
|
||||
impl From<FileProgDelete> for TaskSummary {
|
||||
|
|
@ -118,13 +117,13 @@ impl From<FileProgDelete> for TaskSummary {
|
|||
}
|
||||
|
||||
impl FileProgDelete {
|
||||
pub(crate) fn running(self) -> bool {
|
||||
pub fn running(self) -> bool {
|
||||
!self.collected || self.success_files + self.failed_files != self.total_files
|
||||
}
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.collected && self.success_files == self.total_files }
|
||||
pub fn success(self) -> bool { self.collected && self.success_files == self.total_files }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> {
|
||||
pub fn percent(self) -> Option<f32> {
|
||||
Some(if self.success() {
|
||||
100.0
|
||||
} else if self.total_bytes == 0 {
|
||||
|
|
@ -136,9 +135,9 @@ impl FileProgDelete {
|
|||
}
|
||||
|
||||
// --- Trash
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct FileProgTrash {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct FileProgTrash {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<FileProgTrash> for TaskSummary {
|
||||
|
|
@ -153,9 +152,9 @@ impl From<FileProgTrash> for TaskSummary {
|
|||
}
|
||||
|
||||
impl FileProgTrash {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use serde::Serialize;
|
||||
use yazi_parser::app::TaskSummary;
|
||||
|
||||
// --- Entry
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct PluginProgEntry {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct PluginProgEntry {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<PluginProgEntry> for TaskSummary {
|
||||
|
|
@ -18,9 +19,9 @@ impl From<PluginProgEntry> for TaskSummary {
|
|||
}
|
||||
|
||||
impl PluginProgEntry {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use serde::Serialize;
|
||||
use yazi_parser::app::TaskSummary;
|
||||
|
||||
// --- Fetch
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct PreworkProgFetch {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct PreworkProgFetch {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<PreworkProgFetch> for TaskSummary {
|
||||
|
|
@ -18,17 +19,17 @@ impl From<PreworkProgFetch> for TaskSummary {
|
|||
}
|
||||
|
||||
impl PreworkProgFetch {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
||||
// --- Load
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct PreworkProgLoad {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct PreworkProgLoad {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<PreworkProgLoad> for TaskSummary {
|
||||
|
|
@ -43,17 +44,17 @@ impl From<PreworkProgLoad> for TaskSummary {
|
|||
}
|
||||
|
||||
impl PreworkProgLoad {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
||||
// --- Size
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct PreworkProgSize {
|
||||
pub(crate) done: bool,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct PreworkProgSize {
|
||||
pub done: bool,
|
||||
}
|
||||
|
||||
impl From<PreworkProgSize> for TaskSummary {
|
||||
|
|
@ -68,9 +69,9 @@ impl From<PreworkProgSize> for TaskSummary {
|
|||
}
|
||||
|
||||
impl PreworkProgSize {
|
||||
pub(crate) fn running(self) -> bool { !self.done }
|
||||
pub fn running(self) -> bool { !self.done }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.done }
|
||||
pub fn success(self) -> bool { self.done }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use serde::Serialize;
|
||||
use yazi_parser::app::TaskSummary;
|
||||
|
||||
// --- Block
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct ProcessProgBlock {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct ProcessProgBlock {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ProcessProgBlock> for TaskSummary {
|
||||
|
|
@ -18,17 +19,17 @@ impl From<ProcessProgBlock> for TaskSummary {
|
|||
}
|
||||
|
||||
impl ProcessProgBlock {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
||||
// --- Orphan
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct ProcessProgOrphan {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct ProcessProgOrphan {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ProcessProgOrphan> for TaskSummary {
|
||||
|
|
@ -43,17 +44,17 @@ impl From<ProcessProgOrphan> for TaskSummary {
|
|||
}
|
||||
|
||||
impl ProcessProgOrphan {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
||||
// --- Bg
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub(crate) struct ProcessProgBg {
|
||||
pub(crate) state: Option<bool>,
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct ProcessProgBg {
|
||||
pub state: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ProcessProgBg> for TaskSummary {
|
||||
|
|
@ -68,9 +69,9 @@ impl From<ProcessProgBg> for TaskSummary {
|
|||
}
|
||||
|
||||
impl ProcessProgBg {
|
||||
pub(crate) fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
|
||||
pub(crate) fn success(self) -> bool { self.state == Some(true) }
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> { None }
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use serde::Serialize;
|
||||
use yazi_parser::app::TaskSummary;
|
||||
|
||||
use crate::{file::{FileProgDelete, FileProgHardlink, FileProgLink, FileProgPaste, FileProgTrash}, impl_from_prog, plugin::PluginProgEntry, prework::{PreworkProgFetch, PreworkProgLoad, PreworkProgSize}, process::{ProcessProgBg, ProcessProgBlock, ProcessProgOrphan}};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) enum TaskProg {
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
|
||||
#[serde(tag = "kind")]
|
||||
pub enum TaskProg {
|
||||
// File
|
||||
FilePaste(FileProgPaste),
|
||||
FileLink(FileProgLink),
|
||||
|
|
@ -57,7 +59,7 @@ impl From<TaskProg> for TaskSummary {
|
|||
}
|
||||
|
||||
impl TaskProg {
|
||||
pub(crate) fn running(self) -> bool {
|
||||
pub fn running(self) -> bool {
|
||||
match self {
|
||||
// File
|
||||
Self::FilePaste(p) => p.running(),
|
||||
|
|
@ -78,7 +80,7 @@ impl TaskProg {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn success(self) -> bool {
|
||||
pub fn success(self) -> bool {
|
||||
match self {
|
||||
// File
|
||||
Self::FilePaste(p) => p.success(),
|
||||
|
|
@ -99,7 +101,7 @@ impl TaskProg {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn percent(self) -> Option<f32> {
|
||||
pub fn percent(self) -> Option<f32> {
|
||||
match self {
|
||||
// File
|
||||
Self::FilePaste(p) => p.percent(),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use yazi_config::{YAZI, plugin::{Fetcher, Preloader}};
|
|||
use yazi_dds::Pump;
|
||||
use yazi_fs::{must_be_dir, path::unique_name, provider, remove_dir_clean};
|
||||
use yazi_parser::{app::PluginOpt, tasks::ProcessExecOpt};
|
||||
use yazi_proxy::MgrProxy;
|
||||
use yazi_proxy::TasksProxy;
|
||||
use yazi_shared::{Id, Throttle, url::UrlBuf};
|
||||
|
||||
use super::{Ongoing, TaskOp};
|
||||
|
|
@ -174,7 +174,7 @@ impl Scheduler {
|
|||
move |canceled: bool| async move {
|
||||
if !canceled {
|
||||
provider::remove_dir_all(&target).await.ok();
|
||||
MgrProxy::update_tasks(&target);
|
||||
TasksProxy::update_succeed(&target);
|
||||
Pump::push_delete(target);
|
||||
}
|
||||
ongoing.lock().remove(id);
|
||||
|
|
@ -199,7 +199,7 @@ impl Scheduler {
|
|||
|
||||
move |canceled: bool| async move {
|
||||
if !canceled {
|
||||
MgrProxy::update_tasks(&target);
|
||||
TasksProxy::update_succeed(&target);
|
||||
Pump::push_trash(target);
|
||||
}
|
||||
ongoing.lock().remove(id);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
use crate::Task;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
use crate::{Task, TaskProg};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize)]
|
||||
pub struct TaskSnap {
|
||||
pub name: String,
|
||||
pub prog: TaskProg,
|
||||
}
|
||||
|
||||
impl From<&Task> for TaskSnap {
|
||||
fn from(task: &Task) -> Self { TaskSnap { name: task.name.clone() } }
|
||||
fn from(task: &Task) -> Self { TaskSnap { name: task.name.clone(), prog: task.prog } }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue