refactor: integrate tasks into scheduler (#406)

This commit is contained in:
三咲雅 · Misaki Masa 2023-11-29 01:37:06 +08:00 committed by GitHub
parent b41bea9e8f
commit 6d29420e2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 230 additions and 164 deletions

26
Cargo.lock generated
View file

@ -2554,9 +2554,7 @@ name = "yazi-core"
version = "0.1.5"
dependencies = [
"anyhow",
"async-channel",
"bitflags 2.4.1",
"clipboard-win",
"crossterm",
"futures",
"indexmap",
@ -2566,16 +2564,15 @@ dependencies = [
"ratatui",
"regex",
"serde",
"serde_json",
"syntect",
"tokio",
"tokio-stream",
"tracing",
"trash",
"unicode-width",
"yazi-adaptor",
"yazi-config",
"yazi-prebuild",
"yazi-scheduler",
"yazi-shared",
]
@ -2625,6 +2622,27 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "394457709d77af570fcb3c0ef878336213b4e9c8f298eccde728aecd602aa7e0"
[[package]]
name = "yazi-scheduler"
version = "0.1.5"
dependencies = [
"anyhow",
"async-channel",
"clipboard-win",
"futures",
"libc",
"parking_lot",
"regex",
"serde",
"serde_json",
"tokio",
"tracing",
"trash",
"yazi-adaptor",
"yazi-config",
"yazi-shared",
]
[[package]]
name = "yazi-shared"
version = "0.1.5"

View file

@ -9,13 +9,13 @@ homepage = "https://yazi-rs.github.io"
repository = "https://github.com/sxyazi/yazi"
[dependencies]
yazi-adaptor = { path = "../yazi-adaptor", version = "0.1.5" }
yazi-config = { path = "../yazi-config", version = "0.1.5" }
yazi-shared = { path = "../yazi-shared", version = "0.1.5" }
yazi-adaptor = { path = "../yazi-adaptor", version = "0.1.5" }
yazi-config = { path = "../yazi-config", version = "0.1.5" }
yazi-scheduler = { path = "../yazi-scheduler", version = "0.1.5" }
yazi-shared = { path = "../yazi-shared", version = "0.1.5" }
# External dependencies
anyhow = "^1"
async-channel = "^1"
bitflags = "^2"
crossterm = "^0"
futures = "^0"
@ -26,16 +26,11 @@ parking_lot = "^0"
ratatui = "^0"
regex = "^1"
serde = "^1"
serde_json = "^1"
syntect = { version = "^5", default-features = false, features = [ "parsing", "default-themes", "plist-load", "regex-onig" ] }
tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "time", "fs", "process", "io-std", "io-util" ] }
tokio-stream = "^0"
trash = "^3"
unicode-width = "^0"
yazi-prebuild = "^0"
# Logging
tracing = { version = "^0", features = [ "max_level_debug", "release_max_level_warn" ] }
[target."cfg(windows)".dependencies]
clipboard-win = "^4"

View file

@ -1,7 +1,5 @@
use ratatui::prelude::Rect;
use tokio::sync::oneshot;
use yazi_config::popup::{Origin, Position};
use yazi_shared::{emit, event::Exec, Layer};
use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which};
@ -29,19 +27,10 @@ impl Ctx {
}
#[inline]
pub async fn stop() {
let (tx, rx) = oneshot::channel::<()>();
emit!(Call(Exec::call("stop", vec!["true".to_string()]).with_data(Some(tx)).vec(), Layer::App));
rx.await.ok();
}
pub async fn stop() { yazi_scheduler::Scheduler::app_stop().await }
#[inline]
pub fn resume() {
emit!(Call(
Exec::call("stop", vec!["false".to_string()]).with_data(None::<oneshot::Sender<()>>).vec(),
Layer::App
));
}
pub fn resume() { yazi_scheduler::Scheduler::app_resume() }
pub fn area(&self, position: &Position) -> Rect {
if position.origin != Origin::Hovered {

View file

@ -3,7 +3,7 @@ use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, sync::atomic::Orde
use anyhow::Result;
use tokio::{fs, select, sync::mpsc::{self, UnboundedReceiver}};
use yazi_config::{manager::SortBy, MANAGER};
use yazi_shared::{files::{File, FILES_TICKET}, fs::Url};
use yazi_shared::fs::{File, Url, FILES_TICKET};
use super::FilesSorter;

View file

@ -1,7 +1,7 @@
use std::{cmp::Ordering, collections::BTreeMap, mem};
use yazi_config::manager::SortBy;
use yazi_shared::{files::File, fs::Url, natsort};
use yazi_shared::{fs::File, fs::Url, natsort};
#[derive(Clone, Copy, Default, PartialEq)]
pub struct FilesSorter {

View file

@ -1,6 +1,7 @@
use yazi_scheduler::external;
use yazi_shared::event::Exec;
use crate::{external, input::{op::InputOp, Input}};
use crate::input::{op::InputOp, Input};
pub struct Opt {
before: bool,

View file

@ -3,10 +3,10 @@ use std::ops::Range;
use tokio::sync::mpsc::UnboundedSender;
use unicode_width::UnicodeWidthStr;
use yazi_config::{popup::Position, INPUT};
use yazi_scheduler::external;
use yazi_shared::InputError;
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
use crate::external;
#[derive(Default)]
pub struct Input {

View file

@ -6,10 +6,8 @@
clippy::unit_arg
)]
mod blocker;
pub mod completion;
mod context;
pub mod external;
pub mod files;
pub mod help;
mod highlighter;
@ -22,9 +20,8 @@ pub mod tab;
pub mod tasks;
pub mod which;
pub use blocker::*;
pub use context::*;
pub use highlighter::*;
pub use step::*;
pub fn init() { init_blocker(); }
pub fn init() { yazi_scheduler::init(); }

View file

@ -2,7 +2,7 @@ use std::path::{PathBuf, MAIN_SEPARATOR};
use tokio::fs;
use yazi_config::popup::InputCfg;
use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::Url};
use yazi_shared::{emit, event::Exec, fs::{File, FilesOp}, fs::Url};
use crate::{input::Input, manager::Manager};

View file

@ -1,9 +1,10 @@
use std::ffi::OsString;
use yazi_config::{popup::SelectCfg, OPEN};
use yazi_scheduler::external;
use yazi_shared::{event::Exec, MIME_DIR};
use crate::{external, manager::Manager, select::Select, tasks::Tasks};
use crate::{manager::Manager, select::Select, tasks::Tasks};
pub struct Opt {
interactive: bool,

View file

@ -3,9 +3,10 @@ use std::{collections::BTreeMap, ffi::OsStr, io::{stdout, BufWriter, Write}, pat
use anyhow::{anyhow, bail, Result};
use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}};
use yazi_config::{popup::InputCfg, OPEN, PREVIEW};
use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::{max_common_root, Url}, term::Term, Defer};
use yazi_scheduler::{external::{self, ShellOpt}, BLOCKER};
use yazi_shared::{emit, event::Exec, fs::{max_common_root, File, FilesOp, Url}, term::Term, Defer};
use crate::{external::{self, ShellOpt}, input::Input, manager::Manager, Ctx, BLOCKER};
use crate::{input::Input, manager::Manager, Ctx};
pub struct Opt {
force: bool,

View file

@ -1,6 +1,6 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use yazi_shared::{files::{File, FilesOp}, fs::Url};
use yazi_shared::{fs::{File, FilesOp}, fs::Url};
use super::{Tabs, Watcher};
use crate::{tab::{Folder, Tab}, tasks::Tasks};

View file

@ -5,9 +5,10 @@ use notify::{event::{MetadataKind, ModifyKind}, EventKind, RecommendedWatcher, R
use parking_lot::RwLock;
use tokio::{fs, pin, sync::mpsc::{self, UnboundedReceiver}};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
use yazi_shared::{emit, files::{File, FilesOp}, fs::Url};
use yazi_scheduler::external;
use yazi_shared::{emit, fs::{File, FilesOp, Url}};
use crate::{external, files::Files};
use crate::files::Files;
pub struct Watcher {
watcher: RecommendedWatcher,

View file

@ -4,7 +4,7 @@ use tokio::{pin, task::JoinHandle};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
use yazi_adaptor::ADAPTOR;
use yazi_config::MANAGER;
use yazi_shared::{emit, event::{PreviewData, PreviewLock}, files::FilesOp, fs::{Cha, Url}, MimeKind, PeekError};
use yazi_shared::{emit, event::{PreviewData, PreviewLock}, fs::{Cha, FilesOp, Url}, MimeKind, PeekError};
use super::Provider;
use crate::{files::Files, manager::Manager, Highlighter};

View file

@ -3,9 +3,10 @@ use std::path::Path;
use tokio::fs;
use yazi_adaptor::ADAPTOR;
use yazi_config::{MANAGER, PREVIEW};
use yazi_scheduler::external;
use yazi_shared::{event::PreviewData, MimeKind, PeekError};
use crate::{external, Highlighter};
use crate::Highlighter;
pub(super) struct Provider;

View file

@ -1,8 +1,9 @@
use std::ffi::{OsStr, OsString};
use yazi_scheduler::external;
use yazi_shared::event::Exec;
use crate::{external, tab::Tab};
use crate::tab::Tab;
pub struct Opt<'a> {
type_: &'a str,

View file

@ -1,6 +1,7 @@
use yazi_scheduler::{external::{self, FzfOpt, ZoxideOpt}, BLOCKER};
use yazi_shared::{event::Exec, fs::ends_with_slash, Defer};
use crate::{external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Ctx, BLOCKER};
use crate::{tab::Tab, Ctx};
pub struct Opt {
type_: OptType,

View file

@ -1,4 +1,4 @@
use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::{expand_path, Url}, Layer};
use yazi_shared::{emit, event::Exec, fs::{File, FilesOp}, fs::{expand_path, Url}, Layer};
use crate::{manager::Manager, tab::Tab};

View file

@ -4,9 +4,10 @@ use anyhow::bail;
use tokio::pin;
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
use yazi_config::popup::InputCfg;
use yazi_shared::{emit, event::Exec, files::FilesOp};
use yazi_scheduler::external;
use yazi_shared::{emit, event::Exec, fs::FilesOp};
use crate::{external, input::Input, manager::Manager, tab::Tab};
use crate::{input::Input, manager::Manager, tab::Tab};
pub struct Opt {
pub type_: OptType,

View file

@ -1,6 +1,6 @@
use ratatui::layout::Rect;
use yazi_config::MANAGER;
use yazi_shared::{emit, files::{File, FilesOp}, fs::Url};
use yazi_shared::{emit, fs::{File, FilesOp}, fs::Url};
use crate::{files::Files, Step};

View file

@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::BTreeMap};
use anyhow::Result;
use tokio::task::JoinHandle;
use yazi_shared::{event::PreviewLock, files::File, fs::Url};
use yazi_shared::{event::PreviewLock, fs::File, fs::Url};
use super::{Backstack, Config, Finder, Folder, Mode};
use crate::preview::Preview;

View file

@ -2,9 +2,10 @@ use std::io::{stdout, Write};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time};
use yazi_scheduler::BLOCKER;
use yazi_shared::{event::Exec, term::Term, Defer};
use crate::{tasks::Tasks, Ctx, BLOCKER};
use crate::{tasks::Tasks, Ctx};
pub struct Opt;

View file

@ -1,13 +1,8 @@
mod commands;
mod running;
mod scheduler;
mod task;
mod progress;
mod tasks;
mod workers;
use running::*;
use scheduler::*;
use task::*;
pub use progress::*;
pub use tasks::*;
pub const TASKS_PADDING: u16 = 2;

View file

@ -0,0 +1,31 @@
use serde::Serialize;
use yazi_scheduler::Running;
#[derive(Clone, Copy, Default, Eq, PartialEq, Serialize)]
pub struct TasksProgress {
pub total: u32,
pub succ: u32,
pub fail: u32,
pub found: u64,
pub processed: u64,
}
impl From<&Running> for TasksProgress {
fn from(running: &Running) -> Self {
let mut progress = Self::default();
if running.is_empty() {
return progress;
}
for task in running.values() {
progress.total += task.total;
progress.succ += task.succ;
progress.fail += task.fail;
progress.found += task.found;
progress.processed += task.processed;
}
progress
}
}

View file

@ -1,11 +1,12 @@
use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::Path, sync::Arc};
use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::Path, sync::Arc, time::Duration};
use serde::Serialize;
use tokio::time::sleep;
use tracing::debug;
use yazi_config::{manager::SortBy, open::Opener, popup::InputCfg, OPEN};
use yazi_shared::{files::File, fs::Url, term::Term, MimeKind};
use yazi_scheduler::{Scheduler, TaskSummary};
use yazi_shared::{fs::{File, Url}, term::Term, MimeKind};
use super::{running::Running, task::TaskSummary, Scheduler, TASKS_PADDING, TASKS_PERCENT};
use super::{TasksProgress, TASKS_PADDING, TASKS_PERCENT};
use crate::{files::Files, input::Input};
pub struct Tasks {
@ -18,12 +19,28 @@ pub struct Tasks {
impl Tasks {
pub fn start() -> Self {
Self {
let tasks = Self {
scheduler: Arc::new(Scheduler::start()),
visible: false,
cursor: 0,
progress: Default::default(),
}
};
let running = tasks.scheduler.running.clone();
tokio::spawn(async move {
let mut last = TasksProgress::default();
loop {
sleep(Duration::from_millis(500)).await;
let new = TasksProgress::from(&*running.read());
if last != new {
last = new;
Tasks::_update(new);
}
}
});
tasks
}
#[inline]
@ -209,32 +226,3 @@ impl Tasks {
#[inline]
pub fn len(&self) -> usize { self.scheduler.running.read().len() }
}
#[derive(Clone, Copy, Default, Eq, PartialEq, Serialize)]
pub struct TasksProgress {
pub total: u32,
pub succ: u32,
pub fail: u32,
pub found: u64,
pub processed: u64,
}
impl From<&Running> for TasksProgress {
fn from(running: &Running) -> Self {
let mut progress = Self::default();
if running.is_empty() {
return progress;
}
for task in running.values() {
progress.total += task.total;
progress.succ += task.succ;
progress.fail += task.fail;
progress.found += task.found;
progress.processed += task.processed;
}
progress
}
}

View file

@ -5,7 +5,7 @@ use crossterm::event::KeyEvent;
use ratatui::{backend::Backend, prelude::Rect};
use yazi_config::{keymap::Key, BOOT};
use yazi_core::{input::InputMode, preview::COLLISION, Ctx};
use yazi_shared::{emit, event::{Event, Exec}, files::FilesOp, term::Term, Layer};
use yazi_shared::{emit, event::{Event, Exec}, fs::FilesOp, term::Term, Layer};
use crate::{Executor, Logs, Panic, Root, Signals};

View file

@ -104,7 +104,7 @@ impl<'a, 'b> Active<'a, 'b> {
fn file(
&self,
idx: usize,
inner: &'a yazi_shared::files::File,
inner: &'a yazi_shared::fs::File,
folder: &'a yazi_core::tab::Folder,
) -> mlua::Result<AnyUserData<'a>> {
let ud = self.scope.create_any_userdata_ref(inner)?;

View file

@ -6,10 +6,10 @@ use yazi_config::THEME;
use super::{Range, Url};
use crate::{layout::Style, LUA};
pub struct File(yazi_shared::files::File);
pub struct File(yazi_shared::fs::File);
impl From<&yazi_shared::files::File> for File {
fn from(value: &yazi_shared::files::File) -> Self { Self(value.clone()) }
impl From<&yazi_shared::fs::File> for File {
fn from(value: &yazi_shared::fs::File) -> Self { Self(value.clone()) }
}
impl UserData for File {
@ -47,7 +47,7 @@ impl Files {
});
})?;
LUA.register_userdata_type::<yazi_shared::files::File>(|reg| {
LUA.register_userdata_type::<yazi_shared::fs::File>(|reg| {
reg.add_field_method_get("url", |_, me| Ok(Url::from(&me.url)));
reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from)));
reg.add_field_method_get("is_link", |_, me| Ok(me.is_link()));
@ -87,7 +87,7 @@ impl Files {
Ok(me.url.file_name().map(|n| n.to_string_lossy().to_string()))
});
reg.add_function("size", |_, me: AnyUserData| {
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
if !file.is_dir() {
return Ok(Some(file.len));
}
@ -97,7 +97,7 @@ impl Files {
});
reg.add_function("mime", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<yazi_core::manager::Manager>>("manager")?;
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
Ok(manager.mimetype.get(&file.url).cloned())
});
reg.add_function("prefix", |_, me: AnyUserData| {
@ -106,7 +106,7 @@ impl Files {
return Ok(None);
}
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
let mut p = file.url.strip_prefix(&folder.cwd).unwrap_or(&file.url).components();
p.next_back();
Ok(Some(p.as_path().to_string_lossy().to_string()))
@ -122,7 +122,7 @@ impl Files {
});
reg.add_function("style", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<yazi_core::manager::Manager>>("manager")?;
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
let mime = manager.mimetype.get(&file.url);
Ok(
THEME
@ -134,12 +134,12 @@ impl Files {
});
reg.add_function("is_hovered", |_, me: AnyUserData| {
let folder = me.named_user_value::<UserDataRef<yazi_core::tab::Folder>>("folder")?;
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
Ok(matches!(folder.hovered(), Some(f) if f.url == file.url))
});
reg.add_function("is_yanked", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<yazi_core::manager::Manager>>("manager")?;
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
Ok(if !manager.yanked.1.contains(&file.url) {
0u8
} else if manager.yanked.0 {
@ -151,7 +151,7 @@ impl Files {
reg.add_function("is_selected", |_, me: AnyUserData| {
let manager = me.named_user_value::<UserDataRef<yazi_core::manager::Manager>>("manager")?;
let folder = me.named_user_value::<UserDataRef<yazi_core::tab::Folder>>("folder")?;
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
let selected = folder.files.is_selected(&file.url);
Ok(if !manager.active().mode.is_visual() {
@ -167,7 +167,7 @@ impl Files {
return Ok(None);
};
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
if let Some(idx) = finder.matched_idx(&file.url) {
return Some(
lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?]),
@ -182,7 +182,7 @@ impl Files {
return Ok(None);
};
let file = me.borrow::<yazi_shared::files::File>()?;
let file = me.borrow::<yazi_shared::fs::File>()?;
let Some(h) = file.name().and_then(|n| finder.highlighted(n)) else {
return Ok(None);
};

32
yazi-scheduler/Cargo.toml Normal file
View file

@ -0,0 +1,32 @@
[package]
name = "yazi-scheduler"
version = "0.1.5"
edition = "2021"
license = "MIT"
authors = [ "sxyazi <sxyazi@gmail.com>" ]
description = "Yazi task scheduler"
homepage = "https://yazi-rs.github.io"
repository = "https://github.com/sxyazi/yazi"
[dependencies]
yazi-adaptor = { path = "../yazi-adaptor", version = "0.1.5" }
yazi-config = { path = "../yazi-config", version = "0.1.5" }
yazi-shared = { path = "../yazi-shared", version = "0.1.5" }
# External dependencies
anyhow = "^1"
async-channel = "^1"
futures = "^0"
libc = "^0"
parking_lot = "^0"
regex = "^1"
serde = "^1"
serde_json = "^1"
tokio = { version = "^1", features = [ "parking_lot", "rt-multi-thread" ] }
trash = "^3"
# Logging
tracing = { version = "^0", features = [ "max_level_debug", "release_max_level_warn" ] }
[target."cfg(windows)".dependencies]
clipboard-win = "^4"

View file

@ -2,7 +2,7 @@ use std::process::Stdio;
use anyhow::Result;
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}};
use yazi_shared::{files::File, fs::Url};
use yazi_shared::fs::{File, Url};
pub struct FdOpt {
pub cwd: Url,

View file

@ -2,7 +2,7 @@ use std::process::Stdio;
use anyhow::Result;
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}};
use yazi_shared::{files::File, fs::Url};
use yazi_shared::fs::{File, Url};
pub struct RgOpt {
pub cwd: Url,

15
yazi-scheduler/src/lib.rs Normal file
View file

@ -0,0 +1,15 @@
#![allow(clippy::unit_arg)]
mod blocker;
pub mod external;
mod running;
mod scheduler;
mod task;
pub mod workers;
pub use blocker::*;
pub use running::*;
pub use scheduler::*;
pub use task::*;
pub fn init() { init_blocker(); }

View file

@ -5,7 +5,7 @@ use futures::future::BoxFuture;
use super::{Task, TaskStage};
#[derive(Default)]
pub(super) struct Running {
pub struct Running {
incr: usize,
pub(super) hooks:
@ -21,25 +21,25 @@ impl Running {
}
#[inline]
pub(super) fn get(&self, id: usize) -> Option<&Task> { self.all.get(&id) }
pub fn get(&self, id: usize) -> Option<&Task> { self.all.get(&id) }
#[inline]
pub(super) fn get_mut(&mut self, id: usize) -> Option<&mut Task> { self.all.get_mut(&id) }
pub fn get_mut(&mut self, id: usize) -> Option<&mut Task> { self.all.get_mut(&id) }
#[inline]
pub(super) fn get_id(&self, idx: usize) -> Option<usize> { self.values().nth(idx).map(|t| t.id) }
pub fn get_id(&self, idx: usize) -> Option<usize> { self.values().nth(idx).map(|t| t.id) }
#[inline]
pub(super) fn len(&self) -> usize { self.all.len() }
pub fn len(&self) -> usize { self.all.len() }
#[inline]
pub(super) fn exists(&self, id: usize) -> bool { self.all.contains_key(&id) }
#[inline]
pub(super) fn values(&self) -> impl Iterator<Item = &Task> { self.all.values() }
pub fn values(&self) -> impl Iterator<Item = &Task> { self.all.values() }
#[inline]
pub(super) fn is_empty(&self) -> bool { self.all.is_empty() }
pub fn is_empty(&self) -> bool { self.all.is_empty() }
pub(super) fn try_remove(
&mut self,

View file

@ -2,25 +2,25 @@ use std::{ffi::OsStr, sync::Arc, time::Duration};
use futures::{future::BoxFuture, FutureExt};
use parking_lot::RwLock;
use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}, time::sleep};
use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}};
use yazi_config::{open::Opener, TASKS};
use yazi_shared::{fs::{unique_path, Url}, Throttle};
use yazi_shared::{emit, event::Exec, fs::{unique_path, Url}, Layer, Throttle};
use super::{workers::{File, FileOpDelete, FileOpLink, FileOpPaste, FileOpTrash, Precache, PrecacheOpMime, PrecacheOpSize, Process, ProcessOpOpen}, Running, TaskOp, TaskStage, TasksProgress};
use crate::tasks::Tasks;
use super::{Running, TaskOp, TaskStage};
use crate::workers::{File, FileOpDelete, FileOpLink, FileOpPaste, FileOpTrash, Precache, PrecacheOpMime, PrecacheOpSize, Process, ProcessOpOpen};
pub struct Scheduler {
file: Arc<File>,
precache: Arc<Precache>,
process: Arc<Process>,
todo: async_channel::Sender<BoxFuture<'static, ()>>,
prog: mpsc::UnboundedSender<TaskOp>,
pub(super) running: Arc<RwLock<Running>>,
todo: async_channel::Sender<BoxFuture<'static, ()>>,
prog: mpsc::UnboundedSender<TaskOp>,
pub running: Arc<RwLock<Running>>,
}
impl Scheduler {
pub(super) fn start() -> Self {
pub fn start() -> Self {
let (todo_tx, todo_rx) = async_channel::unbounded();
let (prog_tx, prog_rx) = mpsc::unbounded_channel();
@ -147,23 +147,9 @@ impl Scheduler {
}
}
});
let running = self.running.clone();
tokio::spawn(async move {
let mut last = TasksProgress::default();
loop {
sleep(Duration::from_millis(500)).await;
let new = TasksProgress::from(&*running.read());
if last != new {
last = new;
Tasks::_update(new);
}
}
});
}
pub(super) fn cancel(&self, id: usize) -> bool {
pub fn cancel(&self, id: usize) -> bool {
let mut running = self.running.write();
let b = running.all.remove(&id).is_some();
@ -173,7 +159,20 @@ impl Scheduler {
b
}
pub(super) fn file_cut(&self, from: Url, mut to: Url, force: bool) {
pub async fn app_stop() {
let (tx, rx) = oneshot::channel::<()>();
emit!(Call(Exec::call("stop", vec!["true".to_string()]).with_data(Some(tx)).vec(), Layer::App));
rx.await.ok();
}
pub fn app_resume() {
emit!(Call(
Exec::call("stop", vec!["false".to_string()]).with_data(None::<oneshot::Sender<()>>).vec(),
Layer::App
));
}
pub fn file_cut(&self, from: Url, mut to: Url, force: bool) {
let mut running = self.running.write();
let id = running.add(format!("Cut {:?} to {:?}", from, to));
@ -204,7 +203,7 @@ impl Scheduler {
});
}
pub(super) fn file_copy(&self, from: Url, mut to: Url, force: bool) {
pub fn file_copy(&self, from: Url, mut to: Url, force: bool) {
let name = format!("Copy {:?} to {:?}", from, to);
let id = self.running.write().add(name);
@ -220,7 +219,7 @@ impl Scheduler {
});
}
pub(super) fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) {
pub fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) {
let name = format!("Link {from:?} to {to:?}");
let id = self.running.write().add(name);
@ -239,7 +238,7 @@ impl Scheduler {
});
}
pub(super) fn file_delete(&self, target: Url) {
pub fn file_delete(&self, target: Url) {
let mut running = self.running.write();
let id = running.add(format!("Delete {:?}", target));
@ -267,7 +266,7 @@ impl Scheduler {
});
}
pub(super) fn file_trash(&self, target: Url) {
pub fn file_trash(&self, target: Url) {
let name = format!("Trash {:?}", target);
let id = self.running.write().add(name);
@ -280,7 +279,7 @@ impl Scheduler {
});
}
pub(super) fn process_open(&self, opener: &Opener, args: &[impl AsRef<OsStr>]) {
pub fn process_open(&self, opener: &Opener, args: &[impl AsRef<OsStr>]) {
let name = {
let s = format!("Execute `{}`", opener.exec);
let args = args.iter().map(|a| a.as_ref().to_string_lossy()).collect::<Vec<_>>().join(" ");
@ -324,7 +323,7 @@ impl Scheduler {
});
}
pub(super) fn precache_size(&self, targets: Vec<&Url>) {
pub fn precache_size(&self, targets: Vec<&Url>) {
let throttle = Arc::new(Throttle::new(targets.len(), Duration::from_millis(300)));
let mut handing = self.precache.size_handing.lock();
let mut running = self.running.write();
@ -349,7 +348,7 @@ impl Scheduler {
}
}
pub(super) fn precache_mime(&self, targets: Vec<Url>) {
pub fn precache_mime(&self, targets: Vec<Url>) {
let name = format!("Preload mimetype for {} files", targets.len());
let id = self.running.write().add(name);
@ -362,21 +361,21 @@ impl Scheduler {
});
}
pub(super) fn precache_image(&self, targets: Vec<Url>) {
pub fn precache_image(&self, targets: Vec<Url>) {
let name = format!("Precache of {} image files", targets.len());
let id = self.running.write().add(name);
self.precache.image(id, targets).ok();
}
pub(super) fn precache_video(&self, targets: Vec<Url>) {
pub fn precache_video(&self, targets: Vec<Url>) {
let name = format!("Precache of {} video files", targets.len());
let id = self.running.write().add(name);
self.precache.video(id, targets).ok();
}
pub(super) fn precache_pdf(&self, targets: Vec<Url>) {
pub fn precache_pdf(&self, targets: Vec<Url>) {
let name = format!("Precache of {} PDF files", targets.len());
let id = self.running.write().add(name);

View file

@ -7,7 +7,7 @@ use tracing::warn;
use yazi_config::TASKS;
use yazi_shared::fs::{calculate_size, copy_with_progress, path_relative_to, Url};
use crate::tasks::TaskOp;
use crate::TaskOp;
pub(crate) struct File {
tx: async_channel::Sender<FileOp>,

View file

@ -5,9 +5,9 @@ use parking_lot::Mutex;
use tokio::{fs, sync::mpsc};
use yazi_adaptor::Image;
use yazi_config::PREVIEW;
use yazi_shared::{emit, files::FilesOp, fs::{calculate_size, Url}, Throttle};
use yazi_shared::{emit, fs::{calculate_size, FilesOp, Url}, Throttle};
use crate::{external, tasks::TaskOp};
use crate::{external, TaskOp};
pub(crate) struct Precache {
tx: async_channel::Sender<PrecacheOp>,

View file

@ -3,7 +3,7 @@ use std::{ffi::OsString, mem};
use anyhow::Result;
use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}};
use crate::{external::{self, ShellOpt}, tasks::TaskOp, Ctx, BLOCKER};
use crate::{external::{self, ShellOpt}, Scheduler, TaskOp, BLOCKER};
pub(crate) struct Process {
sch: mpsc::UnboundedSender<TaskOp>,
@ -37,7 +37,7 @@ impl Process {
let opt = ShellOpt::from(&mut task);
if task.block {
let _guard = BLOCKER.acquire().await.unwrap();
Ctx::stop().await;
Scheduler::app_stop().await;
match external::shell(opt) {
Ok(mut child) => {
@ -49,7 +49,7 @@ impl Process {
self.fail(task.id, format!("Failed to spawn process: {e}"))?;
}
}
return Ok(Ctx::resume());
return Ok(Scheduler::app_resume());
}
if task.orphan {

View file

@ -4,7 +4,7 @@ use crossterm::event::KeyEvent;
use tokio::sync::{mpsc::UnboundedSender, oneshot};
use super::Exec;
use crate::{files::FilesOp, fs::{Cha, Url}, term::Term, Layer, RoCell};
use crate::{fs::{Cha, FilesOp, Url}, term::Term, Layer, RoCell};
static TX: RoCell<UnboundedSender<Event>> = RoCell::new();

View file

@ -1,5 +0,0 @@
mod file;
mod op;
pub use file::*;
pub use op::*;

View file

@ -1,9 +1,13 @@
mod cha;
mod file;
mod fns;
mod op;
mod path;
mod url;
pub use cha::*;
pub use file::*;
pub use fns::*;
pub use op::*;
pub use path::*;
pub use url::*;

View file

@ -6,7 +6,6 @@ mod defer;
mod env;
mod errors;
pub mod event;
pub mod files;
pub mod fs;
mod layer;
mod mime;