feat: parallel loading

This commit is contained in:
electria 2026-08-09 15:10:16 -07:00
commit e179b824c8
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs
3 changed files with 45 additions and 3 deletions

View file

@ -4,6 +4,7 @@ use std::{
env,
path::{Path, PathBuf},
process,
sync::Arc,
};
use iced::{
@ -11,16 +12,23 @@ use iced::{
keyboard, theme, widget, window,
};
use ignore::{WalkBuilder, types::TypesBuilder};
use image::ImageError;
use rayon::iter::{ParallelBridge, ParallelIterator};
use rfd::AsyncFileDialog;
use crate::{SUPPORTED_TYPES, app::maybe_image::MaybeImage};
use crate::{
SUPPORTED_TYPES,
app::maybe_image::{MaybeImage, handle_from_image},
utils,
};
mod maybe_image;
#[derive(Clone, Debug)]
enum Message {
LoadImage(PathBuf),
ImageLoaded(Result<(PathBuf, widget::image::Handle), Arc<ImageError>>),
UnloadImage(PathBuf),
OpenImage(PathBuf),
@ -58,10 +66,34 @@ impl State {
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::LoadImage(path) => {
self.images.entry(path.clone()).and_modify(|e| {
*e = MaybeImage::Loaded(widget::image::Handle::from_path(path))
let path_clone = path.clone();
let (task, handle) = Task::perform(
async {
utils::load_image(&path)
.map(|img| (path, handle_from_image(img)))
.map_err(Arc::new)
},
Message::ImageLoaded,
)
.abortable();
self.images.entry(path_clone).and_modify(|e| {
*e = MaybeImage::Loading(handle);
});
return task;
}
Message::ImageLoaded(result) => {
self.error = result.as_ref().err().map(|e| e.to_string());
if let Ok((path, handle)) = result {
self.images
.entry(path)
.and_modify(|e| *e = MaybeImage::Loaded(handle));
}
}
Message::UnloadImage(path) => {
self.images.entry(path).and_modify(MaybeImage::unload);
}

View file

@ -1,4 +1,5 @@
mod app;
mod utils;
const SUPPORTED_TYPES: &[&str; 20] = &[
"*.png", "*.PNG", "*.jpg", "*.JPG", "*.jpeg", "*.JPEG", "*.avif", "*.jxl", "*.bmp", "*.exr",

9
src/utils.rs Normal file
View file

@ -0,0 +1,9 @@
use std::path::Path;
use image::{DynamicImage, ImageReader, ImageResult};
pub fn load_image(path: impl AsRef<Path>) -> ImageResult<DynamicImage> {
Ok(DynamicImage::from_decoder(
ImageReader::open(path)?.into_decoder()?,
)?)
}