From 92b0184036976d74e2d7f17a9206ccb50db278e4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 24 Jan 2024 13:15:31 +0100 Subject: [PATCH] Load images in the background --- crates/gpui/src/elements/img.rs | 2 +- crates/gpui/src/image_cache.rs | 75 ++++++++++++++++----------------- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/crates/gpui/src/elements/img.rs b/crates/gpui/src/elements/img.rs index 191cadf2939834eb68c4b70abf18b92c8bdc6ff8..e7377373fe18cd7d6d26a610c2d5b776e02874fc 100644 --- a/crates/gpui/src/elements/img.rs +++ b/crates/gpui/src/elements/img.rs @@ -104,7 +104,7 @@ impl Element for Img { cx.with_z_index(1, |cx| { match source { ImageSource::Uri(uri) => { - let image_future = cx.image_cache.get(uri.clone()); + let image_future = cx.image_cache.get(uri.clone(), cx); if let Some(data) = image_future .clone() .now_or_never() diff --git a/crates/gpui/src/image_cache.rs b/crates/gpui/src/image_cache.rs index dd7b7b571e43c20609e6920f0da59093b5aa010f..95b41c3b2c0619c24deb4207e41b01d23e615b21 100644 --- a/crates/gpui/src/image_cache.rs +++ b/crates/gpui/src/image_cache.rs @@ -1,9 +1,6 @@ -use crate::{ImageData, ImageId, SharedUrl}; +use crate::{AppContext, ImageData, ImageId, SharedUrl, Task}; use collections::HashMap; -use futures::{ - future::{BoxFuture, Shared}, - AsyncReadExt, FutureExt, TryFutureExt, -}; +use futures::{future::Shared, AsyncReadExt, FutureExt, TryFutureExt}; use image::ImageError; use parking_lot::Mutex; use std::sync::Arc; @@ -44,10 +41,10 @@ impl From for Error { pub(crate) struct ImageCache { client: Arc, - images: Arc>>, + images: Arc>>, } -type FetchImageFuture = Shared, Error>>>; +type FetchImageTask = Shared, Error>>>; impl ImageCache { pub fn new(client: Arc) -> Self { @@ -57,10 +54,7 @@ impl ImageCache { } } - pub fn get( - &self, - uri: impl Into, - ) -> Shared, Error>>> { + pub fn get(&self, uri: impl Into, cx: &AppContext) -> FetchImageTask { let uri = uri.into(); let mut images = self.images.lock(); @@ -68,36 +62,39 @@ impl ImageCache { Some(future) => future.clone(), None => { let client = self.client.clone(); - let future = { - let uri = uri.clone(); - async move { - let mut response = client.get(uri.as_ref(), ().into(), true).await?; - let mut body = Vec::new(); - response.body_mut().read_to_end(&mut body).await?; + let future = cx + .background_executor() + .spawn( + { + let uri = uri.clone(); + async move { + let mut response = + client.get(uri.as_ref(), ().into(), true).await?; + let mut body = Vec::new(); + response.body_mut().read_to_end(&mut body).await?; - if !response.status().is_success() { - return Err(Error::BadStatus { - status: response.status(), - body: String::from_utf8_lossy(&body).into_owned(), - }); - } - - let format = image::guess_format(&body)?; - let image = - image::load_from_memory_with_format(&body, format)?.into_bgra8(); - Ok(Arc::new(ImageData::new(image))) - } - } - .map_err({ - let uri = uri.clone(); + if !response.status().is_success() { + return Err(Error::BadStatus { + status: response.status(), + body: String::from_utf8_lossy(&body).into_owned(), + }); + } - move |error| { - log::log!(log::Level::Error, "{:?} {:?}", &uri, &error); - error - } - }) - .boxed() - .shared(); + let format = image::guess_format(&body)?; + let image = image::load_from_memory_with_format(&body, format)? + .into_bgra8(); + Ok(Arc::new(ImageData::new(image))) + } + } + .map_err({ + let uri = uri.clone(); + move |error| { + log::log!(log::Level::Error, "{:?} {:?}", &uri, &error); + error + } + }), + ) + .shared(); images.insert(uri, future.clone()); future