From 0d5db29bc96d09b0933350f2d799ef4b8f25ceef Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 27 May 2024 06:55:44 -0400 Subject: [PATCH] After creating a comment, update the unread comments for the post. (#4742) * After creating a comment, update the unread comments for the post. - Fixes #3863 * Addressing PR comments. * Add comment. --------- Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> --- crates/api/src/post/like.rs | 1 - crates/api/src/post/save.rs | 1 - crates/api_common/src/utils.rs | 31 +++++++++++++++++++++------ crates/api_crud/src/comment/create.rs | 28 ++++++++++++++++++++---- crates/api_crud/src/post/create.rs | 1 - crates/api_crud/src/post/read.rs | 29 +++++++++---------------- 6 files changed, 58 insertions(+), 33 deletions(-) diff --git a/crates/api/src/post/like.rs b/crates/api/src/post/like.rs index 707874ded..fccd9f8df 100644 --- a/crates/api/src/post/like.rs +++ b/crates/api/src/post/like.rs @@ -68,7 +68,6 @@ pub async fn like_post( .with_lemmy_type(LemmyErrorType::CouldntLikePost)?; } - // Mark the post as read mark_post_as_read(person_id, post_id, &mut context.pool()).await?; let community = Community::read(&mut context.pool(), post.community_id) diff --git a/crates/api/src/post/save.rs b/crates/api/src/post/save.rs index 0876992ad..96dd85579 100644 --- a/crates/api/src/post/save.rs +++ b/crates/api/src/post/save.rs @@ -38,7 +38,6 @@ pub async fn save_post( .await? .ok_or(LemmyErrorType::CouldntFindPost)?; - // Mark the post as read mark_post_as_read(person_id, post_id, &mut context.pool()).await?; Ok(Json(PostResponse { post_view })) diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index d66ce1700..bad3b8180 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -6,6 +6,7 @@ use crate::{ use chrono::{DateTime, Days, Local, TimeZone, Utc}; use enum_map::{enum_map, EnumMap}; use lemmy_db_schema::{ + aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm}, newtypes::{CommunityId, DbUrl, InstanceId, PersonId, PostId}, source::{ comment::{Comment, CommentUpdateForm}, @@ -139,13 +140,7 @@ pub fn is_top_mod( } } -#[tracing::instrument(skip_all)] -pub async fn get_post(post_id: PostId, pool: &mut DbPool<'_>) -> LemmyResult { - Post::read(pool, post_id) - .await? - .ok_or(LemmyErrorType::CouldntFindPost.into()) -} - +/// Marks a post as read for a given person. #[tracing::instrument(skip_all)] pub async fn mark_post_as_read( person_id: PersonId, @@ -158,6 +153,28 @@ pub async fn mark_post_as_read( Ok(()) } +/// Updates the read comment count for a post. Usually done when reading or creating a new comment. +#[tracing::instrument(skip_all)] +pub async fn update_read_comments( + person_id: PersonId, + post_id: PostId, + read_comments: i64, + pool: &mut DbPool<'_>, +) -> LemmyResult<()> { + let person_post_agg_form = PersonPostAggregatesForm { + person_id, + post_id, + read_comments, + ..PersonPostAggregatesForm::default() + }; + + PersonPostAggregates::upsert(pool, &person_post_agg_form) + .await + .with_lemmy_type(LemmyErrorType::CouldntFindPost)?; + + Ok(()) +} + pub fn check_user_valid(person: &Person) -> LemmyResult<()> { // Check for a site ban if person.banned { diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 6493d6803..2efd46964 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -9,11 +9,11 @@ use lemmy_api_common::{ check_community_user_action, check_post_deleted_or_removed, generate_local_apub_endpoint, - get_post, get_url_blocklist, is_mod_or_admin, local_site_to_slur_regex, process_markdown, + update_read_comments, EndpointType, }, }; @@ -28,7 +28,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Likeable}, }; -use lemmy_db_views::structs::LocalUserView; +use lemmy_db_views::structs::{LocalUserView, PostView}; use lemmy_utils::{ error::{LemmyErrorExt, LemmyErrorType, LemmyResult}, utils::{mention::scrape_text_for_mentions, validation::is_valid_body_field}, @@ -51,8 +51,19 @@ pub async fn create_comment( // Check for a community ban let post_id = data.post_id; - let post = get_post(post_id, &mut context.pool()).await?; - let community_id = post.community_id; + + // Read the full post view in order to get the comments count. + let post_view = PostView::read( + &mut context.pool(), + post_id, + Some(local_user_view.person.id), + true, + ) + .await? + .ok_or(LemmyErrorType::CouldntFindPost)?; + + let post = post_view.post; + let community_id = post_view.community.id; check_community_user_action(&local_user_view.person, community_id, &mut context.pool()).await?; check_post_deleted_or_removed(&post)?; @@ -164,6 +175,15 @@ pub async fn create_comment( ) .await?; + // Update the read comments, so your own new comment doesn't appear as a +1 unread + update_read_comments( + local_user_view.person.id, + post_id, + post_view.counts.comments + 1, + &mut context.pool(), + ) + .await?; + // If we're responding to a comment where we're the recipient, // (ie we're the grandparent, or the recipient of the parent comment_reply), // then mark the parent as read. diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 82a208a9c..21a989d3f 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -176,7 +176,6 @@ pub async fn create_post( .await .with_lemmy_type(LemmyErrorType::CouldntLikePost)?; - // Mark the post as read mark_post_as_read(person_id, post_id, &mut context.pool()).await?; if let Some(url) = updated_post.url.clone() { diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index 2a567187f..506b97299 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -2,10 +2,9 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, post::{GetPost, GetPostResponse}, - utils::{check_private_instance, is_mod_or_admin_opt, mark_post_as_read}, + utils::{check_private_instance, is_mod_or_admin_opt, mark_post_as_read, update_read_comments}, }; use lemmy_db_schema::{ - aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm}, source::{comment::Comment, post::Post}, traits::Crud, }; @@ -14,7 +13,7 @@ use lemmy_db_views::{ structs::{LocalUserView, PostView, SiteView}, }; use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView}; -use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult}; +use lemmy_utils::error::{LemmyErrorType, LemmyResult}; #[tracing::instrument(skip(context))] pub async fn get_post( @@ -60,10 +59,17 @@ pub async fn get_post( .await? .ok_or(LemmyErrorType::CouldntFindPost)?; - // Mark the post as read let post_id = post_view.post.id; if let Some(person_id) = person_id { mark_post_as_read(person_id, post_id, &mut context.pool()).await?; + + update_read_comments( + person_id, + post_id, + post_view.counts.comments, + &mut context.pool(), + ) + .await?; } // Necessary for the sidebar subscribed @@ -76,21 +82,6 @@ pub async fn get_post( .await? .ok_or(LemmyErrorType::CouldntFindCommunity)?; - // Insert into PersonPostAggregates - // to update the read_comments count - if let Some(person_id) = person_id { - let read_comments = post_view.counts.comments; - let person_post_agg_form = PersonPostAggregatesForm { - person_id, - post_id, - read_comments, - ..PersonPostAggregatesForm::default() - }; - PersonPostAggregates::upsert(&mut context.pool(), &person_post_agg_form) - .await - .with_lemmy_type(LemmyErrorType::CouldntFindPost)?; - } - let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id).await?; // Fetch the cross_posts