diff options
author | Colin Reeder <colin@vpzom.click> | 2020-06-29 23:34:28 -0600 |
---|---|---|
committer | Colin Reeder <colin@vpzom.click> | 2020-06-29 23:34:28 -0600 |
commit | 34126a8421eab043202b693fb55df13d3334a8f7 (patch) | |
tree | 6234e84786a5ef9e9268cf8f87b8fe73eef41716 /src/routes/mod.rs | |
parent | 1c9e1a95cfdd1394724f4edb48a5598438e0d163 (diff) |
Split off more modules
Diffstat (limited to 'src/routes/mod.rs')
-rw-r--r-- | src/routes/mod.rs | 330 |
1 files changed, 4 insertions, 326 deletions
diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 6e3a7d8..06f5448 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -2,6 +2,10 @@ use serde_derive::Deserialize; use std::borrow::Cow; use std::sync::Arc; +use crate::components::{Content, HTPage, PostItem, UserLink}; +use crate::resp_types::{RespPostCommentInfo, RespPostListPost}; +use crate::PageBaseData; + mod communities; mod posts; mod r#static; @@ -54,32 +58,6 @@ fn with_auth( Ok(new_req) } -fn author_is_me(author: &Option<RespMinimalAuthorInfo<'_>>, login: &Option<RespLoginInfo>) -> bool { - if let Some(author) = author { - if let Some(login) = login { - if author.id == login.user.id { - return true; - } - } - } - false -} - -#[derive(Deserialize, Debug)] -struct RespLoginInfoUser { - id: i64, -} - -#[derive(Deserialize, Debug)] -struct RespLoginInfo { - user: RespLoginInfoUser, -} - -#[derive(Debug)] -struct PageBaseData { - login: Option<RespLoginInfo>, -} - async fn fetch_base_data( backend_host: &str, http_client: &crate::HttpClient, @@ -106,306 +84,6 @@ async fn fetch_base_data( Ok(PageBaseData { login }) } -#[derive(Deserialize, Debug)] -struct RespMinimalAuthorInfo<'a> { - id: i64, - username: Cow<'a, str>, - local: bool, - host: Cow<'a, str>, -} - -trait HavingContent { - fn content_text(&self) -> Option<&str>; - fn content_html(&self) -> Option<&str>; -} - -#[derive(Deserialize, Debug)] -struct RespPostListPost<'a> { - id: i64, - title: Cow<'a, str>, - href: Option<Cow<'a, str>>, - content_text: Option<Cow<'a, str>>, - content_html: Option<Cow<'a, str>>, - #[serde(borrow)] - author: Option<RespMinimalAuthorInfo<'a>>, - created: Cow<'a, str>, - #[serde(borrow)] - community: RespMinimalCommunityInfo<'a>, -} - -impl<'a> HavingContent for RespPostListPost<'a> { - fn content_text(&self) -> Option<&str> { - self.content_text.as_deref() - } - fn content_html(&self) -> Option<&str> { - self.content_html.as_deref() - } -} - -#[derive(Deserialize, Debug)] -struct RespPostCommentInfo<'a> { - id: i64, - #[serde(borrow)] - author: Option<RespMinimalAuthorInfo<'a>>, - created: Cow<'a, str>, - content_text: Option<Cow<'a, str>>, - content_html: Option<Cow<'a, str>>, - #[serde(borrow)] - replies: Option<Vec<RespPostCommentInfo<'a>>>, -} - -impl<'a> HavingContent for RespPostCommentInfo<'a> { - fn content_text(&self) -> Option<&str> { - self.content_text.as_deref() - } - fn content_html(&self) -> Option<&str> { - self.content_html.as_deref() - } -} - -#[derive(Deserialize, Debug)] -struct RespPostInfo<'a> { - #[serde(flatten, borrow)] - pub base: RespPostListPost<'a>, - pub score: i64, - #[serde(borrow)] - pub comments: Vec<RespPostCommentInfo<'a>>, -} - -impl<'a> AsRef<RespPostListPost<'a>> for RespPostInfo<'a> { - fn as_ref(&self) -> &RespPostListPost<'a> { - &self.base - } -} - -#[render::component] -fn HTPage<'base_data, Children: render::Render>( - base_data: &'base_data PageBaseData, - children: Children, -) { - render::rsx! { - <> - <render::html::HTML5Doctype /> - <html> - <head> - <meta charset={"utf-8"} /> - <link rel={"stylesheet"} href={"/static/main.css"} /> - </head> - <body> - <header class={"mainHeader"}> - <div class={"left actionList"}> - <a href={"/"} class={"siteName"}>{"lotide"}</a> - <a href={"/communities"}>{"Communities"}</a> - </div> - <div class={"right actionList"}> - { - match base_data.login { - Some(_) => None, - None => { - Some(render::rsx! { - <a href={"/login"}>{"Login"}</a> - }) - } - } - } - </div> - </header> - {children} - </body> - </html> - </> - } -} - -fn abbreviate_link(href: &str) -> &str { - // Attempt to find the hostname from the URL - match href.find("://") { - Some(idx1) => match href[(idx1 + 3)..].find('/') { - Some(idx2) => Some(&href[(idx1 + 3)..(idx1 + 3 + idx2)]), - None => None, - }, - None => None, - } - .unwrap_or(href) -} - -#[render::component] -fn PostItem<'post>(post: &'post RespPostListPost<'post>, in_community: bool) { - render::rsx! { - <li> - <a href={format!("/posts/{}", post.id)}> - {post.title.as_ref()} - </a> - { - if let Some(href) = &post.href { - Some(render::rsx! { - <> - {" "} - <em><a href={href.as_ref()}>{abbreviate_link(&href)}{" ↗"}</a></em> - </> - }) - } else { - None - } - } - <br /> - {"Submitted by "}<UserLink user={post.author.as_ref()} /> - { - if !in_community { - Some(render::rsx! { - <>{" to "}<CommunityLink community={&post.community} /></> - }) - } else { - None - } - } - </li> - } -} - -#[derive(Deserialize, Debug)] -struct RespMinimalCommunityInfo<'a> { - id: i64, - name: Cow<'a, str>, - local: bool, - host: Cow<'a, str>, -} - -struct UserLink<'user> { - user: Option<&'user RespMinimalAuthorInfo<'user>>, -} - -impl<'user> render::Render for UserLink<'user> { - fn render_into<W: std::fmt::Write>(self, writer: &mut W) -> std::fmt::Result { - match self.user { - None => "[unknown]".render_into(writer), - Some(user) => { - let href = format!("/users/{}", user.id); - (render::rsx! { - <a href={&href}> - { - (if user.local { - user.username.as_ref().into() - } else { - Cow::Owned(format!("{}@{}", user.username, user.host)) - }).as_ref() - } - </a> - }) - .render_into(writer) - } - } - } -} - -struct CommunityLink<'community> { - community: &'community RespMinimalCommunityInfo<'community>, -} -impl<'community> render::Render for CommunityLink<'community> { - fn render_into<W: std::fmt::Write>(self, writer: &mut W) -> std::fmt::Result { - let community = &self.community; - - let href = format!("/communities/{}", community.id); - (render::rsx! { - <a href={&href}> - { - (if community.local { - community.name.as_ref().into() - } else { - Cow::Owned(format!("{}@{}", community.name, community.host)) - }).as_ref() - } - </a> - }) - .render_into(writer) - } -} - -struct Content<'a, T: HavingContent + 'a> { - src: &'a T, -} - -impl<'a, T: HavingContent + 'a> render::Render for Content<'a, T> { - fn render_into<W: std::fmt::Write>(self, writer: &mut W) -> std::fmt::Result { - match self.src.content_html() { - Some(html) => { - let cleaned = ammonia::clean(&html); - writer.write_str("<p>")?; - render::raw!(cleaned.as_ref()).render_into(writer)?; - writer.write_str("</p>")?; - } - None => match self.src.content_text() { - Some(text) => { - writer.write_str("<p>")?; - text.render_into(writer)?; - writer.write_str("</p>")?; - } - None => {} - }, - } - - Ok(()) - } -} - -#[render::component] -fn Comment<'comment, 'base_data>( - comment: &'comment RespPostCommentInfo<'comment>, - base_data: &'base_data PageBaseData, -) { - render::rsx! { - <li> - <small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small> - <Content src={comment} /> - <div class={"actionList"}> - { - if base_data.login.is_some() { - Some(render::rsx! { - <> - <form method={"POST"} action={format!("/comments/{}/like", comment.id)} style={"display: inline"}> - <button r#type={"submit"}>{"Like"}</button> - </form> - <a href={format!("/comments/{}", comment.id)}>{"reply"}</a> - </> - }) - } else { - None - } - } - { - if author_is_me(&comment.author, &base_data.login) { - Some(render::rsx! { - <a href={format!("/comments/{}/delete", comment.id)}>{"delete"}</a> - }) - } else { - None - } - } - </div> - - { - match &comment.replies { - Some(replies) => { - Some(render::rsx! { - <ul> - { - replies.iter().map(|reply| { - render::rsx! { - <Comment comment={reply} base_data /> - } - }) - .collect::<Vec<_>>() - } - </ul> - }) - }, - None => None, - } - } - </li> - } -} - fn html_response(html: String) -> hyper::Response<hyper::Body> { let mut res = hyper::Response::new(html.into()); res.headers_mut().insert( |