2021-01-22 05:47:47 +00:00
|
|
|
use crate::{
|
|
|
|
error::Error,
|
2021-01-23 02:19:58 +00:00
|
|
|
extensions::{ProfileExt, SubmissionExt},
|
2021-01-22 05:47:47 +00:00
|
|
|
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;
|
2021-01-23 01:54:48 +00:00
|
|
|
use hyaenidae_toolkit::{BannerColor, Button, Tile};
|
2021-01-22 05:47:47 +00:00
|
|
|
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()?;
|
|
|
|
|
2021-01-23 02:19:58 +00:00
|
|
|
let tile = Tile::new(IconImage::new(key, &submission.title_text()))
|
|
|
|
.title(&submission.title_text())
|
|
|
|
.description(&author.name())
|
2021-01-22 05:47:47 +00:00
|
|
|
.link(&submission.view_path());
|
|
|
|
|
2021-01-23 01:54:48 +00:00
|
|
|
if submission.files().len() > 1 {
|
|
|
|
Some(tile.banner(
|
|
|
|
&format!("+{}", submission.files().len() - 1),
|
|
|
|
BannerColor::White,
|
|
|
|
))
|
|
|
|
} else {
|
|
|
|
Some(tile)
|
|
|
|
}
|
2021-01-22 05:47:47 +00:00
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn nav(&self, dark: bool) -> Vec<Button> {
|
|
|
|
let mut nav = vec![];
|
|
|
|
|
|
|
|
if let Some(prev) = self.previous_id {
|
|
|
|
nav.push(
|
|
|
|
Button::secondary("Previous")
|
|
|
|
.href(&format!("{}?min={}", self.path, prev))
|
|
|
|
.dark(dark),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(next) = self.next_id {
|
|
|
|
nav.push(
|
|
|
|
Button::secondary("Next")
|
|
|
|
.href(&format!("{}?max={}", self.path, next))
|
|
|
|
.dark(dark),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.reset {
|
|
|
|
nav.push(Button::secondary("Reset").href(&self.path).dark(dark));
|
|
|
|
}
|
|
|
|
|
|
|
|
nav
|
|
|
|
}
|
|
|
|
}
|