diff --git a/src/app/mod.rs b/src/app/mod.rs index f2a43f2..496479c 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -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>), + UnloadImage(PathBuf), OpenImage(PathBuf), @@ -58,10 +66,34 @@ impl State { fn update(&mut self, message: Message) -> Task { 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); } diff --git a/src/main.rs b/src/main.rs index 8a836ad..96bfe83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod app; +mod utils; const SUPPORTED_TYPES: &[&str; 20] = &[ "*.png", "*.PNG", "*.jpg", "*.JPG", "*.jpeg", "*.JPEG", "*.avif", "*.jxl", "*.bmp", "*.exr", diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..9baabee --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,9 @@ +use std::path::Path; + +use image::{DynamicImage, ImageReader, ImageResult}; + +pub fn load_image(path: impl AsRef) -> ImageResult { + Ok(DynamicImage::from_decoder( + ImageReader::open(path)?.into_decoder()?, + )?) +}