feat: new ya.confirm() API (#2095)

This commit is contained in:
三咲雅 · Misaki Masa 2024-12-25 00:35:46 +08:00 committed by GitHub
parent 50a81bea31
commit 7d3e58951c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 74 additions and 39 deletions

View file

@ -204,7 +204,7 @@ overwrite_offset = [ 0, 0, 50, 15 ]
# quit
quit_title = "Quit?"
quit_content = "The following task is still running, are you sure you want to quit?"
quit_content = "The following tasks are still running, are you sure you want to quit?"
quit_origin = "center"
quit_offset = [ 0, 0, 50, 15 ]

View file

@ -1,4 +1,4 @@
use ratatui::{text::Text, widgets::{Paragraph, Wrap}};
use ratatui::{text::{Line, Text}, widgets::{Paragraph, Wrap}};
use yazi_shared::url::Url;
use super::{Offset, Origin, Position};
@ -24,8 +24,8 @@ pub struct PickCfg {
#[derive(Default)]
pub struct ConfirmCfg {
pub title: String,
pub position: Position,
pub title: Line<'static>,
pub content: Paragraph<'static>,
pub list: Paragraph<'static>,
}
@ -112,10 +112,10 @@ impl ConfirmCfg {
list: Option<Text<'static>>,
) -> Self {
Self {
title,
position: Position::new(origin, offset),
content: content.map(|c| Paragraph::new(c).wrap(Wrap { trim: false })).unwrap_or_default(),
list: list.map(|l| Paragraph::new(l).wrap(Wrap { trim: false })).unwrap_or_default(),
title: Line::raw(title),
content: content.map(|c| Paragraph::new(c).wrap(Wrap { trim: false })).unwrap_or_default(),
list: list.map(|l| Paragraph::new(l).wrap(Wrap { trim: false })).unwrap_or_default(),
}
}

View file

@ -29,8 +29,8 @@ impl Confirm {
self.content = opt.cfg.content;
self.list = opt.cfg.list;
self.offset = 0;
self.position = opt.cfg.position;
self.offset = 0;
self.callback = Some(opt.tx);
self.visible = true;

View file

@ -1,15 +1,15 @@
use ratatui::widgets::Paragraph;
use ratatui::{text::Line, widgets::Paragraph};
use tokio::sync::oneshot::Sender;
use yazi_config::popup::Position;
#[derive(Default)]
pub struct Confirm {
pub title: String,
pub title: Line<'static>,
pub content: Paragraph<'static>,
pub list: Paragraph<'static>,
pub offset: usize,
pub position: Position,
pub offset: usize,
pub(super) callback: Option<Sender<bool>>,
pub visible: bool,

View file

@ -1,4 +1,4 @@
use ratatui::{buffer::Buffer, layout::{Alignment, Constraint, Layout, Margin, Rect}, text::Line, widgets::{Block, BorderType, Widget}};
use ratatui::{buffer::Buffer, layout::{Alignment, Constraint, Layout, Margin, Rect}, widgets::{Block, BorderType, Widget}};
use yazi_config::THEME;
use crate::Ctx;
@ -12,7 +12,7 @@ impl<'a> Confirm<'a> {
}
impl Widget for Confirm<'_> {
fn render(self, _win: Rect, buf: &mut Buffer) {
fn render(self, _: Rect, buf: &mut Buffer) {
let confirm = &self.cx.confirm;
let area = self.cx.manager.area(confirm.position);
@ -21,21 +21,26 @@ impl Widget for Confirm<'_> {
Block::bordered()
.border_type(BorderType::Rounded)
.border_style(THEME.confirm.border)
.title(Line::styled(&confirm.title, THEME.confirm.title))
.title(confirm.title.clone().style(THEME.confirm.title.derive(confirm.title.style)))
.title_alignment(Alignment::Center)
.render(area, buf);
let content = confirm.content.clone();
let content_height = content.line_count(area.width).saturating_add(1) as u16;
let content_border = confirm.list.line_count(area.width) != 0;
let content_height = content.line_count(area.width) as u16;
let chunks = Layout::vertical([
Constraint::Length(if content_height == 1 { 0 } else { content_height }),
Constraint::Length(if content_height == 0 {
0
} else {
content_height.saturating_add(content_border as u16)
}),
Constraint::Fill(1),
Constraint::Length(1),
])
.split(area.inner(Margin::new(0, 1)));
super::Content::new(content).render(chunks[0], buf);
super::Content::new(self.cx, content_border).render(chunks[0], buf);
super::List::new(self.cx).render(chunks[1], buf);
super::Buttons.render(chunks[2], buf);
}

View file

@ -1,28 +1,37 @@
use ratatui::{buffer::Buffer, layout::{Margin, Rect}, widgets::{Block, Borders, Paragraph, Widget}};
use ratatui::{buffer::Buffer, layout::{Margin, Rect}, style::Styled, widgets::{Block, Borders, Widget}};
use yazi_config::THEME;
use crate::Ctx;
pub(crate) struct Content<'a> {
p: Paragraph<'a>,
cx: &'a Ctx,
border: bool,
}
impl<'a> Content<'a> {
pub(crate) fn new(p: Paragraph<'a>) -> Self { Self { p } }
pub(crate) fn new(cx: &'a Ctx, border: bool) -> Self { Self { cx, border } }
}
impl Widget for Content<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let confirm = &self.cx.confirm;
// Content area
let inner = area.inner(Margin::new(1, 0));
// Bottom border
let block = Block::new().borders(Borders::BOTTOM).border_style(THEME.confirm.border);
block.clone().render(area.inner(Margin::new(1, 0)), buf);
// Border
let block = if self.border {
Block::new().borders(Borders::BOTTOM).border_style(THEME.confirm.border)
} else {
Block::new()
};
self
.p
confirm
.content
.clone()
.alignment(ratatui::layout::Alignment::Center)
.block(block)
.style(THEME.confirm.content)
.style(THEME.confirm.content.derive(Styled::style(&confirm.content)))
.render(inner, buf);
}
}

View file

@ -93,6 +93,10 @@ impl TryFrom<Table> for Line {
}
}
impl From<Line> for ratatui::text::Line<'static> {
fn from(value: Line) -> Self { value.0 }
}
impl UserData for Line {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
crate::impl_style_method!(methods, 0.style);

View file

@ -3,13 +3,13 @@ use std::{str::FromStr, time::Duration};
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, Table, Value};
use tokio::sync::mpsc;
use tokio_stream::wrappers::UnboundedReceiverStream;
use yazi_config::{keymap::{Chord, Key}, popup::InputCfg};
use yazi_config::{keymap::{Chord, Key}, popup::{ConfirmCfg, InputCfg}};
use yazi_macro::emit;
use yazi_proxy::{AppProxy, InputProxy};
use yazi_proxy::{AppProxy, ConfirmProxy, InputProxy};
use yazi_shared::{Debounce, Layer, event::Cmd};
use super::Utils;
use crate::{bindings::InputRx, elements::Pos};
use crate::{bindings::InputRx, elements::{Line, Pos, Text}};
impl Utils {
pub(super) fn which(lua: &Lua) -> mlua::Result<Function> {
@ -68,17 +68,26 @@ impl Utils {
})
}
// TODO: redesign the confirm API
// pub(super) fn confirm(lua: &Lua, ya: &Table) -> mlua::Result<Function> {
// lua.create_async_function(|_, t: Table| async move {
// let result = ConfirmProxy::show(ConfirmCfg {
// title: t.raw_get("title")?,
// content: t.raw_get("content")?,
// position: Position::try_from(t.raw_get::<_, Table>("position")?)?.into(),
// });
// Ok(result.await)
// })
// }
pub(super) fn confirm(lua: &Lua) -> mlua::Result<Function> {
fn content(t: &Table) -> mlua::Result<ratatui::widgets::Paragraph<'static>> {
Ok(match t.raw_get::<Value>("content") {
Ok(v) if v.is_nil() => Default::default(),
Ok(v) => Text::try_from(v)?.into(),
Err(e) => Err(e)?,
})
}
lua.create_async_function(|_, t: Table| async move {
let result = ConfirmProxy::show(ConfirmCfg {
position: Pos::try_from(t.raw_get::<Table>("pos")?)?.into(),
title: Line::try_from(t.raw_get::<Value>("title")?)?.into(),
content: content(&t)?,
list: Default::default(), // TODO
});
Ok(result.await)
})
}
pub(super) fn notify(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|_, t: Table| {

View file

@ -30,6 +30,7 @@ pub fn compose(lua: &Lua, isolate: bool) -> mlua::Result<Table> {
// Layout
b"which" => Utils::which(lua)?,
b"input" => Utils::input(lua)?,
b"confirm" => Utils::confirm(lua)?,
b"notify" => Utils::notify(lua)?,
// Log

View file

@ -36,6 +36,13 @@ impl From<Style> for ratatui::style::Style {
}
}
impl Style {
#[inline]
pub fn derive(self, other: ratatui::style::Style) -> ratatui::style::Style {
ratatui::style::Style::from(self).patch(other)
}
}
#[derive(Default, Deserialize)]
pub struct StyleShadow {
#[serde(default)]