mirror of
https://github.com/danbulant/despot
synced 2026-06-18 22:11:03 +00:00
update image loading
This commit is contained in:
parent
d08dd6dcfc
commit
f3760ec4e8
2 changed files with 65 additions and 33 deletions
|
|
@ -1,11 +1,15 @@
|
|||
use std::sync::Arc;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use cushy::{kludgine::{AnyTexture, LazyTexture}, value::{CallbackDisconnected, CallbackHandle, Destination, Dynamic, Source, Value}, widgets::Image};
|
||||
use cushy::{
|
||||
kludgine::{AnyTexture, LazyTexture},
|
||||
value::{CallbackDisconnected, CallbackHandle, Destination, Dynamic, Source, Value},
|
||||
widgets::Image,
|
||||
};
|
||||
use futures_util::lock::Mutex;
|
||||
use http_cache_reqwest::{CACacheManager, Cache, CacheMode, HttpCache, HttpCacheOptions};
|
||||
use image::imageops::FilterType;
|
||||
use reqwest::Client;
|
||||
use reqwest_middleware::ClientBuilder;
|
||||
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use crate::rt::tokio_runtime;
|
||||
|
|
@ -16,13 +20,24 @@ pub trait ImageExt {
|
|||
fn load_url(&mut self, url: Dynamic<Option<String>>) -> CallbackHandle;
|
||||
|
||||
fn with_url(mut self, url: Dynamic<Option<String>>) -> Self
|
||||
where Self: Sized
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.load_url(url).persist();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
static CLIENT: LazyLock<ClientWithMiddleware> = LazyLock::new(|| {
|
||||
ClientBuilder::new(Client::new())
|
||||
.with(Cache(HttpCache {
|
||||
mode: CacheMode::Default,
|
||||
manager: CACacheManager::default(),
|
||||
options: HttpCacheOptions::default(),
|
||||
}))
|
||||
.build()
|
||||
});
|
||||
|
||||
impl ImageExt for Image {
|
||||
fn new_empty() -> Self {
|
||||
Image::new(Dynamic::new(get_empty_texture()))
|
||||
|
|
@ -31,15 +46,6 @@ impl ImageExt for Image {
|
|||
/// Makes the image connected to a URL
|
||||
/// Calling this multiple times on a single image may cause memory leaks
|
||||
fn load_url(&mut self, url: Dynamic<Option<String>>) -> CallbackHandle {
|
||||
let client = ClientBuilder::new(Client::new())
|
||||
.with(Cache(HttpCache {
|
||||
mode: CacheMode::Default,
|
||||
manager: CACacheManager::default(),
|
||||
options: HttpCacheOptions::default(),
|
||||
}))
|
||||
.build();
|
||||
|
||||
|
||||
// let texture = Dynamic::new(get_empty_texture());
|
||||
match &mut self.contents {
|
||||
Value::Constant(_) => self.contents = Value::Dynamic(Dynamic::new(get_empty_texture())),
|
||||
|
|
@ -47,9 +53,9 @@ impl ImageExt for Image {
|
|||
}
|
||||
let texture = match &self.contents {
|
||||
Value::Dynamic(dynamic) => dynamic,
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
||||
let prev_request_join = Arc::new(Mutex::new(None::<JoinHandle<()>>));
|
||||
url.for_each_try({
|
||||
let texture = texture.clone();
|
||||
|
|
@ -58,16 +64,18 @@ impl ImageExt for Image {
|
|||
if texture_count <= 1 {
|
||||
return Err(CallbackDisconnected);
|
||||
}
|
||||
println!("loading url {:?}", url);
|
||||
let guard = tokio_runtime().enter();
|
||||
let url = url.clone();
|
||||
let prev_request_join = prev_request_join.clone();
|
||||
let texture = texture.clone();
|
||||
let client = client.clone();
|
||||
let client = CLIENT.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut prev_request_join = prev_request_join.lock().await;
|
||||
if let Some(prev_request_join) = prev_request_join.take() {
|
||||
prev_request_join.abort();
|
||||
}
|
||||
println!("loading url {:?}", url);
|
||||
if let Some(url) = url {
|
||||
let texture = texture.clone();
|
||||
let client = client.clone();
|
||||
|
|
@ -75,8 +83,11 @@ impl ImageExt for Image {
|
|||
let response = client.get(url).send().await.unwrap();
|
||||
let bytes = response.bytes().await.unwrap();
|
||||
let image = image::load_from_memory(&bytes).unwrap();
|
||||
let image = image.resize(128, 128, FilterType::Lanczos3);
|
||||
let image_texture = LazyTexture::from_image(image, cushy::kludgine::wgpu::FilterMode::Linear);
|
||||
// let image = image.resize(128, 128, FilterType::Lanczos3);
|
||||
let image_texture = LazyTexture::from_image(
|
||||
image,
|
||||
cushy::kludgine::wgpu::FilterMode::Linear,
|
||||
);
|
||||
let image_texture = AnyTexture::Lazy(image_texture);
|
||||
texture.set(image_texture);
|
||||
}));
|
||||
|
|
@ -91,14 +102,9 @@ impl ImageExt for Image {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn get_empty_texture() -> AnyTexture {
|
||||
AnyTexture::Lazy(
|
||||
LazyTexture::from_image(
|
||||
image::DynamicImage::ImageRgba8(
|
||||
image::ImageBuffer::new(1, 1)
|
||||
),
|
||||
cushy::kludgine::wgpu::FilterMode::Linear
|
||||
)
|
||||
)
|
||||
}
|
||||
AnyTexture::Lazy(LazyTexture::from_image(
|
||||
image::DynamicImage::ImageRgba8(image::ImageBuffer::new(1, 1)),
|
||||
cushy::kludgine::wgpu::FilterMode::Linear,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ use cushy::{
|
|||
styles::{Dimension, DimensionRange},
|
||||
value::{Destination, Dynamic, Source},
|
||||
widget::{MakeWidget, WidgetInstance},
|
||||
widgets::{label::LabelOverflow, Image, Label, Space, VirtualList},
|
||||
widgets::{
|
||||
label::{Displayable, LabelOverflow},
|
||||
Image, Label, Space, VirtualList,
|
||||
},
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rspotify::model::SavedTrack;
|
||||
|
|
@ -35,7 +38,6 @@ fn get_or_create_track_image(
|
|||
idx: usize,
|
||||
create: impl FnOnce() -> WidgetInstance,
|
||||
) -> WidgetInstance {
|
||||
println!("Getting image");
|
||||
let mut locked = track_images.lock().unwrap();
|
||||
if let Some(image) = locked.get(&idx) {
|
||||
image.clone()
|
||||
|
|
@ -147,19 +149,43 @@ impl LikedSongsPage {
|
|||
.and(track.map_each(|track| {
|
||||
track
|
||||
.as_ref()
|
||||
.map(|track| track.track.album.name.clone().make_widget())
|
||||
.map(|track| {
|
||||
track
|
||||
.track
|
||||
.album
|
||||
.name
|
||||
.clone()
|
||||
.into_label()
|
||||
.overflow(LabelOverflow::Clip)
|
||||
.make_widget()
|
||||
})
|
||||
.unwrap_or(Space::primary().make_widget())
|
||||
}))
|
||||
.and(track.map_each(|track| {
|
||||
track
|
||||
.as_ref()
|
||||
.map(|track| track.added_at.to_string().make_widget())
|
||||
.map(|track| {
|
||||
track
|
||||
.added_at
|
||||
.to_string()
|
||||
.into_label()
|
||||
.overflow(LabelOverflow::Clip)
|
||||
.make_widget()
|
||||
})
|
||||
.unwrap_or(Space::primary().make_widget())
|
||||
}))
|
||||
.and(track.map_each(|track| {
|
||||
track
|
||||
.as_ref()
|
||||
.map(|track| track.track.duration.to_string().make_widget())
|
||||
.map(|track| {
|
||||
track
|
||||
.track
|
||||
.duration
|
||||
.to_string()
|
||||
.into_label()
|
||||
.overflow(LabelOverflow::Clip)
|
||||
.make_widget()
|
||||
})
|
||||
.unwrap_or(Space::primary().make_widget())
|
||||
}))
|
||||
.into_columns()
|
||||
|
|
|
|||
Loading…
Reference in a new issue