diff --git a/yazi-fm/src/app/commands/update_progress.rs b/yazi-fm/src/app/commands/update_progress.rs index 2805c2e2..15d9633c 100644 --- a/yazi-fm/src/app/commands/update_progress.rs +++ b/yazi-fm/src/app/commands/update_progress.rs @@ -1,9 +1,8 @@ -use ratatui::backend::Backend; use yazi_core::tasks::TasksProgress; use yazi_macro::render; use yazi_shared::event::Cmd; -use crate::{app::App, lives::Lives, tasks::Progress}; +use crate::app::App; pub struct Opt { progress: TasksProgress, @@ -19,41 +18,28 @@ impl TryFrom for Opt { impl App { pub(crate) fn update_progress(&mut self, opt: impl TryInto) { - let Ok(opt) = opt.try_into() else { - return; - }; + let Ok(opt) = opt.try_into() else { return }; // Update the progress of all tasks. let tasks = &mut self.cx.tasks; + let progressed = tasks.progress != opt.progress; tasks.progress = opt.progress; // If the task manager is visible, update the summaries with a complete render. if tasks.visible { let new = tasks.paginate(); - if new.len() != tasks.summaries.len() - || new.iter().zip(&tasks.summaries).any(|(a, b)| a.name != b.name) - { + if tasks.summaries != new { tasks.summaries = new; tasks.arrow(0); return render!(); } } - // Otherwise, only partially update the progress. - let Some(term) = &mut self.term else { - return; - }; - - _ = Lives::scope(&self.cx, |_| { - for patch in Progress::partial_render(term.current_buffer_mut()) { - term.backend_mut().draw(patch.iter().map(|(x, y, cell)| (*x, *y, cell)))?; - if let Some(pos) = self.cx.cursor() { - term.show_cursor()?; - term.set_cursor_position(pos)?; - } - term.backend_mut().flush()?; - } - Ok(()) - }); + if !progressed { + } else if tasks.progress.total == 0 { + render!(); + } else { + self.render_partially(); + } } } diff --git a/yazi-fm/src/tasks/progress.rs b/yazi-fm/src/tasks/progress.rs index 4091cc3f..f9795dcc 100644 --- a/yazi-fm/src/tasks/progress.rs +++ b/yazi-fm/src/tasks/progress.rs @@ -1,41 +1,23 @@ -use std::mem; - -use mlua::{AnyUserData, Table, TableExt}; +use mlua::{Table, TableExt}; +use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use tracing::error; -use yazi_plugin::{LUA, cast_to_renderable}; +use yazi_config::LAYOUT; +use yazi_plugin::{LUA, elements::render_widgets}; pub(crate) struct Progress; -impl Progress { - pub(crate) fn partial_render( - buf: &mut ratatui::buffer::Buffer, - ) -> Vec> { - let mut patches = vec![]; +impl Widget for Progress { + fn render(self, _: Rect, buf: &mut Buffer) { let mut f = || { - let comp: Table = LUA.globals().raw_get("Progress")?; - for widget in comp.call_method::<_, Vec>("partial_redraw", ())? { - let Some(w) = cast_to_renderable(&widget) else { continue }; + let area = yazi_plugin::elements::Rect::from(LAYOUT.get().progress); + let progress = + LUA.globals().raw_get::<_, Table>("Progress")?.call_method::<_, Table>("use", area)?; - let area = w.area(); - w.render(buf); - - let mut patch = Vec::with_capacity(area.width as usize * area.height as usize); - for y in area.top()..area.bottom() { - for x in area.left()..area.right() { - patch.push((x, y, mem::take(&mut buf[(x, y)]))); - } - } - - buf.reset(); - patches.push(patch); - } - - Ok::<_, anyhow::Error>(()) + render_widgets(progress.call_method("redraw", ())?, buf); + Ok::<_, mlua::Error>(()) }; - if let Err(e) = f() { - error!("{e}"); + error!("Failed to redraw the `Progress` component:\n{e}"); } - patches } }