asonix
7ed5264bef
- Don't show sensitive content to logged-out users - Add sensitive indicator on submission tiles, thumbnails - Improve mobile nav UI
208 lines
5.8 KiB
Rust
208 lines
5.8 KiB
Rust
use crate::{
|
|
error::{Error, OptionExt},
|
|
extensions::{ProfileExt, SubmissionExt},
|
|
images::{BannerImage, IconImage, ThumbnailImage},
|
|
ActixLoader,
|
|
};
|
|
use hyaenidae_profiles::store::{File, Profile, Submission};
|
|
use hyaenidae_toolkit::{IndicatorColor, Thumbnail, Tile};
|
|
use i18n_embed_fl::fl;
|
|
use uuid::Uuid;
|
|
|
|
pub struct OwnedProfileView {
|
|
pub(crate) profile: Profile,
|
|
pub(crate) icon: Option<File>,
|
|
pub(crate) banner: Option<File>,
|
|
}
|
|
|
|
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<File>,
|
|
pub(crate) current_file: Option<Uuid>,
|
|
}
|
|
|
|
pub struct SubmissionView<'a> {
|
|
pub(crate) author: &'a Profile,
|
|
pub(crate) submission: &'a Submission,
|
|
pub(crate) files: Vec<&'a File>,
|
|
}
|
|
|
|
impl<'a> SubmissionView<'a> {
|
|
pub(crate) fn thumbnail(&self) -> Option<Thumbnail> {
|
|
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());
|
|
|
|
let sensitive_color = if self.submission.is_sensitive() {
|
|
Some(IndicatorColor::Red)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
if self.files.len() > 1 {
|
|
Some(thumb.indicator(
|
|
&format!("+{}", self.files.len() - 1),
|
|
sensitive_color.unwrap_or(IndicatorColor::White),
|
|
))
|
|
} else {
|
|
if let Some(sensitive_color) = sensitive_color {
|
|
Some(thumb.indicator("", sensitive_color))
|
|
} else {
|
|
Some(thumb)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl OwnedSubmissionView {
|
|
pub(crate) fn tiles(&self, loader: &ActixLoader) -> Vec<Tile> {
|
|
self.files
|
|
.iter()
|
|
.enumerate()
|
|
.filter_map(|(index, file)| {
|
|
let key = file.pictrs_key()?;
|
|
|
|
let alt = fl!(loader, "file-num", num = (index + 1));
|
|
|
|
let tile = Tile::new(IconImage::new(key, &alt))
|
|
.link(&self.submission.file_page_link(index));
|
|
|
|
if self
|
|
.current_file
|
|
.map(|f_id| f_id == file.id())
|
|
.unwrap_or(false)
|
|
{
|
|
Some(tile.indicator("", IndicatorColor::Gray))
|
|
} else {
|
|
Some(tile)
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
}
|
|
|
|
impl OwnedProfileView {
|
|
pub(crate) fn heading(&self, loader: &ActixLoader) -> hyaenidae_toolkit::Profile {
|
|
ProfileView {
|
|
profile: &self.profile,
|
|
icon: self.icon.as_ref(),
|
|
banner: self.banner.as_ref(),
|
|
}
|
|
.heading(loader)
|
|
}
|
|
|
|
pub(crate) fn icon(&self, loader: &ActixLoader) -> hyaenidae_toolkit::Icon {
|
|
ProfileView {
|
|
profile: &self.profile,
|
|
icon: self.icon.as_ref(),
|
|
banner: self.banner.as_ref(),
|
|
}
|
|
.icon(loader)
|
|
}
|
|
|
|
pub(crate) fn banner_image(&self, loader: &ActixLoader) -> Option<BannerImage> {
|
|
ProfileView {
|
|
profile: &self.profile,
|
|
icon: self.icon.as_ref(),
|
|
banner: self.banner.as_ref(),
|
|
}
|
|
.banner_image(loader)
|
|
}
|
|
|
|
pub(crate) fn from_id(
|
|
profile_id: Uuid,
|
|
store: &hyaenidae_profiles::store::Store,
|
|
) -> Result<Self, Error> {
|
|
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, loader: &ActixLoader) -> 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(img) = self.icon_image(loader) {
|
|
heading.icon_image(img)
|
|
} else {
|
|
heading
|
|
};
|
|
|
|
if let Some(img) = self.banner_image(loader) {
|
|
heading.banner_image(img)
|
|
} else {
|
|
heading
|
|
}
|
|
}
|
|
|
|
pub(crate) fn banner_image(&self, loader: &ActixLoader) -> Option<BannerImage> {
|
|
let banner = self.banner?;
|
|
let key = banner.pictrs_key()?;
|
|
|
|
Some(BannerImage::new(
|
|
key,
|
|
&fl!(loader, "profile-banner", profileName = self.profile.name()),
|
|
))
|
|
}
|
|
|
|
fn icon_image(&self, loader: &ActixLoader) -> Option<IconImage> {
|
|
let icon = self.icon?;
|
|
let key = icon.pictrs_key()?;
|
|
|
|
Some(IconImage::new(
|
|
key,
|
|
&fl!(loader, "profile-icon", profileName = self.profile.name()),
|
|
))
|
|
}
|
|
|
|
pub(crate) fn icon(&self, loader: &ActixLoader) -> hyaenidae_toolkit::Icon {
|
|
let icon = hyaenidae_toolkit::Icon::new(self.profile.view_path());
|
|
|
|
if let Some(img) = self.icon_image(loader) {
|
|
icon.image(img)
|
|
} else {
|
|
icon
|
|
}
|
|
}
|
|
}
|