From c9e93bb6a6edfa4a9a839493819b3b977e52a47a Mon Sep 17 00:00:00 2001 From: FineFindus Date: Tue, 7 May 2024 18:49:27 +0200 Subject: [PATCH 1/5] fix: apply filters only in appropriate context Currently Filters in AccountSession are applied regardless of the FilterContext. --- .../org/joinmastodon/android/api/session/AccountSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java index 8f5a6fcbac..55da7e8e36 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java @@ -314,7 +314,7 @@ public boolean filterStatusContainingObject(T object, Function ex // Even with server-side filters, clients are expected to remove statuses that match a filter that hides them if(getLocalPreferences().serverSideFiltersSupported){ for(FilterResult filter : s.filtered){ - if(filter.filter.isActive() && filter.filter.filterAction==FilterAction.HIDE) + if(filter.filter.isActive() && filter.filter.filterAction==FilterAction.HIDE && filter.filter.context.contains(context)) return true; } }else if(wordFilters!=null){ From 00726abec13f7a0e9c72831619a24aa8f6f5e421 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Tue, 7 May 2024 18:50:25 +0200 Subject: [PATCH 2/5] feat(CustomLocalTimeline): set Public FitlterContext --- .../android/fragments/CustomLocalTimelineFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java index 9fd6bcef49..9933555ffd 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java @@ -82,7 +82,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @Override protected FilterContext getFilterContext() { - return null; + return FilterContext.PUBLIC; } @Override From 28c851a63093981fe86efa76935128b32ed37fd3 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Wed, 8 May 2024 16:43:33 +0200 Subject: [PATCH 3/5] refactor: remove StatusFilterPredicate Removes the deprecated StatusFilterPredicate class, as it has been replaced upstream. Client-side filters are now directly applied in the when building a StatusDisplayItem. --- .../utils/StatusFilterPredicateTest.java | 104 --------------- .../CustomLocalTimelineFragment.java | 6 +- .../android/model/AltTextFilter.java | 10 +- .../ui/displayitems/StatusDisplayItem.java | 28 ++-- .../android/utils/StatusFilterPredicate.java | 120 ------------------ 5 files changed, 25 insertions(+), 243 deletions(-) delete mode 100644 mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java delete mode 100644 mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java diff --git a/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java b/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java deleted file mode 100644 index 87235de8fa..0000000000 --- a/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.joinmastodon.android.utils; - -import static org.joinmastodon.android.model.FilterAction.*; -import static org.joinmastodon.android.model.FilterContext.*; -import static org.junit.Assert.*; - -import android.graphics.drawable.ColorDrawable; - -import org.joinmastodon.android.model.Attachment; -import org.joinmastodon.android.model.LegacyFilter; -import org.joinmastodon.android.model.Status; -import org.junit.Test; - -import java.time.Instant; -import java.util.EnumSet; -import java.util.List; - -public class StatusFilterPredicateTest { - - private static final LegacyFilter hideMeFilter = new LegacyFilter(), warnMeFilter = new LegacyFilter(); - private static final List allFilters = List.of(hideMeFilter, warnMeFilter); - - private static final Status - hideInHomePublic = Status.ofFake(null, "hide me, please", Instant.now()), - warnInHomePublic = Status.ofFake(null, "display me with a warning", Instant.now()), - noAltText = Status.ofFake(null, "display me with a warning", Instant.now()), - withAltText = Status.ofFake(null, "display me with a warning", Instant.now()); - - static { - hideMeFilter.phrase = "hide me"; - hideMeFilter.filterAction = HIDE; - hideMeFilter.context = EnumSet.of(PUBLIC, HOME); - - warnMeFilter.phrase = "warning"; - warnMeFilter.filterAction = WARN; - warnMeFilter.context = EnumSet.of(PUBLIC, HOME); - -// noAltText.mediaAttachments = Attachment.createFakeAttachments("fakeurl", new ColorDrawable()); -// withAltText.mediaAttachments = Attachment.createFakeAttachments("fakeurl", new ColorDrawable()); -// for (Attachment mediaAttachment : withAltText.mediaAttachments) { -// mediaAttachment.description = "Alt Text"; -// } - } - - @Test - public void testHide() { - assertFalse("should not pass because matching filter applies to given context", - new StatusFilterPredicate(allFilters, HOME).test(hideInHomePublic)); - } - - @Test - public void testHideRegardlessOfContext() { - assertTrue("filters without context should always pass", - new StatusFilterPredicate(allFilters, null).test(hideInHomePublic)); - } - - @Test - public void testHideInDifferentContext() { - assertTrue("should pass because matching filter does not apply to given context", - new StatusFilterPredicate(allFilters, THREAD).test(hideInHomePublic)); - } - - @Test - public void testHideWithWarningText() { - assertTrue("should pass because matching filter is for warnings", - new StatusFilterPredicate(allFilters, HOME).test(warnInHomePublic)); - } - - @Test - public void testWarn() { - assertFalse("should not pass because filter applies to given context", - new StatusFilterPredicate(allFilters, HOME, WARN).test(warnInHomePublic)); - } - - @Test - public void testWarnRegardlessOfContext() { - assertTrue("filters without context should always pass", - new StatusFilterPredicate(allFilters, null, WARN).test(warnInHomePublic)); - } - - @Test - public void testWarnInDifferentContext() { - assertTrue("should pass because filter does not apply to given context", - new StatusFilterPredicate(allFilters, THREAD, WARN).test(warnInHomePublic)); - } - - @Test - public void testWarnWithHideText() { - assertTrue("should pass because matching filter is for hiding", - new StatusFilterPredicate(allFilters, HOME, WARN).test(hideInHomePublic)); - } - - @Test - public void testAltTextFilterNoPass() { - assertFalse("should not pass because of no alt text", - new StatusFilterPredicate(allFilters, HOME).test(noAltText)); - } - - @Test - public void testAltTextFilterPass() { - assertTrue("should pass because of alt text", - new StatusFilterPredicate(allFilters, HOME).test(withAltText)); - } -} \ No newline at end of file diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java index 9933555ffd..d742a1451d 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/CustomLocalTimelineFragment.java @@ -7,16 +7,14 @@ import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.timelines.GetPublicTimeline; -import org.joinmastodon.android.model.Filter; +import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.model.FilterContext; import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.TimelineDefinition; import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.utils.ProvidesAssistContent; -import org.joinmastodon.android.utils.StatusFilterPredicate; import java.util.List; -import java.util.stream.Collectors; import me.grishka.appkit.api.SimpleCallback; @@ -53,7 +51,7 @@ public void onSuccess(List result){ if(!result.isEmpty()) maxID=result.get(result.size()-1).id; if (getActivity() == null) return; - result=result.stream().filter(new StatusFilterPredicate(accountID, FilterContext.PUBLIC)).collect(Collectors.toList()); + AccountSessionManager.get(accountID).filterStatuses(result, FilterContext.PUBLIC); result.stream().forEach(status -> { status.account.acct += "@"+domain; status.mentions.forEach(mention -> mention.id = null); diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java b/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java index 4168e65051..880f2ef62b 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java @@ -1,19 +1,25 @@ package org.joinmastodon.android.model; +import org.joinmastodon.android.GlobalUserPreferences; import org.jsoup.internal.StringUtil; import java.util.EnumSet; public class AltTextFilter extends LegacyFilter { - public AltTextFilter(FilterAction filterAction, FilterContext firstContext, FilterContext... restContexts) { + public AltTextFilter(FilterAction filterAction, EnumSet filterContexts) { this.filterAction = filterAction; isRemote = false; - context = EnumSet.of(firstContext, restContexts); + context = filterContexts; } @Override public boolean matches(Status status) { return status.getContentStatus().mediaAttachments.stream().map(attachment -> attachment.description).anyMatch(StringUtil::isBlank); } + + @Override + public boolean isActive(){ + return !GlobalUserPreferences.showPostsWithoutAlt; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index 835eaba66a..baf17d8f19 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -26,6 +26,7 @@ import org.joinmastodon.android.fragments.StatusListFragment; import org.joinmastodon.android.fragments.ThreadFragment; import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.AltTextFilter; import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.DisplayItemsParent; import org.joinmastodon.android.model.FilterAction; @@ -40,11 +41,11 @@ import org.joinmastodon.android.ui.text.HtmlParser; import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.viewholders.AccountViewHolder; -import org.joinmastodon.android.utils.StatusFilterPredicate; import org.parceler.Parcels; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -168,10 +169,6 @@ public static ArrayList buildItems(BaseStatusListFragment args.putString("account", accountID); ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus s ? s : null; - // Hide statuses that have a filter action of hide - if(!new StatusFilterPredicate(accountID, filterContext, FilterAction.HIDE).test(status)) - return new ArrayList() ; - HeaderStatusDisplayItem header=null; boolean hideCounts=!AccountSessionManager.get(accountID).getLocalPreferences().showInteractionCounts; @@ -233,20 +230,25 @@ public static ArrayList buildItems(BaseStatusListFragment LegacyFilter applyingFilter=null; if(status.filtered!=null){ - for(FilterResult filter:status.filtered){ + List filters = status.filtered; + + //add a client side filter to filter posts that have no alt text + //it only applies when activated in the settings + AltTextFilter altTextFilter=new AltTextFilter(FilterAction.WARN, EnumSet.allOf(FilterContext.class)); + if(altTextFilter.matches(status)){ + FilterResult filterResult=new FilterResult(); + filterResult.filter=altTextFilter; + filterResult.keywordMatches=List.of(); + filters.add(filterResult); + } + + for(FilterResult filter:filters){ LegacyFilter f=filter.filter; if(f.isActive() && filterContext != null && f.context.contains(filterContext)){ applyingFilter=f; break; } } - - // Moshidon - if(applyingFilter==null){ - StatusFilterPredicate predicate = new StatusFilterPredicate(accountID, filterContext, FilterAction.WARN); - predicate.test(status); - applyingFilter = predicate.getApplyingFilter(); - } } ArrayList contentItems; diff --git a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java deleted file mode 100644 index 2529dcf645..0000000000 --- a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.joinmastodon.android.utils; - -import static org.joinmastodon.android.model.FilterAction.HIDE; -import static org.joinmastodon.android.model.FilterAction.WARN; -import static org.joinmastodon.android.model.FilterContext.ACCOUNT; -import static org.joinmastodon.android.model.FilterContext.HOME; -import static org.joinmastodon.android.model.FilterContext.NOTIFICATIONS; -import static org.joinmastodon.android.model.FilterContext.PUBLIC; -import static org.joinmastodon.android.model.FilterContext.THREAD; - -import org.joinmastodon.android.GlobalUserPreferences; -import org.joinmastodon.android.api.session.AccountSessionManager; -import org.joinmastodon.android.model.AltTextFilter; -import org.joinmastodon.android.model.LegacyFilter; -import org.joinmastodon.android.model.FilterAction; -import org.joinmastodon.android.model.FilterContext; -import org.joinmastodon.android.model.Status; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -// TODO: This whole class has been ditched upstream. I plan to eventually refactor it to only have the still relevant clientFilters code - -public class StatusFilterPredicate implements Predicate{ - private final List clientFilters; - private final List filters; - private final FilterContext context; - private final FilterAction action; - private LegacyFilter applyingFilter; - - /** - * @param context null makes the predicate pass automatically - * @param action defines what the predicate should check: - * status should not be hidden or should not display with warning - */ - public StatusFilterPredicate(List filters, FilterContext context, FilterAction action){ - this.filters = filters; - this.context = context; - this.action = action; - this.clientFilters = getClientFilters(); - } - - public StatusFilterPredicate(List filters, FilterContext context){ - this(filters, context, HIDE); - } - - /** - * @param context null makes the predicate pass automatically - * @param action defines what the predicate should check: - * status should not be hidden or should not display with warning - */ - public StatusFilterPredicate(String accountID, FilterContext context, FilterAction action){ - filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(context)).collect(Collectors.toList()); - this.context = context; - this.action = action; - this.clientFilters = getClientFilters(); - } - - private List getClientFilters() { - List filters = new ArrayList<>(); - if(!GlobalUserPreferences.showPostsWithoutAlt) { - filters.add(new AltTextFilter(WARN, HOME, PUBLIC, ACCOUNT, THREAD, NOTIFICATIONS)); - } - return filters; - } - - /** - * @param context null makes the predicate pass automatically - */ - public StatusFilterPredicate(String accountID, FilterContext context){ - this(accountID, context, HIDE); - } - - /** - * @return whether the status should be displayed without being hidden/warned about. - * will always return true if the context is null. - * true = display this status, - * false = filter this status - */ - @Override - public boolean test(Status status){ - if (context == null) return true; - - Stream matchingFilters = status.filtered != null - // use server-provided per-status info (status.filtered) if available - ? status.filtered.stream().map(f -> f.filter) - // or fall back to cached filters - : filters.stream().filter(filter -> filter.matches(status)); - - Optional applyingFilter = matchingFilters - // discard expired filters - .filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now())) - // only apply filters for given context - .filter(filter -> filter.context.contains(context)) - // treating filterAction = null (from filters list) as FilterAction.HIDE - .filter(filter -> filter.filterAction == null ? action == HIDE : filter.filterAction == action) - .findAny(); - - //Apply client filters if no server filter is triggered - if (applyingFilter.isEmpty() && !clientFilters.isEmpty()) { - applyingFilter = clientFilters.stream() - .filter(filter -> filter.context.contains(context)) - .filter(filter -> filter.filterAction == null ? action == HIDE : filter.filterAction == action) - .filter(filter -> filter.matches(status)) - .findAny(); - } - - this.applyingFilter = applyingFilter.orElse(null); - return applyingFilter.isEmpty(); - } - - public LegacyFilter getApplyingFilter() { - return applyingFilter; - } -} From ebf3b075b80d09b2664a3523906eb7b218ed47b8 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Wed, 8 May 2024 17:08:18 +0200 Subject: [PATCH 4/5] fix(StatusDisplayItem): apply filter highlight The filter highlight was not correctly shown, as the source text was re-parsed when creating the TextStatusDisplayItem. --- .../android/ui/displayitems/StatusDisplayItem.java | 5 +++-- .../java/org/joinmastodon/android/ui/text/HtmlParser.java | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index baf17d8f19..10a4a48cc6 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -275,8 +275,9 @@ public static ArrayList buildItems(BaseStatusListFragment boolean hasSpoiler=!TextUtils.isEmpty(statusForContent.spoilerText); if(!TextUtils.isEmpty(statusForContent.content)){ SpannableStringBuilder parsedText=HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID, fragment.getContext()); - HtmlParser.applyFilterHighlights(fragment.getActivity(), parsedText, status.filtered); - TextStatusDisplayItem text=new TextStatusDisplayItem(parentID, HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID, fragment.getContext()), fragment, statusForContent, (flags & FLAG_NO_TRANSLATE) != 0); + if(applyingFilter!=null) + HtmlParser.applyFilterHighlights(fragment.getActivity(), parsedText, status.filtered); + TextStatusDisplayItem text=new TextStatusDisplayItem(parentID, parsedText, fragment, statusForContent, (flags & FLAG_NO_TRANSLATE) != 0); contentItems.add(text); }else if(!hasSpoiler && header!=null){ header.needBottomPadding=true; diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java b/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java index 0e468d653c..cc956906f4 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/text/HtmlParser.java @@ -321,12 +321,11 @@ public static CharSequence parseLinks(String text){ } public static void applyFilterHighlights(Context context, SpannableStringBuilder text, List filters){ - if (filters == null) return; int fgColor=UiUtils.getThemeColor(context, R.attr.colorM3Error); int bgColor=UiUtils.getThemeColor(context, R.attr.colorM3ErrorContainer); for(FilterResult filter:filters){ if(!filter.filter.isActive()) - continue;; + continue; for(String word:filter.keywordMatches){ Matcher matcher=Pattern.compile("\\b"+Pattern.quote(word)+"\\b", Pattern.CASE_INSENSITIVE).matcher(text); while(matcher.find()){ From d1d8f2ef45143780a67c8c973fb227c904e7e325 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Thu, 9 May 2024 06:39:50 +0200 Subject: [PATCH 5/5] refactor(StatusDisplayItem): move client filters to AccountSession --- .../android/api/session/AccountSession.java | 17 +++++++++++++++++ .../ui/displayitems/StatusDisplayItem.java | 16 ++-------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java index 55da7e8e36..e2cd5bf91a 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSession.java @@ -21,6 +21,7 @@ import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken; import org.joinmastodon.android.events.NotificationsMarkerUpdatedEvent; import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.AltTextFilter; import org.joinmastodon.android.model.Application; import org.joinmastodon.android.model.FilterAction; import org.joinmastodon.android.model.FilterContext; @@ -37,6 +38,7 @@ import java.io.File; import java.util.ArrayList; +import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -326,6 +328,21 @@ public boolean filterStatusContainingObject(T object, Function ex return false; } + public List getClientSideFilters(Status status) { + List filters = List.of(); + + // filter post that have no alt text + // it only applies when activated in the settings + AltTextFilter altTextFilter=new AltTextFilter(FilterAction.WARN, EnumSet.allOf(FilterContext.class)); + if(altTextFilter.matches(status)){ + FilterResult filterResult=new FilterResult(); + filterResult.filter=altTextFilter; + filterResult.keywordMatches=List.of(); + filters.add(filterResult); + } + return filters; + } + public void updateAccountInfo(){ AccountSessionManager.getInstance().updateSessionLocalInfo(this); } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index 10a4a48cc6..9d5e5dbb8b 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -26,13 +26,11 @@ import org.joinmastodon.android.fragments.StatusListFragment; import org.joinmastodon.android.fragments.ThreadFragment; import org.joinmastodon.android.model.Account; -import org.joinmastodon.android.model.AltTextFilter; import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.DisplayItemsParent; -import org.joinmastodon.android.model.FilterAction; -import org.joinmastodon.android.model.LegacyFilter; import org.joinmastodon.android.model.FilterContext; import org.joinmastodon.android.model.FilterResult; +import org.joinmastodon.android.model.LegacyFilter; import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Poll; import org.joinmastodon.android.model.ScheduledStatus; @@ -45,7 +43,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -231,16 +228,7 @@ public static ArrayList buildItems(BaseStatusListFragment LegacyFilter applyingFilter=null; if(status.filtered!=null){ List filters = status.filtered; - - //add a client side filter to filter posts that have no alt text - //it only applies when activated in the settings - AltTextFilter altTextFilter=new AltTextFilter(FilterAction.WARN, EnumSet.allOf(FilterContext.class)); - if(altTextFilter.matches(status)){ - FilterResult filterResult=new FilterResult(); - filterResult.filter=altTextFilter; - filterResult.keywordMatches=List.of(); - filters.add(filterResult); - } + filters.addAll(AccountSessionManager.get(accountID).getClientSideFilters(status)); for(FilterResult filter:filters){ LegacyFilter f=filter.filter;