perf: new UI rendering architecture

This commit is contained in:
sxyazi 2024-01-01 23:55:27 +08:00
parent 10a78b5dbc
commit f8d73a95e3
No known key found for this signature in database
13 changed files with 59 additions and 54 deletions

View file

@ -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<Exec>, layer: Layer) {
if Executor::new(self).dispatch(&exec, layer) {
emit!(Render);
}
Executor::new(self).dispatch(&exec, layer);
}
fn dispatch_module(&mut self, event: Event) {

View file

@ -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<yazi_plugin::Opt>) -> bool {
pub(crate) fn plugin(&mut self, opt: impl TryInto<yazi_plugin::Opt>) {
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<yazi_plugin::Opt>) -> bool {
pub(crate) fn plugin_do(&mut self, opt: impl TryInto<yazi_plugin::Opt>) {
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
}
}

View file

@ -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<()> {

View file

@ -18,9 +18,9 @@ impl TryFrom<&Exec> for Opt {
}
impl App {
pub(crate) fn stop(&mut self, opt: impl TryInto<Opt>) -> bool {
pub(crate) fn stop(&mut self, opt: impl TryInto<Opt>) {
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
}
}

View file

@ -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 {

View file

@ -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,
}

View file

@ -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;

View file

@ -7,9 +7,9 @@ use super::{RectRef, Renderable, Style};
pub struct Bar {
area: ratatui::layout::Rect,
position: ratatui::widgets::Borders,
symbol: String,
style: Option<ratatui::style::Style>,
direction: ratatui::widgets::Borders,
symbol: String,
style: Option<ratatui::style::Style>,
}
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);

View file

@ -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)?),

View file

@ -10,7 +10,6 @@ pub enum Event {
Quit(bool), // no-cwd-file
Key(KeyEvent),
Paste(String),
Render(String),
Resize(u16, u16),
Call(Vec<Exec>, 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();
};

View file

@ -2,6 +2,8 @@
mod event;
mod exec;
mod render;
pub use event::*;
pub use exec::*;
pub use render::*;

View file

@ -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);
};
}

View file

@ -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);