yazi_core/tasks/
tasks.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use std::{sync::Arc, time::Duration};

use parking_lot::Mutex;
use tokio::{task::JoinHandle, time::sleep};
use yazi_adapter::Dimension;
use yazi_macro::emit;
use yazi_scheduler::{Ongoing, Scheduler, TaskSummary};
use yazi_shared::{Layer, event::Cmd};

use super::{TASKS_BORDER, TASKS_PADDING, TASKS_PERCENT, TasksProgress};

pub struct Tasks {
	pub(super) scheduler: Arc<Scheduler>,
	handle:               JoinHandle<()>,

	pub visible:   bool,
	pub cursor:    usize,
	pub progress:  TasksProgress,
	pub summaries: Vec<TaskSummary>,
}

impl Tasks {
	pub fn serve() -> Self {
		let scheduler = Scheduler::serve();
		let ongoing = scheduler.ongoing.clone();

		let handle = tokio::spawn(async move {
			let mut last = TasksProgress::default();
			loop {
				sleep(Duration::from_millis(500)).await;

				let new = TasksProgress::from(&*ongoing.lock());
				if last != new {
					last = new;
					emit!(Call(Cmd::new("update_progress").with_any("progress", new), Layer::App));
				}
			}
		});

		Self {
			scheduler: Arc::new(scheduler),
			handle,

			visible: false,
			cursor: 0,
			progress: Default::default(),
			summaries: Default::default(),
		}
	}

	pub fn shutdown(&self) {
		self.scheduler.shutdown();
		self.handle.abort();
	}

	#[inline]
	pub fn limit() -> usize {
		(Dimension::available().rows * TASKS_PERCENT / 100).saturating_sub(TASKS_BORDER + TASKS_PADDING)
			as usize
	}

	pub fn paginate(&self) -> Vec<TaskSummary> {
		self.ongoing().lock().values().take(Self::limit()).map(Into::into).collect()
	}

	#[inline]
	pub fn ongoing(&self) -> &Arc<Mutex<Ongoing>> { &self.scheduler.ongoing }
}