mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 15:21:04 +00:00
feat: fill in error messages if preview fails (#2917)
This commit is contained in:
parent
e218f1d8bb
commit
590d336716
11 changed files with 77 additions and 29 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use image::{DynamicImage, ExtendedColorType, ImageDecoder, ImageEncoder, ImageError, ImageReader, ImageResult, Limits, codecs::{jpeg::JpegEncoder, png::PngEncoder}, imageops::FilterType, metadata::Orientation};
|
||||
|
|
@ -10,7 +10,7 @@ use crate::Dimension;
|
|||
pub struct Image;
|
||||
|
||||
impl Image {
|
||||
pub async fn precache(path: &Path, cache: PathBuf) -> Result<()> {
|
||||
pub async fn precache(path: &Path, cache: &Path) -> Result<()> {
|
||||
let (mut img, orientation, icc) = Self::decode_from(path).await?;
|
||||
let (w, h) = Self::flip_size(orientation, (YAZI.preview.max_width, YAZI.preview.max_height));
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ function M:peek(job)
|
|||
|
||||
local ok, err = self:preload(job)
|
||||
if not ok or err then
|
||||
return
|
||||
return ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock()))
|
||||
|
||||
local _, err = ya.image_show(cache, job.area)
|
||||
ya.preview_widget(job, err and ui.Text(err):area(job.area):wrap(ui.Wrap.YES))
|
||||
ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
function M:seek() end
|
||||
|
|
@ -45,10 +45,12 @@ function M:preload(job)
|
|||
"JPG:" .. tostring(cache),
|
||||
}):status()
|
||||
|
||||
if status then
|
||||
return status.success
|
||||
else
|
||||
if not status then
|
||||
return true, Err("Failed to start `magick`, error: %s", err)
|
||||
elseif not status.success then
|
||||
return false, Err("`magick` exited with error code: %s", status.code)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ function M:peek(job)
|
|||
|
||||
local ok, err = self:preload(job)
|
||||
if not ok or err then
|
||||
return
|
||||
return ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock()))
|
||||
|
||||
local _, err = ya.image_show(cache, job.area)
|
||||
ya.preview_widget(job, err and ui.Text(err):area(job.area):wrap(ui.Wrap.YES))
|
||||
ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
function M:seek() end
|
||||
|
|
@ -38,10 +38,12 @@ function M:preload(job)
|
|||
string.format("JPG:%s", cache),
|
||||
}:status()
|
||||
|
||||
if status then
|
||||
return status.success
|
||||
else
|
||||
if not status then
|
||||
return true, Err("Failed to start `magick`, error: %s", err)
|
||||
elseif not status.success then
|
||||
return false, Err("`magick` exited with error code: %s", status.code)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ function M:peek(job)
|
|||
|
||||
local ok, err = self:preload(job)
|
||||
if not ok or err then
|
||||
return
|
||||
return ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock()))
|
||||
|
||||
local _, err = ya.image_show(cache, job.area)
|
||||
ya.preview_widget(job, err and ui.Text(err):area(job.area):wrap(ui.Wrap.YES))
|
||||
ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
function M:seek(job)
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ function M:peek(job)
|
|||
|
||||
local ok, err = self:preload(job)
|
||||
if not ok or err then
|
||||
return
|
||||
return ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock()))
|
||||
|
||||
local _, err = ya.image_show(cache, job.area)
|
||||
ya.preview_widget(job, err and ui.Text(err):area(job.area):wrap(ui.Wrap.YES))
|
||||
ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
function M:seek() end
|
||||
|
|
@ -60,10 +60,12 @@ function M:preload(job)
|
|||
end
|
||||
end
|
||||
|
||||
if status then
|
||||
return status.success
|
||||
else
|
||||
if not status then
|
||||
return true, Err("Error while running `resvg`: %s", err)
|
||||
elseif not status.success then
|
||||
return false, Err("`resvg` exited with error code: %s", status.code)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ function M:peek(job)
|
|||
|
||||
local ok, err = self:preload(job)
|
||||
if not ok or err then
|
||||
return
|
||||
return ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock()))
|
||||
|
||||
local _, err = ya.image_show(cache, job.area)
|
||||
ya.preview_widget(job, err and ui.Text(err):area(job.area):wrap(ui.Wrap.YES))
|
||||
ya.preview_widget(job, err)
|
||||
end
|
||||
|
||||
function M:seek(job)
|
||||
|
|
@ -76,10 +76,12 @@ function M:preload(job)
|
|||
"-y", tostring(cache),
|
||||
}):status()
|
||||
|
||||
if status then
|
||||
return status.success
|
||||
else
|
||||
if not status then
|
||||
return true, Err("Failed to start `ffmpeg`, error: %s", err)
|
||||
elseif not status.success then
|
||||
return false, Err("`ffmpeg` exited with error code: %s", status.code)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ impl Area {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Rect> for Area {
|
||||
fn from(rect: Rect) -> Self { Self::Rect(rect) }
|
||||
}
|
||||
|
||||
impl TryFrom<AnyUserData> for Area {
|
||||
type Error = mlua::Error;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std::any::TypeId;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError};
|
||||
use yazi_binding::Error;
|
||||
|
||||
use super::{Bar, Border, Clear, Gauge, Line, List, Table, Text};
|
||||
use crate::elements::Rect;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Renderable {
|
||||
|
|
@ -35,10 +37,10 @@ impl Renderable {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<AnyUserData> for Renderable {
|
||||
impl TryFrom<&AnyUserData> for Renderable {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(ud: AnyUserData) -> Result<Self, Self::Error> {
|
||||
fn try_from(ud: &AnyUserData) -> Result<Self, Self::Error> {
|
||||
Ok(match ud.type_id() {
|
||||
Some(t) if t == TypeId::of::<Line>() => Self::Line(ud.take()?),
|
||||
Some(t) if t == TypeId::of::<Text>() => Self::Text(ud.take()?),
|
||||
|
|
@ -52,3 +54,20 @@ impl TryFrom<AnyUserData> for Renderable {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<AnyUserData> for Renderable {
|
||||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(ud: AnyUserData) -> Result<Self, Self::Error> { Self::try_from(&ud) }
|
||||
}
|
||||
|
||||
impl From<(Rect, Error)> for Renderable {
|
||||
fn from((area, error): (Rect, Error)) -> Self {
|
||||
Self::Text(Text {
|
||||
area: area.into(),
|
||||
inner: error.into_string().into(),
|
||||
wrap: ratatui::widgets::Wrap { trim: false }.into(),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ impl Wrap {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ratatui::widgets::Wrap> for Wrap {
|
||||
fn from(value: ratatui::widgets::Wrap) -> Self { Self(Some(value)) }
|
||||
}
|
||||
|
||||
impl From<PreviewWrap> for Wrap {
|
||||
fn from(value: PreviewWrap) -> Self {
|
||||
Self(match value {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,11 @@ impl Utils {
|
|||
}
|
||||
|
||||
pub(super) fn image_precache(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|_, (src, dist): (UrlRef, UrlRef)| async move {
|
||||
Ok(Image::precache(&src, dist.to_path_buf()).await.is_ok())
|
||||
lua.create_async_function(|lua, (src, dist): (UrlRef, UrlRef)| async move {
|
||||
match Image::precache(&src, &dist).await {
|
||||
Ok(()) => true.into_lua_multi(&lua),
|
||||
Err(e) => (false, Error::Custom(e.to_string().into())).into_lua_multi(&lua),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use mlua::{AnyUserData, ExternalError, Function, IntoLuaMulti, Lua, Table, Value};
|
||||
use yazi_binding::Error;
|
||||
use yazi_config::YAZI;
|
||||
use yazi_macro::emit;
|
||||
use yazi_shared::{errors::PeekError, event::Cmd};
|
||||
|
|
@ -69,7 +70,16 @@ impl Utils {
|
|||
.sequence_values::<AnyUserData>()
|
||||
.map(|ud| ud.and_then(Renderable::try_from))
|
||||
.collect::<mlua::Result<_>>()?,
|
||||
Value::UserData(ud) => vec![Renderable::try_from(ud)?],
|
||||
Value::UserData(ud) => match Renderable::try_from(&ud) {
|
||||
Ok(r) => vec![r],
|
||||
Err(e) => {
|
||||
if let Ok(err) = ud.take::<Error>() {
|
||||
vec![(lock.area, err).into()]
|
||||
} else {
|
||||
Err(e)?
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => Err("preview widget must be a renderable element or a table of them".into_lua_err())?,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue