use crate::{ error::{Error, OptionExt}, extensions::{ProfileExt, SubmissionExt}, images::{BannerImage, IconImage}, pagination::{ submission::{draft_page, main_page, Cache}, PageSource, }, views::ProfileView, ActixLoader, State, }; use hyaenidae_profiles::store::{File, Profile}; use hyaenidae_toolkit::{Button, FileInput, IndicatorColor, TextInput, Tile}; use i18n_embed_fl::fl; use uuid::Uuid; const ACCEPT_TYPES: &str = "image/png,image/webp,image/jpeg,image/gif,.png,.webp,.jpg,.jpeg,.gif"; pub struct ViewProfileState { cache: Cache, profile_id: Uuid, submissions: Vec, previous_id: Option, next_id: Option, reset: bool, path: String, drafts: bool, is_self: bool, is_follow_requested: bool, is_followed: bool, is_blocked: bool, viewer_exists: bool, } pub struct EditProfileState { pub(crate) profile: Profile, icon: Option, banner: Option, display_name_value: Option, display_name_error: Option, description_value: Option, description_error: Option, pub(crate) icon_error: Option, pub(crate) banner_error: Option, login_required_value: Option, pub(crate) login_required_error: Option, } impl ViewProfileState { fn unwrap_profile(&self) -> &Profile { self.cache.profile_map.get(&self.profile_id).unwrap() } pub(crate) fn profile<'a>(&'a self) -> ProfileView<'a> { let profile = self.cache.profile_map.get(&self.profile_id).unwrap(); let icon = if let Some(icon) = profile.icon() { self.cache.file_map.get(&icon) } else { None }; let banner = if let Some(banner) = profile.banner() { self.cache.file_map.get(&banner) } else { None }; ProfileView { profile, icon, banner, } } pub(crate) fn submissions(&self) -> Vec { self.submissions .iter() .filter_map(move |submission_id| { let submission = self.cache.submission_map.get(&submission_id)?; let author = self.cache.profile_map.get(&submission.profile_id())?; let file_id = submission.files().get(0)?; let file = self.cache.file_map.get(&file_id)?; let key = file.pictrs_key()?; let tile = Tile::new(IconImage::new(key, submission.title())) .title(&submission.title_text()) .description(&author.name()) .link(&submission.view_path()); let sensitive_color = if submission.is_sensitive() { Some(IndicatorColor::Red) } else { None }; if submission.files().len() > 1 { Some(tile.indicator( &format!("+{}", submission.files().len() - 1), sensitive_color.unwrap_or(IndicatorColor::White), )) } else { if let Some(sensitive_color) = sensitive_color { Some(tile.indicator("", sensitive_color)) } else { Some(tile) } } }) .collect() } fn view_profile_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "view-profile-button")) .href(&self.unwrap_profile().view_path()) } fn account_settings_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "account-settings-button")).href("/session/account") } fn edit_profile_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "edit-profile-button")).href("/profiles/current") } fn switch_profile_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "switch-profile-button")).href("/profiles/change") } fn view_drafts_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "drafts-button")).href("/profiles/drafts") } fn cancel_request_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "cancel-follow-button")) .href(&self.unwrap_profile().unfollow_path()) } fn block_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "block-button")).form(&self.unwrap_profile().block_path()) } fn report_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "report-button")).href(&self.unwrap_profile().report_path()) } fn unfollow_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "unfollow-button")) .form(&self.unwrap_profile().unfollow_path()) } fn unblock_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "unblock-button")) .form(&self.unwrap_profile().unblock_path()) } fn follow_button(&self, loader: &ActixLoader) -> Button { Button::secondary(&fl!(loader, "follow-button")).form(&self.unwrap_profile().follow_path()) } pub(crate) fn buttons(&self, loader: &ActixLoader) -> Vec