hyaenidae/server/src/home.rs

132 lines
3.5 KiB
Rust
Raw Normal View History

use crate::{
error::Error,
extensions::{ProfileExt, SubmissionExt},
images::IconImage,
middleware::UserProfile,
nav::NavState,
pagination::{
submission::{home_page, Cache},
PageSource,
},
profiles::SubmissionPage,
State,
};
use actix_web::{web, HttpRequest, HttpResponse};
use hyaenidae_accounts::User;
use hyaenidae_toolkit::{Button, IndicatorColor, Tile};
use uuid::Uuid;
pub(crate) async fn home(
req: HttpRequest,
page: Option<web::Query<SubmissionPage>>,
user: Option<User>,
profile: Option<UserProfile>,
nav_state: NavState,
state: web::Data<State>,
) -> Result<HttpResponse, Error> {
let profile = profile.map(|p| p.0);
if user.is_some() && profile.is_none() {
return Ok(crate::profiles::to_change_profile_page());
}
let viewer = profile.map(|p| p.id());
let view = ViewHomeState::build(
req.path().to_owned(),
viewer,
page.map(|q| q.into_inner().into()),
&state,
)
.await?;
crate::rendered(HttpResponse::Ok(), |cursor| {
crate::templates::index(cursor, &view, &nav_state)
})
}
pub struct ViewHomeState {
cache: Cache,
submissions: Vec<Uuid>,
previous_id: Option<Uuid>,
next_id: Option<Uuid>,
reset: bool,
path: String,
}
impl ViewHomeState {
async fn build(
path: String,
viewer: Option<Uuid>,
source: Option<PageSource>,
state: &State,
) -> Result<Self, Error> {
let store = state.profiles.clone();
let state = actix_web::web::block(move || {
let mut cache = Cache::new();
let page = home_page(viewer, &store, &mut cache, source);
Ok(ViewHomeState {
cache,
submissions: page.items,
next_id: page.next,
previous_id: page.prev,
reset: page.reset,
path,
})
})
.await?;
Ok(state)
}
pub(crate) fn submissions(&self) -> Vec<Tile> {
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_text()))
.title(&submission.title_text())
.description(&author.name())
.link(&submission.view_path());
if submission.files().len() > 1 {
Some(tile.indicator(
&format!("+{}", submission.files().len() - 1),
IndicatorColor::White,
))
} else {
Some(tile)
}
})
.collect()
}
pub(crate) fn nav(&self) -> Vec<Button> {
let mut nav = vec![];
if let Some(prev) = self.previous_id {
nav.push(Button::secondary("Previous").href(&format!("{}?min={}", self.path, prev)));
}
if let Some(next) = self.next_id {
nav.push(Button::secondary("Next").href(&format!("{}?max={}", self.path, next)));
}
if self.reset {
nav.push(Button::secondary("Reset").href(&self.path));
}
nav
}
}