diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index db987d63c3..543e39495b 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -99,6 +99,8 @@ pub struct GetPosts { #[cfg_attr(feature = "full", ts(optional))] pub saved_only: Option, #[cfg_attr(feature = "full", ts(optional))] + pub read_only: Option, + #[cfg_attr(feature = "full", ts(optional))] pub liked_only: Option, #[cfg_attr(feature = "full", ts(optional))] pub disliked_only: Option, diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs index 63e737fdd0..20e25f9a5d 100644 --- a/crates/apub/src/api/list_posts.rs +++ b/crates/apub/src/api/list_posts.rs @@ -42,6 +42,7 @@ pub async fn list_posts( data.community_id }; let saved_only = data.saved_only; + let read_only = data.read_only; let show_hidden = data.show_hidden; let show_read = data.show_read; let show_nsfw = data.show_nsfw; @@ -78,6 +79,7 @@ pub async fn list_posts( sort, community_id, saved_only, + read_only, liked_only, disliked_only, page, diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 6ed89e3643..38701ebb3c 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -323,6 +323,12 @@ fn queries<'a>() -> Queries< .filter(post_actions::saved.is_not_null()) .then_order_by(post_actions::saved.desc()); } + + if options.read_only.unwrap_or_default() { + query = query + .filter(post_actions::read.is_not_null()) + .then_order_by(post_actions::read.desc()) + } // Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read // setting wont be able to see saved posts. else if !options @@ -519,6 +525,7 @@ pub struct PostQuery<'a> { pub search_term: Option, pub url_only: Option, pub saved_only: Option, + pub read_only: Option, pub liked_only: Option, pub disliked_only: Option, pub title_only: Option, @@ -1245,6 +1252,34 @@ mod tests { Ok(()) } + #[test_context(Data)] + #[tokio::test] + #[serial] + async fn post_listing_read_only(data: &mut Data) -> LemmyResult<()> { + let pool = &data.pool(); + let pool = &mut pool.into(); + + // Only mark the bot post as read + // The read_only should only show the bot post + let post_read_form = + PostReadForm::new(data.inserted_bot_post.id, data.local_user_view.person.id); + PostRead::mark_as_read(pool, &post_read_form).await?; + + // Only read the post marked as read + let read_read_post_listing = PostQuery { + community_id: Some(data.inserted_community.id), + read_only: Some(true), + ..data.default_post_query() + } + .list(&data.site, pool) + .await?; + + // This should only include the bot post, not the one you created + assert_eq!(vec![POST_BY_BOT], names(&read_read_post_listing)); + + Ok(()) + } + #[test_context(Data)] #[tokio::test] #[serial] diff --git a/migrations/2024-12-15-151642_add_index_on_person_id_read_for_read_only_post_actions/down.sql b/migrations/2024-12-15-151642_add_index_on_person_id_read_for_read_only_post_actions/down.sql new file mode 100644 index 0000000000..08750942c5 --- /dev/null +++ b/migrations/2024-12-15-151642_add_index_on_person_id_read_for_read_only_post_actions/down.sql @@ -0,0 +1,2 @@ +DROP INDEX idx_post_actions_on_read_read_not_null; + diff --git a/migrations/2024-12-15-151642_add_index_on_person_id_read_for_read_only_post_actions/up.sql b/migrations/2024-12-15-151642_add_index_on_person_id_read_for_read_only_post_actions/up.sql new file mode 100644 index 0000000000..03f9e4008c --- /dev/null +++ b/migrations/2024-12-15-151642_add_index_on_person_id_read_for_read_only_post_actions/up.sql @@ -0,0 +1,4 @@ +CREATE INDEX idx_post_actions_on_read_read_not_null ON post_actions (person_id, read, post_id) +WHERE + read IS NOT NULL; +