diff --git a/crates/notedeck/src/lib.rs b/crates/notedeck/src/lib.rs index 741437ca..516d9f57 100644 --- a/crates/notedeck/src/lib.rs +++ b/crates/notedeck/src/lib.rs @@ -49,6 +49,7 @@ pub use theme::ColorTheme; pub use time::time_ago_since; pub use timecache::TimeCached; pub use unknowns::{get_unknown_note_ids, NoteRefsUnkIdAction, SingleUnkIdAction, UnknownIds}; +pub use urls::{supported_mime_hosted_at_url, UrlMimes}; pub use user_account::UserAccount; // export libs diff --git a/crates/notedeck/src/urls.rs b/crates/notedeck/src/urls.rs index 21dce4d3..ee7c77d5 100644 --- a/crates/notedeck/src/urls.rs +++ b/crates/notedeck/src/urls.rs @@ -9,6 +9,7 @@ use std::{ use egui::TextBuffer; use poll_promise::Promise; +use url::Url; use crate::Error; @@ -218,7 +219,6 @@ struct SupportedMimeType { } impl SupportedMimeType { - #[allow(unused)] pub fn from_extension(extension: &str) -> Result { if let Some(mime) = mime_guess::from_ext(extension) .first() @@ -239,3 +239,42 @@ impl SupportedMimeType { fn is_mime_supported(mime: &mime_guess::Mime) -> bool { mime.type_() == mime_guess::mime::IMAGE } + +fn url_has_supported_mime(url: &str) -> MimeHostedAtUrl { + if let Ok(url) = Url::parse(url) { + if let Some(path) = url.path_segments() { + if let Some(file_name) = path.last() { + if let Some(ext) = std::path::Path::new(file_name) + .extension() + .and_then(|ext| ext.to_str()) + { + if SupportedMimeType::from_extension(ext).is_ok() { + return MimeHostedAtUrl::Yes; + } else { + return MimeHostedAtUrl::No; + } + } + } + } + } + MimeHostedAtUrl::Maybe +} + +pub fn supported_mime_hosted_at_url(urls: &mut UrlMimes, url: &str) -> bool { + match url_has_supported_mime(url) { + MimeHostedAtUrl::Yes => true, + MimeHostedAtUrl::Maybe => urls + .get(url) + .and_then(|s| s.parse::().ok()) + .map_or(false, |mime: mime_guess::mime::Mime| { + is_mime_supported(&mime) + }), + MimeHostedAtUrl::No => false, + } +} + +enum MimeHostedAtUrl { + Yes, + Maybe, + No, +} diff --git a/crates/notedeck_columns/src/ui/note/contents.rs b/crates/notedeck_columns/src/ui/note/contents.rs index 26ffd5c2..243e7f77 100644 --- a/crates/notedeck_columns/src/ui/note/contents.rs +++ b/crates/notedeck_columns/src/ui/note/contents.rs @@ -8,7 +8,7 @@ use egui::{Color32, Hyperlink, Image, RichText}; use nostrdb::{BlockType, Mention, Ndb, Note, NoteKey, Transaction}; use tracing::warn; -use notedeck::{Images, NoteCache}; +use notedeck::{supported_mime_hosted_at_url, Images, NoteCache}; pub struct NoteContents<'a> { ndb: &'a Ndb, @@ -127,10 +127,6 @@ pub fn render_note_preview( .inner } -fn is_image_link(url: &str) -> bool { - url.ends_with("png") || url.ends_with("jpg") || url.ends_with("jpeg") -} - #[allow(clippy::too_many_arguments)] fn render_note_contents( ui: &mut egui::Ui, @@ -212,9 +208,12 @@ fn render_note_contents( } BlockType::Url => { - let lower_url = block.as_str().to_lowercase(); - if !hide_media && is_image_link(&lower_url) { - images.push(block.as_str().to_string()); + if !hide_media { + let url = block.as_str().to_string(); + + if supported_mime_hosted_at_url(&mut img_cache.urls, &url) { + images.push(url); + } } else { #[cfg(feature = "profiling")] puffin::profile_scope!("url contents");