parent
9dc4b46fdb
commit
8bf21db632
|
@ -126,9 +126,22 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
popupAddFilterBinding.contextWholeWord.setChecked(filter.whole_word);
|
popupAddFilterBinding.contextWholeWord.setChecked(filter.whole_word);
|
||||||
popupAddFilterBinding.contextDrop.setChecked(filter.irreversible);
|
if (filter.irreversible) {
|
||||||
|
popupAddFilterBinding.actionRemove.setChecked(true);
|
||||||
|
popupAddFilterBinding.actionHide.setChecked(false);
|
||||||
|
} else {
|
||||||
|
popupAddFilterBinding.actionRemove.setChecked(false);
|
||||||
|
popupAddFilterBinding.actionHide.setChecked(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
popupAddFilterBinding.actionRemove.setOnClickListener(v -> {
|
||||||
|
popupAddFilterBinding.actionHide.setChecked(false);
|
||||||
|
popupAddFilterBinding.actionRemove.setChecked(true);
|
||||||
|
});
|
||||||
|
popupAddFilterBinding.actionHide.setOnClickListener(v -> {
|
||||||
|
popupAddFilterBinding.actionRemove.setChecked(false);
|
||||||
|
popupAddFilterBinding.actionHide.setChecked(true);
|
||||||
|
});
|
||||||
|
|
||||||
AlertDialog alertDialog = dialogBuilder.setPositiveButton(R.string.validate, null)
|
AlertDialog alertDialog = dialogBuilder.setPositiveButton(R.string.validate, null)
|
||||||
.setNegativeButton(R.string.cancel, null).create();
|
.setNegativeButton(R.string.cancel, null).create();
|
||||||
|
@ -161,7 +174,7 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete
|
||||||
filterSent.expires_at_sent = expire[0];
|
filterSent.expires_at_sent = expire[0];
|
||||||
filterSent.phrase = popupAddFilterBinding.addPhrase.getText().toString();
|
filterSent.phrase = popupAddFilterBinding.addPhrase.getText().toString();
|
||||||
filterSent.whole_word = popupAddFilterBinding.contextWholeWord.isChecked();
|
filterSent.whole_word = popupAddFilterBinding.contextWholeWord.isChecked();
|
||||||
filterSent.irreversible = popupAddFilterBinding.contextDrop.isChecked();
|
filterSent.irreversible = popupAddFilterBinding.actionRemove.isChecked();
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
accountsVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filter.id, filterSent.phrase, filterSent.context, filterSent.irreversible, filterSent.whole_word, filterSent.expires_at_sent)
|
accountsVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filter.id, filterSent.phrase, filterSent.context, filterSent.irreversible, filterSent.whole_word, filterSent.expires_at_sent)
|
||||||
.observe((LifecycleOwner) context, listener::callback);
|
.observe((LifecycleOwner) context, listener::callback);
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.List;
|
||||||
|
|
||||||
import app.fedilab.android.client.entities.api.Account;
|
import app.fedilab.android.client.entities.api.Account;
|
||||||
import app.fedilab.android.client.entities.api.FeaturedTag;
|
import app.fedilab.android.client.entities.api.FeaturedTag;
|
||||||
import app.fedilab.android.client.entities.api.Filter;
|
|
||||||
import app.fedilab.android.client.entities.api.IdentityProof;
|
import app.fedilab.android.client.entities.api.IdentityProof;
|
||||||
import app.fedilab.android.client.entities.api.MastodonList;
|
import app.fedilab.android.client.entities.api.MastodonList;
|
||||||
import app.fedilab.android.client.entities.api.Preferences;
|
import app.fedilab.android.client.entities.api.Preferences;
|
||||||
|
@ -40,7 +39,6 @@ import retrofit2.http.Headers;
|
||||||
import retrofit2.http.Multipart;
|
import retrofit2.http.Multipart;
|
||||||
import retrofit2.http.PATCH;
|
import retrofit2.http.PATCH;
|
||||||
import retrofit2.http.POST;
|
import retrofit2.http.POST;
|
||||||
import retrofit2.http.PUT;
|
|
||||||
import retrofit2.http.Part;
|
import retrofit2.http.Part;
|
||||||
import retrofit2.http.Path;
|
import retrofit2.http.Path;
|
||||||
import retrofit2.http.Query;
|
import retrofit2.http.Query;
|
||||||
|
@ -320,48 +318,6 @@ public interface MastodonAccountsService {
|
||||||
@Field("domain") String domain
|
@Field("domain") String domain
|
||||||
);
|
);
|
||||||
|
|
||||||
//Get filters
|
|
||||||
@GET("filters")
|
|
||||||
Call<List<Filter>> getFilters(
|
|
||||||
@Header("Authorization") String token);
|
|
||||||
|
|
||||||
//Get a filter with its id
|
|
||||||
@GET("filters/{id}")
|
|
||||||
Call<Filter> getFilter(
|
|
||||||
@Header("Authorization") String token,
|
|
||||||
@Path("id") String id);
|
|
||||||
|
|
||||||
//Add a filter
|
|
||||||
@FormUrlEncoded
|
|
||||||
@POST("filters")
|
|
||||||
Call<Filter> addFilter(
|
|
||||||
@Header("Authorization") String token,
|
|
||||||
@Field("phrase") String phrase,
|
|
||||||
@Field("context[]") List<String> context,
|
|
||||||
@Field("irreversible") boolean irreversible,
|
|
||||||
@Field("whole_word") boolean whole_word,
|
|
||||||
@Field("expires_in") String expires_in
|
|
||||||
);
|
|
||||||
|
|
||||||
//Edit a filter
|
|
||||||
@FormUrlEncoded
|
|
||||||
@PUT("filters/{id}")
|
|
||||||
Call<Filter> editFilter(
|
|
||||||
@Header("Authorization") String token,
|
|
||||||
@Path("id") String id,
|
|
||||||
@Field("phrase") String phrase,
|
|
||||||
@Field("context[]") List<String> context,
|
|
||||||
@Field("irreversible") boolean irreversible,
|
|
||||||
@Field("whole_word") boolean whole_word,
|
|
||||||
@Field("expires_in") String expires_in
|
|
||||||
);
|
|
||||||
|
|
||||||
//Remove a filter
|
|
||||||
@DELETE("filters/{id}")
|
|
||||||
Call<Void> removeFilter(
|
|
||||||
@Header("Authorization") String token,
|
|
||||||
@Path("id") String id
|
|
||||||
);
|
|
||||||
|
|
||||||
//Post a report
|
//Post a report
|
||||||
@Headers({"Accept: application/json"})
|
@Headers({"Accept: application/json"})
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
package app.fedilab.android.client.endpoints;
|
||||||
|
/* Copyright 2022 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Fedilab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import app.fedilab.android.client.entities.api.Filter;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.DELETE;
|
||||||
|
import retrofit2.http.Field;
|
||||||
|
import retrofit2.http.FormUrlEncoded;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.Header;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
import retrofit2.http.PUT;
|
||||||
|
import retrofit2.http.Path;
|
||||||
|
|
||||||
|
|
||||||
|
public interface MastodonFiltersService {
|
||||||
|
|
||||||
|
|
||||||
|
//Get filters
|
||||||
|
@GET("filters")
|
||||||
|
Call<List<Filter>> getFilters(
|
||||||
|
@Header("Authorization") String token);
|
||||||
|
|
||||||
|
//Get a filter with its id
|
||||||
|
@GET("filters/{id}")
|
||||||
|
Call<Filter> getFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("id") String id);
|
||||||
|
|
||||||
|
//Add a filter
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("filters")
|
||||||
|
Call<Filter> addFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Field("title") String title,
|
||||||
|
@Field("expires_in") Integer expires_in,
|
||||||
|
@Field("filter_action") String filter_action,
|
||||||
|
@Field("context[]") List<String> context,
|
||||||
|
@Field("keywords_attributes") List<Filter.KeywordsAttributes> keywordsAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
//Edit a filter
|
||||||
|
@FormUrlEncoded
|
||||||
|
@PUT("filters/{id}")
|
||||||
|
Call<Filter> editFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("id") String id,
|
||||||
|
@Field("title") String title,
|
||||||
|
@Field("expires_in") Integer expires_in,
|
||||||
|
@Field("filter_action") String filter_action,
|
||||||
|
@Field("context[]") List<String> context,
|
||||||
|
@Field("keywords_attributes") List<Filter.KeywordsAttributes> keywordsAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
//Remove a filter
|
||||||
|
@DELETE("filters/{id}")
|
||||||
|
Call<Void> removeFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("id") String id
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//Get a filter with its id
|
||||||
|
@GET("filters/{id}/keywords")
|
||||||
|
Call<List<Filter.KeywordsAttributes>> getKeywordFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("id") String id);
|
||||||
|
|
||||||
|
//Add a keyword to a filter
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("filters/{filter_id}/keywords/{id}")
|
||||||
|
Call<Filter.KeywordsAttributes> addKeywordFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("filter_id") String filter_id,
|
||||||
|
@Path("id") String id,
|
||||||
|
@Field("keyword") Filter.Keyword keyword
|
||||||
|
);
|
||||||
|
|
||||||
|
//Edit a keyword for a filter
|
||||||
|
@FormUrlEncoded
|
||||||
|
@PUT("filters/{filter_id}/keywords/{id}")
|
||||||
|
Call<Filter.KeywordsAttributes> editKeywordFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("filter_id") String filter_id,
|
||||||
|
@Path("id") String id,
|
||||||
|
@Field("keyword") Filter.Keyword keyword
|
||||||
|
);
|
||||||
|
|
||||||
|
//Remove a keyword for a filter
|
||||||
|
@DELETE("filters/keywords/{id}")
|
||||||
|
Call<Void> removeKeywordFilter(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("id") String id
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -2,10 +2,11 @@ package app.fedilab.android.client.entities.api;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/* Copyright 2021 Thomas Schneider
|
/* Copyright 2022 Thomas Schneider
|
||||||
*
|
*
|
||||||
* This file is a part of Fedilab
|
* This file is a part of Fedilab
|
||||||
*
|
*
|
||||||
|
@ -20,7 +21,7 @@ import java.util.List;
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
public class Filter {
|
public class Filter implements Serializable {
|
||||||
@SerializedName("id")
|
@SerializedName("id")
|
||||||
public String id;
|
public String id;
|
||||||
@SerializedName("phrase")
|
@SerializedName("phrase")
|
||||||
|
@ -31,8 +32,50 @@ public class Filter {
|
||||||
public boolean whole_word;
|
public boolean whole_word;
|
||||||
@SerializedName("expires_at")
|
@SerializedName("expires_at")
|
||||||
public Date expires_at;
|
public Date expires_at;
|
||||||
@SerializedName("expires_at_sent")
|
@SerializedName("filter_action")
|
||||||
public long expires_at_sent;
|
public String filter_action;
|
||||||
@SerializedName("irreversible")
|
@SerializedName("keywords")
|
||||||
public boolean irreversible;
|
public List<FilterKeyword> keywords;
|
||||||
|
|
||||||
|
public static class FilterKeyword implements Serializable {
|
||||||
|
@SerializedName("id")
|
||||||
|
public String id;
|
||||||
|
@SerializedName("keyword")
|
||||||
|
public String keyword;
|
||||||
|
@SerializedName("whole_word")
|
||||||
|
public boolean whole_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FilterResult implements Serializable {
|
||||||
|
@SerializedName("id")
|
||||||
|
public String id;
|
||||||
|
@SerializedName("phrase")
|
||||||
|
public String phrase;
|
||||||
|
@SerializedName("context")
|
||||||
|
public List<String> context;
|
||||||
|
@SerializedName("whole_word")
|
||||||
|
public boolean whole_word;
|
||||||
|
@SerializedName("expires_at")
|
||||||
|
public Date expires_at;
|
||||||
|
@SerializedName("filter_action")
|
||||||
|
public String filter_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Keyword {
|
||||||
|
@SerializedName("keyword")
|
||||||
|
public String keyword;
|
||||||
|
@SerializedName("whole_word")
|
||||||
|
public boolean whole_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class KeywordsAttributes {
|
||||||
|
@SerializedName("id")
|
||||||
|
public String id;
|
||||||
|
@SerializedName("keyword")
|
||||||
|
public String keyword;
|
||||||
|
@SerializedName("whole_word")
|
||||||
|
public boolean whole_word;
|
||||||
|
@SerializedName("_destroy")
|
||||||
|
public boolean _destroy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,8 @@ public class Status implements Serializable, Cloneable {
|
||||||
public Card card;
|
public Card card;
|
||||||
@SerializedName("poll")
|
@SerializedName("poll")
|
||||||
public Poll poll;
|
public Poll poll;
|
||||||
|
@SerializedName("filtered")
|
||||||
|
public Filter.FilterResult filtered;
|
||||||
@SerializedName("pleroma")
|
@SerializedName("pleroma")
|
||||||
public Pleroma pleroma;
|
public Pleroma pleroma;
|
||||||
@SerializedName("cached")
|
@SerializedName("cached")
|
||||||
|
|
|
@ -33,7 +33,6 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import app.fedilab.android.BaseMainActivity;
|
|
||||||
import app.fedilab.android.R;
|
import app.fedilab.android.R;
|
||||||
import app.fedilab.android.activities.MainActivity;
|
import app.fedilab.android.activities.MainActivity;
|
||||||
import app.fedilab.android.client.endpoints.MastodonAccountsService;
|
import app.fedilab.android.client.endpoints.MastodonAccountsService;
|
||||||
|
@ -1090,158 +1089,6 @@ public class AccountsVM extends AndroidViewModel {
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* View all filters created by the user
|
|
||||||
*
|
|
||||||
* @return {@link LiveData} containing a {@link List} of {@link Filter}s
|
|
||||||
*/
|
|
||||||
public LiveData<List<Filter>> getFilters(@NonNull String instance, String token) {
|
|
||||||
filterListMutableLiveData = new MutableLiveData<>();
|
|
||||||
MastodonAccountsService mastodonAccountsService = init(instance);
|
|
||||||
new Thread(() -> {
|
|
||||||
List<Filter> filterList = null;
|
|
||||||
Call<List<Filter>> getFiltersCall = mastodonAccountsService.getFilters(token);
|
|
||||||
if (getFiltersCall != null) {
|
|
||||||
try {
|
|
||||||
Response<List<Filter>> getFiltersResponse = getFiltersCall.execute();
|
|
||||||
if (getFiltersResponse.isSuccessful()) {
|
|
||||||
BaseMainActivity.filterFetched = true;
|
|
||||||
filterList = getFiltersResponse.body();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
||||||
List<Filter> finalFilterList = filterList;
|
|
||||||
Runnable myRunnable = () -> filterListMutableLiveData.setValue(finalFilterList);
|
|
||||||
mainHandler.post(myRunnable);
|
|
||||||
}).start();
|
|
||||||
return filterListMutableLiveData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View a single filter
|
|
||||||
*
|
|
||||||
* @param id the id of the filter
|
|
||||||
* @return {@link LiveData} containing a {@link Filter}
|
|
||||||
*/
|
|
||||||
public LiveData<Filter> getFilter(@NonNull String instance, String token, @NonNull String id) {
|
|
||||||
filterMutableLiveData = new MutableLiveData<>();
|
|
||||||
MastodonAccountsService mastodonAccountsService = init(instance);
|
|
||||||
new Thread(() -> {
|
|
||||||
Filter filter = null;
|
|
||||||
Call<Filter> getFilterCall = mastodonAccountsService.getFilter(token, id);
|
|
||||||
if (getFilterCall != null) {
|
|
||||||
try {
|
|
||||||
Response<Filter> getFiltersResponse = getFilterCall.execute();
|
|
||||||
if (getFiltersResponse.isSuccessful()) {
|
|
||||||
filter = getFiltersResponse.body();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
||||||
Filter finalFilter = filter;
|
|
||||||
Runnable myRunnable = () -> filterMutableLiveData.setValue(finalFilter);
|
|
||||||
mainHandler.post(myRunnable);
|
|
||||||
}).start();
|
|
||||||
return filterMutableLiveData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a filter
|
|
||||||
*
|
|
||||||
* @param phrase Text to be filtered
|
|
||||||
* @param filterContext Array of enumerable strings "home", "notifications", "public", "thread". At least one context must be specified.
|
|
||||||
* @param irreversible Should the server irreversibly drop matching entities from home and notifications?
|
|
||||||
* @param wholeWord Consider word boundaries?
|
|
||||||
* @param expiresIn Number of seconds from now the filter should expire. Otherwise, null for a filter that doesn't expire.
|
|
||||||
* @return {@link LiveData} containing a {@link Filter}
|
|
||||||
*/
|
|
||||||
public LiveData<Filter> addFilter(@NonNull String instance, String token,
|
|
||||||
@NonNull String phrase,
|
|
||||||
@NonNull List<String> filterContext,
|
|
||||||
boolean irreversible,
|
|
||||||
boolean wholeWord,
|
|
||||||
long expiresIn) {
|
|
||||||
filterMutableLiveData = new MutableLiveData<>();
|
|
||||||
MastodonAccountsService mastodonAccountsService = init(instance);
|
|
||||||
new Thread(() -> {
|
|
||||||
Filter filter = null;
|
|
||||||
Call<Filter> addFilterCall = mastodonAccountsService.addFilter(token, phrase, filterContext, irreversible, wholeWord, expiresIn == -1 ? "" : String.valueOf(expiresIn));
|
|
||||||
if (addFilterCall != null) {
|
|
||||||
try {
|
|
||||||
Response<Filter> addFiltersResponse = addFilterCall.execute();
|
|
||||||
if (addFiltersResponse.isSuccessful()) {
|
|
||||||
filter = addFiltersResponse.body();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
||||||
Filter finalFilter = filter;
|
|
||||||
Runnable myRunnable = () -> filterMutableLiveData.setValue(finalFilter);
|
|
||||||
mainHandler.post(myRunnable);
|
|
||||||
}).start();
|
|
||||||
return filterMutableLiveData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a filter
|
|
||||||
*
|
|
||||||
* @param id ID of the filter
|
|
||||||
* @param phrase Text to be filtered
|
|
||||||
* @param filterContext Array of enumerable strings "home", "notifications", "public", "thread". At least one context must be specified.
|
|
||||||
* @param irreversible Should the server irreversibly drop matching entities from home and notifications?
|
|
||||||
* @param wholeWord Consider word boundaries?
|
|
||||||
* @param expiresIn Number of seconds from now the filter should expire. Otherwise, null for a filter that doesn't expire.
|
|
||||||
* @return {@link LiveData} containing a {@link Filter}
|
|
||||||
*/
|
|
||||||
public LiveData<Filter> editFilter(@NonNull String instance, String token, @NonNull String id, @NonNull String phrase, @NonNull List<String> filterContext, boolean irreversible, boolean wholeWord, long expiresIn) {
|
|
||||||
filterMutableLiveData = new MutableLiveData<>();
|
|
||||||
MastodonAccountsService mastodonAccountsService = init(instance);
|
|
||||||
new Thread(() -> {
|
|
||||||
Filter filter = null;
|
|
||||||
Call<Filter> editFilterCall = mastodonAccountsService.editFilter(token, id, phrase, filterContext, irreversible, wholeWord, expiresIn == -1 ? "" : String.valueOf(expiresIn));
|
|
||||||
if (editFilterCall != null) {
|
|
||||||
try {
|
|
||||||
Response<Filter> editFiltersResponse = editFilterCall.execute();
|
|
||||||
if (editFiltersResponse.isSuccessful()) {
|
|
||||||
filter = editFiltersResponse.body();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
||||||
Filter finalFilter = filter;
|
|
||||||
Runnable myRunnable = () -> filterMutableLiveData.setValue(finalFilter);
|
|
||||||
mainHandler.post(myRunnable);
|
|
||||||
}).start();
|
|
||||||
return filterMutableLiveData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a filter
|
|
||||||
*
|
|
||||||
* @param id ID of the filter
|
|
||||||
*/
|
|
||||||
public void removeFilter(@NonNull String instance, String token, @NonNull String id) {
|
|
||||||
MastodonAccountsService mastodonAccountsService = init(instance);
|
|
||||||
new Thread(() -> {
|
|
||||||
Call<Void> removeFilterCall = mastodonAccountsService.removeFilter(token, id);
|
|
||||||
if (removeFilterCall != null) {
|
|
||||||
try {
|
|
||||||
removeFilterCall.execute();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File a report
|
* File a report
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
package app.fedilab.android.viewmodel.mastodon;
|
||||||
|
/* Copyright 2022 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Fedilab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import app.fedilab.android.BaseMainActivity;
|
||||||
|
import app.fedilab.android.client.endpoints.MastodonFiltersService;
|
||||||
|
import app.fedilab.android.client.entities.api.Filter;
|
||||||
|
import app.fedilab.android.helper.Helper;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Response;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
|
public class FiltersVM extends AndroidViewModel {
|
||||||
|
|
||||||
|
|
||||||
|
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
||||||
|
.readTimeout(60, TimeUnit.SECONDS)
|
||||||
|
.connectTimeout(60, TimeUnit.SECONDS)
|
||||||
|
.callTimeout(60, TimeUnit.SECONDS)
|
||||||
|
.proxy(Helper.getProxy(getApplication().getApplicationContext()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
private MutableLiveData<Filter> filterMutableLiveData;
|
||||||
|
private MutableLiveData<List<Filter>> filterListMutableLiveData;
|
||||||
|
|
||||||
|
public FiltersVM(@NonNull Application application) {
|
||||||
|
super(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MastodonFiltersService initV2(String instance) {
|
||||||
|
Retrofit retrofit = new Retrofit.Builder()
|
||||||
|
.baseUrl("https://" + instance + "/api/v2/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder()))
|
||||||
|
.client(okHttpClient)
|
||||||
|
.build();
|
||||||
|
return retrofit.create(MastodonFiltersService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View all filters created by the user
|
||||||
|
*
|
||||||
|
* @return {@link LiveData} containing a {@link List} of {@link Filter}s
|
||||||
|
*/
|
||||||
|
public LiveData<List<Filter>> getFilters(@NonNull String instance, String token) {
|
||||||
|
filterListMutableLiveData = new MutableLiveData<>();
|
||||||
|
MastodonFiltersService mastodonFiltersService = initV2(instance);
|
||||||
|
new Thread(() -> {
|
||||||
|
List<Filter> filterList = null;
|
||||||
|
Call<List<Filter>> getFiltersCall = mastodonFiltersService.getFilters(token);
|
||||||
|
if (getFiltersCall != null) {
|
||||||
|
try {
|
||||||
|
Response<List<Filter>> getFiltersResponse = getFiltersCall.execute();
|
||||||
|
if (getFiltersResponse.isSuccessful()) {
|
||||||
|
BaseMainActivity.filterFetched = true;
|
||||||
|
filterList = getFiltersResponse.body();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
List<Filter> finalFilterList = filterList;
|
||||||
|
Runnable myRunnable = () -> filterListMutableLiveData.setValue(finalFilterList);
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
}).start();
|
||||||
|
return filterListMutableLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View a single filter
|
||||||
|
*
|
||||||
|
* @param id the id of the filter
|
||||||
|
* @return {@link LiveData} containing a {@link Filter}
|
||||||
|
*/
|
||||||
|
public LiveData<Filter> getFilter(@NonNull String instance, String token, @NonNull String id) {
|
||||||
|
filterMutableLiveData = new MutableLiveData<>();
|
||||||
|
MastodonFiltersService mastodonFiltersService = initV2(instance);
|
||||||
|
new Thread(() -> {
|
||||||
|
Filter filter = null;
|
||||||
|
Call<Filter> getFilterCall = mastodonFiltersService.getFilter(token, id);
|
||||||
|
if (getFilterCall != null) {
|
||||||
|
try {
|
||||||
|
Response<Filter> getFiltersResponse = getFilterCall.execute();
|
||||||
|
if (getFiltersResponse.isSuccessful()) {
|
||||||
|
filter = getFiltersResponse.body();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
Filter finalFilter = filter;
|
||||||
|
Runnable myRunnable = () -> filterMutableLiveData.setValue(finalFilter);
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
}).start();
|
||||||
|
return filterMutableLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a filter
|
||||||
|
*
|
||||||
|
* @param phrase Text to be filtered
|
||||||
|
* @param filterContext Array of enumerable strings "home", "notifications", "public", "thread". At least one context must be specified.
|
||||||
|
* @param irreversible Should the server irreversibly drop matching entities from home and notifications?
|
||||||
|
* @param wholeWord Consider word boundaries?
|
||||||
|
* @param expiresIn Number of seconds from now the filter should expire. Otherwise, null for a filter that doesn't expire.
|
||||||
|
* @return {@link LiveData} containing a {@link Filter}
|
||||||
|
*/
|
||||||
|
public LiveData<Filter> addFilter(@NonNull String instance, String token,
|
||||||
|
@NonNull String phrase,
|
||||||
|
@NonNull List<String> filterContext,
|
||||||
|
boolean irreversible,
|
||||||
|
boolean wholeWord,
|
||||||
|
int expiresIn) {
|
||||||
|
filterMutableLiveData = new MutableLiveData<>();
|
||||||
|
MastodonFiltersService mastodonFiltersService = initV2(instance);
|
||||||
|
new Thread(() -> {
|
||||||
|
Filter filter = null;
|
||||||
|
Call<Filter> addFilterCall = mastodonFiltersService.addFilter(token, phrase, filterContext, irreversible, wholeWord, expiresIn == -1 ? null : expiresIn);
|
||||||
|
if (addFilterCall != null) {
|
||||||
|
try {
|
||||||
|
Response<Filter> addFiltersResponse = addFilterCall.execute();
|
||||||
|
if (addFiltersResponse.isSuccessful()) {
|
||||||
|
filter = addFiltersResponse.body();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
Filter finalFilter = filter;
|
||||||
|
Runnable myRunnable = () -> filterMutableLiveData.setValue(finalFilter);
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
}).start();
|
||||||
|
return filterMutableLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a filter
|
||||||
|
*
|
||||||
|
* @param id ID of the filter
|
||||||
|
* @param phrase Text to be filtered
|
||||||
|
* @param filterContext Array of enumerable strings "home", "notifications", "public", "thread". At least one context must be specified.
|
||||||
|
* @param irreversible Should the server irreversibly drop matching entities from home and notifications?
|
||||||
|
* @param wholeWord Consider word boundaries?
|
||||||
|
* @param expiresIn Number of seconds from now the filter should expire. Otherwise, null for a filter that doesn't expire.
|
||||||
|
* @return {@link LiveData} containing a {@link Filter}
|
||||||
|
*/
|
||||||
|
public LiveData<Filter> editFilter(@NonNull String instance, String token, @NonNull String id, @NonNull String phrase, @NonNull List<String> filterContext, boolean irreversible, boolean wholeWord, int expiresIn) {
|
||||||
|
filterMutableLiveData = new MutableLiveData<>();
|
||||||
|
MastodonFiltersService mastodonFiltersService = initV2(instance);
|
||||||
|
new Thread(() -> {
|
||||||
|
Filter filter = null;
|
||||||
|
Call<Filter> editFilterCall = mastodonFiltersService.editFilter(token, id, phrase, filterContext, irreversible, wholeWord, expiresIn == -1 ? null : expiresIn);
|
||||||
|
if (editFilterCall != null) {
|
||||||
|
Log.v(Helper.TAG, "request: " + editFilterCall.request());
|
||||||
|
try {
|
||||||
|
Response<Filter> editFiltersResponse = editFilterCall.execute();
|
||||||
|
if (editFiltersResponse.isSuccessful()) {
|
||||||
|
filter = editFiltersResponse.body();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
Filter finalFilter = filter;
|
||||||
|
Runnable myRunnable = () -> filterMutableLiveData.setValue(finalFilter);
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
}).start();
|
||||||
|
return filterMutableLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a filter
|
||||||
|
*
|
||||||
|
* @param id ID of the filter
|
||||||
|
*/
|
||||||
|
public void removeFilter(@NonNull String instance, String token, @NonNull String id) {
|
||||||
|
MastodonFiltersService mastodonAccountsService = initV2(instance);
|
||||||
|
new Thread(() -> {
|
||||||
|
Call<Void> removeFilterCall = mastodonAccountsService.removeFilter(token, id);
|
||||||
|
if (removeFilterCall != null) {
|
||||||
|
try {
|
||||||
|
removeFilterCall.execute();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,21 +25,10 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="10dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:labelFor="@+id/add_phrase"
|
|
||||||
android:text="@string/filter_keyword" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/filter_keyword_explanations"
|
|
||||||
android:textColor="@color/cyanea_accent_dark_reference"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatEditText
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
android:id="@+id/add_phrase"
|
android:id="@+id/add_title"
|
||||||
|
android:hint="@string/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:importantForAutofill="noExcludeDescendants"
|
android:importantForAutofill="noExcludeDescendants"
|
||||||
|
@ -76,7 +65,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/context_home"
|
android:text="@string/context_home_list"
|
||||||
app:buttonTint="@color/cyanea_accent_dark_reference" />
|
app:buttonTint="@color/cyanea_accent_dark_reference" />
|
||||||
|
|
||||||
<com.google.android.material.checkbox.MaterialCheckBox
|
<com.google.android.material.checkbox.MaterialCheckBox
|
||||||
|
@ -125,24 +114,71 @@
|
||||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
<com.google.android.material.checkbox.MaterialCheckBox
|
|
||||||
android:id="@+id/context_drop"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/context_drop"
|
|
||||||
app:buttonTint="@color/cyanea_accent_dark_reference" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="20dp"
|
android:text="@string/filter_action"
|
||||||
android:layout_marginLeft="20dp"
|
android:textSize="12sp" />
|
||||||
android:layout_marginEnd="20dp"
|
|
||||||
android:layout_marginRight="20dp"
|
<TextView
|
||||||
android:text="@string/context_drop_explanations"
|
android:id="@+id/actionDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/filter_action_explanations"
|
||||||
android:textColor="@color/cyanea_accent_dark_reference"
|
android:textColor="@color/cyanea_accent_dark_reference"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/location"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/action_hide"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hide_with_warning"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/val1_more"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:text="@string/hide_with_warning_description" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/action_remove"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hide_completely"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:text="@string/hide_completely_description" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.checkbox.MaterialCheckBox
|
<com.google.android.material.checkbox.MaterialCheckBox
|
||||||
android:id="@+id/context_whole_word"
|
android:id="@+id/context_whole_word"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -1989,4 +1989,12 @@
|
||||||
<string name="watch_trends_for_instance">Watch trends for this instance</string>
|
<string name="watch_trends_for_instance">Watch trends for this instance</string>
|
||||||
<string name="notif_update">Edited a message</string>
|
<string name="notif_update">Edited a message</string>
|
||||||
<string name="notif_display_updates">Updates</string>
|
<string name="notif_display_updates">Updates</string>
|
||||||
|
<string name="filter_action">Filter action</string>
|
||||||
|
<string name="filter_action_explanations">Chose which action to perform when a post matches the filter</string>
|
||||||
|
<string name="hide_with_warning">Hide with a warning</string>
|
||||||
|
<string name="hide_completely">Hide completely</string>
|
||||||
|
<string name="hide_with_warning_description">Hide the filtered content behind a warning mentioning the filter\'s title</string>
|
||||||
|
<string name="hide_completely_description">Completely hide the filtered content, behaving as if it did not exist</string>
|
||||||
|
<string name="context_home_list">Home and lists</string>
|
||||||
|
<string name="title">Title</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue