use matched filter for determining warning title

fixes a bug where, when multiple filters apply, the
WarningFilteredStatusDisplayItem would not check if the warning applies to the
current context. now, matched filter is determined through the predicate
(though not exactly what a predicate is supposed to do, i guess) and passed
down to the WarningFilteredStatusDisplayItem. cc @LucasGGamerM
This commit is contained in:
sk 2023-05-27 13:09:36 +02:00
parent 1fc2f81dab
commit c38eb545b1
3 changed files with 26 additions and 10 deletions

View File

@ -95,10 +95,6 @@ public abstract class StatusDisplayItem{
args.putString("account", accountID); args.putString("account", accountID);
ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus ? (ScheduledStatus) parentObject : null; ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus ? (ScheduledStatus) parentObject : null;
if (!statusForContent.filterRevealed) {
statusForContent.filterRevealed = new StatusFilterPredicate(accountID, filterContext, Filter.FilterAction.WARN).test(status);
}
ReblogOrReplyLineStatusDisplayItem replyLine = null; ReblogOrReplyLineStatusDisplayItem replyLine = null;
boolean threadReply = statusForContent.inReplyToAccountId != null && boolean threadReply = statusForContent.inReplyToAccountId != null &&
statusForContent.inReplyToAccountId.equals(statusForContent.account.id); statusForContent.inReplyToAccountId.equals(statusForContent.account.id);
@ -206,8 +202,15 @@ public abstract class StatusDisplayItem{
item.index=i++; item.index=i++;
} }
Filter applyingFilter = null;
if (!statusForContent.filterRevealed) {
StatusFilterPredicate predicate = new StatusFilterPredicate(accountID, filterContext, Filter.FilterAction.WARN);
statusForContent.filterRevealed = predicate.test(status);
applyingFilter = predicate.getApplyingFilter();
}
ArrayList<StatusDisplayItem> result = statusForContent.filterRevealed ? items : ArrayList<StatusDisplayItem> result = statusForContent.filterRevealed ? items :
new ArrayList<>(List.of(new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items))); new ArrayList<>(List.of(new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items, applyingFilter)));
if (addFooter && status.hasGapAfter && !(fragment instanceof ThreadFragment)) { if (addFooter && status.hasGapAfter && !(fragment instanceof ThreadFragment)) {
StatusDisplayItem gap = new GapStatusDisplayItem(parentID, fragment); StatusDisplayItem gap = new GapStatusDisplayItem(parentID, fragment);

View File

@ -7,6 +7,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import java.util.List; import java.util.List;
@ -15,11 +16,13 @@ public class WarningFilteredStatusDisplayItem extends StatusDisplayItem{
public boolean loading; public boolean loading;
public final Status status; public final Status status;
public List<StatusDisplayItem> filteredItems; public List<StatusDisplayItem> filteredItems;
public Filter applyingFilter;
public WarningFilteredStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, List<StatusDisplayItem> filteredItems){ public WarningFilteredStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, List<StatusDisplayItem> filteredItems, Filter applyingFilter){
super(parentID, parentFragment); super(parentID, parentFragment);
this.status=status; this.status=status;
this.filteredItems = filteredItems; this.filteredItems = filteredItems;
this.applyingFilter = applyingFilter;
} }
@Override @Override
@ -41,7 +44,7 @@ public class WarningFilteredStatusDisplayItem extends StatusDisplayItem{
@Override @Override
public void onBind(WarningFilteredStatusDisplayItem item) { public void onBind(WarningFilteredStatusDisplayItem item) {
filteredItems = item.filteredItems; filteredItems = item.filteredItems;
text.setText(item.parentFragment.getString(R.string.sk_filtered, item.status.filtered.get(item.status.filtered.size() -1).filter.title)); text.setText(item.parentFragment.getString(R.string.sk_filtered, item.applyingFilter.title));
} }
@Override @Override

View File

@ -6,6 +6,7 @@ import org.joinmastodon.android.model.Status;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -14,6 +15,7 @@ public class StatusFilterPredicate implements Predicate<Status>{
private final List<Filter> filters; private final List<Filter> filters;
private final Filter.FilterContext context; private final Filter.FilterContext context;
private final Filter.FilterAction action; private final Filter.FilterAction action;
private Filter applyingFilter;
/** /**
* @param context null makes the predicate pass automatically * @param context null makes the predicate pass automatically
@ -58,18 +60,26 @@ public class StatusFilterPredicate implements Predicate<Status>{
public boolean test(Status status){ public boolean test(Status status){
if (context == null) return true; if (context == null) return true;
Stream<Filter> stream = status.filtered != null Stream<Filter> matchingFilters = status.filtered != null
// use server-provided per-status info (status.filtered) if available // use server-provided per-status info (status.filtered) if available
? status.filtered.stream().map(f -> f.filter) ? status.filtered.stream().map(f -> f.filter)
// or fall back to cached filters // or fall back to cached filters
: filters.stream().filter(filter -> filter.matches(status)); : filters.stream().filter(filter -> filter.matches(status));
return stream Optional<Filter> applyingFilter = matchingFilters
// discard expired filters // discard expired filters
.filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now())) .filter(filter -> filter.expiresAt == null || filter.expiresAt.isAfter(Instant.now()))
// only apply filters for given context // only apply filters for given context
.filter(filter -> filter.context.contains(context)) .filter(filter -> filter.context.contains(context))
// treating filterAction = null (from filters list) as FilterAction.HIDE // treating filterAction = null (from filters list) as FilterAction.HIDE
.noneMatch(filter -> filter.filterAction == null ? action == Filter.FilterAction.HIDE : filter.filterAction == action); .filter(filter -> filter.filterAction == null ? action == Filter.FilterAction.HIDE : filter.filterAction == action)
.findAny();
this.applyingFilter = applyingFilter.orElse(null);
return applyingFilter.isEmpty();
}
public Filter getApplyingFilter() {
return applyingFilter;
} }
} }