perf(wallpaper): avoid recursion for system wallpapers

This commit is contained in:
Michael Aaron Murphy 2025-01-11 12:19:39 +01:00
parent 7576ad1af7
commit 0bf63a0d91
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
3 changed files with 46 additions and 50 deletions

View file

@ -221,12 +221,10 @@ impl page::Page<crate::pages::Message> for Page {
let current_folder = self.config.current_folder().to_owned(); let current_folder = self.config.current_folder().to_owned();
let recurse = self.categories.selected == Some(Category::Wallpapers);
let (task, on_enter_handle) = Task::future(async move { let (task, on_enter_handle) = Task::future(async move {
let (service_config, displays) = wallpaper::config().await; let (service_config, displays) = wallpaper::config().await;
let mut selection = change_folder(current_folder, recurse).await; let mut selection = change_folder(current_folder).await;
// `selection.active` is usually empty because `change_folder` creates a fresh context. // `selection.active` is usually empty because `change_folder` creates a fresh context.
// This leads to blank previews in certain conditions when the program is restarted. // This leads to blank previews in certain conditions when the program is restarted.
@ -578,7 +576,7 @@ impl Page {
if self.config.current_folder.is_some() { if self.config.current_folder.is_some() {
let _ = self.config.set_current_folder(None); let _ = self.config.set_current_folder(None);
task = cosmic::task::future(async move { task = cosmic::task::future(async move {
let folder = change_folder(Config::default_folder().to_owned(), true).await; let folder = change_folder(Config::default_folder().to_owned()).await;
Message::ChangeFolder(folder) Message::ChangeFolder(folder)
}); });
} else { } else {
@ -598,7 +596,7 @@ impl Page {
} }
task = cosmic::task::future(async move { task = cosmic::task::future(async move {
Message::ChangeFolder(change_folder(path, false).await) Message::ChangeFolder(change_folder(path).await)
}); });
} }
} }
@ -903,12 +901,9 @@ impl Page {
} }
} }
// Avoid walking user-selected folders.
let recurse = self.categories.selected == Some(Category::Wallpapers);
// Load the wallpapers from the selected folder into the view. // Load the wallpapers from the selected folder into the view.
return cosmic::Task::future(async move { return cosmic::Task::future(async move {
let message = Message::ChangeFolder(change_folder(path, recurse).await); let message = Message::ChangeFolder(change_folder(path).await);
let page_message = crate::pages::Message::DesktopWallpaper(message); let page_message = crate::pages::Message::DesktopWallpaper(message);
crate::Message::PageMessage(page_message) crate::Message::PageMessage(page_message)
}); });
@ -1138,10 +1133,18 @@ impl Context {
} }
} }
pub async fn change_folder(current_folder: PathBuf, recurse: bool) -> Context { pub async fn change_folder(current_folder: PathBuf) -> Context {
let mut update = Context::default(); let mut update = Context::default();
let mut wallpapers = wallpaper::load_each_from_path(current_folder, recurse).await; 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 {
while let Some((path, display_image, selection_image)) = wallpapers.next().await { while let Some((path, display_image, selection_image)) = wallpapers.next().await {
let id = update.paths.insert(path); let id = update.paths.insert(path);
@ -1155,6 +1158,7 @@ pub async fn change_folder(current_folder: PathBuf, recurse: bool) -> Context {
update.selection_handles.insert(id, selection_handle); update.selection_handles.insert(id, selection_handle);
} }
}
update update
} }

View file

@ -22,7 +22,6 @@ use slab::Slab;
use slotmap::{Key, SecondaryMap, SlotMap}; use slotmap::{Key, SecondaryMap, SlotMap};
use std::{collections::BTreeMap, process::ExitStatus, sync::Arc}; use std::{collections::BTreeMap, process::ExitStatus, sync::Arc};
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tokio::task::JoinHandle;
use tracing::error; use tracing::error;
static DPI_SCALES: &[u32] = &[50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300]; static DPI_SCALES: &[u32] = &[50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300];
@ -30,6 +29,7 @@ static DPI_SCALE_LABELS: Lazy<Vec<String>> =
Lazy::new(|| DPI_SCALES.iter().map(|scale| format!("{scale}%")).collect()); Lazy::new(|| DPI_SCALES.iter().map(|scale| format!("{scale}%")).collect());
/// Display color depth options /// Display color depth options
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct ColorDepth(usize); pub struct ColorDepth(usize);

View file

@ -97,15 +97,11 @@ pub fn cache_dir() -> Option<PathBuf> {
#[must_use] #[must_use]
pub async fn load_each_from_path( pub async fn load_each_from_path(
path: PathBuf, path: PathBuf,
recurse: bool,
) -> Pin<Box<dyn Send + Stream<Item = (PathBuf, RgbaImage, RgbaImage)>>> { ) -> Pin<Box<dyn Send + Stream<Item = (PathBuf, RgbaImage, RgbaImage)>>> {
let wallpapers = tokio::task::spawn_blocking(move || { let wallpapers = tokio::task::spawn_blocking(move || {
// Directories to search recursively.
let mut paths = vec![path];
// Discovered image files that will be loaded as wallpapers. // Discovered image files that will be loaded as wallpapers.
let mut wallpapers = BTreeSet::new(); let mut wallpapers = BTreeSet::new();
while let Some(path) = paths.pop() {
if let Ok(dir) = path.read_dir() { if let Ok(dir) = path.read_dir() {
for entry in dir.filter_map(Result::ok) { for entry in dir.filter_map(Result::ok) {
let Ok(file_type) = entry.file_type() else { let Ok(file_type) = entry.file_type() else {
@ -114,10 +110,7 @@ pub async fn load_each_from_path(
let path = entry.path(); let path = entry.path();
// Recursively search directories, while storing only image files. if file_type.is_file() {
if recurse && file_type.is_dir() {
paths.push(path);
} else if file_type.is_file() {
let path = if path.extension().map_or(false, |ext| ext == "jxl") { let path = if path.extension().map_or(false, |ext| ext == "jxl") {
path path
} else if let Ok(Some(kind)) = infer::get_from_path(&path) { } else if let Ok(Some(kind)) = infer::get_from_path(&path) {
@ -138,7 +131,6 @@ pub async fn load_each_from_path(
} }
} }
} }
}
wallpapers wallpapers
}); });