Skip to content

Commit

Permalink
Cache album art (#495)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacksongoode authored Jul 11, 2024
1 parent 1810b6e commit 23bd55e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
27 changes: 27 additions & 0 deletions psst-gui/src/webapi/cache.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::{
collections::hash_map::DefaultHasher,
fs::{self, File},
hash::{Hash, Hasher},
path::PathBuf,
sync::Arc,
};

use druid::image;
use druid::ImageBuf;
use lru_cache::LruCache;
use parking_lot::Mutex;
Expand Down Expand Up @@ -31,6 +34,30 @@ impl WebApiCache {
self.images.lock().insert(uri, image);
}

pub fn get_image_from_disk(&self, uri: &Arc<str>) -> Option<ImageBuf> {
let hash = Self::hash_uri(uri);
self.key("images", &format!("{:016x}", hash))
.and_then(|path| std::fs::read(path).ok())
.and_then(|bytes| image::load_from_memory(&bytes).ok())
.map(ImageBuf::from_dynamic_image)
}

pub fn save_image_to_disk(&self, uri: &Arc<str>, data: &[u8]) {
let hash = Self::hash_uri(uri);
if let Some(path) = self.key("images", &format!("{:016x}", hash)) {
if let Some(parent) = path.parent() {
let _ = std::fs::create_dir_all(parent);
}
let _ = std::fs::write(path, data);
}
}

fn hash_uri(uri: &str) -> u64 {
let mut hasher = DefaultHasher::new();
uri.hash(&mut hasher);
hasher.finish()
}

pub fn get(&self, bucket: &str, key: &str) -> Option<File> {
self.key(bucket, key).and_then(|path| File::open(path).ok())
}
Expand Down
13 changes: 13 additions & 0 deletions psst-gui/src/webapi/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,15 @@ impl WebApi {
}

pub fn get_image(&self, uri: Arc<str>) -> Result<ImageBuf, Error> {
if let Some(cached_image) = self.cache.get_image(&uri) {
return Ok(cached_image);
}

if let Some(disk_cached_image) = self.cache.get_image_from_disk(&uri) {
self.cache.set_image(uri.clone(), disk_cached_image.clone());
return Ok(disk_cached_image);
}

let response = self.agent.get(&uri).call()?;
let format = match response.content_type() {
"image/jpeg" => Some(ImageFormat::Jpeg),
Expand All @@ -734,6 +743,10 @@ impl WebApi {
};
let mut body = Vec::new();
response.into_reader().read_to_end(&mut body)?;

// Save raw image data to disk cache
self.cache.save_image_to_disk(&uri, &body);

let image = if let Some(format) = format {
image::load_from_memory_with_format(&body, format)?
} else {
Expand Down

0 comments on commit 23bd55e

Please sign in to comment.