~vpzom/lotide

7002c79a2b7a2324d9c9bb29c0c354182a36e080 — Colin Reeder a month ago 2abe9f3
make pagination work for comment replies
2 files changed, 26 insertions(+), 8 deletions(-)

M src/routes/api/comments.rs
M src/routes/api/mod.rs
M src/routes/api/comments.rs => src/routes/api/comments.rs +3 -1
@@ 521,13 521,14 @@ async fn route_unstable_comments_replies_list(
    let (comment_id,) = params;

    #[derive(Deserialize)]
    struct RepliesListQuery {
    struct RepliesListQuery<'a> {
        #[serde(default)]
        include_your: bool,
        #[serde(default = "super::default_replies_depth")]
        depth: u8,
        #[serde(default = "super::default_replies_limit")]
        limit: u8,
        page: Option<Cow<'a, str>>,
    }

    let query: RepliesListQuery = serde_urlencoded::from_str(req.uri().query().unwrap_or(""))?;


@@ 546,6 547,7 @@ async fn route_unstable_comments_replies_list(
        include_your_for,
        query.depth,
        query.limit,
        query.page.as_deref(),
        &db,
        &ctx,
    )

M src/routes/api/mod.rs => src/routes/api/mod.rs +23 -7
@@ 872,6 872,7 @@ fn get_comments_replies_box<'a: 'b, 'b>(
        include_your_for,
        depth,
        limit,
        None,
        db,
        ctx,
    ))


@@ 882,24 883,39 @@ async fn get_comments_replies<'a>(
    include_your_for: Option<UserLocalID>,
    depth: u8,
    limit: u8,
    page: Option<&str>,
    db: &tokio_postgres::Client,
    ctx: &'a crate::BaseContext,
) -> Result<HashMap<CommentLocalID, (Vec<RespPostCommentInfo<'a>>, Option<String>)>, crate::Error> {
    use futures::TryStreamExt;
    use std::fmt::Write;

    let page = page
        .map(parse_number_58)
        .transpose()
        .map_err(|_| InvalidPage.to_user_error())?;
    let limit_i = i64::from(limit) + 1;

    let sql1 = "SELECT result.* FROM UNNEST($1::BIGINT[]) JOIN LATERAL (SELECT reply.id, reply.author, reply.content_text, reply.created, reply.parent, reply.content_html, person.username, person.local, person.ap_id, reply.deleted, person.avatar, reply.attachment_href, reply.local, (SELECT COUNT(*) FROM reply_like WHERE reply = reply.id)";
    let (sql2, values): (_, Vec<&(dyn tokio_postgres::types::ToSql + Sync)>) =
    let (sql2, mut values): (_, Vec<&(dyn tokio_postgres::types::ToSql + Sync)>) =
        if include_your_for.is_some() {
            (
                ", EXISTS(SELECT 1 FROM reply_like WHERE reply = reply.id AND person = $2)",
                vec![&parents, &include_your_for],
                ", EXISTS(SELECT 1 FROM reply_like WHERE reply = reply.id AND person = $3)",
                vec![&parents, &limit_i, &include_your_for],
            )
        } else {
            ("", vec![&parents])
            ("", vec![&parents, &limit_i])
        };
    let sql3 = " FROM reply LEFT OUTER JOIN person ON (person.id = reply.author) WHERE parent = unnest ORDER BY hot_rank((SELECT COUNT(*) FROM reply_like WHERE reply = reply.id AND person != reply.author), reply.created) DESC) AS result ON TRUE";
    let sql3 = " FROM reply LEFT OUTER JOIN person ON (person.id = reply.author) WHERE parent = unnest ORDER BY hot_rank((SELECT COUNT(*) FROM reply_like WHERE reply = reply.id AND person != reply.author), reply.created) DESC) AS result ON TRUE LIMIT $2";

    let mut sql: String = format!("{}{}{}", sql1, sql2, sql3);

    if let Some(page) = &page {
        values.push(page);
        write!(sql, " OFFSET ${}", values.len()).unwrap();
    }

    let sql: &str = &format!("{}{}{}", sql1, sql2, sql3);
    let sql: &str = &sql;

    let stream = crate::query_stream(db, sql, &values).await?;



@@ 978,7 994,7 @@ async fn get_comments_replies<'a>(
        if entry.0.len() < limit.into() {
            entry.0.push(comment);
        } else {
            entry.1 = Some(limit.to_string());
            entry.1 = Some(format_number_58(i64::from(limit) + page.unwrap_or(0)));
        }
    }