2
0
Fork 0
mirror of https://github.com/LemmyNet/lemmy synced 2025-02-20 16:08:59 +00:00

Add media filter setting ()

* Add hide_media filter

* Test media is returned when hide_media is false

* Add GIN index

* SQL fmt

* Drop GIN index in migration
This commit is contained in:
flamingos-cant 2025-01-16 11:57:58 +00:00 committed by GitHub
parent 3f06317878
commit 099328a5b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 103 additions and 0 deletions
crates
migrations/2025-01-14-023145_media_filter

View file

@ -132,6 +132,7 @@ pub async fn save_user_settings(
enable_private_messages: data.enable_private_messages,
collapse_bot_comments: data.collapse_bot_comments,
auto_mark_fetched_posts_as_read: data.auto_mark_fetched_posts_as_read,
hide_media: data.hide_media,
..Default::default()
};

View file

@ -189,6 +189,9 @@ pub struct SaveUserSettings {
/// Whether to automatically mark fetched posts as read.
#[cfg_attr(feature = "full", ts(optional))]
pub auto_mark_fetched_posts_as_read: Option<bool>,
/// Whether to hide posts containing images/videos.
#[cfg_attr(feature = "full", ts(optional))]
pub hide_media: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]

View file

@ -112,6 +112,9 @@ pub struct GetPosts {
/// If true, then show the nsfw posts (even if your user setting is to hide them)
#[cfg_attr(feature = "full", ts(optional))]
pub show_nsfw: Option<bool>,
/// If false, then show posts with media attached (even if your user setting is to hide them)
#[cfg_attr(feature = "full", ts(optional))]
pub hide_media: Option<bool>,
/// Whether to automatically mark fetched posts as read.
#[cfg_attr(feature = "full", ts(optional))]
pub mark_as_read: Option<bool>,

View file

@ -45,6 +45,7 @@ pub async fn list_posts(
let show_hidden = data.show_hidden;
let show_read = data.show_read;
let show_nsfw = data.show_nsfw;
let hide_media = data.hide_media;
let no_comments_only = data.no_comments_only;
let liked_only = data.liked_only;
@ -86,6 +87,7 @@ pub async fn list_posts(
show_hidden,
show_read,
show_nsfw,
hide_media,
no_comments_only,
..Default::default()
}

View file

@ -297,6 +297,7 @@ pub trait LocalUserOptionHelper {
fn show_read_posts(&self) -> bool;
fn is_admin(&self) -> bool;
fn show_nsfw(&self, site: &Site) -> bool;
fn hide_media(&self) -> bool;
fn visible_communities_only<Q>(&self, query: Q) -> Q
where
Q: diesel::query_dsl::methods::FilterDsl<
@ -332,6 +333,10 @@ impl LocalUserOptionHelper for Option<&LocalUser> {
.unwrap_or(site.content_warning.is_some())
}
fn hide_media(&self) -> bool {
self.map(|l| l.hide_media).unwrap_or(false)
}
// TODO: use this function for private community checks, but the generics get extremely confusing
fn visible_communities_only<Q>(&self, query: Q) -> Q
where

View file

@ -513,6 +513,7 @@ diesel::table! {
collapse_bot_comments -> Bool,
default_comment_sort_type -> CommentSortTypeEnum,
auto_mark_fetched_posts_as_read -> Bool,
hide_media -> Bool,
}
}

View file

@ -70,6 +70,8 @@ pub struct LocalUser {
pub default_comment_sort_type: CommentSortType,
/// Whether to automatically mark fetched posts as read.
pub auto_mark_fetched_posts_as_read: bool,
/// Whether to hide posts containing images/videos
pub hide_media: bool,
}
#[derive(Clone, derive_new::new)]
@ -128,6 +130,8 @@ pub struct LocalUserInsertForm {
pub default_comment_sort_type: Option<CommentSortType>,
#[new(default)]
pub auto_mark_fetched_posts_as_read: Option<bool>,
#[new(default)]
pub hide_media: Option<bool>,
}
#[derive(Clone, Default)]
@ -160,4 +164,5 @@ pub struct LocalUserUpdateForm {
pub collapse_bot_comments: Option<bool>,
pub default_comment_sort_type: Option<CommentSortType>,
pub auto_mark_fetched_posts_as_read: Option<bool>,
pub hide_media: Option<bool>,
}

View file

@ -12,6 +12,7 @@ use diesel::{
OptionalExtension,
PgTextExpressionMethods,
QueryDsl,
TextExpressionMethods,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
@ -320,6 +321,16 @@ fn queries<'a>() -> Queries<
query = query.filter(post_actions::hidden.is_null());
}
if o.hide_media.unwrap_or(o.local_user.hide_media()) {
query = query.filter(not(
post::url_content_type.is_not_null().and(
post::url_content_type
.like("image/%")
.or(post::url_content_type.like("video/%")),
),
));
}
if let Some(my_id) = o.local_user.person_id() {
let not_creator_filter = post_aggregates::creator_id.ne(my_id);
if o.liked_only.unwrap_or_default() {
@ -518,6 +529,7 @@ pub struct PostQuery<'a> {
pub show_hidden: Option<bool>,
pub show_read: Option<bool>,
pub show_nsfw: Option<bool>,
pub hide_media: Option<bool>,
pub no_comments_only: Option<bool>,
}
@ -2192,6 +2204,66 @@ mod tests {
Ok(())
}
#[test_context(Data)]
#[tokio::test]
#[serial]
async fn post_listings_hide_media(data: &mut Data) -> LemmyResult<()> {
let pool = &data.pool();
let pool = &mut pool.into();
// Make one post an image post
Post::update(
pool,
data.inserted_bot_post.id,
&PostUpdateForm {
url_content_type: Some(Some(String::from("image/png"))),
..Default::default()
},
)
.await?;
// Make sure all the posts are returned when `hide_media` is unset
let hide_media_listing = PostQuery {
community_id: Some(data.inserted_community.id),
local_user: Some(&data.local_user_view.local_user),
..Default::default()
}
.list(&data.site, pool)
.await?;
assert_eq!(3, hide_media_listing.len());
// Ensure the `hide_media` user setting is set
let local_user_form = LocalUserUpdateForm {
hide_media: Some(true),
..Default::default()
};
LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form).await?;
data.local_user_view.local_user.hide_media = true;
// Ensure you don't see the image post
let hide_media_listing = PostQuery {
community_id: Some(data.inserted_community.id),
local_user: Some(&data.local_user_view.local_user),
..Default::default()
}
.list(&data.site, pool)
.await?;
assert_eq!(2, hide_media_listing.len());
// Make sure the `hide_media` override works
let hide_media_listing = PostQuery {
community_id: Some(data.inserted_community.id),
local_user: Some(&data.local_user_view.local_user),
hide_media: Some(false),
..Default::default()
}
.list(&data.site, pool)
.await?;
assert_eq!(3, hide_media_listing.len());
Ok(())
}
#[test_context(Data)]
#[tokio::test]
#[serial]

View file

@ -243,6 +243,7 @@ mod tests {
enable_private_messages: inserted_sara_local_user.enable_private_messages,
collapse_bot_comments: inserted_sara_local_user.collapse_bot_comments,
auto_mark_fetched_posts_as_read: false,
hide_media: false,
},
creator: Person {
id: inserted_sara_person.id,

View file

@ -0,0 +1,5 @@
ALTER TABLE local_user
DROP COLUMN hide_media;
DROP INDEX idx_post_url_content_type;

View file

@ -0,0 +1,5 @@
ALTER TABLE local_user
ADD COLUMN hide_media boolean DEFAULT FALSE NOT NULL;
CREATE INDEX idx_post_url_content_type ON post USING gin (url_content_type gin_trgm_ops);