mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
17ce4bf3a9
commit
c176de9a30
13 changed files with 81 additions and 53 deletions
|
|
@ -4,11 +4,10 @@ use scopeguard::defer;
|
|||
use tracing::{error, warn};
|
||||
use yazi_binding::runtime_mut;
|
||||
use yazi_core::app::PluginMode;
|
||||
use yazi_dds::Sendable;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::app::PluginForm;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_runner::loader::{LOADER, Loader};
|
||||
use yazi_runner::{entry::EntryJob, loader::{LOADER, Loader}};
|
||||
use yazi_scheduler::NotifyProxy;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
|
|
@ -48,8 +47,7 @@ impl Actor for PluginDo {
|
|||
if let Some(cb) = opt.callback {
|
||||
cb(&LUA, plugin)
|
||||
} else {
|
||||
let job = LUA.create_table_from([("args", Sendable::args_to_table(&LUA, opt.args)?)])?;
|
||||
plugin.call_method("entry", job)
|
||||
plugin.call_method("entry", EntryJob { args: opt.args, ..Default::default() })
|
||||
}
|
||||
});
|
||||
if let Err(ref e) = result {
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ impl From<FetchProg> for TaskSummary {
|
|||
fn from(value: FetchProg) -> Self {
|
||||
Self {
|
||||
total: 1,
|
||||
success: (value.state == Some(true)) as u32,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
success: value.success() as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,8 +119,8 @@ impl From<FileProgLink> for TaskSummary {
|
|||
fn from(value: FileProgLink) -> Self {
|
||||
Self {
|
||||
total: 1,
|
||||
success: (value.state == Some(true)) as u32,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
success: value.success() as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
@ -243,8 +243,8 @@ impl From<FileProgTrash> for TaskSummary {
|
|||
fn from(value: FileProgTrash) -> Self {
|
||||
Self {
|
||||
total: 1,
|
||||
success: (value.state == Some(true)) as u32,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
success: value.success() as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,12 @@ use yazi_dds::Pump;
|
|||
use yazi_fs::ok_or_not_found;
|
||||
use yazi_vfs::provider;
|
||||
|
||||
use crate::{Ongoing, TaskOp, TaskOps, TasksProxy, file::{FileOutCopy, FileOutCut, FileOutDelete, FileOutDownload, FileOutHardlink, FileOutLink, FileOutTrash, FileOutUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInOutCopy, HookInOutCut, HookInOutHardlink, HookInOutLink, HookInTrash, HookInUpload}};
|
||||
use crate::{Ongoing, TaskOp, TaskOps, TasksProxy, file::{FileOutCopy, FileOutCut, FileOutDelete, FileOutDownload, FileOutHardlink, FileOutLink, FileOutTrash, FileOutUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInOutCopy, HookInOutCut, HookInOutHardlink, HookInOutLink, HookInPreload, HookInTrash, HookInUpload}, preload::{Preload, PreloadOut}};
|
||||
|
||||
pub(crate) struct Hook {
|
||||
ops: TaskOps,
|
||||
ongoing: Arc<Mutex<Ongoing>>,
|
||||
preload: Arc<Preload>,
|
||||
tx: async_priority_channel::Sender<HookIn, u8>,
|
||||
}
|
||||
|
||||
|
|
@ -18,9 +19,10 @@ impl Hook {
|
|||
pub(crate) fn new(
|
||||
ops: &mpsc::UnboundedSender<TaskOp>,
|
||||
ongoing: &Arc<Mutex<Ongoing>>,
|
||||
preload: &Arc<Preload>,
|
||||
tx: async_priority_channel::Sender<HookIn, u8>,
|
||||
) -> Self {
|
||||
Self { ops: ops.into(), ongoing: ongoing.clone(), tx }
|
||||
Self { ops: ops.into(), ongoing: ongoing.clone(), preload: preload.clone(), tx }
|
||||
}
|
||||
|
||||
// --- File
|
||||
|
|
@ -98,6 +100,15 @@ impl Hook {
|
|||
}
|
||||
self.ops.out(task.id, FileOutUpload::Clean);
|
||||
}
|
||||
|
||||
// --- Preload
|
||||
pub(crate) async fn preload(&self, task: HookInPreload) {
|
||||
if !self.ongoing.lock().intact(task.id) {
|
||||
self.preload.loaded.lock().get_mut(&task.hash).map(|x| *x &= !(1 << task.idx));
|
||||
}
|
||||
|
||||
self.ops.out(task.id, PreloadOut::Clean);
|
||||
}
|
||||
}
|
||||
|
||||
impl Hook {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ pub(crate) enum HookIn {
|
|||
Hardlink(HookInOutHardlink),
|
||||
Download(HookInDownload),
|
||||
Upload(HookInUpload),
|
||||
Preload(HookInPreload),
|
||||
}
|
||||
|
||||
impl_from_in!(
|
||||
|
|
@ -23,6 +24,7 @@ impl_from_in!(
|
|||
Hardlink(HookInOutHardlink),
|
||||
Download(HookInDownload),
|
||||
Upload(HookInUpload),
|
||||
Preload(HookInPreload),
|
||||
);
|
||||
|
||||
impl HookIn {
|
||||
|
|
@ -36,6 +38,7 @@ impl HookIn {
|
|||
Self::Hardlink(r#in) => r#in.id,
|
||||
Self::Download(r#in) => r#in.id,
|
||||
Self::Upload(r#in) => r#in.id,
|
||||
Self::Preload(r#in) => r#in.id,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +52,7 @@ impl HookIn {
|
|||
Self::Hardlink(r#in) => Self::Hardlink(HookInOutHardlink { id, ..r#in }),
|
||||
Self::Download(r#in) => Self::Download(HookInDownload { id, ..r#in }),
|
||||
Self::Upload(r#in) => Self::Upload(HookInUpload { id, ..r#in }),
|
||||
Self::Preload(r#in) => Self::Preload(HookInPreload { id, ..r#in }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,3 +214,15 @@ impl HookInUpload {
|
|||
Self { id: Id::ZERO, target: target.into() }
|
||||
}
|
||||
}
|
||||
|
||||
// --- Preload
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HookInPreload {
|
||||
pub(crate) id: Id,
|
||||
pub(crate) idx: u8,
|
||||
pub(crate) hash: u64,
|
||||
}
|
||||
|
||||
impl HookInPreload {
|
||||
pub(crate) fn new(idx: u8, hash: u64) -> Self { Self { id: Id::ZERO, idx, hash } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ impl From<PluginProgEntry> for TaskSummary {
|
|||
fn from(value: PluginProgEntry) -> Self {
|
||||
Self {
|
||||
total: 1,
|
||||
success: (value.state == Some(true)) as u32,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
success: value.success() as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use yazi_config::plugin::Preloader;
|
||||
use yazi_shared::{CompletionToken, Id};
|
||||
use yazi_shared::Id;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct PreloadIn {
|
||||
pub(crate) id: Id,
|
||||
pub(crate) plugin: &'static Preloader,
|
||||
pub(crate) target: yazi_fs::File,
|
||||
pub(crate) done: CompletionToken,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::{Task, TaskProg};
|
|||
pub(crate) enum PreloadOut {
|
||||
Succ,
|
||||
Fail(String),
|
||||
Clean,
|
||||
}
|
||||
|
||||
impl From<PreloadError> for PreloadOut {
|
||||
|
|
@ -23,6 +24,9 @@ impl PreloadOut {
|
|||
prog.state = Some(false);
|
||||
task.log(reason);
|
||||
}
|
||||
Self::Clean => {
|
||||
prog.cleaned = Some(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use tracing::error;
|
|||
use yazi_config::Priority;
|
||||
use yazi_fs::FsHash64;
|
||||
use yazi_runner::{RUNNER, preloader::{PreloadError, PreloadJob}};
|
||||
use yazi_shared::CompletionToken;
|
||||
|
||||
use crate::{HIGH, LOW, NORMAL, TaskOp, TaskOps, preload::{PreloadIn, PreloadOut}};
|
||||
|
||||
|
|
@ -17,7 +16,7 @@ pub struct Preload {
|
|||
tx: async_priority_channel::Sender<PreloadIn, u8>,
|
||||
|
||||
pub loaded: Mutex<LruCache<u64, u16>>,
|
||||
pub loading: Mutex<LruCache<u64, CompletionToken>>,
|
||||
pub loading: Mutex<LruCache<u64, yazi_shared::Id>>,
|
||||
}
|
||||
|
||||
impl Preload {
|
||||
|
|
@ -35,12 +34,7 @@ impl Preload {
|
|||
}
|
||||
|
||||
pub(crate) async fn preload(&self, task: PreloadIn) -> Result<(), PreloadOut> {
|
||||
let url_hash = task.target.url.hash_u64();
|
||||
let file_hash = task.target.hash_u64();
|
||||
|
||||
if let Some(prev) = self.loading.lock().put(url_hash, task.done) {
|
||||
prev.complete(false);
|
||||
}
|
||||
let hash = task.target.hash_u64();
|
||||
|
||||
let mut rx = RUNNER.preload(PreloadJob { action: &task.plugin.run, file: task.target }).await;
|
||||
let state = match rx.recv().await.unwrap_or(Err(PreloadError::Cancelled)) {
|
||||
|
|
@ -50,7 +44,7 @@ impl Preload {
|
|||
};
|
||||
|
||||
if !state.complete {
|
||||
self.loaded.lock().get_mut(&file_hash).map(|x| *x &= !(1 << task.plugin.idx));
|
||||
self.loaded.lock().get_mut(&hash).map(|x| *x &= !(1 << task.plugin.idx));
|
||||
}
|
||||
if let Some(e) = state.error {
|
||||
error!("Error when running preloader `{}`:\n{e}", task.plugin.run.name);
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ use crate::TaskSummary;
|
|||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct PreloadProg {
|
||||
pub state: Option<bool>,
|
||||
pub state: Option<bool>,
|
||||
pub cleaned: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<PreloadProg> for TaskSummary {
|
||||
fn from(value: PreloadProg) -> Self {
|
||||
Self {
|
||||
total: 1,
|
||||
success: (value.state == Some(true)) as u32,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
success: value.success() as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
@ -21,13 +22,13 @@ impl From<PreloadProg> for TaskSummary {
|
|||
impl PreloadProg {
|
||||
pub fn cooked(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn running(self) -> bool { self.state.is_none() }
|
||||
pub fn running(self) -> bool { self.state.is_none() || (self.cleaned.is_none() && self.cooked()) }
|
||||
|
||||
pub fn success(self) -> bool { self.cooked() }
|
||||
pub fn success(self) -> bool { self.cleaned == Some(true) && self.cooked() }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
pub fn failed(self) -> bool { self.cleaned == Some(false) || self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> Option<bool> { None }
|
||||
pub fn cleaned(self) -> Option<bool> { self.cleaned }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ pub struct ProcessProgBlock {
|
|||
impl From<ProcessProgBlock> for TaskSummary {
|
||||
fn from(value: ProcessProgBlock) -> Self {
|
||||
Self {
|
||||
total: (value.state == Some(false)) as u32,
|
||||
total: value.failed() as u32,
|
||||
success: 0,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
@ -42,9 +42,9 @@ pub struct ProcessProgOrphan {
|
|||
impl From<ProcessProgOrphan> for TaskSummary {
|
||||
fn from(value: ProcessProgOrphan) -> Self {
|
||||
Self {
|
||||
total: (value.state == Some(false)) as u32,
|
||||
total: value.failed() as u32,
|
||||
success: 0,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
@ -74,8 +74,8 @@ impl From<ProcessProgBg> for TaskSummary {
|
|||
fn from(value: ProcessProgBg) -> Self {
|
||||
Self {
|
||||
total: 1,
|
||||
success: (value.state == Some(true)) as u32,
|
||||
failed: (value.state == Some(false)) as u32,
|
||||
success: value.success() as u32,
|
||||
failed: value.failed() as u32,
|
||||
percent: value.percent().map(Into::into),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ use std::{ops::Deref, sync::Arc, time::Duration};
|
|||
use hashbrown::HashMap;
|
||||
use tokio::task::JoinHandle;
|
||||
use yazi_config::{YAZI, plugin::{Fetcher, Preloader}};
|
||||
use yazi_fs::FsHash64;
|
||||
use yazi_runner::entry::EntryJob;
|
||||
use yazi_shared::{CompletionToken, Id, SStr, Throttle, data::{Data, DataKey}, url::{UrlBuf, UrlLike}};
|
||||
|
||||
use crate::{Behavior, HIGH, LOW, NORMAL, Task, TaskProg, Worker, fetch::{FetchIn, FetchProg}, file::{FileInCopy, FileInCut, FileInDelete, FileInDownload, FileInHardlink, FileInLink, FileInTrash, FileInUpload, FileOutCopy, FileOutCut, FileOutDownload, FileOutHardlink, FileOutUpload, FileProgCopy, FileProgCut, FileProgDelete, FileProgDownload, FileProgHardlink, FileProgLink, FileProgTrash, FileProgUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInTrash, HookInUpload}, plugin::{PluginInEntry, PluginProgEntry}, preload::{PreloadIn, PreloadProg}, process::{ProcessInBg, ProcessInBlock, ProcessInOrphan, ProcessOpt, ProcessProgBg, ProcessProgBlock, ProcessProgOrphan}, size::{SizeIn, SizeProg}};
|
||||
use crate::{Behavior, HIGH, LOW, NORMAL, Task, TaskProg, Worker, fetch::{FetchIn, FetchProg}, file::{FileInCopy, FileInCut, FileInDelete, FileInDownload, FileInHardlink, FileInLink, FileInTrash, FileInUpload, FileOutCopy, FileOutCut, FileOutDownload, FileOutHardlink, FileOutUpload, FileProgCopy, FileProgCut, FileProgDelete, FileProgDownload, FileProgHardlink, FileProgLink, FileProgTrash, FileProgUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInPreload, HookInTrash, HookInUpload}, plugin::{PluginInEntry, PluginProgEntry}, preload::{PreloadIn, PreloadProg}, process::{ProcessInBg, ProcessInBlock, ProcessInOrphan, ProcessOpt, ProcessProgBg, ProcessProgBlock, ProcessProgOrphan}, size::{SizeIn, SizeProg}};
|
||||
|
||||
pub struct Scheduler {
|
||||
pub worker: Worker,
|
||||
|
|
@ -202,9 +203,14 @@ impl Scheduler {
|
|||
|
||||
pub fn preload_paged(&self, preloader: &'static Preloader, target: &yazi_fs::File) {
|
||||
let name = format!("Run preloader `{}`", preloader.run.name);
|
||||
let (id, done) = self.add::<PreloadProg, _>(name, |t| (t.id, t.done.clone()));
|
||||
let hook = HookInPreload::new(preloader.idx, target.hash_u64());
|
||||
|
||||
self.preload.submit(PreloadIn { id, plugin: preloader, target: target.clone(), done });
|
||||
let id = self.add_hooked::<PreloadProg, _>(name, hook, |t| t.id);
|
||||
if let Some(prev) = self.preload.loading.lock().put(target.url.hash_u64(), id) {
|
||||
self.cancel(prev);
|
||||
}
|
||||
|
||||
self.preload.submit(PreloadIn { id, plugin: preloader, target: target.clone() });
|
||||
}
|
||||
|
||||
pub fn prework_size(&self, targets: Vec<&UrlBuf>) {
|
||||
|
|
|
|||
|
|
@ -30,20 +30,18 @@ impl Worker {
|
|||
let (process_tx, process_rx) = async_priority_channel::unbounded();
|
||||
let (hook_tx, hook_rx) = async_priority_channel::unbounded();
|
||||
let (op_tx, op_rx) = mpsc::unbounded_channel();
|
||||
|
||||
let ongoing = Arc::new(Mutex::new(Ongoing::default()));
|
||||
let file = Arc::new(File::new(&op_tx, file_tx));
|
||||
let plugin = Arc::new(Plugin::new(&op_tx, plugin_tx));
|
||||
let fetch = Arc::new(Fetch::new(&op_tx, fetch_tx));
|
||||
let preload = Arc::new(Preload::new(&op_tx, preload_tx));
|
||||
let size = Arc::new(Size::new(&op_tx, size_tx));
|
||||
let process = Arc::new(Process::new(&op_tx, process_tx));
|
||||
let hook = Arc::new(Hook::new(&op_tx, &ongoing, &preload, hook_tx));
|
||||
|
||||
let me = Self {
|
||||
file: Arc::new(File::new(&op_tx, file_tx)),
|
||||
plugin: Arc::new(Plugin::new(&op_tx, plugin_tx)),
|
||||
fetch: Arc::new(Fetch::new(&op_tx, fetch_tx)),
|
||||
preload: Arc::new(Preload::new(&op_tx, preload_tx)),
|
||||
size: Arc::new(Size::new(&op_tx, size_tx)),
|
||||
process: Arc::new(Process::new(&op_tx, process_tx)),
|
||||
hook: Arc::new(Hook::new(&op_tx, &ongoing, hook_tx)),
|
||||
|
||||
ops: TaskOps(op_tx),
|
||||
ongoing,
|
||||
};
|
||||
let me =
|
||||
Self { file, plugin, fetch, preload, size, process, hook, ops: TaskOps(op_tx), ongoing };
|
||||
|
||||
let handles = []
|
||||
.into_iter()
|
||||
|
|
@ -270,6 +268,7 @@ impl Worker {
|
|||
HookIn::Hardlink(r#in) => self.hook.hardlink(r#in).await,
|
||||
HookIn::Download(r#in) => self.hook.download(r#in).await,
|
||||
HookIn::Upload(r#in) => self.hook.upload(r#in).await,
|
||||
HookIn::Preload(r#in) => self.hook.preload(r#in).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue