diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java index 41311e6a3..b3e2c3794 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java @@ -118,4 +118,10 @@ public class AccountTimelineFragment extends StatusListFragment{ protected void onRemoveAccountPostsEvent(RemoveAccountPostsEvent ev){ // no-op } + + + @Override + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.ACCOUNT; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarkedStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarkedStatusListFragment.java index 6fd12d95d..6f863bdd2 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarkedStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarkedStatusListFragment.java @@ -4,6 +4,7 @@ import android.app.Activity; import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.statuses.GetBookmarkedStatuses; +import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.HeaderPaginationList; import org.joinmastodon.android.model.Status; @@ -35,4 +36,9 @@ public class BookmarkedStatusListFragment extends StatusListFragment{ }) .exec(accountID); } + + @Override + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.ACCOUNT; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/FavoritedStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/FavoritedStatusListFragment.java index 31fdd8442..41e6e0c7f 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/FavoritedStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/FavoritedStatusListFragment.java @@ -4,6 +4,7 @@ import android.app.Activity; import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.statuses.GetFavoritedStatuses; +import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.HeaderPaginationList; import org.joinmastodon.android.model.Status; @@ -35,4 +36,9 @@ public class FavoritedStatusListFragment extends StatusListFragment{ }) .exec(accountID); } + + @Override + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.ACCOUNT; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java index bd8dec69c..204a0bbd6 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java @@ -280,4 +280,9 @@ public class HomeTimelineFragment extends StatusListFragment { protected boolean shouldRemoveAccountPostsWhenUnfollowing(){ return true; } + + @Override + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.HOME; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ListTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ListTimelineFragment.java index fd2155b54..20712f76f 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ListTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ListTimelineFragment.java @@ -162,4 +162,10 @@ public class ListTimelineFragment extends PinnableStatusListFragment { protected void onSetFabBottomInset(int inset) { ((ViewGroup.MarginLayoutParams) fab.getLayoutParams()).bottomMargin=V.dp(24)+inset; } + + + @Override + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.HOME; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java index 3023bd20b..487b84759 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java @@ -34,7 +34,11 @@ public abstract class StatusListFragment extends BaseStatusListFragment{ protected List buildDisplayItems(Status s){ boolean addFooter = !GlobalUserPreferences.spectatorMode || (this instanceof ThreadFragment t && s.id.equals(t.mainStatus.id)); - return StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, false, addFooter, null, Filter.FilterContext.HOME); + return StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, false, addFooter, null, getFilterContext()); + } + + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.PUBLIC; } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java index c16d776c4..206792f63 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java @@ -181,4 +181,10 @@ public class ThreadFragment extends StatusListFragment{ public boolean wantsLightNavigationBar(){ return !UiUtils.isDarkTheme(); } + + + @Override + protected Filter.FilterContext getFilterContext() { + return Filter.FilterContext.THREAD; + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Filter.java b/mastodon/src/main/java/org/joinmastodon/android/model/Filter.java index 867679498..4a134c1cd 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Filter.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Filter.java @@ -15,9 +15,7 @@ import java.util.regex.Pattern; @Parcel public class Filter extends BaseModel{ - @RequiredField public String id; - @RequiredField public String phrase; public String title; public transient EnumSet context=EnumSet.noneOf(FilterContext.class); diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/FilterResult.java b/mastodon/src/main/java/org/joinmastodon/android/model/FilterResult.java index 2b67ef4bf..361a5fac5 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/FilterResult.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/FilterResult.java @@ -1,8 +1,15 @@ package org.joinmastodon.android.model; +import org.joinmastodon.android.api.ObjectValidationException; import org.parceler.Parcel; @Parcel public class FilterResult extends BaseModel { public Filter filter; + + @Override + public void postprocess() throws ObjectValidationException { + super.postprocess(); + if (filter != null) filter.postprocess(); + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Status.java b/mastodon/src/main/java/org/joinmastodon/android/model/Status.java index add0dd772..156a3d874 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Status.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Status.java @@ -101,6 +101,9 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{ card.postprocess(); if(reblog!=null) reblog.postprocess(); + if(filtered!=null) + for(FilterResult fr : filtered) + fr.postprocess(); spoilerRevealed=GlobalUserPreferences.alwaysExpandContentWarnings || !sensitive; if (visibility.equals(StatusPrivacy.LOCAL)) localOnly = true; 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 300f16185..f52382f5a 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 @@ -107,7 +107,7 @@ public abstract class StatusDisplayItem{ StatusFilterPredicate filterPredicate = new StatusFilterPredicate(filters); if(!statusForContent.filterRevealed){ - statusForContent.filterRevealed = filterPredicate.testWithWarning(status); + statusForContent.filterRevealed = !filterPredicate.testHasStatusWarning(status, filterContext); } ReblogOrReplyLineStatusDisplayItem replyLine = null; diff --git a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java index 9e4b91413..b4f170339 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java +++ b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java @@ -20,6 +20,7 @@ public class StatusFilterPredicate implements Predicate{ filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(context)).collect(Collectors.toList()); } + // TODO: rewrite (see testHasStatusWarning) and generalize @Override public boolean test(Status status){ if(status.filtered!=null){ @@ -39,21 +40,19 @@ public class StatusFilterPredicate implements Predicate{ return true; } - public boolean testWithWarning(Status status) { - if(status.filtered!=null){ - if (status.filtered.isEmpty()){ - return true; - } - boolean matches=status.filtered.stream() - .map(filterResult->filterResult.filter) - .filter(filter->filter.expiresAt==null||filter.expiresAt.isAfter(Instant.now())) - .anyMatch(filter->filter.filterAction==Filter.FilterAction.WARN); - return !matches; + // TODO: move this method elsewhere; it's not part of the actual StatusFilterPredicate + public boolean testHasStatusWarning(Status status, Filter.FilterContext context) { + if (status.filtered != null) { + // use server-provided info on whether this status was filtered + if (status.filtered.isEmpty()) return false; + return status.filtered.stream() + .map(filterResult -> filterResult.filter) + .filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now())) + .filter(filter -> filter.context.contains(context)) + .anyMatch(filter -> filter.filterAction == Filter.FilterAction.WARN); + } else { + // look through local filters instead + return filters.stream().anyMatch(filter -> filter.matches(status)); } - for(Filter filter:filters){ - if(filter.matches(status)) - return false; - } - return true; } }