~vpzom/hitide

c818c3a5456fca7f7903cb37922e4fc7a57a3884 — Colin Reeder 1 year, 2 months ago 47838d5
List post likes
4 files changed, 99 insertions(+), 3 deletions(-)

M res/lang/en.ftl
M res/lang/eo.ftl
M src/resp_types.rs
M src/routes/posts.rs
M res/lang/en.ftl => res/lang/en.ftl +5 -0
@@ 8,6 8,7 @@ about_versions = This instance is running hitide { $hitide_version } on { $backe
add_by_remote_id = Add by ID:
all = All
all_title = The Whole Known Network
and_more = …and more
by = by
comment = Comment
comment_delete_title = Delete Comment


@@ 31,6 32,8 @@ home_follow_prompt1 = Why not
home_follow_prompt2 = follow some communities?
like = Like
like_undo = Unlike
liked_by = Liked by:
likes = Likes
local = Local
login = Login
login_signup_link = create a new account


@@ 47,12 50,14 @@ or_start = Or
password_prompt = Password:
post_delete_question = Delete this post?
post_delete_title = Delete Post
post_likes_nothing = Looks like nobody has liked this post yet.
post_new = New Post
register = Register
remote = Remote
reply = reply
reply_submit = Reply
reply_to = Reply to
score = { $score } likes
submit = Submit
submitted = Submitted
text_with_markdown = Text (markdown supported)

M res/lang/eo.ftl => res/lang/eo.ftl +6 -1
@@ 6,6 6,7 @@ about_text2 = Por pli da informo aŭ vidi la fontkodon, kontrolu la
about_sourcehut = SourceHut paĝon
about_versions = Ĉi tiu servilo uzas hitide { $hitide_version } kun { $backend_name } { $backend_version }.
add_by_remote_id = Aldoni per ID:
and_more = …kaj pli
all = Ĉiuj
all_title = La Tuta Konata Reto
by = de


@@ 31,6 32,8 @@ home_follow_prompt1 = Kial ne
home_follow_prompt2 = aboni iujn komunumojn?
like = Ŝati
like_undo = Ne plu ŝati
liked_by = Ŝatata de:
likes = Ŝatantoj
local = Loka
login = Ensaluti
login_signup_link = krei novan konton


@@ 47,12 50,14 @@ or_start = Aŭ
password_prompt = Pasvorto:
post_delete_question = Ĉu vi volas forigi ĉi tiun poŝton?
post_delete_title = Forigi Poŝton
post_likes_nothing = Ŝajnas, ke neniu ankoraŭ ŝatis ĉi tion poŝton.
post_new = Nova Poŝto
register = Registriĝi
remote = Fora
reply = respondi
reply_to = Respondo al
reply_submit = Respondi
reply_to = Respondo al
score = { $score } ŝatantoj
submit = Sendi
submitted = Afiŝita
text_with_markdown = Teksto (markdown estas permesita)

M src/resp_types.rs => src/resp_types.rs +11 -0
@@ 220,3 220,14 @@ pub struct RespNotification<'a> {

    pub unseen: bool,
}

#[derive(Deserialize, Debug)]
pub struct JustUser<'a> {
    pub user: RespMinimalAuthorInfo<'a>,
}

#[derive(Deserialize, Debug)]
pub struct RespList<'a, T: std::fmt::Debug + 'a> {
    pub items: Vec<T>,
    pub next_page: Option<Cow<'a, str>>,
}

M src/routes/posts.rs => src/routes/posts.rs +77 -2
@@ 3,7 3,7 @@ use super::{
    res_to_error,
};
use crate::components::{Comment, CommunityLink, Content, HTPage, TimeAgo, UserLink};
use crate::resp_types::RespPostInfo;
use crate::resp_types::{JustUser, RespList, RespPostInfo};
use crate::util::author_is_me;
use std::sync::Arc;



@@ 50,7 50,9 @@ async fn page_post(
        <HTPage base_data={&base_data} lang={&lang} title={title}>
            <h1>{title}</h1>
            <p>
                <em>{post.score.to_string()}{" points"}</em>
                <a href={format!("/posts/{}/likes", post_id)}>
                    <em>{lang.tr("score", Some(&fluent::fluent_args!["score" => post.score]))}</em>
                </a>
                {" "}
                {
                    if base_data.login.is_some() {


@@ 234,6 236,75 @@ async fn handler_post_like(
        .body("Successfully liked.".into())?)
}

async fn page_post_likes(
    params: (i64,),
    ctx: Arc<crate::RouteContext>,
    req: hyper::Request<hyper::Body>,
) -> Result<hyper::Response<hyper::Body>, crate::Error> {
    let (post_id,) = params;

    let lang = crate::get_lang_for_req(&req);
    let cookies = get_cookie_map_for_req(&req)?;

    let base_data =
        fetch_base_data(&ctx.backend_host, &ctx.http_client, req.headers(), &cookies).await?;

    let api_res = res_to_error(
        ctx.http_client
            .request(for_client(
                hyper::Request::get(format!(
                    "{}/api/unstable/posts/{}/likes",
                    ctx.backend_host, post_id,
                ))
                .body(Default::default())?,
                req.headers(),
                &cookies,
            )?)
            .await?,
    )
    .await?;
    let api_res = hyper::body::to_bytes(api_res.into_body()).await?;
    let api_res: RespList<JustUser> = serde_json::from_slice(&api_res)?;

    Ok(html_response(render::html! {
        <HTPage base_data={&base_data} lang={&lang} title={&lang.tr("likes", None)}>
        {
            if api_res.items.is_empty() {
                Some(render::rsx! { <p>{lang.tr("post_likes_nothing", None)}</p> })
            } else {
                None
            }
        }
        {
            if api_res.items.is_empty() {
                None
            } else {
                Some(render::rsx! {
                    <>
                        <p>{lang.tr("liked_by", None)}</p>
                        <ul>
                            {
                                api_res.items.iter().map(|like| {
                                    render::rsx! { <li><UserLink user={Some(&like.user)} /></li> }
                                })
                                .collect::<Vec<_>>()
                            }
                            {
                                if api_res.next_page.is_some() {
                                    Some(render::rsx! { <li>{lang.tr("and_more", None)}</li> })
                                } else {
                                    None
                                }
                            }
                        </ul>
                    </>
                })
            }
        }
        </HTPage>
    }))
}

async fn handler_post_unlike(
    params: (i64,),
    ctx: Arc<crate::RouteContext>,


@@ 318,6 389,10 @@ pub fn route_posts() -> crate::RouteNode<()> {
                crate::RouteNode::new().with_handler_async("POST", handler_post_like),
            )
            .with_child(
                "likes",
                crate::RouteNode::new().with_handler_async("GET", page_post_likes),
            )
            .with_child(
                "unlike",
                crate::RouteNode::new().with_handler_async("POST", handler_post_unlike),
            )