use crate::{ error::{Error, OptionExt}, extensions::{ProfileExt, SubmissionExt}, images::{BannerImage, IconImage, ThumbnailImage}, }; use hyaenidae_profiles::store::{File, Profile, Submission}; use hyaenidae_toolkit::{IndicatorColor, Thumbnail, Tile}; use uuid::Uuid; pub struct OwnedProfileView { pub(crate) profile: Profile, pub(crate) icon: Option, pub(crate) banner: Option, } pub struct ProfileView<'a> { pub(crate) profile: &'a Profile, pub(crate) icon: Option<&'a File>, pub(crate) banner: Option<&'a File>, } pub struct OwnedSubmissionView { pub(crate) submission: Submission, pub(crate) files: Vec, pub(crate) current_file: Option, } pub struct SubmissionView<'a> { pub(crate) author: &'a Profile, pub(crate) author_icon: Option<&'a File>, pub(crate) submission: &'a Submission, pub(crate) files: Vec<&'a File>, } impl<'a> SubmissionView<'a> { pub(crate) fn profile(&self) -> ProfileView<'a> { ProfileView { profile: self.author, icon: self.author_icon, banner: None, } } pub(crate) fn thumbnail(&self) -> Option { let file = self.files.get(0)?; let key = file.pictrs_key()?; let image = ThumbnailImage::new(key, &self.submission.title_text()); let thumb = Thumbnail::new(image, &self.submission.view_path()) .title(&self.submission.title_text()) .author(&self.author.name(), &self.author.view_path()); if self.files.len() > 1 { Some(thumb.indicator(&format!("+{}", self.files.len() - 1), IndicatorColor::White)) } else { Some(thumb) } } } impl OwnedSubmissionView { pub(crate) fn tiles(&self) -> Vec { self.files .iter() .enumerate() .filter_map(|(index, file)| { let key = file.pictrs_key()?; let title = format!("{} file {}", self.submission.title_text(), index + 1); if self .current_file .map(|f_id| f_id == file.id()) .unwrap_or(false) { Some( Tile::new(IconImage::new(key, &title)) .title(&title) .link(&self.submission.file_page_link(index)) .indicator("", IndicatorColor::Gray), ) } else { Some( Tile::new(IconImage::new(key, &title)) .title(&title) .link(&self.submission.file_page_link(index)), ) } }) .collect() } } impl OwnedProfileView { pub(crate) fn heading(&self) -> hyaenidae_toolkit::Profile { ProfileView { profile: &self.profile, icon: self.icon.as_ref(), banner: self.banner.as_ref(), } .heading() } pub(crate) fn icon(&self) -> hyaenidae_toolkit::Icon { ProfileView { profile: &self.profile, icon: self.icon.as_ref(), banner: self.banner.as_ref(), } .icon() } pub(crate) fn from_id( profile_id: Uuid, store: &hyaenidae_profiles::store::Store, ) -> Result { let profile = store.profiles.by_id(profile_id)?.req()?; let icon = if let Some(icon) = profile.icon() { store.files.by_id(icon)? } else { None }; let banner = if let Some(banner) = profile.banner() { store.files.by_id(banner)? } else { None }; Ok(OwnedProfileView { profile, icon, banner, }) } } impl<'a> ProfileView<'a> { pub(crate) fn heading(&self) -> hyaenidae_toolkit::Profile { let heading = hyaenidae_toolkit::Profile::new(self.profile.full_handle(), self.profile.view_path()); let heading = if let Some(display_name) = self.profile.display_name() { heading.display_name(display_name) } else { heading }; let heading = if let Some(description) = self.profile.description_text() { heading.description(description) } else { heading }; let heading = if let Some(icon) = self.icon_key() { heading.icon_image(IconImage::new( icon, &format!("{}'s icon", self.profile.name()), )) } else { heading }; if let Some(banner) = self.banner_key() { heading.banner_image(BannerImage::new( banner, &format!("{}'s banner", self.profile.name()), )) } else { heading } } pub(crate) fn icon(&self) -> hyaenidae_toolkit::Icon { let icon = hyaenidae_toolkit::Icon::new(self.profile.view_path()); if let Some(key) = self.icon_key() { icon.image(IconImage::new( key, &format!("{}'s icon", self.profile.name()), )) } else { icon } } fn icon_key(&self) -> Option<&str> { self.icon.and_then(|icon| icon.pictrs_key()) } fn banner_key(&self) -> Option<&str> { self.banner.and_then(|banner| banner.pictrs_key()) } }