Apply filters to statuses
This commit is contained in:
parent
789d02d810
commit
12ac5e9425
|
@ -10,7 +10,7 @@ android {
|
||||||
applicationId "org.joinmastodon.android"
|
applicationId "org.joinmastodon.android"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 31
|
targetSdk 31
|
||||||
versionCode 24
|
versionCode 25
|
||||||
versionName "0.1"
|
versionName "0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,10 @@ import org.joinmastodon.android.BuildConfig;
|
||||||
import org.joinmastodon.android.MastodonApp;
|
import org.joinmastodon.android.MastodonApp;
|
||||||
import org.joinmastodon.android.api.requests.notifications.GetNotifications;
|
import org.joinmastodon.android.api.requests.notifications.GetNotifications;
|
||||||
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
|
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.model.Filter;
|
||||||
import org.joinmastodon.android.model.Notification;
|
import org.joinmastodon.android.model.Notification;
|
||||||
|
import org.joinmastodon.android.model.PaginatedResponse;
|
||||||
import org.joinmastodon.android.model.SearchResult;
|
import org.joinmastodon.android.model.SearchResult;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
|
|
||||||
|
@ -22,6 +25,7 @@ import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
@ -45,22 +49,31 @@ public class CacheController{
|
||||||
this.accountID=accountID;
|
this.accountID=accountID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getHomeTimeline(String maxID, int count, boolean forceReload, Callback<List<Status>> callback){
|
public void getHomeTimeline(String maxID, int count, boolean forceReload, Callback<PaginatedResponse<List<Status>>> callback){
|
||||||
cancelDelayedClose();
|
cancelDelayedClose();
|
||||||
databaseThread.postRunnable(()->{
|
databaseThread.postRunnable(()->{
|
||||||
try{
|
try{
|
||||||
|
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.HOME)).collect(Collectors.toList());
|
||||||
if(!forceReload){
|
if(!forceReload){
|
||||||
SQLiteDatabase db=getOrOpenDatabase();
|
SQLiteDatabase db=getOrOpenDatabase();
|
||||||
try(Cursor cursor=db.query("home_timeline", new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
|
try(Cursor cursor=db.query("home_timeline", new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
|
||||||
if(cursor.getCount()==count){
|
if(cursor.getCount()==count){
|
||||||
ArrayList<Status> result=new ArrayList<>();
|
ArrayList<Status> result=new ArrayList<>();
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
|
String newMaxID;
|
||||||
|
outer:
|
||||||
do{
|
do{
|
||||||
Status status=MastodonAPIController.gson.fromJson(cursor.getString(0), Status.class);
|
Status status=MastodonAPIController.gson.fromJson(cursor.getString(0), Status.class);
|
||||||
status.postprocess();
|
status.postprocess();
|
||||||
|
newMaxID=status.id;
|
||||||
|
for(Filter filter:filters){
|
||||||
|
if(filter.matches(status.getContentStatus().content))
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
result.add(status);
|
result.add(status);
|
||||||
}while(cursor.moveToNext());
|
}while(cursor.moveToNext());
|
||||||
uiHandler.post(()->callback.onSuccess(result));
|
String _newMaxID=newMaxID;
|
||||||
|
uiHandler.post(()->callback.onSuccess(new PaginatedResponse<>(result, _newMaxID)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}catch(IOException x){
|
}catch(IOException x){
|
||||||
|
@ -71,7 +84,14 @@ public class CacheController{
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Status> result){
|
public void onSuccess(List<Status> result){
|
||||||
callback.onSuccess(result);
|
callback.onSuccess(new PaginatedResponse<>(result.stream().filter(post->{
|
||||||
|
for(Filter filter:filters){
|
||||||
|
if(filter.matches(post.getContentStatus().content)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id));
|
||||||
putHomeTimeline(result, maxID==null);
|
putHomeTimeline(result, maxID==null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,22 +123,33 @@ public class CacheController{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getNotifications(String maxID, int count, boolean onlyMentions, boolean forceReload, Callback<List<Notification>> callback){
|
public void getNotifications(String maxID, int count, boolean onlyMentions, boolean forceReload, Callback<PaginatedResponse<List<Notification>>> callback){
|
||||||
cancelDelayedClose();
|
cancelDelayedClose();
|
||||||
databaseThread.postRunnable(()->{
|
databaseThread.postRunnable(()->{
|
||||||
try{
|
try{
|
||||||
|
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.NOTIFICATIONS)).collect(Collectors.toList());
|
||||||
if(!forceReload){
|
if(!forceReload){
|
||||||
SQLiteDatabase db=getOrOpenDatabase();
|
SQLiteDatabase db=getOrOpenDatabase();
|
||||||
try(Cursor cursor=db.query(onlyMentions ? "notifications_mentions" : "notifications_all", new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
|
try(Cursor cursor=db.query(onlyMentions ? "notifications_mentions" : "notifications_all", new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
|
||||||
if(cursor.getCount()==count){
|
if(cursor.getCount()==count){
|
||||||
ArrayList<Notification> result=new ArrayList<>();
|
ArrayList<Notification> result=new ArrayList<>();
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
|
String newMaxID;
|
||||||
|
outer:
|
||||||
do{
|
do{
|
||||||
Notification ntf=MastodonAPIController.gson.fromJson(cursor.getString(0), Notification.class);
|
Notification ntf=MastodonAPIController.gson.fromJson(cursor.getString(0), Notification.class);
|
||||||
ntf.postprocess();
|
ntf.postprocess();
|
||||||
|
newMaxID=ntf.id;
|
||||||
|
if(ntf.status!=null){
|
||||||
|
for(Filter filter:filters){
|
||||||
|
if(filter.matches(ntf.status.getContentStatus().content))
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
result.add(ntf);
|
result.add(ntf);
|
||||||
}while(cursor.moveToNext());
|
}while(cursor.moveToNext());
|
||||||
uiHandler.post(()->callback.onSuccess(result));
|
String _newMaxID=newMaxID;
|
||||||
|
uiHandler.post(()->callback.onSuccess(new PaginatedResponse<>(result, _newMaxID)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}catch(IOException x){
|
}catch(IOException x){
|
||||||
|
@ -129,7 +160,16 @@ public class CacheController{
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Notification> result){
|
public void onSuccess(List<Notification> result){
|
||||||
callback.onSuccess(result);
|
callback.onSuccess(new PaginatedResponse<>(result.stream().filter(ntf->{
|
||||||
|
if(ntf.status!=null){
|
||||||
|
for(Filter filter:filters){
|
||||||
|
if(filter.matches(ntf.status.getContentStatus().content)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id));
|
||||||
putNotifications(result, onlyMentions, maxID==null);
|
putNotifications(result, onlyMentions, maxID==null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.joinmastodon.android.api.requests.accounts;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
|
import org.joinmastodon.android.model.Filter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GetWordFilters extends MastodonAPIRequest<List<Filter>>{
|
||||||
|
public GetWordFilters(){
|
||||||
|
super(HttpMethod.GET, "/filters", new TypeToken<>(){});
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,9 +6,13 @@ import org.joinmastodon.android.api.PushSubscriptionManager;
|
||||||
import org.joinmastodon.android.api.StatusInteractionController;
|
import org.joinmastodon.android.api.StatusInteractionController;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.Application;
|
import org.joinmastodon.android.model.Application;
|
||||||
|
import org.joinmastodon.android.model.Filter;
|
||||||
import org.joinmastodon.android.model.PushSubscription;
|
import org.joinmastodon.android.model.PushSubscription;
|
||||||
import org.joinmastodon.android.model.Token;
|
import org.joinmastodon.android.model.Token;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class AccountSession{
|
public class AccountSession{
|
||||||
public Token token;
|
public Token token;
|
||||||
public Account self;
|
public Account self;
|
||||||
|
@ -21,6 +25,8 @@ public class AccountSession{
|
||||||
public String pushAuthKey;
|
public String pushAuthKey;
|
||||||
public PushSubscription pushSubscription;
|
public PushSubscription pushSubscription;
|
||||||
public boolean needUpdatePushSettings;
|
public boolean needUpdatePushSettings;
|
||||||
|
public long filtersLastUpdated;
|
||||||
|
public List<Filter> wordFilters=new ArrayList<>();
|
||||||
private transient MastodonAPIController apiController;
|
private transient MastodonAPIController apiController;
|
||||||
private transient StatusInteractionController statusInteractionController;
|
private transient StatusInteractionController statusInteractionController;
|
||||||
private transient CacheController cacheController;
|
private transient CacheController cacheController;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.joinmastodon.android.MastodonApp;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.MastodonAPIController;
|
import org.joinmastodon.android.api.MastodonAPIController;
|
||||||
import org.joinmastodon.android.api.PushSubscriptionManager;
|
import org.joinmastodon.android.api.PushSubscriptionManager;
|
||||||
|
import org.joinmastodon.android.api.requests.accounts.GetWordFilters;
|
||||||
import org.joinmastodon.android.api.requests.instance.GetCustomEmojis;
|
import org.joinmastodon.android.api.requests.instance.GetCustomEmojis;
|
||||||
import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
|
import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
|
||||||
import org.joinmastodon.android.api.requests.instance.GetInstance;
|
import org.joinmastodon.android.api.requests.instance.GetInstance;
|
||||||
|
@ -24,6 +25,7 @@ import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.Application;
|
import org.joinmastodon.android.model.Application;
|
||||||
import org.joinmastodon.android.model.Emoji;
|
import org.joinmastodon.android.model.Emoji;
|
||||||
import org.joinmastodon.android.model.EmojiCategory;
|
import org.joinmastodon.android.model.EmojiCategory;
|
||||||
|
import org.joinmastodon.android.model.Filter;
|
||||||
import org.joinmastodon.android.model.Instance;
|
import org.joinmastodon.android.model.Instance;
|
||||||
import org.joinmastodon.android.model.Token;
|
import org.joinmastodon.android.model.Token;
|
||||||
|
|
||||||
|
@ -228,6 +230,9 @@ public class AccountSessionManager{
|
||||||
if(now-session.infoLastUpdated>24L*3600_000L){
|
if(now-session.infoLastUpdated>24L*3600_000L){
|
||||||
updateSessionLocalInfo(session);
|
updateSessionLocalInfo(session);
|
||||||
}
|
}
|
||||||
|
if(now-session.filtersLastUpdated>3600_000L){
|
||||||
|
updateSessionWordFilters(session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(loadedInstances){
|
if(loadedInstances){
|
||||||
maybeUpdateCustomEmojis(domains);
|
maybeUpdateCustomEmojis(domains);
|
||||||
|
@ -262,6 +267,24 @@ public class AccountSessionManager{
|
||||||
.exec(session.getID());
|
.exec(session.getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSessionWordFilters(AccountSession session){
|
||||||
|
new GetWordFilters()
|
||||||
|
.setCallback(new Callback<>(){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Filter> result){
|
||||||
|
session.wordFilters=result;
|
||||||
|
session.filtersLastUpdated=System.currentTimeMillis();
|
||||||
|
writeAccountsFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error){
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec(session.getID());
|
||||||
|
}
|
||||||
|
|
||||||
public void updateInstanceInfo(String domain){
|
public void updateInstanceInfo(String domain){
|
||||||
new GetInstance()
|
new GetInstance()
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
|
|
|
@ -18,6 +18,7 @@ import com.squareup.otto.Subscribe;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.events.StatusCreatedEvent;
|
import org.joinmastodon.android.events.StatusCreatedEvent;
|
||||||
|
import org.joinmastodon.android.model.PaginatedResponse;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ import me.grishka.appkit.api.SimpleCallback;
|
||||||
public class HomeTimelineFragment extends StatusListFragment{
|
public class HomeTimelineFragment extends StatusListFragment{
|
||||||
private ImageButton fab;
|
private ImageButton fab;
|
||||||
|
|
||||||
|
private String maxID;
|
||||||
|
|
||||||
public HomeTimelineFragment(){
|
public HomeTimelineFragment(){
|
||||||
setListLayoutId(R.layout.recycler_fragment_with_fab);
|
setListLayoutId(R.layout.recycler_fragment_with_fab);
|
||||||
}
|
}
|
||||||
|
@ -45,12 +48,13 @@ public class HomeTimelineFragment extends StatusListFragment{
|
||||||
protected void doLoadData(int offset, int count){
|
protected void doLoadData(int offset, int count){
|
||||||
AccountSessionManager.getInstance()
|
AccountSessionManager.getInstance()
|
||||||
.getAccount(accountID).getCacheController()
|
.getAccount(accountID).getCacheController()
|
||||||
.getHomeTimeline(offset>0 ? getMaxID() : null, count, refreshing, new SimpleCallback<>(this){
|
.getHomeTimeline(offset>0 ? maxID : null, count, refreshing, new SimpleCallback<>(this){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Status> result){
|
public void onSuccess(PaginatedResponse<List<Status>> result){
|
||||||
if(getActivity()==null)
|
if(getActivity()==null)
|
||||||
return;
|
return;
|
||||||
onDataLoaded(result, !result.isEmpty());
|
onDataLoaded(result.items, !result.items.isEmpty());
|
||||||
|
maxID=result.maxID;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.events.PollUpdatedEvent;
|
import org.joinmastodon.android.events.PollUpdatedEvent;
|
||||||
import org.joinmastodon.android.model.Notification;
|
import org.joinmastodon.android.model.Notification;
|
||||||
|
import org.joinmastodon.android.model.PaginatedResponse;
|
||||||
import org.joinmastodon.android.model.Poll;
|
import org.joinmastodon.android.model.Poll;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
||||||
|
@ -40,6 +41,7 @@ import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class NotificationsListFragment extends BaseStatusListFragment<Notification>{
|
public class NotificationsListFragment extends BaseStatusListFragment<Notification>{
|
||||||
private boolean onlyMentions;
|
private boolean onlyMentions;
|
||||||
|
private String maxID;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
@ -100,19 +102,20 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
|
||||||
protected void doLoadData(int offset, int count){
|
protected void doLoadData(int offset, int count){
|
||||||
AccountSessionManager.getInstance()
|
AccountSessionManager.getInstance()
|
||||||
.getAccount(accountID).getCacheController()
|
.getAccount(accountID).getCacheController()
|
||||||
.getNotifications(offset>0 ? getMaxID() : null, count, onlyMentions, refreshing, new SimpleCallback<>(this){
|
.getNotifications(offset>0 ? maxID : null, count, onlyMentions, refreshing, new SimpleCallback<>(this){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Notification> result){
|
public void onSuccess(PaginatedResponse<List<Notification>> result){
|
||||||
if(getActivity()==null)
|
if(getActivity()==null)
|
||||||
return;
|
return;
|
||||||
if(refreshing)
|
if(refreshing)
|
||||||
relationships.clear();
|
relationships.clear();
|
||||||
onDataLoaded(result.stream().filter(n->n.type!=null).collect(Collectors.toList()), !result.isEmpty());
|
onDataLoaded(result.items.stream().filter(n->n.type!=null).collect(Collectors.toList()), !result.items.isEmpty());
|
||||||
Set<String> needRelationships=result.stream()
|
Set<String> needRelationships=result.items.stream()
|
||||||
.filter(ntf->ntf.status==null && !relationships.containsKey(ntf.account.id))
|
.filter(ntf->ntf.status==null && !relationships.containsKey(ntf.account.id))
|
||||||
.map(ntf->ntf.account.id)
|
.map(ntf->ntf.account.id)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
loadRelationships(needRelationships);
|
loadRelationships(needRelationships);
|
||||||
|
maxID=result.maxID;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,10 @@ 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.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.model.StatusContext;
|
import org.joinmastodon.android.model.StatusContext;
|
||||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||||
|
@ -17,6 +19,7 @@ import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.grishka.appkit.api.SimpleCallback;
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
|
||||||
|
@ -59,6 +62,8 @@ public class ThreadFragment extends StatusListFragment{
|
||||||
data.add(mainStatus);
|
data.add(mainStatus);
|
||||||
onAppendItems(Collections.singletonList(mainStatus));
|
onAppendItems(Collections.singletonList(mainStatus));
|
||||||
}
|
}
|
||||||
|
result.descendants=filterStatuses(result.descendants);
|
||||||
|
result.ancestors=filterStatuses(result.ancestors);
|
||||||
footerProgress.setVisibility(View.GONE);
|
footerProgress.setVisibility(View.GONE);
|
||||||
data.addAll(result.descendants);
|
data.addAll(result.descendants);
|
||||||
int prevCount=displayItems.size();
|
int prevCount=displayItems.size();
|
||||||
|
@ -78,6 +83,19 @@ public class ThreadFragment extends StatusListFragment{
|
||||||
.exec(accountID);
|
.exec(accountID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
if(filters.isEmpty())
|
||||||
|
return statuses;
|
||||||
|
return statuses.stream().filter(status->{
|
||||||
|
for(Filter filter:filters){
|
||||||
|
if(filter.matches(status.getContentStatus().content))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onShown(){
|
protected void onShown(){
|
||||||
super.onShown();
|
super.onShown();
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.RequiredField;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class Filter extends BaseModel{
|
||||||
|
@RequiredField
|
||||||
|
public String id;
|
||||||
|
@RequiredField
|
||||||
|
public String phrase;
|
||||||
|
@RequiredField
|
||||||
|
public EnumSet<FilterContext> context;
|
||||||
|
public Instant expiresAt;
|
||||||
|
public boolean irreversible;
|
||||||
|
public boolean wholeWord;
|
||||||
|
|
||||||
|
private transient Pattern pattern;
|
||||||
|
|
||||||
|
public boolean matches(CharSequence text){
|
||||||
|
if(TextUtils.isEmpty(text))
|
||||||
|
return false;
|
||||||
|
if(pattern==null){
|
||||||
|
if(wholeWord)
|
||||||
|
pattern=Pattern.compile("\\b"+Pattern.quote(phrase)+"\\b", Pattern.CASE_INSENSITIVE);
|
||||||
|
else
|
||||||
|
pattern=Pattern.compile(Pattern.quote(phrase), Pattern.CASE_INSENSITIVE);
|
||||||
|
}
|
||||||
|
return pattern.matcher(text).find();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "Filter{"+
|
||||||
|
"id='"+id+'\''+
|
||||||
|
", phrase='"+phrase+'\''+
|
||||||
|
", context="+context+
|
||||||
|
", expiresAt="+expiresAt+
|
||||||
|
", irreversible="+irreversible+
|
||||||
|
", wholeWord="+wholeWord+
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FilterContext{
|
||||||
|
@SerializedName("home")
|
||||||
|
HOME,
|
||||||
|
@SerializedName("notifications")
|
||||||
|
NOTIFICATIONS,
|
||||||
|
@SerializedName("public")
|
||||||
|
PUBLIC,
|
||||||
|
@SerializedName("thread")
|
||||||
|
THREAD
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
public class PaginatedResponse<T>{
|
||||||
|
public T items;
|
||||||
|
public String maxID;
|
||||||
|
|
||||||
|
public PaginatedResponse(T items, String maxID){
|
||||||
|
this.items=items;
|
||||||
|
this.maxID=maxID;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue