diff --git a/crates/api/src/local_user/notifications/list_mentions.rs b/crates/api/src/local_user/notifications/list_comment_mentions.rs similarity index 63% rename from crates/api/src/local_user/notifications/list_mentions.rs rename to crates/api/src/local_user/notifications/list_comment_mentions.rs index bf3cd8e0d..4617844ba 100644 --- a/crates/api/src/local_user/notifications/list_mentions.rs +++ b/crates/api/src/local_user/notifications/list_comment_mentions.rs @@ -1,18 +1,18 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, - person::{GetPersonMentions, GetPersonMentionsResponse}, + person::{GetPersonCommentMentions, GetPersonCommentMentionsResponse}, }; use lemmy_db_views::structs::LocalUserView; -use lemmy_db_views_actor::person_mention_view::PersonMentionQuery; +use lemmy_db_views_actor::person_comment_mention_view::PersonCommentMentionQuery; use lemmy_utils::error::LemmyResult; #[tracing::instrument(skip(context))] -pub async fn list_mentions( - data: Query, +pub async fn list_comment_mentions( + data: Query, context: Data, local_user_view: LocalUserView, -) -> LemmyResult> { +) -> LemmyResult> { let sort = data.sort; let page = data.page; let limit = data.limit; @@ -20,7 +20,7 @@ pub async fn list_mentions( let person_id = Some(local_user_view.person.id); let show_bot_accounts = local_user_view.local_user.show_bot_accounts; - let mentions = PersonMentionQuery { + let comment_mentions = PersonCommentMentionQuery { recipient_id: person_id, my_person_id: person_id, sort, @@ -32,5 +32,5 @@ pub async fn list_mentions( .list(&mut context.pool()) .await?; - Ok(Json(GetPersonMentionsResponse { mentions })) + Ok(Json(GetPersonCommentMentionsResponse { comment_mentions })) } diff --git a/crates/api/src/local_user/notifications/mark_all_read.rs b/crates/api/src/local_user/notifications/mark_all_read.rs index 558d276f7..929af5ac3 100644 --- a/crates/api/src/local_user/notifications/mark_all_read.rs +++ b/crates/api/src/local_user/notifications/mark_all_read.rs @@ -2,7 +2,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{context::LemmyContext, person::GetRepliesResponse}; use lemmy_db_schema::source::{ comment_reply::CommentReply, - person_mention::PersonMention, + person_comment_mention::PersonCommentMention, private_message::PrivateMessage, }; use lemmy_db_views::structs::LocalUserView; @@ -20,8 +20,8 @@ pub async fn mark_all_notifications_read( .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; - // Mark all user mentions as read - PersonMention::mark_all_as_read(&mut context.pool(), person_id) + // Mark all comment mentions as read + PersonCommentMention::mark_all_as_read(&mut context.pool(), person_id) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; diff --git a/crates/api/src/local_user/notifications/mark_comment_mention_read.rs b/crates/api/src/local_user/notifications/mark_comment_mention_read.rs new file mode 100644 index 000000000..4a9c40092 --- /dev/null +++ b/crates/api/src/local_user/notifications/mark_comment_mention_read.rs @@ -0,0 +1,50 @@ +use actix_web::web::{Data, Json}; +use lemmy_api_common::{ + context::LemmyContext, + person::{MarkPersonCommentMentionAsRead, PersonCommentMentionResponse}, +}; +use lemmy_db_schema::{ + source::person_comment_mention::{PersonCommentMention, PersonCommentMentionUpdateForm}, + traits::Crud, +}; +use lemmy_db_views::structs::LocalUserView; +use lemmy_db_views_actor::structs::PersonCommentMentionView; +use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult}; + +#[tracing::instrument(skip(context))] +pub async fn mark_comment_mention_as_read( + data: Json, + context: Data, + local_user_view: LocalUserView, +) -> LemmyResult> { + let person_comment_mention_id = data.person_comment_mention_id; + let read_person_comment_mention = + PersonCommentMention::read(&mut context.pool(), person_comment_mention_id).await?; + + if local_user_view.person.id != read_person_comment_mention.recipient_id { + Err(LemmyErrorType::CouldntUpdateComment)? + } + + let person_comment_mention_id = read_person_comment_mention.id; + let read = Some(data.read); + PersonCommentMention::update( + &mut context.pool(), + person_comment_mention_id, + &PersonCommentMentionUpdateForm { read }, + ) + .await + .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; + + let person_comment_mention_id = read_person_comment_mention.id; + let person_id = local_user_view.person.id; + let person_comment_mention_view = PersonCommentMentionView::read( + &mut context.pool(), + person_comment_mention_id, + Some(person_id), + ) + .await?; + + Ok(Json(PersonCommentMentionResponse { + person_comment_mention_view, + })) +} diff --git a/crates/api/src/local_user/notifications/mark_mention_read.rs b/crates/api/src/local_user/notifications/mark_mention_read.rs deleted file mode 100644 index 9a839b2b4..000000000 --- a/crates/api/src/local_user/notifications/mark_mention_read.rs +++ /dev/null @@ -1,45 +0,0 @@ -use actix_web::web::{Data, Json}; -use lemmy_api_common::{ - context::LemmyContext, - person::{MarkPersonMentionAsRead, PersonMentionResponse}, -}; -use lemmy_db_schema::{ - source::person_mention::{PersonMention, PersonMentionUpdateForm}, - traits::Crud, -}; -use lemmy_db_views::structs::LocalUserView; -use lemmy_db_views_actor::structs::PersonMentionView; -use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult}; - -#[tracing::instrument(skip(context))] -pub async fn mark_person_mention_as_read( - data: Json, - context: Data, - local_user_view: LocalUserView, -) -> LemmyResult> { - let person_mention_id = data.person_mention_id; - let read_person_mention = PersonMention::read(&mut context.pool(), person_mention_id).await?; - - if local_user_view.person.id != read_person_mention.recipient_id { - Err(LemmyErrorType::CouldntUpdateComment)? - } - - let person_mention_id = read_person_mention.id; - let read = Some(data.read); - PersonMention::update( - &mut context.pool(), - person_mention_id, - &PersonMentionUpdateForm { read }, - ) - .await - .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; - - let person_mention_id = read_person_mention.id; - let person_id = local_user_view.person.id; - let person_mention_view = - PersonMentionView::read(&mut context.pool(), person_mention_id, Some(person_id)).await?; - - Ok(Json(PersonMentionResponse { - person_mention_view, - })) -} diff --git a/crates/api/src/local_user/notifications/mod.rs b/crates/api/src/local_user/notifications/mod.rs index 35567afde..a3580b930 100644 --- a/crates/api/src/local_user/notifications/mod.rs +++ b/crates/api/src/local_user/notifications/mod.rs @@ -1,6 +1,6 @@ -pub mod list_mentions; +pub mod list_comment_mentions; pub mod list_replies; pub mod mark_all_read; -pub mod mark_mention_read; +pub mod mark_comment_mention_read; pub mod mark_reply_read; pub mod unread_count; diff --git a/crates/api/src/local_user/notifications/unread_count.rs b/crates/api/src/local_user/notifications/unread_count.rs index 4c6c65263..90891f21e 100644 --- a/crates/api/src/local_user/notifications/unread_count.rs +++ b/crates/api/src/local_user/notifications/unread_count.rs @@ -1,7 +1,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{context::LemmyContext, person::GetUnreadCountResponse}; use lemmy_db_views::structs::{LocalUserView, PrivateMessageView}; -use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView}; +use lemmy_db_views_actor::structs::{CommentReplyView, PersonCommentMentionView}; use lemmy_utils::error::LemmyResult; #[tracing::instrument(skip(context))] @@ -12,14 +12,14 @@ pub async fn unread_count( let person_id = local_user_view.person.id; let replies = - CommentReplyView::get_unread_replies(&mut context.pool(), &local_user_view.local_user).await?; + CommentReplyView::get_unread_count(&mut context.pool(), &local_user_view.local_user).await?; let mentions = - PersonMentionView::get_unread_mentions(&mut context.pool(), &local_user_view.local_user) + PersonCommentMentionView::get_unread_count(&mut context.pool(), &local_user_view.local_user) .await?; let private_messages = - PrivateMessageView::get_unread_messages(&mut context.pool(), person_id).await?; + PrivateMessageView::get_unread_count(&mut context.pool(), person_id).await?; Ok(Json(GetUnreadCountResponse { replies, diff --git a/crates/api_common/src/build_response.rs b/crates/api_common/src/build_response.rs index d40f4c23d..8e79867f1 100644 --- a/crates/api_common/src/build_response.rs +++ b/crates/api_common/src/build_response.rs @@ -18,7 +18,7 @@ use lemmy_db_schema::{ comment::Comment, comment_reply::{CommentReply, CommentReplyInsertForm}, person::Person, - person_mention::{PersonMention, PersonMentionInsertForm}, + person_comment_mention::{PersonCommentMention, PersonCommentMentionInsertForm}, }, traits::Crud, }; @@ -127,7 +127,7 @@ pub async fn send_local_notifs( // below by checking recipient ids recipient_ids.push(mention_user_view.local_user.id); - let user_mention_form = PersonMentionInsertForm { + let person_comment_mention_form = PersonCommentMentionInsertForm { recipient_id: mention_user_view.person.id, comment_id, read: None, @@ -135,7 +135,7 @@ pub async fn send_local_notifs( // Allow this to fail softly, since comment edits might re-update or replace it // Let the uniqueness handle this fail - PersonMention::create(&mut context.pool(), &user_mention_form) + PersonCommentMention::create(&mut context.pool(), &person_comment_mention_form) .await .ok(); diff --git a/crates/api_common/src/person.rs b/crates/api_common/src/person.rs index 6f1ddfe43..a4020f57e 100644 --- a/crates/api_common/src/person.rs +++ b/crates/api_common/src/person.rs @@ -1,5 +1,5 @@ use lemmy_db_schema::{ - newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId}, + newtypes::{CommentReplyId, CommunityId, LanguageId, PersonCommentMentionId, PersonId}, sensitive::SensitiveString, source::{login_token::LoginToken, site::Site}, CommentSortType, @@ -11,7 +11,7 @@ use lemmy_db_views::structs::{CommentView, LocalImageView, PostView}; use lemmy_db_views_actor::structs::{ CommentReplyView, CommunityModeratorView, - PersonMentionView, + PersonCommentMentionView, PersonView, }; use serde::{Deserialize, Serialize}; @@ -293,7 +293,7 @@ pub struct GetRepliesResponse { #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] /// Get mentions for your user. -pub struct GetPersonMentions { +pub struct GetPersonCommentMentions { pub sort: Option, pub page: Option, pub limit: Option, @@ -304,16 +304,16 @@ pub struct GetPersonMentions { #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] /// The response of mentions for your user. -pub struct GetPersonMentionsResponse { - pub mentions: Vec, +pub struct GetPersonCommentMentionsResponse { + pub comment_mentions: Vec, } #[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] /// Mark a person mention as read. -pub struct MarkPersonMentionAsRead { - pub person_mention_id: PersonMentionId, +pub struct MarkPersonCommentMentionAsRead { + pub person_comment_mention_id: PersonCommentMentionId, pub read: bool, } @@ -321,8 +321,8 @@ pub struct MarkPersonMentionAsRead { #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] /// The response for a person mention action. -pub struct PersonMentionResponse { - pub person_mention_view: PersonMentionView, +pub struct PersonCommentMentionResponse { + pub person_comment_mention_view: PersonCommentMentionView, } #[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)] diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 2f67fa7e7..1347918c2 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -22,7 +22,7 @@ use lemmy_db_schema::{ comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm}, comment_reply::{CommentReply, CommentReplyUpdateForm}, local_site::LocalSite, - person_mention::{PersonMention, PersonMentionUpdateForm}, + person_comment_mention::{PersonCommentMention, PersonCommentMentionUpdateForm}, }, traits::{Crud, Likeable}, }; @@ -174,17 +174,18 @@ pub async fn create_comment( .with_lemmy_type(LemmyErrorType::CouldntUpdateReplies)?; } - // If the parent has PersonMentions mark them as read too - let person_mention = - PersonMention::read_by_comment_and_person(&mut context.pool(), parent_id, person_id).await; - if let Ok(Some(mention)) = person_mention { - PersonMention::update( + // If the parent has PersonCommentMentions mark them as read too + let person_comment_mention = + PersonCommentMention::read_by_comment_and_person(&mut context.pool(), parent_id, person_id) + .await; + if let Ok(Some(mention)) = person_comment_mention { + PersonCommentMention::update( &mut context.pool(), mention.id, - &PersonMentionUpdateForm { read: Some(true) }, + &PersonCommentMentionUpdateForm { read: Some(true) }, ) .await - .with_lemmy_type(LemmyErrorType::CouldntUpdatePersonMentions)?; + .with_lemmy_type(LemmyErrorType::CouldntUpdatePersonCommentMentions)?; } } diff --git a/crates/db_schema/src/impls/mod.rs b/crates/db_schema/src/impls/mod.rs index f115a101f..50cb6b6df 100644 --- a/crates/db_schema/src/impls/mod.rs +++ b/crates/db_schema/src/impls/mod.rs @@ -27,7 +27,8 @@ pub mod oauth_provider; pub mod password_reset_request; pub mod person; pub mod person_block; -pub mod person_mention; +pub mod person_comment_mention; +pub mod person_post_mention; pub mod post; pub mod post_report; pub mod private_message; diff --git a/crates/db_schema/src/impls/person_comment_mention.rs b/crates/db_schema/src/impls/person_comment_mention.rs new file mode 100644 index 000000000..2cc303396 --- /dev/null +++ b/crates/db_schema/src/impls/person_comment_mention.rs @@ -0,0 +1,83 @@ +use crate::{ + diesel::OptionalExtension, + newtypes::{CommentId, PersonCommentMentionId, PersonId}, + schema::person_comment_mention, + source::person_comment_mention::{ + PersonCommentMention, + PersonCommentMentionInsertForm, + PersonCommentMentionUpdateForm, + }, + traits::Crud, + utils::{get_conn, DbPool}, +}; +use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl}; +use diesel_async::RunQueryDsl; + +#[async_trait] +impl Crud for PersonCommentMention { + type InsertForm = PersonCommentMentionInsertForm; + type UpdateForm = PersonCommentMentionUpdateForm; + type IdType = PersonCommentMentionId; + + async fn create( + pool: &mut DbPool<'_>, + person_comment_mention_form: &Self::InsertForm, + ) -> Result { + let conn = &mut get_conn(pool).await?; + // since the return here isnt utilized, we dont need to do an update + // but get_result doesn't return the existing row here + insert_into(person_comment_mention::table) + .values(person_comment_mention_form) + .on_conflict(( + person_comment_mention::recipient_id, + person_comment_mention::comment_id, + )) + .do_update() + .set(person_comment_mention_form) + .get_result::(conn) + .await + } + + async fn update( + pool: &mut DbPool<'_>, + person_comment_mention_id: PersonCommentMentionId, + person_comment_mention_form: &Self::UpdateForm, + ) -> Result { + let conn = &mut get_conn(pool).await?; + diesel::update(person_comment_mention::table.find(person_comment_mention_id)) + .set(person_comment_mention_form) + .get_result::(conn) + .await + } +} + +impl PersonCommentMention { + pub async fn mark_all_as_read( + pool: &mut DbPool<'_>, + for_recipient_id: PersonId, + ) -> Result, Error> { + let conn = &mut get_conn(pool).await?; + diesel::update( + person_comment_mention::table + .filter(person_comment_mention::recipient_id.eq(for_recipient_id)) + .filter(person_comment_mention::read.eq(false)), + ) + .set(person_comment_mention::read.eq(true)) + .get_results::(conn) + .await + } + + pub async fn read_by_comment_and_person( + pool: &mut DbPool<'_>, + for_comment_id: CommentId, + for_recipient_id: PersonId, + ) -> Result, Error> { + let conn = &mut get_conn(pool).await?; + person_comment_mention::table + .filter(person_comment_mention::comment_id.eq(for_comment_id)) + .filter(person_comment_mention::recipient_id.eq(for_recipient_id)) + .first(conn) + .await + .optional() + } +} diff --git a/crates/db_schema/src/impls/person_mention.rs b/crates/db_schema/src/impls/person_mention.rs deleted file mode 100644 index 433176683..000000000 --- a/crates/db_schema/src/impls/person_mention.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::{ - diesel::OptionalExtension, - newtypes::{CommentId, PersonId, PersonMentionId}, - schema::person_mention, - source::person_mention::{PersonMention, PersonMentionInsertForm, PersonMentionUpdateForm}, - traits::Crud, - utils::{get_conn, DbPool}, -}; -use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl}; -use diesel_async::RunQueryDsl; - -#[async_trait] -impl Crud for PersonMention { - type InsertForm = PersonMentionInsertForm; - type UpdateForm = PersonMentionUpdateForm; - type IdType = PersonMentionId; - - async fn create( - pool: &mut DbPool<'_>, - person_mention_form: &Self::InsertForm, - ) -> Result { - let conn = &mut get_conn(pool).await?; - // since the return here isnt utilized, we dont need to do an update - // but get_result doesn't return the existing row here - insert_into(person_mention::table) - .values(person_mention_form) - .on_conflict((person_mention::recipient_id, person_mention::comment_id)) - .do_update() - .set(person_mention_form) - .get_result::(conn) - .await - } - - async fn update( - pool: &mut DbPool<'_>, - person_mention_id: PersonMentionId, - person_mention_form: &Self::UpdateForm, - ) -> Result { - let conn = &mut get_conn(pool).await?; - diesel::update(person_mention::table.find(person_mention_id)) - .set(person_mention_form) - .get_result::(conn) - .await - } -} - -impl PersonMention { - pub async fn mark_all_as_read( - pool: &mut DbPool<'_>, - for_recipient_id: PersonId, - ) -> Result, Error> { - let conn = &mut get_conn(pool).await?; - diesel::update( - person_mention::table - .filter(person_mention::recipient_id.eq(for_recipient_id)) - .filter(person_mention::read.eq(false)), - ) - .set(person_mention::read.eq(true)) - .get_results::(conn) - .await - } - - pub async fn read_by_comment_and_person( - pool: &mut DbPool<'_>, - for_comment_id: CommentId, - for_recipient_id: PersonId, - ) -> Result, Error> { - let conn = &mut get_conn(pool).await?; - person_mention::table - .filter(person_mention::comment_id.eq(for_comment_id)) - .filter(person_mention::recipient_id.eq(for_recipient_id)) - .first(conn) - .await - .optional() - } -} diff --git a/crates/db_schema/src/newtypes.rs b/crates/db_schema/src/newtypes.rs index fe1febef5..2041b0c48 100644 --- a/crates/db_schema/src/newtypes.rs +++ b/crates/db_schema/src/newtypes.rs @@ -82,8 +82,14 @@ impl fmt::Display for PrivateMessageId { #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] #[cfg_attr(feature = "full", derive(DieselNewType, TS))] #[cfg_attr(feature = "full", ts(export))] -/// The person mention id. -pub struct PersonMentionId(i32); +/// The person comment mention id. +pub struct PersonCommentMentionId(i32); + +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "full", derive(DieselNewType, TS))] +#[cfg_attr(feature = "full", ts(export))] +/// The person post mention id. +pub struct PersonPostMentionId(i32); #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] #[cfg_attr(feature = "full", derive(DieselNewType, TS))] diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 9f1d00568..6dc863e48 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -719,16 +719,7 @@ diesel::table! { } diesel::table! { - person_follower (follower_id, person_id) { - person_id -> Int4, - follower_id -> Int4, - published -> Timestamptz, - pending -> Bool, - } -} - -diesel::table! { - person_mention (id) { + person_comment_mention (id) { id -> Int4, recipient_id -> Int4, comment_id -> Int4, @@ -737,6 +728,15 @@ diesel::table! { } } +diesel::table! { + person_follower (follower_id, person_id) { + person_id -> Int4, + follower_id -> Int4, + published -> Timestamptz, + pending -> Bool, + } +} + diesel::table! { person_post_aggregates (person_id, post_id) { person_id -> Int4, @@ -746,6 +746,16 @@ diesel::table! { } } +diesel::table! { + person_post_mention (id) { + id -> Int4, + recipient_id -> Int4, + post_id -> Int4, + read -> Bool, + published -> Timestamp, + } +} + diesel::table! { post (id) { id -> Int4, @@ -1049,10 +1059,12 @@ diesel::joinable!(password_reset_request -> local_user (local_user_id)); diesel::joinable!(person -> instance (instance_id)); diesel::joinable!(person_aggregates -> person (person_id)); diesel::joinable!(person_ban -> person (person_id)); -diesel::joinable!(person_mention -> comment (comment_id)); -diesel::joinable!(person_mention -> person (recipient_id)); +diesel::joinable!(person_comment_mention -> comment (comment_id)); +diesel::joinable!(person_comment_mention -> person (recipient_id)); diesel::joinable!(person_post_aggregates -> person (person_id)); diesel::joinable!(person_post_aggregates -> post (post_id)); +diesel::joinable!(person_post_mention -> person (recipient_id)); +diesel::joinable!(person_post_mention -> post (post_id)); diesel::joinable!(post -> community (community_id)); diesel::joinable!(post -> language (language_id)); diesel::joinable!(post -> person (creator_id)); @@ -1132,9 +1144,10 @@ diesel::allow_tables_to_appear_in_same_query!( person_aggregates, person_ban, person_block, + person_comment_mention, person_follower, - person_mention, person_post_aggregates, + person_post_mention, post, post_aggregates, post_hide, diff --git a/crates/db_schema/src/source/mod.rs b/crates/db_schema/src/source/mod.rs index 377c1aaef..3dac8a4f3 100644 --- a/crates/db_schema/src/source/mod.rs +++ b/crates/db_schema/src/source/mod.rs @@ -32,7 +32,8 @@ pub mod oauth_provider; pub mod password_reset_request; pub mod person; pub mod person_block; -pub mod person_mention; +pub mod person_comment_mention; +pub mod person_post_mention; pub mod post; pub mod post_report; pub mod private_message; diff --git a/crates/db_schema/src/source/person_mention.rs b/crates/db_schema/src/source/person_comment_mention.rs similarity index 63% rename from crates/db_schema/src/source/person_mention.rs rename to crates/db_schema/src/source/person_comment_mention.rs index 9c3005655..bd70af307 100644 --- a/crates/db_schema/src/source/person_mention.rs +++ b/crates/db_schema/src/source/person_comment_mention.rs @@ -1,6 +1,6 @@ -use crate::newtypes::{CommentId, PersonId, PersonMentionId}; +use crate::newtypes::{CommentId, PersonCommentMentionId, PersonId}; #[cfg(feature = "full")] -use crate::schema::person_mention; +use crate::schema::person_comment_mention; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; #[cfg(feature = "full")] @@ -12,12 +12,12 @@ use ts_rs::TS; derive(Queryable, Selectable, Associations, Identifiable, TS) )] #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))] -#[cfg_attr(feature = "full", diesel(table_name = person_mention))] +#[cfg_attr(feature = "full", diesel(table_name = person_comment_mention))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] #[cfg_attr(feature = "full", ts(export))] /// A person mention. -pub struct PersonMention { - pub id: PersonMentionId, +pub struct PersonCommentMention { + pub id: PersonCommentMentionId, pub recipient_id: PersonId, pub comment_id: CommentId, pub read: bool, @@ -25,15 +25,15 @@ pub struct PersonMention { } #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = person_mention))] -pub struct PersonMentionInsertForm { +#[cfg_attr(feature = "full", diesel(table_name = person_comment_mention))] +pub struct PersonCommentMentionInsertForm { pub recipient_id: PersonId, pub comment_id: CommentId, pub read: Option, } #[cfg_attr(feature = "full", derive(AsChangeset))] -#[cfg_attr(feature = "full", diesel(table_name = person_mention))] -pub struct PersonMentionUpdateForm { +#[cfg_attr(feature = "full", diesel(table_name = person_comment_mention))] +pub struct PersonCommentMentionUpdateForm { pub read: Option, } diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs index 0fbc0ee16..f0bf45c3a 100644 --- a/crates/db_views/src/private_message_view.rs +++ b/crates/db_views/src/private_message_view.rs @@ -118,7 +118,7 @@ impl PrivateMessageView { } /// Gets the number of unread messages - pub async fn get_unread_messages( + pub async fn get_unread_count( pool: &mut DbPool<'_>, my_person_id: PersonId, ) -> Result { @@ -356,7 +356,7 @@ mod tests { assert_length!(1, &timmy_messages); - let timmy_unread_messages = PrivateMessageView::get_unread_messages(pool, timmy.id).await?; + let timmy_unread_messages = PrivateMessageView::get_unread_count(pool, timmy.id).await?; assert_eq!(timmy_unread_messages, 1); cleanup(instance.id, pool).await @@ -398,7 +398,7 @@ mod tests { assert_length!(0, &timmy_messages); - let timmy_unread_messages = PrivateMessageView::get_unread_messages(pool, timmy.id).await?; + let timmy_unread_messages = PrivateMessageView::get_unread_count(pool, timmy.id).await?; assert_eq!(timmy_unread_messages, 0); cleanup(instance.id, pool).await } diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 1b657866a..22d05521b 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -247,7 +247,7 @@ impl CommentReplyView { } /// Gets the number of unread replies - pub async fn get_unread_replies( + pub async fn get_unread_count( pool: &mut DbPool<'_>, local_user: &LocalUser, ) -> Result { @@ -389,7 +389,7 @@ mod tests { CommentReply::update(pool, inserted_reply.id, &comment_reply_update_form).await?; // Test to make sure counts and blocks work correctly - let unread_replies = CommentReplyView::get_unread_replies(pool, &recipient_local_user).await?; + let unread_replies = CommentReplyView::get_unread_count(pool, &recipient_local_user).await?; let query = CommentReplyQuery { recipient_id: Some(recipient_id), @@ -412,7 +412,7 @@ mod tests { PersonBlock::block(pool, &block_form).await?; let unread_replies_after_block = - CommentReplyView::get_unread_replies(pool, &recipient_local_user).await?; + CommentReplyView::get_unread_count(pool, &recipient_local_user).await?; let replies_after_block = query.clone().list(pool).await?; assert_eq!(0, unread_replies_after_block); assert_eq!(0, replies_after_block.len()); @@ -440,7 +440,7 @@ mod tests { let recipient_local_user_view = LocalUserView::read(pool, recipient_local_user.id).await?; let unread_replies_after_hide_bots = - CommentReplyView::get_unread_replies(pool, &recipient_local_user_view.local_user).await?; + CommentReplyView::get_unread_count(pool, &recipient_local_user_view.local_user).await?; let mut query_without_bots = query.clone(); query_without_bots.show_bot_accounts = false; diff --git a/crates/db_views_actor/src/lib.rs b/crates/db_views_actor/src/lib.rs index 2ec9652e3..7e1b96757 100644 --- a/crates/db_views_actor/src/lib.rs +++ b/crates/db_views_actor/src/lib.rs @@ -9,7 +9,9 @@ pub mod community_person_ban_view; #[cfg(feature = "full")] pub mod community_view; #[cfg(feature = "full")] -pub mod person_mention_view; +pub mod person_comment_mention_view; +// #[cfg(feature = "full")] +// pub mod person_post_mention_view; #[cfg(feature = "full")] pub mod person_view; pub mod structs; diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_comment_mention_view.rs similarity index 81% rename from crates/db_views_actor/src/person_mention_view.rs rename to crates/db_views_actor/src/person_comment_mention_view.rs index 2478c0183..9a61ff0d9 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_comment_mention_view.rs @@ -1,4 +1,4 @@ -use crate::structs::PersonMentionView; +use crate::structs::PersonCommentMentionView; use diesel::{ dsl::{exists, not}, pg::Pg, @@ -15,7 +15,7 @@ use diesel::{ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases, - newtypes::{PersonId, PersonMentionId}, + newtypes::{PersonCommentMentionId, PersonId}, schema::{ comment, comment_aggregates, @@ -28,7 +28,7 @@ use lemmy_db_schema::{ local_user, person, person_block, - person_mention, + person_comment_mention, post, }, source::local_user::LocalUser, @@ -37,8 +37,8 @@ use lemmy_db_schema::{ }; fn queries<'a>() -> Queries< - impl ReadFn<'a, PersonMentionView, (PersonMentionId, Option)>, - impl ListFn<'a, PersonMentionView, PersonMentionQuery>, + impl ReadFn<'a, PersonCommentMentionView, (PersonCommentMentionId, Option)>, + impl ListFn<'a, PersonCommentMentionView, PersonCommentMentionQuery>, > { let is_creator_banned_from_community = exists( community_person_ban::table.filter( @@ -116,7 +116,7 @@ fn queries<'a>() -> Queries< ), ); - let all_joins = move |query: person_mention::BoxedQuery<'a, Pg>, + let all_joins = move |query: person_comment_mention::BoxedQuery<'a, Pg>, my_person_id: Option| { let is_local_user_banned_from_community_selection: Box< dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>, @@ -163,7 +163,7 @@ fn queries<'a>() -> Queries< .inner_join(aliases::person1) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .select(( - person_mention::all_columns, + person_comment_mention::all_columns, comment::all_columns, person::all_columns, post::all_columns, @@ -181,28 +181,35 @@ fn queries<'a>() -> Queries< )) }; - let read = - move |mut conn: DbConn<'a>, - (person_mention_id, my_person_id): (PersonMentionId, Option)| async move { - all_joins( - person_mention::table.find(person_mention_id).into_boxed(), - my_person_id, - ) - .first(&mut conn) - .await - }; + let read = move |mut conn: DbConn<'a>, + (person_comment_mention_id, my_person_id): ( + PersonCommentMentionId, + Option, + )| async move { + all_joins( + person_comment_mention::table + .find(person_comment_mention_id) + .into_boxed(), + my_person_id, + ) + .first(&mut conn) + .await + }; - let list = move |mut conn: DbConn<'a>, options: PersonMentionQuery| async move { + let list = move |mut conn: DbConn<'a>, options: PersonCommentMentionQuery| async move { // These filters need to be kept in sync with the filters in - // PersonMentionView::get_unread_mentions() - let mut query = all_joins(person_mention::table.into_boxed(), options.my_person_id); + // PersonCommentMentionView::get_unread_mentions() + let mut query = all_joins( + person_comment_mention::table.into_boxed(), + options.my_person_id, + ); if let Some(recipient_id) = options.recipient_id { - query = query.filter(person_mention::recipient_id.eq(recipient_id)); + query = query.filter(person_comment_mention::recipient_id.eq(recipient_id)); } if options.unread_only { - query = query.filter(person_mention::read.eq(false)); + query = query.filter(person_comment_mention::read.eq(false)); } if !options.show_bot_accounts { @@ -229,33 +236,33 @@ fn queries<'a>() -> Queries< query .limit(limit) .offset(offset) - .load::(&mut conn) + .load::(&mut conn) .await }; Queries::new(read, list) } -impl PersonMentionView { +impl PersonCommentMentionView { pub async fn read( pool: &mut DbPool<'_>, - person_mention_id: PersonMentionId, + person_comment_mention_id: PersonCommentMentionId, my_person_id: Option, ) -> Result { queries() - .read(pool, (person_mention_id, my_person_id)) + .read(pool, (person_comment_mention_id, my_person_id)) .await } /// Gets the number of unread mentions - pub async fn get_unread_mentions( + pub async fn get_unread_count( pool: &mut DbPool<'_>, local_user: &LocalUser, ) -> Result { use diesel::dsl::count; let conn = &mut get_conn(pool).await?; - let mut query = person_mention::table + let mut query = person_comment_mention::table .inner_join(comment::table) .left_join( person_block::table.on( @@ -275,18 +282,18 @@ impl PersonMentionView { query // Don't count replies from blocked users .filter(person_block::person_id.is_null()) - .filter(person_mention::recipient_id.eq(local_user.person_id)) - .filter(person_mention::read.eq(false)) + .filter(person_comment_mention::recipient_id.eq(local_user.person_id)) + .filter(person_comment_mention::read.eq(false)) .filter(comment::deleted.eq(false)) .filter(comment::removed.eq(false)) - .select(count(person_mention::id)) + .select(count(person_comment_mention::id)) .first::(conn) .await } } #[derive(Default, Clone)] -pub struct PersonMentionQuery { +pub struct PersonCommentMentionQuery { pub my_person_id: Option, pub recipient_id: Option, pub sort: Option, @@ -296,8 +303,8 @@ pub struct PersonMentionQuery { pub limit: Option, } -impl PersonMentionQuery { - pub async fn list(self, pool: &mut DbPool<'_>) -> Result, Error> { +impl PersonCommentMentionQuery { + pub async fn list(self, pool: &mut DbPool<'_>) -> Result, Error> { queries().list(pool, self).await } } @@ -305,7 +312,10 @@ impl PersonMentionQuery { #[cfg(test)] mod tests { - use crate::{person_mention_view::PersonMentionQuery, structs::PersonMentionView}; + use crate::{ + person_comment_mention_view::PersonCommentMentionQuery, + structs::PersonCommentMentionView, + }; use lemmy_db_schema::{ source::{ comment::{Comment, CommentInsertForm}, @@ -314,7 +324,11 @@ mod tests { local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm}, person::{Person, PersonInsertForm, PersonUpdateForm}, person_block::{PersonBlock, PersonBlockForm}, - person_mention::{PersonMention, PersonMentionInsertForm, PersonMentionUpdateForm}, + person_comment_mention::{ + PersonCommentMention, + PersonCommentMentionInsertForm, + PersonCommentMentionUpdateForm, + }, post::{Post, PostInsertForm}, }, traits::{Blockable, Crud}, @@ -367,15 +381,15 @@ mod tests { ); let inserted_comment = Comment::create(pool, &comment_form, None).await?; - let person_mention_form = PersonMentionInsertForm { + let person_comment_mention_form = PersonCommentMentionInsertForm { recipient_id: inserted_recipient.id, comment_id: inserted_comment.id, read: None, }; - let inserted_mention = PersonMention::create(pool, &person_mention_form).await?; + let inserted_mention = PersonCommentMention::create(pool, &person_comment_mention_form).await?; - let expected_mention = PersonMention { + let expected_mention = PersonCommentMention { id: inserted_mention.id, recipient_id: inserted_mention.recipient_id, comment_id: inserted_mention.comment_id, @@ -383,17 +397,21 @@ mod tests { published: inserted_mention.published, }; - let read_mention = PersonMention::read(pool, inserted_mention.id).await?; + let read_mention = PersonCommentMention::read(pool, inserted_mention.id).await?; - let person_mention_update_form = PersonMentionUpdateForm { read: Some(false) }; - let updated_mention = - PersonMention::update(pool, inserted_mention.id, &person_mention_update_form).await?; + let person_comment_mention_update_form = PersonCommentMentionUpdateForm { read: Some(false) }; + let updated_mention = PersonCommentMention::update( + pool, + inserted_mention.id, + &person_comment_mention_update_form, + ) + .await?; // Test to make sure counts and blocks work correctly let unread_mentions = - PersonMentionView::get_unread_mentions(pool, &recipient_local_user).await?; + PersonCommentMentionView::get_unread_count(pool, &recipient_local_user).await?; - let query = PersonMentionQuery { + let query = PersonCommentMentionQuery { recipient_id: Some(recipient_id), my_person_id: Some(recipient_id), sort: None, @@ -414,7 +432,7 @@ mod tests { PersonBlock::block(pool, &block_form).await?; let unread_mentions_after_block = - PersonMentionView::get_unread_mentions(pool, &recipient_local_user).await?; + PersonCommentMentionView::get_unread_count(pool, &recipient_local_user).await?; let mentions_after_block = query.clone().list(pool).await?; assert_eq!(0, unread_mentions_after_block); assert_eq!(0, mentions_after_block.len()); @@ -442,7 +460,8 @@ mod tests { let recipient_local_user_view = LocalUserView::read(pool, recipient_local_user.id).await?; let unread_mentions_after_hide_bots = - PersonMentionView::get_unread_mentions(pool, &recipient_local_user_view.local_user).await?; + PersonCommentMentionView::get_unread_count(pool, &recipient_local_user_view.local_user) + .await?; let mut query_without_bots = query.clone(); query_without_bots.show_bot_accounts = false; diff --git a/crates/db_views_actor/src/structs.rs b/crates/db_views_actor/src/structs.rs index ecf9ba11d..96013a8c7 100644 --- a/crates/db_views_actor/src/structs.rs +++ b/crates/db_views_actor/src/structs.rs @@ -7,7 +7,7 @@ use lemmy_db_schema::{ comment_reply::CommentReply, community::Community, person::Person, - person_mention::PersonMention, + person_comment_mention::PersonCommentMention, post::Post, }, SubscribedType, @@ -94,8 +94,8 @@ pub enum CommunitySortType { #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] #[cfg_attr(feature = "full", ts(export))] /// A person mention view. -pub struct PersonMentionView { - pub person_mention: PersonMention, +pub struct PersonCommentMentionView { + pub person_comment_mention: PersonCommentMention, pub comment: Comment, pub creator: Person, pub post: Post, @@ -112,6 +112,29 @@ pub struct PersonMentionView { pub my_vote: Option, } +// #[skip_serializing_none] +// #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +// #[cfg_attr(feature = "full", derive(TS, Queryable))] +// #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] +// #[cfg_attr(feature = "full", ts(export))] +// /// A person mention view. +// pub struct PersonPostMentionView { +// pub person_post_mention: PersonPostMention, +// pub creator: Person, +// pub post: Post, +// pub community: Community, +// pub recipient: Person, +// pub counts: CommentAggregates, +// pub creator_banned_from_community: bool, +// pub banned_from_community: bool, +// pub creator_is_moderator: bool, +// pub creator_is_admin: bool, +// pub subscribed: SubscribedType, +// pub saved: bool, +// pub creator_blocked: bool, +// pub my_vote: Option, +// } + #[skip_serializing_none] #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "full", derive(TS, Queryable))] diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index 00518032d..5aa55663f 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -17,8 +17,8 @@ use lemmy_db_views::{ }; use lemmy_db_views_actor::{ comment_reply_view::CommentReplyQuery, - person_mention_view::PersonMentionQuery, - structs::{CommentReplyView, PersonMentionView}, + person_comment_mention_view::PersonCommentMentionQuery, + structs::{CommentReplyView, PersonCommentMentionView}, }; use lemmy_utils::{ cache_header::cache_1hour, @@ -395,7 +395,7 @@ async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> LemmyResult LemmyResult LemmyResult, - mentions: Vec, + comment_mentions: Vec, protocol_and_hostname: &str, ) -> LemmyResult> { let mut reply_items: Vec = replies @@ -444,7 +444,7 @@ fn create_reply_and_mention_items( }) .collect::>>()?; - let mut mention_items: Vec = mentions + let mut comment_mention_items: Vec = comment_mentions .iter() .map(|m| { let mention_url = format!("{}/comment/{}", protocol_and_hostname, m.comment.id); @@ -458,7 +458,7 @@ fn create_reply_and_mention_items( }) .collect::>>()?; - reply_items.append(&mut mention_items); + reply_items.append(&mut comment_mention_items); Ok(reply_items) } diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index c95af03e2..4e5b589bb 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -105,7 +105,7 @@ pub enum LemmyErrorType { CouldntHidePost, CouldntUpdateCommunity, CouldntUpdateReplies, - CouldntUpdatePersonMentions, + CouldntUpdatePersonCommentMentions, CouldntCreatePost, CouldntCreatePrivateMessage, CouldntUpdatePrivate, diff --git a/migrations/2024-11-02-161125_add_post_body_mention/down.sql b/migrations/2024-11-02-161125_add_post_body_mention/down.sql new file mode 100644 index 000000000..37bb14e3c --- /dev/null +++ b/migrations/2024-11-02-161125_add_post_body_mention/down.sql @@ -0,0 +1,5 @@ +-- Rename the person_mention table to person_comment_mention +ALTER TABLE person_comment_mention RENAME TO person_mention; + +-- Drop the new table +DROP TABLE person_post_mention; diff --git a/migrations/2024-11-02-161125_add_post_body_mention/up.sql b/migrations/2024-11-02-161125_add_post_body_mention/up.sql new file mode 100644 index 000000000..dffecf9c2 --- /dev/null +++ b/migrations/2024-11-02-161125_add_post_body_mention/up.sql @@ -0,0 +1,12 @@ +-- Rename the person_mention table to person_comment_mention +ALTER TABLE person_mention RENAME TO person_comment_mention; + +-- Create the new post_mention table +CREATE TABLE person_post_mention ( + id serial PRIMARY KEY, + recipient_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, + read boolean DEFAULT FALSE NOT NULL, + published timestamp NOT NULL DEFAULT now(), + UNIQUE (recipient_id, post_id) +); diff --git a/src/api_routes_http.rs b/src/api_routes_http.rs index df1aebf84..d24b907a8 100644 --- a/src/api_routes_http.rs +++ b/src/api_routes_http.rs @@ -34,10 +34,10 @@ use lemmy_api::{ login::login, logout::logout, notifications::{ - list_mentions::list_mentions, + list_comment_mentions::list_comment_mentions, list_replies::list_replies, mark_all_read::mark_all_notifications_read, - mark_mention_read::mark_person_mention_as_read, + mark_comment_mention_read::mark_comment_mention_as_read, mark_reply_read::mark_reply_as_read, unread_count::unread_count, }, @@ -329,10 +329,10 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { web::scope("/user") .wrap(rate_limit.message()) .route("", web::get().to(read_person)) - .route("/mention", web::get().to(list_mentions)) + .route("/comment_mention", web::get().to(list_comment_mentions)) .route( - "/mention/mark_as_read", - web::post().to(mark_person_mention_as_read), + "/comment_mention/mark_as_read", + web::post().to(mark_comment_mention_as_read), ) .route("/replies", web::get().to(list_replies)) // Admin action. I don't like that it's in /user