Implemented filter function for "All Episodes" list (#3321)
This commit is contained in:
parent
91b171acb3
commit
be957e53b3
@ -0,0 +1,62 @@
|
|||||||
|
package de.danoeh.antennapod.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedItemFilter;
|
||||||
|
|
||||||
|
public abstract class FilterDialog {
|
||||||
|
|
||||||
|
protected FeedItemFilter filter;
|
||||||
|
protected Context context;
|
||||||
|
|
||||||
|
public FilterDialog(Context context, FeedItemFilter feedItemFilter) {
|
||||||
|
this.context = context;
|
||||||
|
this.filter = feedItemFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openDialog() {
|
||||||
|
final String[] items = context.getResources().getStringArray(R.array.episode_filter_options);
|
||||||
|
final String[] values = context.getResources().getStringArray(R.array.episode_filter_values);
|
||||||
|
final boolean[] checkedItems = new boolean[items.length];
|
||||||
|
|
||||||
|
final Set<String> filterValues = new HashSet<>(Arrays.asList(filter.getValues()));
|
||||||
|
|
||||||
|
// make sure we have no empty strings in the filter list
|
||||||
|
for (String filterValue : filterValues) {
|
||||||
|
if (TextUtils.isEmpty(filterValue)) {
|
||||||
|
filterValues.remove(filterValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
String value = values[i];
|
||||||
|
if (filterValues.contains(value)) {
|
||||||
|
checkedItems[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle(R.string.filter);
|
||||||
|
builder.setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> {
|
||||||
|
if (isChecked) {
|
||||||
|
filterValues.add(values[which]);
|
||||||
|
} else {
|
||||||
|
filterValues.remove(values[which]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||||
|
updateFilter(filterValues);
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(R.string.cancel_label, null);
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void updateFilter(Set<String> filterValues);
|
||||||
|
}
|
@ -21,8 +21,10 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.joanzapata.iconify.Iconify;
|
||||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
@ -31,6 +33,7 @@ import org.greenrobot.eventbus.ThreadMode;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
@ -42,6 +45,7 @@ import de.danoeh.antennapod.core.event.FeedItemEvent;
|
|||||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||||
import de.danoeh.antennapod.core.feed.Feed;
|
import de.danoeh.antennapod.core.feed.Feed;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedItemFilter;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||||
@ -53,6 +57,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
|
|||||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||||
import de.danoeh.antennapod.core.util.LongList;
|
import de.danoeh.antennapod.core.util.LongList;
|
||||||
|
import de.danoeh.antennapod.dialog.FilterDialog;
|
||||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
@ -93,6 +98,9 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
Disposable disposable;
|
Disposable disposable;
|
||||||
private LinearLayoutManager layoutManager;
|
private LinearLayoutManager layoutManager;
|
||||||
|
|
||||||
|
protected TextView txtvInformation;
|
||||||
|
private static FeedItemFilter feedItemFilter = new FeedItemFilter("");
|
||||||
|
|
||||||
boolean showOnlyNewEpisodes() {
|
boolean showOnlyNewEpisodes() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -246,6 +254,9 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
};
|
};
|
||||||
removeAllNewFlagsConfirmationDialog.createNewDialog().show();
|
removeAllNewFlagsConfirmationDialog.createNewDialog().show();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.filter_items:
|
||||||
|
showFilterDialog();
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -292,6 +303,7 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
super.onCreateView(inflater, container, savedInstanceState);
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
View root = inflater.inflate(R.layout.all_episodes_fragment, container, false);
|
View root = inflater.inflate(R.layout.all_episodes_fragment, container, false);
|
||||||
|
txtvInformation = root.findViewById(R.id.txtvInformation);
|
||||||
|
|
||||||
layoutManager = new LinearLayoutManager(getActivity());
|
layoutManager = new LinearLayoutManager(getActivity());
|
||||||
recyclerView = root.findViewById(android.R.id.list);
|
recyclerView = root.findViewById(android.R.id.list);
|
||||||
@ -320,14 +332,21 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFragmentLoaded(List<FeedItem> episodes) {
|
protected void onFragmentLoaded(List<FeedItem> episodes) {
|
||||||
this.episodes = episodes;
|
|
||||||
listAdapter.notifyDataSetChanged();
|
listAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
if (episodes.size() == 0) {
|
if (episodes.size() == 0) {
|
||||||
createRecycleAdapter(recyclerView, emptyView);
|
createRecycleAdapter(recyclerView, emptyView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (feedItemFilter.getValues().length > 0) {
|
||||||
|
txtvInformation.setText("{fa-info-circle} " + this.getString(R.string.filtered_label));
|
||||||
|
Iconify.addIcons(txtvInformation);
|
||||||
|
txtvInformation.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
txtvInformation.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
restoreScrollPosition();
|
restoreScrollPosition();
|
||||||
requireActivity().invalidateOptionsMenu();
|
requireActivity().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
@ -458,13 +477,14 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(data -> {
|
.subscribe(data -> {
|
||||||
progLoading.setVisibility(View.GONE);
|
progLoading.setVisibility(View.GONE);
|
||||||
onFragmentLoaded(data);
|
episodes = data;
|
||||||
|
onFragmentLoaded(episodes);
|
||||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
List<FeedItem> loadData() {
|
List<FeedItem> loadData() {
|
||||||
return DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT);
|
return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeNewFlagWithUndo(FeedItem item) {
|
void removeNewFlagWithUndo(FeedItem item) {
|
||||||
@ -498,4 +518,16 @@ public class AllEpisodesFragment extends Fragment {
|
|||||||
snackbar.show();
|
snackbar.show();
|
||||||
h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
|
h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showFilterDialog() {
|
||||||
|
FilterDialog filterDialog = new FilterDialog(getContext(), feedItemFilter) {
|
||||||
|
@Override
|
||||||
|
protected void updateFilter(Set<String> filterValues) {
|
||||||
|
feedItemFilter = new FeedItemFilter(filterValues.toArray(new String[filterValues.size()]));
|
||||||
|
loadItems();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
filterDialog.openDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import android.support.v7.widget.RecyclerView;
|
|||||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
@ -84,6 +85,19 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
|
super.onPrepareOptionsMenu(menu);
|
||||||
|
|
||||||
|
menu.removeItem(R.id.filter_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFragmentLoaded(List<FeedItem> episodes) {
|
||||||
|
super.onFragmentLoaded(episodes);
|
||||||
|
txtvInformation.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected List<FeedItem> loadData() {
|
protected List<FeedItem> loadData() {
|
||||||
|
@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
|
|||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
@ -92,6 +93,19 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
|
super.onPrepareOptionsMenu(menu);
|
||||||
|
|
||||||
|
menu.removeItem(R.id.filter_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFragmentLoaded(List<FeedItem> episodes) {
|
||||||
|
super.onFragmentLoaded(episodes);
|
||||||
|
txtvInformation.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected List<FeedItem> loadData() {
|
protected List<FeedItem> loadData() {
|
||||||
|
@ -20,11 +20,13 @@ import java.util.Set;
|
|||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||||
import de.danoeh.antennapod.core.feed.Feed;
|
import de.danoeh.antennapod.core.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedItemFilter;
|
||||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||||
import de.danoeh.antennapod.core.util.ShareUtils;
|
import de.danoeh.antennapod.core.util.ShareUtils;
|
||||||
|
import de.danoeh.antennapod.dialog.FilterDialog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles interactions with the FeedItemMenu.
|
* Handles interactions with the FeedItemMenu.
|
||||||
@ -105,42 +107,15 @@ public class FeedMenuHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void showFilterDialog(final Context context, final Feed feed) {
|
private static void showFilterDialog(Context context, Feed selectedFeed) {
|
||||||
final String[] items = context.getResources().getStringArray(R.array.episode_filter_options);
|
FilterDialog filterDialog = new FilterDialog(context, selectedFeed.getItemFilter()) {
|
||||||
final String[] values = context.getResources().getStringArray(R.array.episode_filter_values);
|
@Override
|
||||||
final boolean[] checkedItems = new boolean[items.length];
|
protected void updateFilter(Set<String> filterValues) {
|
||||||
|
selectedFeed.setItemFilter(filterValues.toArray(new String[filterValues.size()]));
|
||||||
|
DBWriter.setFeedItemsFilter(selectedFeed.getId(), filterValues);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
final Set<String> filter = new HashSet<>(Arrays.asList(feed.getItemFilter().getValues()));
|
filterDialog.openDialog();
|
||||||
Iterator<String> it = filter.iterator();
|
|
||||||
while(it.hasNext()) {
|
|
||||||
// make sure we have no empty strings in the filter list
|
|
||||||
if(TextUtils.isEmpty(it.next())) {
|
|
||||||
it.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i=0; i < values.length; i++) {
|
|
||||||
String value = values[i];
|
|
||||||
if(filter.contains(value)) {
|
|
||||||
checkedItems[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
builder.setTitle(R.string.filter);
|
|
||||||
builder.setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> {
|
|
||||||
if (isChecked) {
|
|
||||||
filter.add(values[which]);
|
|
||||||
} else {
|
|
||||||
filter.remove(values[which]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
|
||||||
feed.setItemFilter(filter.toArray(new String[filter.size()]));
|
|
||||||
DBWriter.setFeedItemsFilter(feed.getId(), filter);
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(R.string.cancel_label, null);
|
|
||||||
builder.create().show();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtvInformation"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="(i) Information" />
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:id="@android:id/list"
|
android:id="@android:id/list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/txtvInformation"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:layout_marginBottom="0dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingTop="@dimen/list_vertical_padding"
|
android:paddingTop="@dimen/list_vertical_padding"
|
||||||
android:paddingBottom="@dimen/list_vertical_padding"
|
android:paddingBottom="@dimen/list_vertical_padding"
|
||||||
@ -21,12 +34,13 @@
|
|||||||
android:id="@+id/progLoading"
|
android:id="@+id/progLoading"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:gravity="center"
|
||||||
android:indeterminateOnly="true"
|
android:indeterminateOnly="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
tools:visibility="gone"
|
tools:visibility="gone"
|
||||||
tools:layout_width="match_parent"
|
tools:layout_width="match_parent"
|
||||||
tools:layout_height="64dp"
|
tools:layout_height="64dp"
|
||||||
tools:background="@android:color/holo_red_light"/>
|
tools:background="@android:color/holo_red_light"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</RelativeLayout>
|
@ -17,6 +17,13 @@
|
|||||||
custom:showAsAction="ifRoom"
|
custom:showAsAction="ifRoom"
|
||||||
android:icon="?attr/navigation_refresh"/>
|
android:icon="?attr/navigation_refresh"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/filter_items"
|
||||||
|
android:icon="?attr/ic_filter"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/filter"
|
||||||
|
custom:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/mark_all_read_item"
|
android:id="@+id/mark_all_read_item"
|
||||||
android:title="@string/mark_all_read_label"
|
android:title="@string/mark_all_read_label"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user