diff --git a/adaptor/src/adaptor.rs b/adaptor/src/adaptor.rs index bcce22f2..fde84ada 100644 --- a/adaptor/src/adaptor.rs +++ b/adaptor/src/adaptor.rs @@ -1,7 +1,7 @@ use std::{path::{Path, PathBuf}, sync::atomic::{AtomicBool, Ordering}}; use anyhow::Result; -use config::{preview::PreviewAdaptor, BOOT, PREVIEW}; +use config::{preview::PreviewAdaptor, PREVIEW}; use ratatui::prelude::Rect; use shared::RoCell; use tokio::{fs, sync::mpsc::UnboundedSender}; @@ -19,7 +19,7 @@ pub struct Adaptor; impl Adaptor { pub async fn image_show(mut path: &Path, rect: Rect) -> Result<()> { - let cache = BOOT.cache(path, 0); + let cache = PREVIEW.cache(path, 0); if fs::metadata(&cache).await.is_ok() { path = cache.as_path(); } diff --git a/config/docs/yazi.md b/config/docs/yazi.md index 1e221f4b..7e6f4255 100644 --- a/config/docs/yazi.md +++ b/config/docs/yazi.md @@ -39,6 +39,7 @@ - tab_size: Tab width - max_width: Maximum preview width for images and videos - max_height: Maximum preview height for images and videos +- cache_dir: The system cache directory is used by default, and the cached files will go away on a reboot automatically. If you want to make it more persistent, you can specify the cache directory manually as an absolute path. ## opener diff --git a/config/preset/yazi.toml b/config/preset/yazi.toml index 981b9722..12f9483c 100644 --- a/config/preset/yazi.toml +++ b/config/preset/yazi.toml @@ -10,6 +10,7 @@ show_symlink = true tab_size = 2 max_width = 600 max_height = 900 +cache_dir = "" [opener] folder = [ diff --git a/config/src/boot/boot.rs b/config/src/boot/boot.rs index 982a1826..357956a0 100644 --- a/config/src/boot/boot.rs +++ b/config/src/boot/boot.rs @@ -1,15 +1,13 @@ -use std::{env, fs, path::{Path, PathBuf}, process, time::{self, SystemTime}}; +use std::{env, fs, path::PathBuf, process}; use clap::{command, Parser}; -use md5::{Digest, Md5}; use shared::absolute_path; -use crate::Xdg; +use crate::{Xdg, PREVIEW}; #[derive(Debug)] pub struct Boot { pub cwd: PathBuf, - pub cache_dir: PathBuf, pub state_dir: PathBuf, pub cwd_file: Option, @@ -43,46 +41,37 @@ impl Default for Boot { let cwd = args .cwd .map(|p| futures::executor::block_on(absolute_path(p))) - .and_then(|p| p.is_dir().then_some(p)) + .filter(|p| p.is_dir()) .or_else(|| env::current_dir().ok()); let boot = Self { cwd: cwd.unwrap_or("/".into()), - cache_dir: env::temp_dir().join("yazi"), state_dir: Xdg::state_dir().unwrap(), cwd_file: args.cwd_file, chooser_file: args.chooser_file, }; - if !boot.cache_dir.is_dir() { - fs::create_dir(&boot.cache_dir).unwrap(); - } if !boot.state_dir.is_dir() { fs::create_dir_all(&boot.state_dir).unwrap(); } + if !PREVIEW.cache_dir.is_dir() { + fs::create_dir(&PREVIEW.cache_dir).unwrap(); + } if args.clear_cache { - println!("Clearing cache directory: {:?}", boot.cache_dir); - fs::remove_dir_all(&boot.cache_dir).unwrap(); + if PREVIEW.cache_dir == Xdg::cache_dir() { + println!("Clearing cache directory: \n{:?}", PREVIEW.cache_dir); + fs::remove_dir_all(&PREVIEW.cache_dir).unwrap(); + } else { + println!( + "You've changed the default cache directory, for your data's safety, please clear it manually: \n{:?}", + PREVIEW.cache_dir + ); + } process::exit(0); } boot } } - -impl Boot { - #[inline] - pub fn cache(&self, path: &Path, skip: usize) -> PathBuf { - self - .cache_dir - .join(format!("{:x}", Md5::new_with_prefix(format!("{:?}///{}", path, skip)).finalize())) - } - - #[inline] - pub fn tmpfile(&self, prefix: &str) -> PathBuf { - let nanos = SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().as_nanos(); - self.cache_dir.join(format!("{prefix}-{}", nanos / 1000)) - } -} diff --git a/config/src/lib.rs b/config/src/lib.rs index 12cc0ce9..5e6086c5 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -23,7 +23,6 @@ static MERGED_KEYMAP: RoCell = RoCell::new(); static MERGED_THEME: RoCell = RoCell::new(); static MERGED_YAZI: RoCell = RoCell::new(); -pub static BOOT: RoCell = RoCell::new(); pub static KEYMAP: RoCell = RoCell::new(); pub static LOG: RoCell = RoCell::new(); pub static MANAGER: RoCell = RoCell::new(); @@ -32,12 +31,13 @@ pub static PREVIEW: RoCell = RoCell::new(); pub static TASKS: RoCell = RoCell::new(); pub static THEME: RoCell = RoCell::new(); +pub static BOOT: RoCell = RoCell::new(); + pub fn init() { MERGED_KEYMAP.with(Preset::keymap); MERGED_THEME.with(Preset::theme); MERGED_YAZI.with(Preset::yazi); - BOOT.with(Default::default); KEYMAP.with(Default::default); LOG.with(Default::default); MANAGER.with(Default::default); @@ -45,4 +45,6 @@ pub fn init() { PREVIEW.with(Default::default); TASKS.with(Default::default); THEME.with(Default::default); + + BOOT.with(Default::default); } diff --git a/config/src/preview/preview.rs b/config/src/preview/preview.rs index 80058a4d..37775f03 100644 --- a/config/src/preview/preview.rs +++ b/config/src/preview/preview.rs @@ -1,26 +1,65 @@ +use std::{path::{Path, PathBuf}, time::{self, SystemTime}}; + +use md5::{Digest, Md5}; use serde::Deserialize; use super::PreviewAdaptor; -use crate::MERGED_YAZI; +use crate::{xdg::Xdg, MERGED_YAZI}; -#[derive(Debug, Deserialize)] +#[derive(Debug)] pub struct Preview { - #[serde(skip)] - pub adaptor: PreviewAdaptor, - pub tab_size: u32, + pub adaptor: PreviewAdaptor, + pub tab_size: u32, pub max_width: u32, pub max_height: u32, + + pub cache_dir: PathBuf, } impl Default for Preview { fn default() -> Self { #[derive(Deserialize)] struct Outer { - preview: Preview, + preview: Shadow, + } + #[derive(Deserialize)] + struct Shadow { + pub tab_size: u32, + pub max_width: u32, + pub max_height: u32, + + pub cache_dir: Option, } - let outer: Outer = toml::from_str(&MERGED_YAZI).unwrap(); - outer.preview + let preview = toml::from_str::(&MERGED_YAZI).unwrap().preview; + + let cache_dir = + preview.cache_dir.filter(|p| !p.is_empty()).map_or_else(Xdg::cache_dir, PathBuf::from); + + Preview { + adaptor: Default::default(), + + tab_size: preview.tab_size, + max_width: preview.max_width, + max_height: preview.max_height, + + cache_dir, + } + } +} + +impl Preview { + #[inline] + pub fn cache(&self, path: &Path, skip: usize) -> PathBuf { + self + .cache_dir + .join(format!("{:x}", Md5::new_with_prefix(format!("{:?}///{}", path, skip)).finalize())) + } + + #[inline] + pub fn tmpfile(&self, prefix: &str) -> PathBuf { + let nanos = SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().as_nanos(); + self.cache_dir.join(format!("{prefix}-{}", nanos / 1000)) } } diff --git a/config/src/xdg.rs b/config/src/xdg.rs index a97be928..437048b3 100644 --- a/config/src/xdg.rs +++ b/config/src/xdg.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{env, path::PathBuf}; pub(super) struct Xdg; @@ -12,7 +12,7 @@ impl Xdg { { std::env::var_os("XDG_CONFIG_HOME") .map(PathBuf::from) - .and_then(|p| p.is_absolute().then_some(p)) + .filter(|p| p.is_absolute()) .or_else(|| dirs::home_dir().map(|h| h.join(".config"))) .map(|p| p.join("yazi")) } @@ -27,9 +27,12 @@ impl Xdg { { std::env::var_os("XDG_STATE_HOME") .map(PathBuf::from) - .and_then(|p| p.is_absolute().then_some(p)) + .filter(|p| p.is_absolute()) .or_else(|| dirs::home_dir().map(|h| h.join(".local/state"))) .map(|p| p.join("yazi")) } } + + #[inline] + pub(super) fn cache_dir() -> PathBuf { env::temp_dir().join("yazi") } } diff --git a/core/src/manager/manager.rs b/core/src/manager/manager.rs index c0a26167..35808d6a 100644 --- a/core/src/manager/manager.rs +++ b/core/src/manager/manager.rs @@ -1,7 +1,7 @@ use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, env, ffi::OsStr, io::{stdout, BufWriter, Write}, mem, path::{Path, PathBuf}}; use anyhow::{anyhow, bail, Error, Result}; -use config::{BOOT, OPEN}; +use config::{OPEN, PREVIEW}; use shared::{max_common_root, Defer, Term, MIME_DIR}; use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}}; @@ -222,7 +222,7 @@ impl Manager { let root = max_common_root(&old); let old: Vec<_> = old.into_iter().map(|p| p.strip_prefix(&root).unwrap().to_owned()).collect(); - let tmp = BOOT.tmpfile("bulk"); + let tmp = PREVIEW.tmpfile("bulk"); tokio::spawn(async move { let Some(opener) = OPEN.block_opener("bulk.txt", "text/plain") else { bail!("No opener for bulk rename"); diff --git a/core/src/manager/preview/provider.rs b/core/src/manager/preview/provider.rs index 82e3e535..66bfbaab 100644 --- a/core/src/manager/preview/provider.rs +++ b/core/src/manager/preview/provider.rs @@ -2,7 +2,7 @@ use std::{io::BufRead, path::Path, sync::atomic::{AtomicUsize, Ordering}}; use adaptor::Adaptor; use anyhow::anyhow; -use config::{BOOT, MANAGER, PREVIEW}; +use config::{MANAGER, PREVIEW}; use shared::{MimeKind, PeekError}; use syntect::{easy::HighlightFile, util::as_24_bit_terminal_escaped}; use tokio::fs; @@ -62,7 +62,7 @@ impl Provider { } pub(super) async fn video(path: &Path, skip: usize) -> Result { - let cache = BOOT.cache(path, skip); + let cache = PREVIEW.cache(path, skip); if fs::metadata(&cache).await.is_err() { external::ffmpegthumbnailer(path, &cache, skip).await?; } @@ -71,7 +71,7 @@ impl Provider { } pub(super) async fn pdf(path: &Path, skip: usize) -> Result { - let cache = BOOT.cache(path, skip); + let cache = PREVIEW.cache(path, skip); if fs::metadata(&cache).await.is_err() { external::pdftoppm(path, &cache, skip).await?; } diff --git a/core/src/tasks/workers/precache.rs b/core/src/tasks/workers/precache.rs index 02f57b71..e360eb2d 100644 --- a/core/src/tasks/workers/precache.rs +++ b/core/src/tasks/workers/precache.rs @@ -2,7 +2,7 @@ use std::{collections::{BTreeMap, BTreeSet}, path::PathBuf, sync::Arc}; use adaptor::Image; use anyhow::Result; -use config::BOOT; +use config::PREVIEW; use parking_lot::Mutex; use shared::{calculate_size, Throttle}; use tokio::{fs, sync::mpsc}; @@ -74,7 +74,7 @@ impl Precache { pub(crate) async fn work(&self, task: &mut PrecacheOp) -> Result<()> { match task { PrecacheOp::Image(task) => { - let cache = BOOT.cache(&task.target, 0); + let cache = PREVIEW.cache(&task.target, 0); if fs::metadata(&cache).await.is_ok() { return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?); } @@ -84,7 +84,7 @@ impl Precache { self.sch.send(TaskOp::Adv(task.id, 1, 0))?; } PrecacheOp::Video(task) => { - let cache = BOOT.cache(&task.target, 0); + let cache = PREVIEW.cache(&task.target, 0); if fs::metadata(&cache).await.is_ok() { return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?); } @@ -93,7 +93,7 @@ impl Precache { self.sch.send(TaskOp::Adv(task.id, 1, 0))?; } PrecacheOp::Pdf(task) => { - let cache = BOOT.cache(&task.target, 0); + let cache = PREVIEW.cache(&task.target, 0); if fs::metadata(&cache).await.is_ok() { return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?); }