diff --git a/Cargo.lock b/Cargo.lock index 36724e1..14d133e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,9 +157,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "apply" @@ -318,9 +318,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock 3.3.0", "cfg-if", @@ -389,7 +389,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.3.1", + "async-io 2.3.2", "async-lock 2.8.0", "atomic-waker", "cfg-if", @@ -674,9 +674,9 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "cosmic-comp-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-comp#9cb1adb37cc7e0dab9b5e7076aee292e244c421b" +source = "git+https://github.com/pop-os/cosmic-comp#c685440155063dae2d09ebc70e2a41f88180b2c2" dependencies = [ "cosmic-config", "input", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "atomicwrites", "calloop", @@ -1104,7 +1104,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "quote", "syn 1.0.109", @@ -1113,7 +1113,7 @@ dependencies = [ [[package]] name = "cosmic-panel-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#e51be500fc0e62afe5a9002fd11f230f9fcbae41" +source = "git+https://github.com/pop-os/cosmic-panel#07fcaee64f80d9aa498be53d40077bc0a510437b" dependencies = [ "anyhow", "cosmic-config", @@ -1241,9 +1241,9 @@ dependencies = [ "dirs 5.0.1", "freedesktop-icons", "futures-lite 2.2.0", + "futures-util", "image", "infer", - "rayon", "tokio", "tracing", ] @@ -1251,7 +1251,7 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.11.2" -source = "git+https://github.com/pop-os/cosmic-text.git#a53a0b3a8c085143470a9d26ac2c2911cc479033" +source = "git+https://github.com/pop-os/cosmic-text.git#18c3d2acec5e7f64a670c6643ee3ab220bc92a89" dependencies = [ "bitflags 2.4.2", "fontdb", @@ -1273,7 +1273,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "almost", "cosmic-config", @@ -1972,9 +1972,9 @@ dependencies = [ [[package]] name = "freedesktop-desktop-entry" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45157175a725e81f3f594382430b6b78af5f8f72db9bd51b94f0785f80fc6d29" +checksum = "287f89b1a3d88dd04d2b65dfec39f3c381efbcded7b736456039c4ee49d54b17" dependencies = [ "dirs 3.0.2", "gettext-rs", @@ -2496,7 +2496,7 @@ dependencies = [ "serde", "serde_derive", "thiserror", - "toml 0.8.10", + "toml 0.8.11", "unic-langid", ] @@ -2559,7 +2559,7 @@ dependencies = [ [[package]] name = "iced" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "iced_accessibility", "iced_core", @@ -2574,7 +2574,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "accesskit", "accesskit_unix", @@ -2583,7 +2583,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "bitflags 1.3.2", "iced_accessibility", @@ -2602,7 +2602,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "futures", "iced_core", @@ -2615,7 +2615,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -2639,7 +2639,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2651,7 +2651,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "iced_accessibility", "iced_core", @@ -2663,7 +2663,7 @@ dependencies = [ [[package]] name = "iced_sctk" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "enum-repr", "float-cmp", @@ -2689,7 +2689,7 @@ dependencies = [ [[package]] name = "iced_style" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "iced_core", "once_cell", @@ -2699,7 +2699,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "bytemuck", "cosmic-text", @@ -2716,7 +2716,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -2735,7 +2735,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "iced_renderer", "iced_runtime", @@ -3132,7 +3132,7 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#52491e08ee83254e64d1c3730fed221a40696a85" +source = "git+https://github.com/pop-os/libcosmic#64ecb0ea48f262e13b1036757211b70432fd42e5" dependencies = [ "apply", "ashpd 0.7.0", @@ -4013,9 +4013,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -4956,7 +4956,7 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 0.8.10", + "toml 0.8.11", "version-compare", ] @@ -5012,18 +5012,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", @@ -5161,14 +5161,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.6", + "toml_edit 0.22.7", ] [[package]] @@ -5204,9 +5204,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ "indexmap", "serde", diff --git a/app/src/app.rs b/app/src/app.rs index 40cd54b..c19753f 100644 --- a/app/src/app.rs +++ b/app/src/app.rs @@ -12,7 +12,7 @@ use crate::pages::desktop::{ }, }; use crate::pages::input::{self, keyboard}; -use crate::pages::{display, sound, system, time}; +use crate::pages::{self, display, sound, system, time}; use crate::subscription::desktop_files; use crate::widget::{page_title, search_header}; use crate::PageCommands; @@ -21,7 +21,7 @@ use cosmic::iced::Subscription; use cosmic::widget::{button, row, text_input}; use cosmic::{ app::{Command, Core}, - cosmic_config::config_subscription, + cosmic_config::{config_state_subscription, config_subscription}, iced::{ self, event::{self, wayland, PlatformSpecific}, @@ -228,6 +228,11 @@ impl cosmic::Application for SettingsApp { Message::PanelConfig(update.config) }), + config_state_subscription(0, cosmic_bg_config::NAME.into(), 1).map(|update| { + Message::PageMessage(pages::Message::DesktopWallpaper( + pages::desktop::wallpaper::Message::UpdateState(update.config), + )) + }), ]) } diff --git a/app/src/pages/desktop/panel/applets_inner.rs b/app/src/pages/desktop/panel/applets_inner.rs index 70f181f..c00bd42 100644 --- a/app/src/pages/desktop/panel/applets_inner.rs +++ b/app/src/pages/desktop/panel/applets_inner.rs @@ -259,7 +259,7 @@ impl Page { button(text(fl!("add"))) .style(button::Style::Custom { active: Box::new(|focused, theme| { - let mut style = theme.active(focused, &button::Style::Text); + let mut style = theme.active(focused, false, &button::Style::Text); style.text_color = Some(theme.cosmic().accent_color().into()); style }), @@ -271,12 +271,12 @@ impl Page { style }), hovered: Box::new(|focused, theme| { - let mut style = theme.hovered(focused, &theme::Button::Text); + let mut style = theme.hovered(focused, false, &theme::Button::Text); style.text_color = Some(theme.cosmic().accent_color().into()); style }), pressed: Box::new(|focused, theme| { - let mut style = theme.pressed(focused, &theme::Button::Text); + let mut style = theme.pressed(focused, false, &theme::Button::Text); style.text_color = Some(theme.cosmic().accent_color().into()); style }), diff --git a/app/src/pages/desktop/wallpaper/mod.rs b/app/src/pages/desktop/wallpaper/mod.rs index 6ec711f..a938c7b 100644 --- a/app/src/pages/desktop/wallpaper/mod.rs +++ b/app/src/pages/desktop/wallpaper/mod.rs @@ -5,6 +5,7 @@ mod config; pub mod widgets; pub use config::Config; +use futures::StreamExt; use url::Url; use std::{ @@ -114,6 +115,8 @@ pub enum Message { Select(DefaultKey), /// Changes the slideshow parameter. Slideshow(bool), + /// State change from cosmic-bg + UpdateState(cosmic_bg_config::state::State), } impl From for crate::app::Message { @@ -138,6 +141,9 @@ pub enum Category { /// The page struct for the wallpaper view. pub struct Page { + /// Whether to show the tab_bar or not. + show_tab_bar: bool, + /// The display that is currently being configured. /// /// If set to `None`, all displays will have the same wallpaper. @@ -203,10 +209,12 @@ impl page::Page for Page { fn reload(&mut self, _page: page::Entity) -> Command { let current_folder = self.config.current_folder().to_owned(); + let recurse = self.categories.selected == Some(Category::Wallpapers); + command::future(async move { let (service_config, displays) = wallpaper::config().await; - let selection = change_folder(current_folder).await; + let selection = change_folder(current_folder, recurse).await; crate::pages::Message::DesktopWallpaper(Message::Init(Box::new(InitUpdate { service_config, @@ -222,6 +230,7 @@ impl page::AutoBind for Page {} impl Default for Page { fn default() -> Self { let mut page = Page { + show_tab_bar: false, active_output: None, cached_display_handle: None, categories: { @@ -507,7 +516,7 @@ impl Page { if self.config.current_folder.is_some() { let _ = self.config.set_current_folder(None); command = cosmic::command::future(async move { - let folder = change_folder(Config::default_folder().to_owned()).await; + let folder = change_folder(Config::default_folder().to_owned(), true).await; Message::ChangeFolder(folder).into() }); } else { @@ -527,7 +536,7 @@ impl Page { } command = cosmic::command::future(async move { - Message::ChangeFolder(change_folder(path).await).into() + Message::ChangeFolder(change_folder(path, false).await).into() }); } } @@ -608,6 +617,12 @@ impl Page { #[allow(clippy::too_many_lines)] pub fn update(&mut self, message: Message) -> Command { match message { + Message::UpdateState(_state) => { + if let Choice::Slideshow = self.selection.active { + self.cache_display_image(); + } + } + Message::DragColorDialog => { return cosmic::iced_sctk::commands::window::start_drag_window(self.color_dialog) } @@ -819,9 +834,12 @@ 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. return cosmic::command::future(async move { - let message = Message::ChangeFolder(change_folder(path).await); + let message = Message::ChangeFolder(change_folder(path, recurse).await); let page_message = crate::pages::Message::DesktopWallpaper(message); crate::Message::PageMessage(page_message) }); @@ -842,8 +860,7 @@ impl Page { // Loads a single custom image and its thumbnail for display in the backgrounds view. return cosmic::command::future(async move { - let result = - wallpaper::load_image_with_thumbnail(&mut Vec::new(), path).await; + let result = wallpaper::load_image_with_thumbnail(path); let message = Message::ImageAdd(result.map(Arc::new)); let page_message = crate::pages::Message::DesktopWallpaper(message); @@ -856,6 +873,7 @@ impl Page { self.outputs.clear(); self.wallpaper_service_config = update.service_config; self.selection = update.selection; + self.show_tab_bar = update.displays.len() > 1; // Sync custom colors from config. for color in self.config.custom_colors() { @@ -881,8 +899,7 @@ impl Page { // Load preview images concurrently for each custom image stored in the on-disk config. return cosmic::command::batch(custom_images.iter().cloned().map(|path| { cosmic::command::future(async move { - let result = - wallpaper::load_image_with_thumbnail(&mut Vec::new(), path).await; + let result = wallpaper::load_image_with_thumbnail(path); Message::ImageAdd(result.map(Arc::new)).into() }) @@ -1042,11 +1059,11 @@ impl Context { } } -pub async fn change_folder(current_folder: PathBuf) -> Context { +pub async fn change_folder(current_folder: PathBuf, recurse: bool) -> Context { let mut update = Context::default(); - let mut wallpapers = wallpaper::load_each_from_path(current_folder); + let mut wallpapers = wallpaper::load_each_from_path(current_folder, recurse).await; - while let Some((path, display_image, selection_image)) = wallpapers.recv().await { + while let Some((path, display_image, selection_image)) = wallpapers.next().await { let id = update.paths.insert(path); update.display_images.insert(id, display_image); @@ -1109,8 +1126,8 @@ pub fn settings() -> Section { }, )); - children.push(if page.wallpaper_service_config.same_on_all { - text(fl!("all-displays")) + if page.wallpaper_service_config.same_on_all { + let element = text(fl!("all-displays")) .font(cosmic::font::FONT_SEMIBOLD) .horizontal_alignment(alignment::Horizontal::Center) .vertical_alignment(alignment::Vertical::Center) @@ -1118,13 +1135,16 @@ pub fn settings() -> Section { .height(Length::Fill) .apply(cosmic::widget::container) .width(Length::Fill) - .height(Length::Fixed(32.0)) - .into() - } else { - tab_bar::horizontal(&page.outputs) - .on_activate(Message::Output) - .into() - }); + .height(Length::Fixed(32.0)); + + children.push(element.into()); + } else if page.show_tab_bar { + let element = tab_bar::horizontal(&page.outputs) + .button_alignment(Alignment::Center) + .on_activate(Message::Output); + + children.push(element.into()); + } let wallpaper_fit = cosmic::widget::dropdown(&page.fit_options, Some(page.selected_fit), Message::Fit); diff --git a/app/src/pages/display/mod.rs b/app/src/pages/display/mod.rs index 7d192a6..aa2db3f 100644 --- a/app/src/pages/display/mod.rs +++ b/app/src/pages/display/mod.rs @@ -8,7 +8,7 @@ pub mod text; use crate::{app, pages}; use apply::Apply; use arrangement::Arrangement; -use cosmic::iced::Length; +use cosmic::iced::{Alignment, Length}; use cosmic::iced_widget::scrollable::{Direction, Properties, RelativeOffset}; use cosmic::widget::{ column, container, dropdown, list_column, segmented_button, tab_bar, toggler, @@ -459,8 +459,9 @@ impl Page { let mut content = column().spacing(theme.cosmic().space_m()); if self.list.outputs.len() > 1 { - let display_switcher = - tab_bar::horizontal(&self.display_tabs).on_activate(Message::Display); + let display_switcher = tab_bar::horizontal(&self.display_tabs) + .button_alignment(Alignment::Center) + .on_activate(Message::Display); let display_enable = list_column().add(cosmic::widget::settings::item( &*text::DISPLAY_ENABLE, diff --git a/pages/wallpapers/Cargo.toml b/pages/wallpapers/Cargo.toml index 036d375..c7dac5c 100644 --- a/pages/wallpapers/Cargo.toml +++ b/pages/wallpapers/Cargo.toml @@ -12,8 +12,8 @@ cosmic-randr-shell = { workspace = true } dirs = "5.0.1" freedesktop-icons = "0.2.5" futures-lite = "2.2.0" +futures-util = "0.3.30" image = "0.24.8" infer = "0.15.0" -rayon = "1.8.1" tokio = { version = "1.35.1", features = ["sync"] } tracing = "0.1.40" diff --git a/pages/wallpapers/src/lib.rs b/pages/wallpapers/src/lib.rs index 008774f..7ef399e 100644 --- a/pages/wallpapers/src/lib.rs +++ b/pages/wallpapers/src/lib.rs @@ -1,5 +1,6 @@ pub use cosmic_bg_config::{Color, Config, Entry, Gradient, ScalingMode, Source}; +use futures_lite::Stream; use image::{DynamicImage, ImageBuffer, Rgba, RgbaImage}; use std::{ borrow::Cow, @@ -7,8 +8,8 @@ use std::{ hash::{Hash, Hasher}, io::Read, path::{Path, PathBuf}, + pin::Pin, }; -use tokio::sync::mpsc::{self, Receiver}; pub const DEFAULT_COLORS: &[Color] = &[ Color::Single([0.580, 0.922, 0.922]), @@ -87,12 +88,11 @@ pub fn cache_dir() -> Option { /// Loads wallpapers in parallel by spawning tasks with a rayon thread pool. #[must_use] -pub fn load_each_from_path(path: PathBuf) -> Receiver<(PathBuf, RgbaImage, RgbaImage)> { - let (tx, rx) = mpsc::channel(1); - - tokio::task::spawn(async move { - // Scratch space for storing images into. - let mut buffer = Vec::new(); +pub async fn load_each_from_path( + path: PathBuf, + recurse: bool, +) -> Pin>> { + 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. @@ -108,7 +108,7 @@ pub fn load_each_from_path(path: PathBuf) -> Receiver<(PathBuf, RgbaImage, RgbaI let path = entry.path(); // Recursively search directories, while storing only image files. - if file_type.is_dir() { + if recurse && file_type.is_dir() { paths.push(path); } else if file_type.is_file() { let Ok(Some(kind)) = infer::get_from_path(&path) else { @@ -117,24 +117,34 @@ pub fn load_each_from_path(path: PathBuf) -> Receiver<(PathBuf, RgbaImage, RgbaI if infer::MatcherType::Image == kind.matcher_type() { wallpapers.insert(path); + + if wallpapers.len() > 99 { + break; + } } } } } } - for path in wallpapers { - if let Some(value) = load_image_with_thumbnail(&mut buffer, path).await { - let _res = tx.send(value).await; - } - } + wallpapers }); - rx + 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()) + } } -pub async fn load_image_with_thumbnail( - buffer: &mut Vec, +#[must_use] +pub fn load_image_with_thumbnail( path: PathBuf, ) -> Option<( PathBuf, @@ -142,54 +152,48 @@ pub async fn load_image_with_thumbnail( ImageBuffer, Vec>, )> { let cache_dir = cache_dir(); - let image_operation = load_thumbnail(buffer, cache_dir.as_deref(), &path); - - let (tx, rx) = tokio::sync::oneshot::channel(); + let image_operation = load_thumbnail(&mut Vec::new(), cache_dir.as_deref(), &path); if let Some(image_operation) = image_operation { let tokio_handle = tokio::runtime::Handle::current(); - rayon::spawn_fifo(move || { - let display_thumbnail = match image_operation { - ImageOperation::Cached(thumbnail) => thumbnail.to_rgba8(), + let display_thumbnail = match image_operation { + ImageOperation::Cached(thumbnail) => thumbnail.to_rgba8(), - ImageOperation::GenerateThumbnail { path, image } => { - let image = image.thumbnail(300, 169).to_rgba8(); + ImageOperation::GenerateThumbnail { path, image } => { + let image = image.thumbnail(300, 169).to_rgba8(); - if let Some(path) = path { - // Save thumbnail to disk without blocking. - tokio_handle.spawn_blocking({ - let image = image.clone(); - move || { - if let Err(why) = image.save(&path) { - tracing::error!(?path, ?why, "failed to save image thumbnail"); + if let Some(path) = path { + // Save thumbnail to disk without blocking. + tokio_handle.spawn_blocking({ + let image = image.clone(); + move || { + if let Err(why) = image.save(&path) { + tracing::error!(?path, ?why, "failed to save image thumbnail"); - let _res = std::fs::remove_file(&path); - } + let _res = std::fs::remove_file(&path); } - }); - } - - image + } + }); } - }; - let mut selection_thumbnail = image::imageops::resize( - &display_thumbnail, - 158, - 105, - image::imageops::FilterType::Lanczos3, - ); + image + } + }; - round(&mut selection_thumbnail, [8, 8, 8, 8]); + let mut selection_thumbnail = image::imageops::resize( + &display_thumbnail, + 158, + 105, + image::imageops::FilterType::Lanczos3, + ); - let _res = tx.send(Some((path, display_thumbnail, selection_thumbnail))); - }); + round(&mut selection_thumbnail, [8, 8, 8, 8]); + + Some((path, display_thumbnail, selection_thumbnail)) } else { - let _res = tx.send(None); + None } - - rx.await.unwrap_or(None) } enum ImageOperation {