@@ -1,6 +1,7 @@
|
||||
use crate::urls::{UrlCache, UrlMimes};
|
||||
use crate::Result;
|
||||
use egui::TextureHandle;
|
||||
use image::{Delay, Frame};
|
||||
use poll_promise::Promise;
|
||||
|
||||
use egui::ColorImage;
|
||||
@@ -80,31 +81,8 @@ impl MediaCache {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn fetch(image: &str) -> Result<Image> {
|
||||
let m_cached_promise = img_cache.map().get(image);
|
||||
if m_cached_promise.is_none() {
|
||||
let res = crate::images::fetch_img(
|
||||
img_cache,
|
||||
ui.ctx(),
|
||||
&image,
|
||||
ImageType::Content(width.round() as u32, height.round() as u32),
|
||||
);
|
||||
img_cache.map_mut().insert(image.to_owned(), res);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn write(cache_dir: &path::Path, url: &str, data: ColorImage) -> Result<()> {
|
||||
let file_path = cache_dir.join(Self::key(url));
|
||||
if let Some(p) = file_path.parent() {
|
||||
create_dir_all(p)?;
|
||||
}
|
||||
let file = File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(file_path)?;
|
||||
let file = Self::create_file(cache_dir, url)?;
|
||||
let encoder = image::codecs::webp::WebPEncoder::new_lossless(file);
|
||||
|
||||
encoder.encode(
|
||||
@@ -117,6 +95,33 @@ impl MediaCache {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_file(cache_dir: &path::Path, url: &str) -> Result<File> {
|
||||
let file_path = cache_dir.join(Self::key(url));
|
||||
if let Some(p) = file_path.parent() {
|
||||
create_dir_all(p)?;
|
||||
}
|
||||
Ok(File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(file_path)?)
|
||||
}
|
||||
|
||||
pub fn write_gif(cache_dir: &path::Path, url: &str, data: Vec<ImageFrame>) -> Result<()> {
|
||||
let file = Self::create_file(cache_dir, url)?;
|
||||
|
||||
let mut encoder = image::codecs::gif::GifEncoder::new(file);
|
||||
for img in data {
|
||||
let buf = color_image_to_rgba(img.image);
|
||||
let frame = Frame::from_parts(buf, 0, 0, Delay::from_saturating_duration(img.delay));
|
||||
if let Err(e) = encoder.encode_frame(frame) {
|
||||
tracing::error!("problem encoding frame: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn key(url: &str) -> String {
|
||||
let k: String = sha2::Sha256::digest(url.as_bytes()).encode_hex();
|
||||
PathBuf::from(&k[0..2])
|
||||
@@ -174,12 +179,18 @@ impl MediaCache {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: temporary...
|
||||
pub fn get_texture(textured_image: &TexturedImage) -> &TextureHandle {
|
||||
match textured_image {
|
||||
TexturedImage::Static(texture_handle) => texture_handle,
|
||||
TexturedImage::Animated(_animation) => todo!(), // Temporary...
|
||||
}
|
||||
fn color_image_to_rgba(color_image: ColorImage) -> image::RgbaImage {
|
||||
let width = color_image.width() as u32;
|
||||
let height = color_image.height() as u32;
|
||||
|
||||
let rgba_pixels: Vec<u8> = color_image
|
||||
.pixels
|
||||
.iter()
|
||||
.flat_map(|color| color.to_array()) // Convert Color32 to `[u8; 4]`
|
||||
.collect();
|
||||
|
||||
image::RgbaImage::from_raw(width, height, rgba_pixels)
|
||||
.expect("Failed to create RgbaImage from ColorImage")
|
||||
}
|
||||
|
||||
pub struct Images {
|
||||
|
||||
@@ -32,7 +32,8 @@ pub use error::{Error, FilterError};
|
||||
pub use filter::{FilterState, FilterStates, UnifiedSubscription};
|
||||
pub use fonts::NamedFontFamily;
|
||||
pub use imgcache::{
|
||||
get_texture, GifState, GifStateMap, Images, MediaCache, MediaCacheType, TexturedImage,
|
||||
Animation, GifState, GifStateMap, ImageFrame, Images, MediaCache, MediaCacheType,
|
||||
MediaCacheValue, TextureFrame, TexturedImage,
|
||||
};
|
||||
pub use muted::{MuteFun, Muted};
|
||||
pub use note::{NoteRef, RootIdError, RootNoteId, RootNoteIdBuf};
|
||||
|
||||
@@ -11,7 +11,7 @@ use egui::TextBuffer;
|
||||
use poll_promise::Promise;
|
||||
use url::Url;
|
||||
|
||||
use crate::Error;
|
||||
use crate::{Error, MediaCacheType};
|
||||
|
||||
const FILE_NAME: &str = "urls.bin";
|
||||
const SAVE_INTERVAL: Duration = Duration::from_secs(60);
|
||||
@@ -230,10 +230,26 @@ impl SupportedMimeType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_mime(mime: mime_guess::mime::Mime) -> Result<Self, Error> {
|
||||
if is_mime_supported(&mime) {
|
||||
Ok(Self { mime })
|
||||
} else {
|
||||
Err(Error::Generic("Unsupported mime type".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn to_mime(&self) -> &str {
|
||||
self.mime.essence_str()
|
||||
}
|
||||
|
||||
pub fn to_cache_type(&self) -> MediaCacheType {
|
||||
if self.mime == mime_guess::mime::IMAGE_GIF {
|
||||
MediaCacheType::Gif
|
||||
} else {
|
||||
MediaCacheType::Image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_mime_supported(mime: &mime_guess::Mime) -> bool {
|
||||
@@ -248,8 +264,8 @@ fn url_has_supported_mime(url: &str) -> MimeHostedAtUrl {
|
||||
.extension()
|
||||
.and_then(|ext| ext.to_str())
|
||||
{
|
||||
if SupportedMimeType::from_extension(ext).is_ok() {
|
||||
return MimeHostedAtUrl::Yes;
|
||||
if let Ok(supported) = SupportedMimeType::from_extension(ext) {
|
||||
return MimeHostedAtUrl::Yes(supported.to_cache_type());
|
||||
} else {
|
||||
return MimeHostedAtUrl::No;
|
||||
}
|
||||
@@ -260,21 +276,23 @@ fn url_has_supported_mime(url: &str) -> MimeHostedAtUrl {
|
||||
MimeHostedAtUrl::Maybe
|
||||
}
|
||||
|
||||
pub fn supported_mime_hosted_at_url(urls: &mut UrlMimes, url: &str) -> bool {
|
||||
pub fn supported_mime_hosted_at_url(urls: &mut UrlMimes, url: &str) -> Option<MediaCacheType> {
|
||||
match url_has_supported_mime(url) {
|
||||
MimeHostedAtUrl::Yes => true,
|
||||
MimeHostedAtUrl::Yes(cache_type) => Some(cache_type),
|
||||
MimeHostedAtUrl::Maybe => urls
|
||||
.get(url)
|
||||
.and_then(|s| s.parse::<mime_guess::mime::Mime>().ok())
|
||||
.map_or(false, |mime: mime_guess::mime::Mime| {
|
||||
is_mime_supported(&mime)
|
||||
.and_then(|mime: mime_guess::mime::Mime| {
|
||||
SupportedMimeType::from_mime(mime)
|
||||
.ok()
|
||||
.map(|s| s.to_cache_type())
|
||||
}),
|
||||
MimeHostedAtUrl::No => false,
|
||||
MimeHostedAtUrl::No => None,
|
||||
}
|
||||
}
|
||||
|
||||
enum MimeHostedAtUrl {
|
||||
Yes,
|
||||
Yes(MediaCacheType),
|
||||
Maybe,
|
||||
No,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user