Comment #467 #464 - Start migration to api/v2 for filters

pull/483/head
Thomas 2 years ago
parent 9dc4b46fdb
commit 8bf21db632

@ -126,9 +126,22 @@ public class FilterActivity extends BaseActivity implements FilterAdapter.Delete
}
}
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)
.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.phrase = popupAddFilterBinding.addPhrase.getText().toString();
filterSent.whole_word = popupAddFilterBinding.contextWholeWord.isChecked();
filterSent.irreversible = popupAddFilterBinding.contextDrop.isChecked();
filterSent.irreversible = popupAddFilterBinding.actionRemove.isChecked();
if (filter != null) {
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);

@ -19,7 +19,6 @@ import java.util.List;
import app.fedilab.android.client.entities.api.Account;
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.MastodonList;
import app.fedilab.android.client.entities.api.Preferences;
@ -40,7 +39,6 @@ import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.PATCH;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.Path;
import retrofit2.http.Query;
@ -320,48 +318,6 @@ public interface MastodonAccountsService {
@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
@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 java.io.Serializable;
import java.util.Date;
import java.util.List;
/* Copyright 2021 Thomas Schneider
/* Copyright 2022 Thomas Schneider
*
* 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,
* see <http://www.gnu.org/licenses>. */
public class Filter {
public class Filter implements Serializable {
@SerializedName("id")
public String id;
@SerializedName("phrase")
@ -31,8 +32,50 @@ public class Filter {
public boolean whole_word;
@SerializedName("expires_at")
public Date expires_at;
@SerializedName("expires_at_sent")
public long expires_at_sent;
@SerializedName("irreversible")
public boolean irreversible;
@SerializedName("filter_action")
public String filter_action;
@SerializedName("keywords")
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;
@SerializedName("poll")
public Poll poll;
@SerializedName("filtered")
public Filter.FilterResult filtered;
@SerializedName("pleroma")
public Pleroma pleroma;
@SerializedName("cached")

@ -33,7 +33,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.client.endpoints.MastodonAccountsService;
@ -1090,158 +1089,6 @@ public class AccountsVM extends AndroidViewModel {
}).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

@ -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: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
android:id="@+id/add_phrase"
android:id="@+id/add_title"
android:hint="@string/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="noExcludeDescendants"
@ -76,7 +65,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/context_home"
android:text="@string/context_home_list"
app:buttonTint="@color/cyanea_accent_dark_reference" />
<com.google.android.material.checkbox.MaterialCheckBox
@ -125,24 +114,71 @@
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/context_drop"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/context_drop"
app:buttonTint="@color/cyanea_accent_dark_reference" />
android:text="@string/filter_action"
android:textSize="12sp" />
<TextView
android:id="@+id/actionDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:text="@string/context_drop_explanations"
android:text="@string/filter_action_explanations"
android:textColor="@color/cyanea_accent_dark_reference"
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
android:id="@+id/context_whole_word"
android:layout_width="match_parent"

@ -1989,4 +1989,12 @@
<string name="watch_trends_for_instance">Watch trends for this instance</string>
<string name="notif_update">Edited a message</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>

Loading…
Cancel
Save