From f8d73a95e3671da9b457b3c0a61a1a316226149c Mon Sep 17 00:00:00 2001 From: sxyazi Date: Mon, 1 Jan 2024 23:55:27 +0800 Subject: [PATCH] perf: new UI rendering architecture --- yazi-fm/src/app/app.rs | 18 ++++++------------ yazi-fm/src/app/commands/plugin.rs | 14 ++++++-------- yazi-fm/src/app/commands/render.rs | 3 +-- yazi-fm/src/app/commands/stop.rs | 5 ++--- yazi-fm/src/executor.rs | 10 +++------- yazi-fm/src/root.rs | 4 ++++ yazi-fm/src/widgets/clear.rs | 3 ++- yazi-plugin/src/elements/bar.rs | 25 +++++++++++++------------ yazi-plugin/src/elements/border.rs | 12 ++++++++++-- yazi-shared/src/event/event.rs | 4 ---- yazi-shared/src/event/mod.rs | 2 ++ yazi-shared/src/event/render.rs | 10 ++++++++++ yazi-shared/src/lib.rs | 3 --- 13 files changed, 59 insertions(+), 54 deletions(-) create mode 100644 yazi-shared/src/event/render.rs diff --git a/yazi-fm/src/app/app.rs b/yazi-fm/src/app/app.rs index bb1ca4c3..1a4af334 100644 --- a/yazi-fm/src/app/app.rs +++ b/yazi-fm/src/app/app.rs @@ -2,7 +2,7 @@ use anyhow::{Ok, Result}; use crossterm::event::KeyEvent; use yazi_config::{keymap::Key, ARGS}; use yazi_core::input::InputMode; -use yazi_shared::{emit, event::{Event, Exec}, term::Term, Layer}; +use yazi_shared::{emit, event::{Event, Exec}, render, term::Term, Layer}; use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Signals}; @@ -32,7 +32,8 @@ impl App { } Event::Key(key) => app.dispatch_key(key), Event::Paste(str) => app.dispatch_paste(str), - Event::Render(_) => app.render()?, + // TODO: render + // Event::Render(_) => app.render()?, Event::Resize(cols, rows) => app.dispatch_resize(cols, rows)?, Event::Call(exec, layer) => app.dispatch_call(exec, layer), event => app.dispatch_module(event), @@ -49,18 +50,13 @@ impl App { Term::goodbye(|| false); } - fn dispatch_key(&mut self, key: KeyEvent) { - let key = Key::from(key); - if Executor::new(self).handle(key) { - emit!(Render); - } - } + fn dispatch_key(&mut self, key: KeyEvent) { Executor::new(self).handle(Key::from(key)); } fn dispatch_paste(&mut self, str: String) { if self.cx.input.visible { let input = &mut self.cx.input; if input.mode() == InputMode::Insert && input.type_str(&str) { - emit!(Render); + render!(); } } } @@ -76,9 +72,7 @@ impl App { #[inline] fn dispatch_call(&mut self, exec: Vec, layer: Layer) { - if Executor::new(self).dispatch(&exec, layer) { - emit!(Render); - } + Executor::new(self).dispatch(&exec, layer); } fn dispatch_module(&mut self, event: Event) { diff --git a/yazi-fm/src/app/commands/plugin.rs b/yazi-fm/src/app/commands/plugin.rs index 53a171f2..2a5adcb5 100644 --- a/yazi-fm/src/app/commands/plugin.rs +++ b/yazi-fm/src/app/commands/plugin.rs @@ -6,9 +6,9 @@ use yazi_shared::{emit, event::Exec, Layer}; use crate::{app::App, lives::Lives}; impl App { - pub(crate) fn plugin(&mut self, opt: impl TryInto) -> bool { + pub(crate) fn plugin(&mut self, opt: impl TryInto) { let Ok(opt) = opt.try_into() else { - return false; + return; }; if !opt.sync { @@ -24,12 +24,11 @@ impl App { emit!(Call(Exec::call("plugin_do", vec![opt.name]).with_data(opt.data).vec(), Layer::App)); } }); - false } - pub(crate) fn plugin_do(&mut self, opt: impl TryInto) -> bool { + pub(crate) fn plugin_do(&mut self, opt: impl TryInto) { let Ok(opt) = opt.try_into() else { - return false; + return; }; let args = Variadic::from_iter(opt.data.args.into_iter().filter_map(|v| v.into_lua(&LUA).ok())); @@ -51,16 +50,15 @@ impl App { if let Err(e) = ret { error!("{e}"); - return false; + return; } let Some(tx) = opt.data.tx else { - return false; + return; }; if let Ok(v) = ret.and_then(|v| v.try_into().into_lua_err()) { tx.send(v).ok(); } - false } } diff --git a/yazi-fm/src/app/commands/render.rs b/yazi-fm/src/app/commands/render.rs index 0e2e3118..38cb5921 100644 --- a/yazi-fm/src/app/commands/render.rs +++ b/yazi-fm/src/app/commands/render.rs @@ -2,9 +2,8 @@ use std::sync::atomic::Ordering; use anyhow::Result; use ratatui::backend::Backend; -use yazi_shared::COLLISION; -use crate::{app::App, lives::Lives, root::Root}; +use crate::{app::App, lives::Lives, root::{Root, COLLISION}}; impl App { pub(crate) fn render(&mut self) -> Result<()> { diff --git a/yazi-fm/src/app/commands/stop.rs b/yazi-fm/src/app/commands/stop.rs index dd78f85e..bffe882c 100644 --- a/yazi-fm/src/app/commands/stop.rs +++ b/yazi-fm/src/app/commands/stop.rs @@ -18,9 +18,9 @@ impl TryFrom<&Exec> for Opt { } impl App { - pub(crate) fn stop(&mut self, opt: impl TryInto) -> bool { + pub(crate) fn stop(&mut self, opt: impl TryInto) { let Ok(opt) = opt.try_into() else { - return false; + return; }; self.cx.manager.active_mut().preview.reset_image(); @@ -38,6 +38,5 @@ impl App { if let Some(tx) = opt.tx { tx.send(()).ok(); } - false } } diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index 17a327d2..0e74233b 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -58,10 +58,9 @@ impl<'a> Executor<'a> { } #[inline] - pub(super) fn dispatch(&mut self, exec: &[Exec], layer: Layer) -> bool { - let mut render = false; + pub(super) fn dispatch(&mut self, exec: &[Exec], layer: Layer) { for e in exec { - render |= match layer { + match layer { Layer::App => self.app(e), Layer::Manager => self.manager(e), Layer::Tasks => self.tasks(e), @@ -72,10 +71,9 @@ impl<'a> Executor<'a> { Layer::Which => unreachable!(), }; } - render } - fn app(&mut self, exec: &Exec) -> bool { + fn app(&mut self, exec: &Exec) { macro_rules! on { ($name:ident) => { if exec.cmd == stringify!($name) { @@ -87,8 +85,6 @@ impl<'a> Executor<'a> { on!(plugin); on!(plugin_do); on!(stop); - - false } fn manager(&mut self, exec: &Exec) -> bool { diff --git a/yazi-fm/src/root.rs b/yazi-fm/src/root.rs index fbcf106c..12ff2074 100644 --- a/yazi-fm/src/root.rs +++ b/yazi-fm/src/root.rs @@ -1,8 +1,12 @@ +use std::sync::atomic::AtomicBool; + use ratatui::{buffer::Buffer, layout::{Constraint, Direction, Layout, Rect}, widgets::Widget}; use super::{completion, input, select, tasks, which}; use crate::{components, help, Ctx}; +pub(super) static COLLISION: AtomicBool = AtomicBool::new(false); + pub(super) struct Root<'a> { cx: &'a Ctx, } diff --git a/yazi-fm/src/widgets/clear.rs b/yazi-fm/src/widgets/clear.rs index ef68110f..fb73b7d4 100644 --- a/yazi-fm/src/widgets/clear.rs +++ b/yazi-fm/src/widgets/clear.rs @@ -3,7 +3,8 @@ use std::sync::atomic::Ordering; use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use yazi_adaptor::ADAPTOR; use yazi_config::LAYOUT; -use yazi_shared::COLLISION; + +use crate::renderer::COLLISION; pub(crate) struct Clear; diff --git a/yazi-plugin/src/elements/bar.rs b/yazi-plugin/src/elements/bar.rs index d0993787..7a19f55f 100644 --- a/yazi-plugin/src/elements/bar.rs +++ b/yazi-plugin/src/elements/bar.rs @@ -7,9 +7,9 @@ use super::{RectRef, Renderable, Style}; pub struct Bar { area: ratatui::layout::Rect, - position: ratatui::widgets::Borders, - symbol: String, - style: Option, + direction: ratatui::widgets::Borders, + symbol: String, + style: Option, } impl Bar { @@ -18,13 +18,14 @@ impl Bar { Ok(Self { area: *area, - position: Borders::from_bits_truncate(direction), - symbol: Default::default(), - style: Default::default(), + direction: Borders::from_bits_truncate(direction), + symbol: Default::default(), + style: Default::default(), }) })?; let bar = lua.create_table_from([ + // Direction ("NONE", Borders::NONE.bits().into_lua(lua)?), ("TOP", Borders::TOP.bits().into_lua(lua)?), ("RIGHT", Borders::RIGHT.bits().into_lua(lua)?), @@ -68,15 +69,15 @@ impl Renderable for Bar { let symbol = if !self.symbol.is_empty() { &self.symbol - } else if self.position.intersects(Borders::TOP | Borders::BOTTOM) { + } else if self.direction.intersects(Borders::TOP | Borders::BOTTOM) { "─" - } else if self.position.intersects(Borders::LEFT | Borders::RIGHT) { + } else if self.direction.intersects(Borders::LEFT | Borders::RIGHT) { "│" } else { " " }; - if self.position.contains(Borders::LEFT) { + if self.direction.contains(Borders::LEFT) { for y in self.area.top()..self.area.bottom() { let cell = buf.get_mut(self.area.left(), y).set_symbol(symbol); if let Some(style) = self.style { @@ -84,7 +85,7 @@ impl Renderable for Bar { } } } - if self.position.contains(Borders::TOP) { + if self.direction.contains(Borders::TOP) { for x in self.area.left()..self.area.right() { let cell = buf.get_mut(x, self.area.top()).set_symbol(symbol); if let Some(style) = self.style { @@ -92,7 +93,7 @@ impl Renderable for Bar { } } } - if self.position.contains(Borders::RIGHT) { + if self.direction.contains(Borders::RIGHT) { let x = self.area.right() - 1; for y in self.area.top()..self.area.bottom() { let cell = buf.get_mut(x, y).set_symbol(symbol); @@ -101,7 +102,7 @@ impl Renderable for Bar { } } } - if self.position.contains(Borders::BOTTOM) { + if self.direction.contains(Borders::BOTTOM) { let y = self.area.bottom() - 1; for x in self.area.left()..self.area.right() { let cell = buf.get_mut(x, y).set_symbol(symbol); diff --git a/yazi-plugin/src/elements/border.rs b/yazi-plugin/src/elements/border.rs index bbea576c..8c8ddae5 100644 --- a/yazi-plugin/src/elements/border.rs +++ b/yazi-plugin/src/elements/border.rs @@ -1,8 +1,9 @@ use mlua::{AnyUserData, ExternalError, IntoLua, Lua, Table, UserData, Value}; -use ratatui::widgets::Widget; +use ratatui::widgets::{Borders, Widget}; use super::{RectRef, Renderable, Style}; +// Type const PLAIN: u8 = 0; const ROUNDED: u8 = 1; const DOUBLE: u8 = 2; @@ -30,7 +31,14 @@ impl Border { })?; let border = lua.create_table_from([ - // Border type + // Position + ("NONE", Borders::NONE.bits().into_lua(lua)?), + ("TOP", Borders::TOP.bits().into_lua(lua)?), + ("RIGHT", Borders::RIGHT.bits().into_lua(lua)?), + ("BOTTOM", Borders::BOTTOM.bits().into_lua(lua)?), + ("LEFT", Borders::LEFT.bits().into_lua(lua)?), + ("ALL", Borders::ALL.bits().into_lua(lua)?), + // Type ("PLAIN", PLAIN.into_lua(lua)?), ("ROUNDED", ROUNDED.into_lua(lua)?), ("DOUBLE", DOUBLE.into_lua(lua)?), diff --git a/yazi-shared/src/event/event.rs b/yazi-shared/src/event/event.rs index 8df486c4..3a410a4d 100644 --- a/yazi-shared/src/event/event.rs +++ b/yazi-shared/src/event/event.rs @@ -10,7 +10,6 @@ pub enum Event { Quit(bool), // no-cwd-file Key(KeyEvent), Paste(String), - Render(String), Resize(u16, u16), Call(Vec, Layer), @@ -36,9 +35,6 @@ macro_rules! emit { (Quit($no_cwd_file:expr)) => { $crate::event::Event::Quit($no_cwd_file).emit(); }; - (Render) => { - $crate::event::Event::Render(format!("{}:{}", file!(), line!())).emit(); - }; (Call($exec:expr, $layer:expr)) => { $crate::event::Event::Call($exec, $layer).emit(); }; diff --git a/yazi-shared/src/event/mod.rs b/yazi-shared/src/event/mod.rs index b85f499c..643d570c 100644 --- a/yazi-shared/src/event/mod.rs +++ b/yazi-shared/src/event/mod.rs @@ -2,6 +2,8 @@ mod event; mod exec; +mod render; pub use event::*; pub use exec::*; +pub use render::*; diff --git a/yazi-shared/src/event/render.rs b/yazi-shared/src/event/render.rs new file mode 100644 index 00000000..7f709414 --- /dev/null +++ b/yazi-shared/src/event/render.rs @@ -0,0 +1,10 @@ +use std::sync::atomic::AtomicBool; + +pub static NEED_RENDER: AtomicBool = AtomicBool::new(false); + +#[macro_export] +macro_rules! render { + () => { + $crate::event::NEED_RENDER.store(true, std::sync::atomic::Ordering::Relaxed); + }; +} diff --git a/yazi-shared/src/lib.rs b/yazi-shared/src/lib.rs index efd304e0..27fb956c 100644 --- a/yazi-shared/src/lib.rs +++ b/yazi-shared/src/lib.rs @@ -30,6 +30,3 @@ pub use number::*; pub use ro_cell::*; pub use throttle::*; pub use time::*; - -// TODO: remove this -pub static COLLISION: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);