mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
perf: new UI rendering architecture
This commit is contained in:
parent
10a78b5dbc
commit
f8d73a95e3
13 changed files with 59 additions and 54 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<()> {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use super::{RectRef, Renderable, Style};
|
|||
pub struct Bar {
|
||||
area: ratatui::layout::Rect,
|
||||
|
||||
position: ratatui::widgets::Borders,
|
||||
direction: ratatui::widgets::Borders,
|
||||
symbol: String,
|
||||
style: Option<ratatui::style::Style>,
|
||||
}
|
||||
|
|
@ -18,13 +18,14 @@ impl Bar {
|
|||
Ok(Self {
|
||||
area: *area,
|
||||
|
||||
position: Borders::from_bits_truncate(direction),
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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)?),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
mod event;
|
||||
mod exec;
|
||||
mod render;
|
||||
|
||||
pub use event::*;
|
||||
pub use exec::*;
|
||||
pub use render::*;
|
||||
|
|
|
|||
10
yazi-shared/src/event/render.rs
Normal file
10
yazi-shared/src/event/render.rs
Normal 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);
|
||||
};
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue