Add ability to mark multiple posts as read. (#5178)

* Removing a few SuccessResponses for PostHide and MarkPostAsRead.

- This also removes the pointless multiple post_ids. These can be done
  as individual calls on the front end anyway.
- Fixes #4755

* Fixing federation tests.

* Upgrading lemmy-js-client deps.

* Add ability to mark several posts as read.

Context:

- https://github.com/LemmyNet/lemmy/pull/5043
- https://github.com/LemmyNet/lemmy/issues/4755
- https://github.com/LemmyNet/lemmy/pull/5160

* Fix ntfy to notify on success builds also.

* Addressing PR comments.
This commit is contained in:
Dessalines 2024-11-14 09:03:39 -05:00 committed by GitHub
parent a9d6d4e6e0
commit 7f4e26e29e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 70 additions and 22 deletions

View file

@ -290,14 +290,14 @@ steps:
when: when:
- event: tag - event: tag
notify_on_failure: notify_on_build:
image: alpine:3 image: alpine:3
commands: commands:
- apk add curl - apk add curl
- "curl -d'Lemmy CI build failed: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci" - "curl -d'Lemmy CI build ${CI_PIPELINE_STATUS}: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci"
when: when:
- event: [pull_request, tag] - event: [pull_request, tag]
status: failure status: [failure, success]
notify_on_tag_deploy: notify_on_tag_deploy:
image: alpine:3 image: alpine:3

View file

@ -0,0 +1,24 @@
use actix_web::web::{Data, Json};
use lemmy_api_common::{context::LemmyContext, post::MarkManyPostsAsRead, SuccessResponse};
use lemmy_db_schema::source::post::PostRead;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::error::{LemmyErrorType, LemmyResult, MAX_API_PARAM_ELEMENTS};
#[tracing::instrument(skip(context))]
pub async fn mark_posts_as_read(
data: Json<MarkManyPostsAsRead>,
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let post_ids = &data.post_ids;
if post_ids.len() > MAX_API_PARAM_ELEMENTS {
Err(LemmyErrorType::TooManyItems)?;
}
let person_id = local_user_view.person.id;
// Mark the posts as read
PostRead::mark_many_as_read(&mut context.pool(), post_ids, person_id).await?;
Ok(Json(SuccessResponse::default()))
}

View file

@ -4,5 +4,6 @@ pub mod hide;
pub mod like; pub mod like;
pub mod list_post_likes; pub mod list_post_likes;
pub mod lock; pub mod lock;
pub mod mark_many_read;
pub mod mark_read; pub mod mark_read;
pub mod save; pub mod save;

View file

@ -200,6 +200,15 @@ pub struct MarkPostAsRead {
pub read: bool, pub read: bool,
} }
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
/// Mark several posts as read.
pub struct MarkManyPostsAsRead {
pub post_ids: Vec<PostId>,
}
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", derive(TS))]

View file

@ -100,10 +100,7 @@ pub async fn list_posts(
.unwrap_or(local_user.auto_mark_fetched_posts_as_read) .unwrap_or(local_user.auto_mark_fetched_posts_as_read)
{ {
let post_ids = posts.iter().map(|p| p.post.id).collect::<Vec<PostId>>(); let post_ids = posts.iter().map(|p| p.post.id).collect::<Vec<PostId>>();
// TODO get rid of this in the next pr PostRead::mark_many_as_read(&mut context.pool(), &post_ids, local_user.person_id).await?;
for post_id in post_ids {
PostRead::mark_as_read(&mut context.pool(), post_id, local_user.person_id).await?;
}
} }
} }

View file

@ -338,21 +338,7 @@ impl PostRead {
post_id: PostId, post_id: PostId,
person_id: PersonId, person_id: PersonId,
) -> LemmyResult<usize> { ) -> LemmyResult<usize> {
let conn = &mut get_conn(pool).await?; Self::mark_many_as_read(pool, &[post_id], person_id).await
let form = (
&PostReadForm { post_id, person_id },
post_actions::read.eq(now().nullable()),
);
insert_into(post_actions::table)
.values(form)
.on_conflict((post_actions::person_id, post_actions::post_id))
.do_update()
.set(form)
.execute(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead)
} }
pub async fn mark_as_unread( pub async fn mark_as_unread(
@ -372,6 +358,35 @@ impl PostRead {
.await .await
.with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead) .with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead)
} }
pub async fn mark_many_as_read(
pool: &mut DbPool<'_>,
post_ids: &[PostId],
person_id: PersonId,
) -> LemmyResult<usize> {
let conn = &mut get_conn(pool).await?;
let forms = post_ids
.iter()
.map(|post_id| {
(
PostReadForm {
post_id: *post_id,
person_id,
},
post_actions::read.eq(now().nullable()),
)
})
.collect::<Vec<_>>();
insert_into(post_actions::table)
.values(forms)
.on_conflict((post_actions::person_id, post_actions::post_id))
.do_update()
.set(post_actions::read.eq(now().nullable()))
.execute(conn)
.await
.with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead)
}
} }
impl PostHide { impl PostHide {

View file

@ -60,6 +60,7 @@ use lemmy_api::{
like::like_post, like::like_post,
list_post_likes::list_post_likes, list_post_likes::list_post_likes,
lock::lock_post, lock::lock_post,
mark_many_read::mark_posts_as_read,
mark_read::mark_post_as_read, mark_read::mark_post_as_read,
save::save_post, save::save_post,
}, },
@ -239,6 +240,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
.route("/delete", web::post().to(delete_post)) .route("/delete", web::post().to(delete_post))
.route("/remove", web::post().to(remove_post)) .route("/remove", web::post().to(remove_post))
.route("/mark_as_read", web::post().to(mark_post_as_read)) .route("/mark_as_read", web::post().to(mark_post_as_read))
.route("/mark_many_as_read", web::post().to(mark_posts_as_read))
.route("/hide", web::post().to(hide_post)) .route("/hide", web::post().to(hide_post))
.route("/lock", web::post().to(lock_post)) .route("/lock", web::post().to(lock_post))
.route("/feature", web::post().to(feature_post)) .route("/feature", web::post().to(feature_post))