Better handling of filter expiration date (#212)

* Better handling of filter expiration date
* Simplify Thread and Home Timeline filtering
This commit is contained in:
Thiago 'Jedi' Abreu 2022-12-29 09:32:22 -03:00 committed by LucasGGamerM
parent 3a962c7c05
commit 98b96c78d7
4 changed files with 33 additions and 23 deletions

View File

@ -19,9 +19,11 @@ import android.widget.Button;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toolbar; import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E; import org.joinmastodon.android.E;
@ -43,12 +45,9 @@ import org.joinmastodon.android.utils.StatusFilterPredicate;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
@ -266,19 +265,15 @@ public class HomeTimelineFragment extends StatusListFragment{
List<StatusDisplayItem> targetList=displayItems.subList(gapPos, gapPos+1); List<StatusDisplayItem> targetList=displayItems.subList(gapPos, gapPos+1);
targetList.clear(); targetList.clear();
List<Status> insertedPosts=data.subList(gapPostIndex+1, gapPostIndex+1); List<Status> insertedPosts=data.subList(gapPostIndex+1, gapPostIndex+1);
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.HOME)).collect(Collectors.toList()); StatusFilterPredicate filterPredicate=new StatusFilterPredicate(accountID, Filter.FilterContext.HOME);
outer:
for(Status s:result){ for(Status s:result){
if(idsBelowGap.contains(s.id)) if(idsBelowGap.contains(s.id))
break; break;
for(Filter filter:filters){ if(filterPredicate.test(s)){
if(filter.matches(s)){
continue outer;
}
}
targetList.addAll(buildDisplayItems(s)); targetList.addAll(buildDisplayItems(s));
insertedPosts.add(s); insertedPosts.add(s);
} }
}
if(targetList.isEmpty()){ if(targetList.isEmpty()){
// oops. We didn't add new posts, but at least we know there are none. // oops. We didn't add new posts, but at least we know there are none.
adapter.notifyItemRemoved(getMainAdapterOffset()+gapPos); adapter.notifyItemRemoved(getMainAdapterOffset()+gapPos);

View File

@ -5,7 +5,6 @@ import android.view.View;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.statuses.GetStatusContext; import org.joinmastodon.android.api.requests.statuses.GetStatusContext;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.StatusCreatedEvent; import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Filter;
@ -17,6 +16,7 @@ import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
import org.joinmastodon.android.ui.text.HtmlParser; import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import org.parceler.Parcels; import org.parceler.Parcels;
import java.util.Collections; import java.util.Collections;
@ -92,16 +92,10 @@ public class ThreadFragment extends StatusListFragment{
} }
private List<Status> filterStatuses(List<Status> statuses){ private List<Status> filterStatuses(List<Status> statuses){
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.THREAD)).collect(Collectors.toList()); StatusFilterPredicate statusFilterPredicate=new StatusFilterPredicate(accountID,Filter.FilterContext.THREAD);
if(filters.isEmpty()) return statuses.stream()
return statuses; .filter(statusFilterPredicate)
return statuses.stream().filter(status->{ .collect(Collectors.toList());
for(Filter filter:filters){
if(filter.matches(status))
return false;
}
return true;
}).collect(Collectors.toList());
} }
@Override @Override

View File

@ -6,12 +6,14 @@ import com.google.gson.annotations.SerializedName;
import org.joinmastodon.android.api.ObjectValidationException; import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.RequiredField; import org.joinmastodon.android.api.RequiredField;
import org.parceler.Parcel;
import java.time.Instant; import java.time.Instant;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@Parcel
public class Filter extends BaseModel{ public class Filter extends BaseModel{
@RequiredField @RequiredField
public String id; public String id;
@ -21,6 +23,7 @@ public class Filter extends BaseModel{
public Instant expiresAt; public Instant expiresAt;
public boolean irreversible; public boolean irreversible;
public boolean wholeWord; public boolean wholeWord;
public FilterAction filterAction;
@SerializedName("context") @SerializedName("context")
private List<FilterContext> _context; private List<FilterContext> _context;
@ -76,4 +79,11 @@ public class Filter extends BaseModel{
@SerializedName("thread") @SerializedName("thread")
THREAD THREAD
} }
public enum FilterAction{
@SerializedName("hide")
HIDE,
@SerializedName("warn")
WARN
}
} }

View File

@ -4,6 +4,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import java.time.Instant;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -21,6 +22,16 @@ public class StatusFilterPredicate implements Predicate<Status>{
@Override @Override
public boolean test(Status status){ public boolean test(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.HIDE);
return !matches;
}
for(Filter filter:filters){ for(Filter filter:filters){
if(filter.matches(status)) if(filter.matches(status))
return false; return false;