fix: wallpaper discovery
Allows settings to show installed wallpapers. - Modified `load_each_from_path` to recursively discover wallpapers, limited depth to 3 for performance.
This commit is contained in:
parent
1b2aba0107
commit
8ca65bafe4
4 changed files with 34 additions and 49 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1844,6 +1844,7 @@ dependencies = [
|
|||
"jxl-oxide",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -1178,11 +1178,6 @@ pub async fn change_folder(current_folder: PathBuf) -> Context {
|
|||
let mut update = Context::default();
|
||||
let mut streams = Vec::with_capacity(2);
|
||||
|
||||
// Include the cosmic background folder when loading the system wallpapers.
|
||||
if current_folder == Config::default_folder() {
|
||||
streams.push(wallpaper::load_each_from_path(Config::default_folder().join("cosmic")).await);
|
||||
}
|
||||
|
||||
streams.push(wallpaper::load_each_from_path(current_folder).await);
|
||||
|
||||
for mut wallpapers in streams {
|
||||
|
|
|
|||
|
|
@ -23,3 +23,4 @@ infer = "0.16.0"
|
|||
jxl-oxide = "0.11.3"
|
||||
tokio = { version = "1.44.1", features = ["sync"] }
|
||||
tracing = "0.1.41"
|
||||
walkdir = "=2.5.0"
|
||||
|
|
|
|||
|
|
@ -2,18 +2,20 @@ pub use cosmic_bg_config::{Color, Config, Entry, Gradient, ScalingMode, Source};
|
|||
use eyre::{eyre, OptionExt};
|
||||
use fast_image_resize::SrcCropping;
|
||||
use futures_lite::Stream;
|
||||
use futures_util::StreamExt;
|
||||
use image::imageops::FilterType;
|
||||
use image::{DynamicImage, ImageBuffer, Rgba, RgbaImage};
|
||||
use jxl_oxide::{EnumColourEncoding, JxlImage, PixelFormat};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{hash_map::DefaultHasher, BTreeSet, HashMap},
|
||||
collections::{hash_map::DefaultHasher, HashMap},
|
||||
hash::{Hash, Hasher},
|
||||
io::Read,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
pub const DEFAULT_COLORS: &[Color] = &[
|
||||
Color::Single([0.580, 0.922, 0.922]),
|
||||
|
|
@ -99,54 +101,40 @@ pub fn cache_dir() -> Option<PathBuf> {
|
|||
pub async fn load_each_from_path(
|
||||
path: PathBuf,
|
||||
) -> Pin<Box<dyn Send + Stream<Item = (PathBuf, RgbaImage, RgbaImage)>>> {
|
||||
let wallpapers = tokio::task::spawn_blocking(move || {
|
||||
// Discovered image files that will be loaded as wallpapers.
|
||||
let mut wallpapers = BTreeSet::new();
|
||||
let candidate_paths: Vec<_> = WalkDir::new(path)
|
||||
.max_depth(3)
|
||||
.into_iter()
|
||||
.filter_map(Result::ok)
|
||||
.filter(|entry| entry.file_type().is_file())
|
||||
.map(|entry| entry.path().to_path_buf())
|
||||
.collect();
|
||||
|
||||
if let Ok(dir) = path.read_dir() {
|
||||
for entry in dir.filter_map(Result::ok) {
|
||||
let Ok(file_type) = entry.file_type() else {
|
||||
continue;
|
||||
let future = futures_util::stream::iter(candidate_paths)
|
||||
.map(|path| {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let is_jxl = path.extension().map(|ext| ext == "jxl").unwrap_or_default();
|
||||
let is_image = if !is_jxl {
|
||||
if let Ok(Some(kind)) = infer::get_from_path(&path) {
|
||||
infer::MatcherType::Image == kind.matcher_type()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
let path = entry.path();
|
||||
|
||||
if file_type.is_file() {
|
||||
let path = if path.extension().map(|ext| ext == "jxl").unwrap_or_default() {
|
||||
path
|
||||
} else if let Ok(Some(kind)) = infer::get_from_path(&path) {
|
||||
if infer::MatcherType::Image == kind.matcher_type() {
|
||||
path
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
wallpapers.insert(path);
|
||||
|
||||
if wallpapers.len() > 99 {
|
||||
break;
|
||||
}
|
||||
if is_jxl || is_image {
|
||||
load_image_with_thumbnail(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.buffered(4)
|
||||
.filter_map(|value| async { value.ok().flatten() })
|
||||
.take(100);
|
||||
|
||||
wallpapers
|
||||
});
|
||||
|
||||
if let Ok(wallpapers) = wallpapers.await {
|
||||
use futures_util::StreamExt;
|
||||
let future = futures_util::stream::iter(wallpapers)
|
||||
.map(|path| tokio::task::spawn_blocking(|| load_image_with_thumbnail(path)))
|
||||
.buffered(4)
|
||||
.filter_map(|value| async { value.ok()? });
|
||||
|
||||
Box::pin(future)
|
||||
} else {
|
||||
Box::pin(futures_lite::stream::empty())
|
||||
}
|
||||
Box::pin(future)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue