Extended subscriptions filter (#4502)

This commit is contained in:
asdoi 2020-10-16 11:56:43 +00:00 committed by GitHub
parent 1324c81f22
commit e334b9cad6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 244 additions and 78 deletions

View File

@ -298,7 +298,7 @@ public class NavListAdapter extends BaseAdapter
convertView = inflater.inflate(R.layout.nav_section_item, parent, false);
TextView feedsFilteredMsg = convertView.findViewById(R.id.nav_feeds_filtered_message);
if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE && showSubscriptionList) {
if (UserPreferences.getSubscriptionsFilter().isEnabled() && showSubscriptionList) {
convertView.setEnabled(true);
feedsFilteredMsg.setText("{md-info-outline} " + context.getString(R.string.subscriptions_are_filtered));
Iconify.addIcons(feedsFilteredMsg);

View File

@ -1,38 +0,0 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
import org.greenrobot.eventbus.EventBus;
import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.preferences.UserPreferences;
public class FeedFilterDialog {
public static void showDialog(Context context) {
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(context.getString(R.string.pref_filter_feed_title));
dialog.setNegativeButton(android.R.string.cancel, (d, listener) -> d.dismiss());
int selected = UserPreferences.getFeedFilter();
List<String> entryValues =
Arrays.asList(context.getResources().getStringArray(R.array.nav_drawer_feed_filter_values));
final int selectedIndex = entryValues.indexOf("" + selected);
String[] items = context.getResources().getStringArray(R.array.nav_drawer_feed_filter_options);
dialog.setSingleChoiceItems(items, selectedIndex, (d, which) -> {
if (selectedIndex != which) {
UserPreferences.setFeedFilter(entryValues.get(which));
//Update subscriptions
EventBus.getDefault().post(new UnreadItemsUpdateEvent());
}
d.dismiss();
});
dialog.show();
}
}

View File

@ -0,0 +1,82 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import androidx.appcompat.app.AlertDialog;
import org.greenrobot.eventbus.EventBus;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.SubscriptionsFilter;
import de.danoeh.antennapod.core.feed.SubscriptionsFilterGroup;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.view.RecursiveRadioGroup;
public class SubscriptionsFilterDialog {
public static void showDialog(Context context) {
SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter();
final Set<String> filterValues = new HashSet<>(Arrays.asList(subscriptionsFilter.getValues()));
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.pref_filter_feed_title));
LayoutInflater inflater = LayoutInflater.from(context);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.filter_dialog, null, false);
builder.setView(layout);
for (SubscriptionsFilterGroup item : SubscriptionsFilterGroup.values()) {
RecursiveRadioGroup row = (RecursiveRadioGroup) inflater.inflate(R.layout.filter_dialog_row, null);
RadioButton filter1 = row.findViewById(R.id.filter_dialog_radioButton1);
RadioButton filter2 = row.findViewById(R.id.filter_dialog_radioButton2);
filter1.setText(item.values[0].displayName);
filter1.setTag(item.values[0].filterId);
if (item.values.length == 2) {
filter2.setText(item.values[1].displayName);
filter2.setTag(item.values[1].filterId);
} else {
filter2.setVisibility(View.GONE);
}
layout.addView(row);
}
for (String filterId : filterValues) {
if (!TextUtils.isEmpty(filterId)) {
((RadioButton) layout.findViewWithTag(filterId)).setChecked(true);
}
}
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
filterValues.clear();
for (int i = 0; i < layout.getChildCount(); i++) {
if (!(layout.getChildAt(i) instanceof RecursiveRadioGroup)) {
continue;
}
RecursiveRadioGroup group = (RecursiveRadioGroup) layout.getChildAt(i);
if (group.getCheckedButton() != null) {
String tag = (String) group.getCheckedButton().getTag();
if (tag != null) { // Clear buttons use no tag
filterValues.add((String) group.getCheckedButton().getTag());
}
}
}
updateFilter(filterValues);
});
builder.setNegativeButton(R.string.cancel_label, null);
builder.show();
}
private static void updateFilter(Set<String> filterValues) {
SubscriptionsFilter subscriptionsFilter = new SubscriptionsFilter(filterValues.toArray(new String[0]));
UserPreferences.setSubscriptionsFilter(subscriptionsFilter);
EventBus.getDefault().post(new UnreadItemsUpdateEvent());
}
}

View File

@ -39,7 +39,7 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.dialog.FeedFilterDialog;
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -398,9 +398,9 @@ public class NavDrawerFragment extends Fragment implements AdapterView.OnItemCli
startActivity(intent);
}
}
} else if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE
} else if (UserPreferences.getSubscriptionsFilter().isEnabled()
&& navAdapter.showSubscriptionList) {
FeedFilterDialog.showDialog(requireContext());
SubscriptionsFilterDialog.showDialog(requireContext());
}
}

View File

@ -49,7 +49,7 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.FeedFilterDialog;
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
import de.danoeh.antennapod.dialog.FeedSortDialog;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
@ -106,7 +106,7 @@ public class SubscriptionFragment extends Fragment {
progressBar = root.findViewById(R.id.progLoading);
feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message);
feedsFilteredMsg.setOnClickListener((l) -> FeedFilterDialog.showDialog(requireContext()));
feedsFilteredMsg.setOnClickListener((l) -> SubscriptionsFilterDialog.showDialog(requireContext()));
SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
swipeRefreshLayout.setOnRefreshListener(() -> {
@ -141,7 +141,7 @@ public class SubscriptionFragment extends Fragment {
AutoUpdateManager.runImmediate(requireContext());
return true;
case R.id.subscriptions_filter:
FeedFilterDialog.showDialog(requireContext());
SubscriptionsFilterDialog.showDialog(requireContext());
return true;
case R.id.subscriptions_sort:
FeedSortDialog.showDialog(requireContext());
@ -225,7 +225,7 @@ public class SubscriptionFragment extends Fragment {
progressBar.setVisibility(View.GONE);
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
if (UserPreferences.getFeedFilter() != UserPreferences.FEED_FILTER_NONE) {
if (UserPreferences.getSubscriptionsFilter().isEnabled()) {
feedsFilteredMsg.setText("{md-info-outline} " + getString(R.string.subscriptions_are_filtered));
Iconify.addIcons(feedsFilteredMsg);
feedsFilteredMsg.setVisibility(View.VISIBLE);

View File

@ -1,7 +1,6 @@
package de.danoeh.antennapod.fragment.preferences;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
@ -9,10 +8,9 @@ import androidx.appcompat.app.AlertDialog;
import androidx.preference.PreferenceFragmentCompat;
import android.widget.ListView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.dialog.FeedFilterDialog;
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
import de.danoeh.antennapod.dialog.FeedSortDialog;
import de.danoeh.antennapod.fragment.NavDrawerFragment;
import org.apache.commons.lang3.ArrayUtils;
@ -79,7 +77,7 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
findPreference(UserPreferences.PREF_FILTER_FEED)
.setOnPreferenceClickListener((preference -> {
FeedFilterDialog.showDialog(requireContext());
SubscriptionsFilterDialog.showDialog(requireContext());
return true;
}));

View File

@ -0,0 +1,106 @@
package de.danoeh.antennapod.core.feed;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.core.util.LongIntMap;
public class SubscriptionsFilter {
private static final String divider = ",";
private final String[] properties;
private boolean showIfCounterGreaterZero = false;
private boolean showAutoDownloadEnabled = false;
private boolean showAutoDownloadDisabled = false;
private boolean showUpdatedEnabled = false;
private boolean showUpdatedDisabled = false;
public SubscriptionsFilter(String properties) {
this(TextUtils.split(properties, divider));
}
public SubscriptionsFilter(String[] properties) {
this.properties = properties;
for (String property : properties) {
// see R.arrays.feed_filter_values
switch (property) {
case "counter_greater_zero":
showIfCounterGreaterZero = true;
break;
case "enabled_auto_download":
showAutoDownloadEnabled = true;
break;
case "disabled_auto_download":
showAutoDownloadDisabled = true;
break;
case "enabled_updates":
showUpdatedEnabled = true;
break;
case "disabled_updates":
showUpdatedDisabled = true;
break;
default:
break;
}
}
}
public boolean isEnabled() {
return properties.length > 0;
}
/**
* Run a list of feed items through the filter.
*/
public List<Feed> filter(List<Feed> items, LongIntMap feedCounters) {
if (properties.length == 0) {
return items;
}
List<Feed> result = new ArrayList<>();
for (Feed item : items) {
FeedPreferences itemPreferences = item.getPreferences();
// If the item does not meet a requirement, skip it.
if (showAutoDownloadEnabled && !itemPreferences.getAutoDownload()) {
continue;
} else if (showAutoDownloadDisabled && itemPreferences.getAutoDownload()) {
continue;
}
if (showUpdatedEnabled && !itemPreferences.getKeepUpdated()) {
continue;
} else if (showUpdatedDisabled && itemPreferences.getKeepUpdated()) {
continue;
}
// If the item reaches here, it meets all criteria (except counter > 0)
result.add(item);
}
if (showIfCounterGreaterZero) {
for (int i = result.size() - 1; i >= 0; i--) {
if (feedCounters.get(result.get(i).getId()) <= 0) {
result.remove(i);
}
}
}
return result;
}
public String[] getValues() {
return properties.clone();
}
public String serialize() {
return TextUtils.join(divider, getValues());
}
}

View File

@ -0,0 +1,30 @@
package de.danoeh.antennapod.core.feed;
import de.danoeh.antennapod.core.R;
public enum SubscriptionsFilterGroup {
COUNTER_GREATER_ZERO(new ItemProperties(R.string.subscriptions_counter_greater_zero, "counter_greater_zero")),
AUTO_DOWNLOAD(new ItemProperties(R.string.auto_downloaded, "enabled_auto_download"),
new ItemProperties(R.string.not_auto_downloaded, "disabled_auto_download")),
UPDATED(new ItemProperties(R.string.kept_updated, "enabled_updates"),
new ItemProperties(R.string.not_kept_updated, "disabled_updates"));
public final ItemProperties[] values;
SubscriptionsFilterGroup(ItemProperties... values) {
this.values = values;
}
public static class ItemProperties {
public final int displayName;
public final String filterId;
public ItemProperties(int displayName, String filterId) {
this.displayName = displayName;
this.filterId = filterId;
}
}
}

View File

@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.feed.SubscriptionsFilter;
import de.danoeh.antennapod.core.service.download.ProxyConfig;
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
@ -66,7 +67,7 @@ public class UserPreferences {
private static final String PREF_SHOW_AUTO_DOWNLOAD_REPORT = "prefShowAutoDownloadReport";
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
public static final String PREF_FILTER_FEED = "prefFeedFilter";
public static final String PREF_FILTER_FEED = "prefSubscriptionsFilter";
public static final String PREF_QUEUE_KEEP_SORTED = "prefQueueKeepSorted";
public static final String PREF_QUEUE_KEEP_SORTED_ORDER = "prefQueueKeepSortedOrder";
@ -149,8 +150,6 @@ public class UserPreferences {
public static final int FEED_COUNTER_SHOW_UNPLAYED = 2;
public static final int FEED_COUNTER_SHOW_NONE = 3;
public static final int FEED_COUNTER_SHOW_DOWNLOADED = 4;
public static final int FEED_FILTER_NONE = 0;
public static final int FEED_FILTER_COUNTER_ZERO = 1;
private static Context context;
private static SharedPreferences prefs;
@ -1046,14 +1045,14 @@ public class UserPreferences {
.apply();
}
public static int getFeedFilter() {
String value = prefs.getString(PREF_FILTER_FEED, "" + FEED_FILTER_NONE);
return Integer.parseInt(value);
public static SubscriptionsFilter getSubscriptionsFilter() {
String value = prefs.getString(PREF_FILTER_FEED, "");
return new SubscriptionsFilter(value);
}
public static void setFeedFilter(String value) {
public static void setSubscriptionsFilter(SubscriptionsFilter value) {
prefs.edit()
.putString(PREF_FILTER_FEED, value)
.putString(PREF_FILTER_FEED, value.serialize())
.apply();
}

View File

@ -19,6 +19,7 @@ import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.SubscriptionsFilter;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
@ -795,6 +796,7 @@ public final class DBReader {
Log.d(TAG, "getNavDrawerData() called with: " + "");
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
List<Feed> feeds = getFeedList(adapter);
long[] feedIds = new long[feeds.size()];
for (int i = 0; i < feeds.size(); i++) {
@ -802,15 +804,8 @@ public final class DBReader {
}
final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
int feedFilter = UserPreferences.getFeedFilter();
if (feedFilter == UserPreferences.FEED_FILTER_COUNTER_ZERO) {
for (int i = feeds.size() - 1; i >= 0; i--) {
if (feedCounters.get(feeds.get(i).getId()) <= 0) {
feedCounters.delete(feeds.get(i).getId());
feeds.remove(i);
}
}
}
SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter();
feeds = subscriptionsFilter.filter(getFeedList(adapter), feedCounters);
Comparator<Feed> comparator;
int feedOrder = UserPreferences.getFeedOrder();

View File

@ -233,16 +233,6 @@
<item>3</item>
</string-array>
<string-array name="nav_drawer_feed_filter_values">
<item>0</item>
<item>1</item>
</string-array>
<string-array name="nav_drawer_feed_filter_options">
<item>@string/no_filter_label</item>
<item>@string/hide_subscriptions_where_counter_is_zero</item>
</string-array>
<string-array name="media_player_options">
<item>@string/media_player_builtin</item>
<item>@string/media_player_sonic</item>

View File

@ -527,9 +527,13 @@
<string name="pref_delete_removes_from_queue_sum">Automatically remove an episode from the queue when it is deleted.</string>
<string name="pref_filter_feed_title">Subscription Filter</string>
<string name="pref_filter_feed_sum">Filter your subscriptions in navigation drawer and subscriptions screen.</string>
<string name="hide_subscriptions_where_counter_is_zero">Hide if counter is zero</string>
<string name="no_filter_label">None</string>
<string name="subscriptions_are_filtered">Subscriptions are filtered.</string>
<string name="subscriptions_counter_greater_zero">Counter greater zero</string>
<string name="auto_downloaded">Auto downloaded</string>
<string name="not_auto_downloaded">Not auto downloaded</string>
<string name="kept_updated">Kept updated</string>
<string name="not_kept_updated">Not kept updated</string>
<!-- About screen -->
<string name="about_pref">About</string>