Loading app/src/main/java/app/fedilab/android/activities/FilterActivity.java +55 −65 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ import android.widget.Button; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatCheckBox; import androidx.appcompat.widget.AppCompatEditText; import androidx.core.content.ContextCompat; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ViewModelProvider; Loading @@ -37,7 +35,6 @@ import androidx.lifecycle.ViewModelStoreOwner; import androidx.recyclerview.widget.LinearLayoutManager; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Objects; Loading @@ -45,11 +42,11 @@ import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Filter; import app.fedilab.android.databinding.ActivityFiltersBinding; import app.fedilab.android.databinding.KeywordsLayoutBinding; import app.fedilab.android.databinding.PopupAddFilterBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.FilterAdapter; import app.fedilab.android.ui.drawer.KeywordAdapter; import app.fedilab.android.viewmodel.mastodon.FiltersVM; public class FilterActivity extends BaseActivity implements FilterAdapter.Delete { Loading @@ -74,6 +71,7 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete R.array.filter_expire, android.R.layout.simple_spinner_dropdown_item); popupAddFilterBinding.filterExpire.setAdapter(adapterResize); final int[] expire = {-1}; Filter.FilterParams filterParams = new Filter.FilterParams(); popupAddFilterBinding.filterExpire.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent1, View view, int position1, long id) { Loading Loading @@ -107,16 +105,29 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete } }); popupAddFilterBinding.addKeyword.setOnClickListener(v -> { KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v2 -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); }); if (filter != null) { filterParams.filter_action = filter.filter_action; filterParams.title = filter.title; // filterParams.expires_in = filter.expires_at; filterParams.context = filter.context; filterParams.id = filter.id; if (filter.keywords != null && filter.keywords.size() > 0) { filterParams.keywords = new ArrayList<>(); for (Filter.KeywordsAttributes keywordsAttributes : filter.keywords) { Filter.KeywordsParams keywordsParams = new Filter.KeywordsParams(); keywordsParams._destroy = null; keywordsParams.id = keywordsAttributes.id; keywordsParams.keyword = keywordsAttributes.keyword; keywordsParams.whole_word = keywordsAttributes.whole_word; filterParams.keywords.add(keywordsParams); } } popupAddFilterBinding.addTitle.setText(filter.title); if (filter.context != null) if (filter.context != null) { for (String val : filter.context) { switch (val) { case "home": Loading @@ -136,29 +147,25 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete break; } } if (filter.keywords != null && filter.keywords.size() > 0) { for (Filter.FilterKeyword filterKeyword : filter.keywords) { KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.keywordPhrase.setText(filterKeyword.keyword); keywordsLayoutBinding.wholeWord.setChecked(filterKeyword.whole_word); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); } } if (popupAddFilterBinding.keywordsContainer.getChildCount() == 0) { KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); } if (filter.filter_action.equalsIgnoreCase("warn")) { popupAddFilterBinding.actionHide.setChecked(true); popupAddFilterBinding.actionRemove.setChecked(false); } else { //Add at least a view KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); popupAddFilterBinding.actionHide.setChecked(false); popupAddFilterBinding.actionRemove.setChecked(true); } } KeywordAdapter keywordAdapter = new KeywordAdapter(filterParams.keywords); popupAddFilterBinding.lvKeywords.setAdapter(keywordAdapter); popupAddFilterBinding.lvKeywords.setLayoutManager(new LinearLayoutManager(context)); popupAddFilterBinding.addKeyword.setOnClickListener(v -> { filterParams.keywords.add(new Filter.KeywordsParams()); keywordAdapter.notifyItemInserted(filterParams.keywords.size() - 1); }); popupAddFilterBinding.actionRemove.setOnClickListener(v -> { popupAddFilterBinding.actionHide.setChecked(false); popupAddFilterBinding.actionRemove.setChecked(true); Loading @@ -170,30 +177,17 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete AlertDialog alertDialog = dialogBuilder.setPositiveButton(R.string.validate, null) .setNegativeButton(R.string.cancel, null).create(); alertDialog.setOnShowListener(dialogInterface -> { Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); button.setOnClickListener(view -> { int keywordsItem = popupAddFilterBinding.keywordsContainer.getChildCount(); List<Filter.KeywordsAttributes> keywordsAttributes = null; boolean canBeSent = true; for (int i = 0; i < keywordsItem; i++) { View itemView = popupAddFilterBinding.keywordsContainer.getChildAt(i); AppCompatEditText keyword = itemView.findViewById(R.id.keyword_phrase); AppCompatCheckBox whole_word = itemView.findViewById(R.id.whole_word); keywordsAttributes = new ArrayList<>(); if (keyword != null && whole_word != null) { Filter.KeywordsAttributes keywordsAttr = new Filter.KeywordsAttributes(); keywordsAttr.keyword = keyword.getText().toString(); keywordsAttr.whole_word = whole_word.isChecked(); if (keywordsAttr.keyword.trim().isEmpty()) { keyword.setError(context.getString(R.string.cannot_be_empty)); for (int i = 0; i < filterParams.keywords.size(); i++) { if (filterParams.keywords.get(i).keyword.trim().isEmpty() && !filterParams.keywords.get(i)._destroy) { canBeSent = false; } keywordsAttributes.add(keywordsAttr); } } if (popupAddFilterBinding.addTitle.getText().toString().trim().isEmpty()) { popupAddFilterBinding.addTitle.setError(context.getString(R.string.cannot_be_empty)); Loading @@ -204,33 +198,29 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete canBeSent = false; } if (canBeSent) { Filter filterSent = new Filter(); ArrayList<String> contextFilter = new ArrayList<>(); filterParams.context = new ArrayList<>(); if (popupAddFilterBinding.contextHome.isChecked()) contextFilter.add("home"); filterParams.context.add("home"); if (popupAddFilterBinding.contextPublic.isChecked()) contextFilter.add("public"); filterParams.context.add("public"); if (popupAddFilterBinding.contextNotification.isChecked()) contextFilter.add("notifications"); filterParams.context.add("notifications"); if (popupAddFilterBinding.contextConversation.isChecked()) contextFilter.add("thread"); filterParams.context.add("thread"); if (popupAddFilterBinding.contextProfiles.isChecked()) contextFilter.add("account"); filterSent.context = contextFilter; filterParams.context.add("account"); if (expire[0] != -1) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND, expire[0]); filterSent.expires_at = calendar.getTime(); filterParams.expires_in = (long) expire[0]; } else { filterSent.expires_at = null; filterParams.expires_in = null; } filterSent.title = popupAddFilterBinding.addTitle.getText().toString().trim(); filterSent.filter_action = popupAddFilterBinding.actionHide.isChecked() ? "hide" : "warn"; if (filter != null) { filtersVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filter.id, filterSent.title, filterSent.expires_at, filterSent.context, filterSent.filter_action, keywordsAttributes) filterParams.title = popupAddFilterBinding.addTitle.getText().toString().trim(); filterParams.filter_action = popupAddFilterBinding.actionRemove.isChecked() ? "hide" : "warn"; if (filterParams.id != null) { filtersVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams) .observe((LifecycleOwner) context, listener::callback); } else { filtersVM.addFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterSent.title, filterSent.expires_at, filterSent.context, filterSent.filter_action, keywordsAttributes) filtersVM.addFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams) .observe((LifecycleOwner) context, listener::callback); } alertDialog.dismiss(); Loading app/src/main/java/app/fedilab/android/client/endpoints/MastodonFiltersService.java +17 −12 Original line number Diff line number Diff line Loading @@ -15,16 +15,17 @@ package app.fedilab.android.client.endpoints; * see <http://www.gnu.org/licenses>. */ import java.util.Date; import java.util.List; import app.fedilab.android.client.entities.api.Filter; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; Loading @@ -50,23 +51,28 @@ public interface MastodonFiltersService { Call<Filter> addFilter( @Header("Authorization") String token, @Field("title") String title, @Field("expires_at") Date expires_at, @Field("expires_in") Long expires_in, @Field("filter_action") String filter_action, @Field("context[]") List<String> context, @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywordsAttributes @Field("keywords_attributes[]") List<Filter.KeywordsParams> keywordsAttributes ); //Edit a filter @FormUrlEncoded @Headers({"Accept: application/json"}) @PUT("filters/{id}") Call<Filter> editFilter( @Header("Authorization") String token, @Path("id") String id, @Body Filter.FilterParams filter /*@Path("id") String id, @Field("title") String title, @Field("expires_at") Date expires_at, @Field("expires_in") Date expires_in, @Field("filter_action") String filter_action, @Field("context[]") List<String> context, @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywordsAttributes @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywords @Field("keywords_attributes[][id]") List<String> keywordId, @Field("keywords_attributes[][keyword]") List<String> keywords, @Field("keywords_attributes[][whole_word]") List<Boolean> wholeWords*/ ); //Remove a filter Loading @@ -77,7 +83,7 @@ public interface MastodonFiltersService { ); //Get a filter with its id //Get a keywords for a filter @GET("filters/{id}/keywords") Call<List<Filter.KeywordsAttributes>> getKeywordFilter( @Header("Authorization") String token, Loading @@ -90,21 +96,20 @@ public interface MastodonFiltersService { @Header("Authorization") String token, @Path("filter_id") String filter_id, @Path("id") String id, @Field("keyword") Filter.Keyword keyword @Field("keyword") Filter.KeywordsAttributes keyword ); //Edit a keyword for a filter @FormUrlEncoded @PUT("filters/{filter_id}/keywords/{id}") @PUT("filter_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 @Field("keyword") Filter.KeywordsAttributes keyword ); //Remove a keyword for a filter @DELETE("filters/keywords/{id}") @DELETE("filter_keywords/{id}") Call<Void> removeKeywordFilter( @Header("Authorization") String token, @Path("id") String id Loading app/src/main/java/app/fedilab/android/client/entities/api/Filter.java +32 −12 Original line number Diff line number Diff line package app.fedilab.android.client.entities.api; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.Serializable; Loading Loading @@ -33,15 +34,26 @@ public class Filter implements Serializable { @SerializedName("filter_action") public String filter_action; @SerializedName("keywords") public List<FilterKeyword> keywords; public List<KeywordsAttributes> keywords; public static class FilterKeyword implements Serializable { public static String getValueOf(FilterParams filterParams) { Gson gson = new Gson(); try { return gson.toJson(filterParams); } catch (Exception e) { return null; } } public static class KeywordsAttributes implements Serializable { @SerializedName("id") public String id; @SerializedName("keyword") public String keyword; @SerializedName("whole_word") public boolean whole_word; public Boolean whole_word; @SerializedName("_destroy") public Boolean _destroy; } public static class FilterResult implements Serializable { Loading @@ -53,27 +65,35 @@ public class Filter implements Serializable { public List<String> context; @SerializedName("whole_word") public boolean whole_word; @SerializedName("expires_at") @SerializedName("expires_in") public Date expires_at; @SerializedName("filter_action") public String filter_action; } public static class Keyword implements Serializable { @SerializedName("keyword") public String keyword; @SerializedName("whole_word") public boolean whole_word; public static class FilterParams implements Serializable { @SerializedName("id") public String id; @SerializedName("title") public String title; @SerializedName("context") public List<String> context; @SerializedName("expires_in") public Long expires_in; @SerializedName("filter_action") public String filter_action; @SerializedName("keywords_attributes") public List<KeywordsParams> keywords; } public static class KeywordsAttributes implements Serializable { public static class KeywordsParams implements Serializable { @SerializedName("id") public String id; @SerializedName("keyword") public String keyword; @SerializedName("whole_word") public boolean whole_word; public Boolean whole_word; @SerializedName("_destroy") public boolean _destroy; public Boolean _destroy; } } app/src/main/java/app/fedilab/android/client/entities/api/Status.java +2 −2 Original line number Diff line number Diff line Loading @@ -92,8 +92,8 @@ public class Status implements Serializable, Cloneable { public Card card; @SerializedName("poll") public Poll poll; @SerializedName("filtered") public Filter.FilterResult filtered; /* @SerializedName("filtered") public Filter.FilterResult filtered;*/ @SerializedName("pleroma") public Pleroma pleroma; @SerializedName("cached") Loading app/src/main/java/app/fedilab/android/helper/TimelineHelper.java +2 −2 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ public class TimelineHelper { if (!filter.context.contains("public")) continue; } if (filter.keywords != null && filter.keywords.size() > 0) { for (Filter.FilterKeyword filterKeyword : filter.keywords) { for (Filter.KeywordsAttributes filterKeyword : filter.keywords) { if (filterKeyword.whole_word) { Pattern p = Pattern.compile("(^|\\W)(" + Pattern.quote(filterKeyword.keyword) + ")($|\\W)", Pattern.CASE_INSENSITIVE); for (Status status : statuses) { Loading Loading @@ -206,7 +206,7 @@ public class TimelineHelper { if (!filter.context.contains("notification")) continue; if (filter.keywords != null && filter.keywords.size() > 0) { for (Filter.FilterKeyword filterKeyword : filter.keywords) { for (Filter.KeywordsAttributes filterKeyword : filter.keywords) { if (filterKeyword.whole_word) { Pattern p = Pattern.compile("(^|\\W)(" + Pattern.quote(filterKeyword.keyword) + ")($|\\W)", Pattern.CASE_INSENSITIVE); for (Notification notification : notifications) { Loading Loading
app/src/main/java/app/fedilab/android/activities/FilterActivity.java +55 −65 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ import android.widget.Button; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatCheckBox; import androidx.appcompat.widget.AppCompatEditText; import androidx.core.content.ContextCompat; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ViewModelProvider; Loading @@ -37,7 +35,6 @@ import androidx.lifecycle.ViewModelStoreOwner; import androidx.recyclerview.widget.LinearLayoutManager; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Objects; Loading @@ -45,11 +42,11 @@ import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Filter; import app.fedilab.android.databinding.ActivityFiltersBinding; import app.fedilab.android.databinding.KeywordsLayoutBinding; import app.fedilab.android.databinding.PopupAddFilterBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.FilterAdapter; import app.fedilab.android.ui.drawer.KeywordAdapter; import app.fedilab.android.viewmodel.mastodon.FiltersVM; public class FilterActivity extends BaseActivity implements FilterAdapter.Delete { Loading @@ -74,6 +71,7 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete R.array.filter_expire, android.R.layout.simple_spinner_dropdown_item); popupAddFilterBinding.filterExpire.setAdapter(adapterResize); final int[] expire = {-1}; Filter.FilterParams filterParams = new Filter.FilterParams(); popupAddFilterBinding.filterExpire.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent1, View view, int position1, long id) { Loading Loading @@ -107,16 +105,29 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete } }); popupAddFilterBinding.addKeyword.setOnClickListener(v -> { KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v2 -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); }); if (filter != null) { filterParams.filter_action = filter.filter_action; filterParams.title = filter.title; // filterParams.expires_in = filter.expires_at; filterParams.context = filter.context; filterParams.id = filter.id; if (filter.keywords != null && filter.keywords.size() > 0) { filterParams.keywords = new ArrayList<>(); for (Filter.KeywordsAttributes keywordsAttributes : filter.keywords) { Filter.KeywordsParams keywordsParams = new Filter.KeywordsParams(); keywordsParams._destroy = null; keywordsParams.id = keywordsAttributes.id; keywordsParams.keyword = keywordsAttributes.keyword; keywordsParams.whole_word = keywordsAttributes.whole_word; filterParams.keywords.add(keywordsParams); } } popupAddFilterBinding.addTitle.setText(filter.title); if (filter.context != null) if (filter.context != null) { for (String val : filter.context) { switch (val) { case "home": Loading @@ -136,29 +147,25 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete break; } } if (filter.keywords != null && filter.keywords.size() > 0) { for (Filter.FilterKeyword filterKeyword : filter.keywords) { KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.keywordPhrase.setText(filterKeyword.keyword); keywordsLayoutBinding.wholeWord.setChecked(filterKeyword.whole_word); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); } } if (popupAddFilterBinding.keywordsContainer.getChildCount() == 0) { KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); } if (filter.filter_action.equalsIgnoreCase("warn")) { popupAddFilterBinding.actionHide.setChecked(true); popupAddFilterBinding.actionRemove.setChecked(false); } else { //Add at least a view KeywordsLayoutBinding keywordsLayoutBinding = KeywordsLayoutBinding.inflate(LayoutInflater.from(context)); keywordsLayoutBinding.deleteKeyword.setOnClickListener(v -> popupAddFilterBinding.keywordsContainer.removeView(keywordsLayoutBinding.getRoot())); keywordsLayoutBinding.deleteKeyword.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(context)); popupAddFilterBinding.keywordsContainer.addView(keywordsLayoutBinding.getRoot()); popupAddFilterBinding.actionHide.setChecked(false); popupAddFilterBinding.actionRemove.setChecked(true); } } KeywordAdapter keywordAdapter = new KeywordAdapter(filterParams.keywords); popupAddFilterBinding.lvKeywords.setAdapter(keywordAdapter); popupAddFilterBinding.lvKeywords.setLayoutManager(new LinearLayoutManager(context)); popupAddFilterBinding.addKeyword.setOnClickListener(v -> { filterParams.keywords.add(new Filter.KeywordsParams()); keywordAdapter.notifyItemInserted(filterParams.keywords.size() - 1); }); popupAddFilterBinding.actionRemove.setOnClickListener(v -> { popupAddFilterBinding.actionHide.setChecked(false); popupAddFilterBinding.actionRemove.setChecked(true); Loading @@ -170,30 +177,17 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete AlertDialog alertDialog = dialogBuilder.setPositiveButton(R.string.validate, null) .setNegativeButton(R.string.cancel, null).create(); alertDialog.setOnShowListener(dialogInterface -> { Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); button.setOnClickListener(view -> { int keywordsItem = popupAddFilterBinding.keywordsContainer.getChildCount(); List<Filter.KeywordsAttributes> keywordsAttributes = null; boolean canBeSent = true; for (int i = 0; i < keywordsItem; i++) { View itemView = popupAddFilterBinding.keywordsContainer.getChildAt(i); AppCompatEditText keyword = itemView.findViewById(R.id.keyword_phrase); AppCompatCheckBox whole_word = itemView.findViewById(R.id.whole_word); keywordsAttributes = new ArrayList<>(); if (keyword != null && whole_word != null) { Filter.KeywordsAttributes keywordsAttr = new Filter.KeywordsAttributes(); keywordsAttr.keyword = keyword.getText().toString(); keywordsAttr.whole_word = whole_word.isChecked(); if (keywordsAttr.keyword.trim().isEmpty()) { keyword.setError(context.getString(R.string.cannot_be_empty)); for (int i = 0; i < filterParams.keywords.size(); i++) { if (filterParams.keywords.get(i).keyword.trim().isEmpty() && !filterParams.keywords.get(i)._destroy) { canBeSent = false; } keywordsAttributes.add(keywordsAttr); } } if (popupAddFilterBinding.addTitle.getText().toString().trim().isEmpty()) { popupAddFilterBinding.addTitle.setError(context.getString(R.string.cannot_be_empty)); Loading @@ -204,33 +198,29 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete canBeSent = false; } if (canBeSent) { Filter filterSent = new Filter(); ArrayList<String> contextFilter = new ArrayList<>(); filterParams.context = new ArrayList<>(); if (popupAddFilterBinding.contextHome.isChecked()) contextFilter.add("home"); filterParams.context.add("home"); if (popupAddFilterBinding.contextPublic.isChecked()) contextFilter.add("public"); filterParams.context.add("public"); if (popupAddFilterBinding.contextNotification.isChecked()) contextFilter.add("notifications"); filterParams.context.add("notifications"); if (popupAddFilterBinding.contextConversation.isChecked()) contextFilter.add("thread"); filterParams.context.add("thread"); if (popupAddFilterBinding.contextProfiles.isChecked()) contextFilter.add("account"); filterSent.context = contextFilter; filterParams.context.add("account"); if (expire[0] != -1) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND, expire[0]); filterSent.expires_at = calendar.getTime(); filterParams.expires_in = (long) expire[0]; } else { filterSent.expires_at = null; filterParams.expires_in = null; } filterSent.title = popupAddFilterBinding.addTitle.getText().toString().trim(); filterSent.filter_action = popupAddFilterBinding.actionHide.isChecked() ? "hide" : "warn"; if (filter != null) { filtersVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filter.id, filterSent.title, filterSent.expires_at, filterSent.context, filterSent.filter_action, keywordsAttributes) filterParams.title = popupAddFilterBinding.addTitle.getText().toString().trim(); filterParams.filter_action = popupAddFilterBinding.actionRemove.isChecked() ? "hide" : "warn"; if (filterParams.id != null) { filtersVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams) .observe((LifecycleOwner) context, listener::callback); } else { filtersVM.addFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterSent.title, filterSent.expires_at, filterSent.context, filterSent.filter_action, keywordsAttributes) filtersVM.addFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams) .observe((LifecycleOwner) context, listener::callback); } alertDialog.dismiss(); Loading
app/src/main/java/app/fedilab/android/client/endpoints/MastodonFiltersService.java +17 −12 Original line number Diff line number Diff line Loading @@ -15,16 +15,17 @@ package app.fedilab.android.client.endpoints; * see <http://www.gnu.org/licenses>. */ import java.util.Date; import java.util.List; import app.fedilab.android.client.entities.api.Filter; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.Header; import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; Loading @@ -50,23 +51,28 @@ public interface MastodonFiltersService { Call<Filter> addFilter( @Header("Authorization") String token, @Field("title") String title, @Field("expires_at") Date expires_at, @Field("expires_in") Long expires_in, @Field("filter_action") String filter_action, @Field("context[]") List<String> context, @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywordsAttributes @Field("keywords_attributes[]") List<Filter.KeywordsParams> keywordsAttributes ); //Edit a filter @FormUrlEncoded @Headers({"Accept: application/json"}) @PUT("filters/{id}") Call<Filter> editFilter( @Header("Authorization") String token, @Path("id") String id, @Body Filter.FilterParams filter /*@Path("id") String id, @Field("title") String title, @Field("expires_at") Date expires_at, @Field("expires_in") Date expires_in, @Field("filter_action") String filter_action, @Field("context[]") List<String> context, @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywordsAttributes @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywords @Field("keywords_attributes[][id]") List<String> keywordId, @Field("keywords_attributes[][keyword]") List<String> keywords, @Field("keywords_attributes[][whole_word]") List<Boolean> wholeWords*/ ); //Remove a filter Loading @@ -77,7 +83,7 @@ public interface MastodonFiltersService { ); //Get a filter with its id //Get a keywords for a filter @GET("filters/{id}/keywords") Call<List<Filter.KeywordsAttributes>> getKeywordFilter( @Header("Authorization") String token, Loading @@ -90,21 +96,20 @@ public interface MastodonFiltersService { @Header("Authorization") String token, @Path("filter_id") String filter_id, @Path("id") String id, @Field("keyword") Filter.Keyword keyword @Field("keyword") Filter.KeywordsAttributes keyword ); //Edit a keyword for a filter @FormUrlEncoded @PUT("filters/{filter_id}/keywords/{id}") @PUT("filter_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 @Field("keyword") Filter.KeywordsAttributes keyword ); //Remove a keyword for a filter @DELETE("filters/keywords/{id}") @DELETE("filter_keywords/{id}") Call<Void> removeKeywordFilter( @Header("Authorization") String token, @Path("id") String id Loading
app/src/main/java/app/fedilab/android/client/entities/api/Filter.java +32 −12 Original line number Diff line number Diff line package app.fedilab.android.client.entities.api; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.Serializable; Loading Loading @@ -33,15 +34,26 @@ public class Filter implements Serializable { @SerializedName("filter_action") public String filter_action; @SerializedName("keywords") public List<FilterKeyword> keywords; public List<KeywordsAttributes> keywords; public static class FilterKeyword implements Serializable { public static String getValueOf(FilterParams filterParams) { Gson gson = new Gson(); try { return gson.toJson(filterParams); } catch (Exception e) { return null; } } public static class KeywordsAttributes implements Serializable { @SerializedName("id") public String id; @SerializedName("keyword") public String keyword; @SerializedName("whole_word") public boolean whole_word; public Boolean whole_word; @SerializedName("_destroy") public Boolean _destroy; } public static class FilterResult implements Serializable { Loading @@ -53,27 +65,35 @@ public class Filter implements Serializable { public List<String> context; @SerializedName("whole_word") public boolean whole_word; @SerializedName("expires_at") @SerializedName("expires_in") public Date expires_at; @SerializedName("filter_action") public String filter_action; } public static class Keyword implements Serializable { @SerializedName("keyword") public String keyword; @SerializedName("whole_word") public boolean whole_word; public static class FilterParams implements Serializable { @SerializedName("id") public String id; @SerializedName("title") public String title; @SerializedName("context") public List<String> context; @SerializedName("expires_in") public Long expires_in; @SerializedName("filter_action") public String filter_action; @SerializedName("keywords_attributes") public List<KeywordsParams> keywords; } public static class KeywordsAttributes implements Serializable { public static class KeywordsParams implements Serializable { @SerializedName("id") public String id; @SerializedName("keyword") public String keyword; @SerializedName("whole_word") public boolean whole_word; public Boolean whole_word; @SerializedName("_destroy") public boolean _destroy; public Boolean _destroy; } }
app/src/main/java/app/fedilab/android/client/entities/api/Status.java +2 −2 Original line number Diff line number Diff line Loading @@ -92,8 +92,8 @@ public class Status implements Serializable, Cloneable { public Card card; @SerializedName("poll") public Poll poll; @SerializedName("filtered") public Filter.FilterResult filtered; /* @SerializedName("filtered") public Filter.FilterResult filtered;*/ @SerializedName("pleroma") public Pleroma pleroma; @SerializedName("cached") Loading
app/src/main/java/app/fedilab/android/helper/TimelineHelper.java +2 −2 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ public class TimelineHelper { if (!filter.context.contains("public")) continue; } if (filter.keywords != null && filter.keywords.size() > 0) { for (Filter.FilterKeyword filterKeyword : filter.keywords) { for (Filter.KeywordsAttributes filterKeyword : filter.keywords) { if (filterKeyword.whole_word) { Pattern p = Pattern.compile("(^|\\W)(" + Pattern.quote(filterKeyword.keyword) + ")($|\\W)", Pattern.CASE_INSENSITIVE); for (Status status : statuses) { Loading Loading @@ -206,7 +206,7 @@ public class TimelineHelper { if (!filter.context.contains("notification")) continue; if (filter.keywords != null && filter.keywords.size() > 0) { for (Filter.FilterKeyword filterKeyword : filter.keywords) { for (Filter.KeywordsAttributes filterKeyword : filter.keywords) { if (filterKeyword.whole_word) { Pattern p = Pattern.compile("(^|\\W)(" + Pattern.quote(filterKeyword.keyword) + ")($|\\W)", Pattern.CASE_INSENSITIVE); for (Notification notification : notifications) { Loading