Add feed item filter

This commit is contained in:
Martin Fietz 2015-04-26 13:37:27 +02:00 committed by Martin Fietz
parent 2cfd15fe88
commit 9ec0d735c8
33 changed files with 342 additions and 93 deletions

View File

@ -45,7 +45,7 @@ public class DBReaderTest extends InstrumentationTestCase {
private void expiredFeedListTestHelper(long lastUpdate, long expirationTime, boolean shouldReturn) {
final Context context = getInstrumentation().getTargetContext();
Feed feed = new Feed(0, new Date(lastUpdate), "feed", "link", "descr", null,
null, null, null, "feed", null, null, "url", false, new FlattrStatus(), false, null);
null, null, null, "feed", null, null, "url", false, new FlattrStatus(), false, null, null);
feed.setItems(new ArrayList<FeedItem>());
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();

View File

@ -4,6 +4,14 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.test.InstrumentationTestCase;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@ -13,14 +21,7 @@ import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static de.test.antennapod.storage.DBTestUtils.*;
import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
/**
* Test class for DBTasks
@ -296,7 +297,7 @@ public class DBTasksTest extends InstrumentationTestCase {
final Context context = getInstrumentation().getTargetContext();
UserPreferences.setUpdateInterval(context, expirationTime);
Feed feed = new Feed(0, new Date(lastUpdate), "feed", "link", "descr", null,
null, null, null, "feed", null, null, "url", false, new FlattrStatus(), false, null);
null, null, null, "feed", null, null, "url", false, new FlattrStatus(), false, null, null);
feed.setItems(new ArrayList<FeedItem>());
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();

View File

@ -47,7 +47,7 @@ public class DBTestUtils {
adapter.open();
for (int i = 0; i < numFeeds; i++) {
Feed f = new Feed(0, new Date(), "feed " + i, "link" + i, "descr", null, null,
null, null, "id" + i, null, null, "url" + i, false, new FlattrStatus(), false, null);
null, null, "id" + i, null, null, "url" + i, false, new FlattrStatus(), false, null, null);
f.setItems(new ArrayList<FeedItem>());
for (int j = 0; j < numItems; j++) {
FeedItem item = new FeedItem(0, "item " + j, "id" + j, "link" + j, new Date(),

View File

@ -7,9 +7,14 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
@ -211,8 +216,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
notifyDataSetChanged();
}
public static interface ItemAccess {
public boolean isInQueue(FeedItem item);
public interface ItemAccess {
boolean isInQueue(FeedItem item);
int getItemDownloadProgressPercent(FeedItem item);

View File

@ -133,6 +133,8 @@ public class StorageCallbacksImpl implements StorageCallbacks {
+ " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
+ " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + PodDBAdapter.KEY_ID
+ " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_FEED + ")");
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_HIDE + " TEXT");
}
}
}

View File

@ -24,6 +24,7 @@ import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.joanzapata.android.iconify.Iconify;
import com.squareup.picasso.Picasso;
import org.apache.commons.lang3.Validate;
@ -42,7 +43,9 @@ import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
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.QueueEvent;
import de.danoeh.antennapod.core.service.download.DownloadService;
@ -55,7 +58,6 @@ import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
import de.greenrobot.event.EventBus;
/**
@ -89,6 +91,8 @@ public class ItemlistFragment extends ListFragment {
private boolean isUpdatingFeed;
private TextView txtvInformation;
/**
* Creates new ItemlistFragment which shows the Feeditems of a specific
* feed. Sets 'showFeedtitle' to false
@ -291,6 +295,13 @@ public class ItemlistFragment extends ListFragment {
startItemLoader();
}
public void onEvent(FeedEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
if(event.feedId == feedID) {
startItemLoader();
}
}
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
@ -330,6 +341,7 @@ public class ItemlistFragment extends ListFragment {
downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback);
downloadObserver.onResume();
}
refreshHeaderView();
setListShown(true);
adapter.notifyDataSetChanged();
@ -343,6 +355,22 @@ public class ItemlistFragment extends ListFragment {
}
private void refreshHeaderView() {
if(feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
if(filter.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);
}
} else {
txtvInformation.setVisibility(View.GONE);
}
}
private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
@Override
public void onContentChanged() {
@ -376,6 +404,7 @@ public class ItemlistFragment extends ListFragment {
ImageView imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo);
txtvInformation = (TextView) header.findViewById(R.id.txtvInformation);
txtvTitle.setText(feed.getTitle());
txtvAuthor.setText(feed.getAuthor());
@ -488,6 +517,10 @@ public class ItemlistFragment extends ListFragment {
Context context = getActivity();
if (context != null) {
Feed feed = DBReader.getFeed(context, feedID);
if(feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
feed.setItems(filter.filter(context, feed.getItems()));
}
LongList queue = DBReader.getQueueIDList(context);
return Pair.create(feed, queue);
} else {

View File

@ -23,10 +23,10 @@ import de.danoeh.antennapod.core.util.ShareUtils;
* Handles interactions with the FeedItemMenu.
*/
public class FeedItemMenuHandler {
private static final String TAG = "FeedItemMenuHandler";
private FeedItemMenuHandler() {
}
/**

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.menuhandler;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -9,6 +10,10 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
@ -62,6 +67,9 @@ public class FeedMenuHandler {
case R.id.refresh_complete_item:
DBTasks.refreshCompleteFeed(context, selectedFeed);
break;
case R.id.hide_items:
showHideDialog(context, selectedFeed);
break;
case R.id.mark_all_read_item:
ConfirmationDialog conDialog = new ConfirmationDialog(context,
R.string.mark_all_read_label,
@ -94,4 +102,43 @@ public class FeedMenuHandler {
}
return true;
}
private static void showHideDialog(final Context context, final Feed feed) {
final String[] items = context.getResources().getStringArray(R.array.episode_hide_options);
final String[] values = context.getResources().getStringArray(R.array.episode_hide_values);
final boolean[] checkedItems = new boolean[items.length];
final List<String> hidden = new ArrayList<String>(Arrays.asList(feed.getItemFilter().getValues()));
for(int i=0; i < values.length; i++) {
String value = values[i];
if(hidden.contains(value)) {
checkedItems[i] = true;
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.hide_episodes_title);
builder.setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
hidden.add(values[which]);
} else {
hidden.remove(values[which]);
}
}
});
builder.setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
feed.setFeedItemsFilter(hidden.toArray(new String[hidden.size()]));
DBWriter.setFeedItemsFilter(context, feed.getId(), hidden);
}
});
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
}

View File

@ -3,7 +3,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/feeditemlist_header_height"
android:layout_height="wrap_content"
tools:context="de.danoeh.antennapod.activity.MainActivity"
tools:background="@android:color/darker_gray">
@ -11,7 +11,7 @@
android:id="@+id/imgvBackground"
style="@style/BigBlurryBackground"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="@dimen/feeditemlist_header_height" />
<ImageView
android:id="@+id/imgvCover"
@ -78,5 +78,16 @@
tools:text="Podcast author"
tools:background="@android:color/holo_green_dark" />
<TextView
android:id="@+id/txtvInformation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/imgvBackground"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:gravity="center"
android:visibility="gone"
tools:text="(i) Information"
/>
</RelativeLayout>

View File

@ -2,6 +2,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/hide_items"
android:icon="?attr/ic_filter"
android:menuCategory="container"
android:title="@string/hide_episodes_title"
custom:showAsAction="always">
</item>
<item
android:id="@+id/refresh_item"
android:icon="?attr/navigation_refresh"

View File

@ -10,9 +10,7 @@ import java.util.Date;
import java.util.List;
import de.danoeh.antennapod.core.asynctask.PicassoImageResource;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.EpisodeFilter;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
@ -81,12 +79,18 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
*/
private String nextPageLink;
/**
* Contains property strings. If such a property applies to a feed item, it is not shown in the feed list
*/
private FeedItemFilter itemfilter;
/**
* This constructor is used for restoring a feed from the database.
*/
public Feed(long id, Date lastUpdate, String title, String link, String description, String paymentLink,
String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
String downloadUrl, boolean downloaded, FlattrStatus status, boolean paged, String nextPageLink) {
String downloadUrl, boolean downloaded, FlattrStatus status, boolean paged, String nextPageLink,
String filter) {
super(fileUrl, downloadUrl, downloaded);
this.id = id;
this.title = title;
@ -106,6 +110,11 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
this.flattrStatus = status;
this.paged = paged;
this.nextPageLink = nextPageLink;
if(filter != null) {
this.itemfilter = new FeedItemFilter(filter);
} else {
this.itemfilter = new FeedItemFilter(new String[0]);
}
items = new ArrayList<FeedItem>();
}
@ -117,7 +126,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
String downloadUrl, boolean downloaded) {
this(id, lastUpdate, title, link, description, paymentLink, author, language, type, feedIdentifier, image,
fileUrl, downloadUrl, downloaded, new FlattrStatus(), false, null);
fileUrl, downloadUrl, downloaded, new FlattrStatus(), false, null, null);
}
/**
@ -159,40 +168,6 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
preferences = new FeedPreferences(0, true, username, password);
}
/**
* Returns the number of FeedItems where 'read' is false. If the 'display
* only episodes' - preference is set to true, this method will only count
* items with episodes.
*/
public int getNumOfNewItems() {
int count = 0;
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (!UserPreferences.isDisplayOnlyEpisodes()
|| item.getMedia() != null) {
count++;
}
}
}
return count;
}
/**
* Returns the number of FeedItems where the media started to play but
* wasn't finished yet.
*/
public int getNumOfStartedItems() {
int count = 0;
for (FeedItem item : items) {
FeedItem.State state = item.getState();
if (state == FeedItem.State.IN_PROGRESS
|| state == FeedItem.State.PLAYING) {
count++;
}
}
return count;
}
/**
* Returns true if at least one item in the itemlist is unread.
@ -204,8 +179,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
public boolean hasNewItems(boolean enableEpisodeFilter) {
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (!(enableEpisodeFilter && UserPreferences
.isDisplayOnlyEpisodes()) || item.getMedia() != null) {
if (item.getMedia() != null) {
return true;
}
}
@ -221,11 +195,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
* user.
*/
public int getNumOfItems(boolean enableEpisodeFilter) {
if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
return EpisodeFilter.countItemsWithEpisodes(items);
} else {
return items.size();
}
return items.size();
}
/**
@ -235,11 +205,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
* the episodes filter has been enabled by the user.
*/
public FeedItem getItemAtIndex(boolean enableEpisodeFilter, int position) {
if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
return EpisodeFilter.accessEpisodeByIndex(items, position);
} else {
return items.get(position);
}
return items.get(position);
}
/**
@ -516,4 +482,15 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
public void setNextPageLink(String nextPageLink) {
this.nextPageLink = nextPageLink;
}
public FeedItemFilter getItemFilter() {
return itemfilter;
}
public void setFeedItemsFilter(String[] filter) {
if(filter != null) {
this.itemfilter = new FeedItemFilter(filter);
}
}
}

View File

@ -0,0 +1,28 @@
package de.danoeh.antennapod.core.feed;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class FeedEvent {
public enum Action {
FILTER_CHANGED
}
public final Action action;
public final long feedId;
public FeedEvent(Action action, long feedId) {
this.action = action;
this.feedId = feedId;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("action", action)
.append("feedId", feedId)
.toString();
}
}

View File

@ -0,0 +1,82 @@
package de.danoeh.antennapod.core.feed;
import android.content.Context;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.core.storage.DBReader;
public class FeedItemFilter {
private final String[] filter;
private boolean hideUnplayed = false;
private boolean hidePaused = false;
private boolean hidePlayed = false;
private boolean hideQueued = false;
private boolean hideNotQueued = false;
private boolean hideDownloaded = false;
private boolean hideNotDownloaded = false;
public FeedItemFilter(String filter) {
this(StringUtils.split(filter, ','));
}
public FeedItemFilter(String[] filter) {
this.filter = filter;
for(String f : filter) {
// see R.arrays.feed_filter_values
switch(f) {
case "unplayed":
hideUnplayed = true;
break;
case "paused":
hidePaused = true;
break;
case "played":
hidePlayed = true;
break;
case "queued":
hideQueued = true;
break;
case "not_queued":
hideNotQueued = true;
break;
case "downloaded":
hideDownloaded = true;
break;
case "not_downloaded":
hideNotDownloaded = true;
break;
}
}
}
public List<FeedItem> filter(Context context, List<FeedItem> items) {
if(filter.length == 0) {
return items;
}
List<FeedItem> result = new ArrayList<FeedItem>();
for(FeedItem item : items) {
if(hideUnplayed && false == item.isRead()) continue;
if(hidePaused && item.getState() == FeedItem.State.IN_PROGRESS) continue;
if(hidePlayed && item.isRead()) continue;
boolean isQueued = DBReader.getQueueIDList(context).contains(item.getId());
if(hideQueued && isQueued) continue;
if(hideNotQueued && false == isQueued) continue;
boolean isDownloaded = item.getMedia() != null && item.getMedia().isDownloaded();
if(hideDownloaded && isDownloaded) continue;
if(hideNotDownloaded && false == isDownloaded) continue;
result.add(item);
}
return result;
}
public String[] getValues() {
return filter.clone();
}
}

View File

@ -6,7 +6,6 @@ import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import java.util.Date;
import java.util.List;
@ -231,7 +230,6 @@ public class FeedMedia extends FeedFile implements Playable {
}
public boolean hasEmbeddedPicture() {
Log.d(TAG, "hasEmbeddedPicture() -> " + hasEmbeddedPicture);
return this.hasEmbeddedPicture;
}
@ -433,7 +431,6 @@ public class FeedMedia extends FeedFile implements Playable {
}
private void checkEmbeddedPicture() {
Log.d(TAG, "checkEmbeddedPicture()");
if (!localFileAvailable()) {
hasEmbeddedPicture = false;
return;

View File

@ -45,7 +45,6 @@ public class UserPreferences implements
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
public static final String PREF_PARALLEL_DOWNLOADS = "prefParallelDownloads";
public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate";
public static final String PREF_DISPLAY_ONLY_EPISODES = "prefDisplayOnlyEpisodes";
public static final String PREF_AUTO_DELETE = "prefAutoDelete";
public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs";
public static final String PREF_AUTO_FLATTR = "pref_auto_flattr";
@ -84,7 +83,6 @@ public class UserPreferences implements
private boolean downloadMediaOnWifiOnly;
private long updateInterval;
private boolean allowMobileUpdate;
private boolean displayOnlyEpisodes;
private boolean autoDelete;
private int smartMarkAsPlayedSecs;
private boolean autoFlattr;
@ -146,7 +144,6 @@ public class UserPreferences implements
updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL,
"0"));
allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES, false);
autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false);
@ -272,12 +269,6 @@ public class UserPreferences implements
return instance.allowMobileUpdate;
}
public static boolean isDisplayOnlyEpisodes() {
instanceAvailable();
//return instance.displayOnlyEpisodes;
return false;
}
public static boolean isAutoDelete() {
instanceAvailable();
return instance.autoDelete;
@ -435,9 +426,6 @@ public class UserPreferences implements
smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
} else if (key.equals(PREF_AUTO_FLATTR)) {
autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false);
} else if (key.equals(PREF_DISPLAY_ONLY_EPISODES)) {
displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES,
false);
} else if (key.equals(PREF_THEME)) {
theme = readThemeValue(sp.getString(PREF_THEME, ""));
} else if (key.equals(PREF_ENABLE_AUTODL_WIFI_FILTER)) {

View File

@ -316,7 +316,9 @@ public final class DBReader {
cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOADED) > 0,
new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS)),
cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_IS_PAGED) > 0,
cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_NEXT_PAGE_LINK));
cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_NEXT_PAGE_LINK),
cursor.getString(cursor.getColumnIndex(PodDBAdapter.KEY_HIDE))
);
if (image != null) {
image.setOwner(feed);

View File

@ -29,6 +29,7 @@ import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@ -1063,4 +1064,28 @@ public class DBWriter {
});
}
/**
* Set filter of the feed
*
* @param context Used for opening a database connection.
* @param feedId The feed's ID
* @param filterValues Values that represent properties to filter by
*/
public static Future<?> setFeedItemsFilter(final Context context, final long feedId,
final List<String> filterValues) {
Log.d(TAG, "setFeedFilter");
return dbExec.submit(new Runnable() {
@Override
public void run() {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.setFeedItemFilter(feedId, filterValues);
adapter.close();
EventBus.getDefault().post(new FeedEvent(FeedEvent.Action.FILTER_CHANGED, feedId));
}
});
}
}

View File

@ -11,6 +11,7 @@ import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.util.Arrays;
@ -149,6 +150,7 @@ public class PodDBAdapter {
public static final String KEY_PASSWORD = "password";
public static final String KEY_IS_PAGED = "is_paged";
public static final String KEY_NEXT_PAGE_LINK = "next_page_link";
public static final String KEY_HIDE = "hide";
// Table names
public static final String TABLE_NAME_FEEDS = "Feeds";
@ -175,7 +177,8 @@ public class PodDBAdapter {
+ KEY_USERNAME + " TEXT,"
+ KEY_PASSWORD + " TEXT,"
+ KEY_IS_PAGED + " INTEGER DEFAULT 0,"
+ KEY_NEXT_PAGE_LINK + " TEXT)";
+ KEY_NEXT_PAGE_LINK + " TEXT,"
+ KEY_HIDE + " TEXT)";
public static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
@ -247,6 +250,7 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_NEXT_PAGE_LINK,
TABLE_NAME_FEEDS + "." + KEY_USERNAME,
TABLE_NAME_FEEDS + "." + KEY_PASSWORD,
TABLE_NAME_FEEDS + "." + KEY_HIDE
};
// column indices for FEED_SEL_STD
@ -403,17 +407,15 @@ public class PodDBAdapter {
values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong());
values.put(KEY_IS_PAGED, feed.isPaged());
values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink());
values.put(KEY_HIDE, StringUtils.join(feed.getItemFilter(), ","));
if (feed.getId() == 0) {
// Create new entry
if (BuildConfig.DEBUG)
Log.d(this.toString(), "Inserting new Feed into db");
Log.d(this.toString(), "Inserting new Feed into db");
feed.setId(db.insert(TABLE_NAME_FEEDS, null, values));
} else {
if (BuildConfig.DEBUG)
Log.d(this.toString(), "Updating existing Feed in db");
Log.d(this.toString(), "Updating existing Feed in db");
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?",
new String[]{String.valueOf(feed.getId())});
}
return feed.getId();
}
@ -429,6 +431,13 @@ public class PodDBAdapter {
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
}
public void setFeedItemFilter(long feedId, List<String> filterValues) {
ContentValues values = new ContentValues();
values.put(KEY_HIDE, StringUtils.join(filterValues, ","));
Log.d(TAG, StringUtils.join(filterValues, ","));
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
}
/**
* Inserts or updates an image entry
*

View File

@ -1,11 +1,12 @@
package de.danoeh.antennapod.core.util;
import de.danoeh.antennapod.core.feed.FeedItem;
import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.core.feed.FeedItem;
public class EpisodeFilter {
private EpisodeFilter() {
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

View File

@ -137,4 +137,24 @@
<item>@string/add_feed_label</item>
</string-array>
<string-array name="episode_hide_options">
<item>@string/hide_unplayed_episodes_label</item>
<item>@string/hide_paused_episodes_label</item>
<item>@string/hide_played_episodes_label</item>
<item>@string/hide_queued_episodes_label</item>
<item>@string/hide_not_queued_episodes_label</item>
<item>@string/hide_downloaded_episodes_label</item>
<item>@string/hide_not_downloaded_episodes_label</item>
</string-array>
<string-array name="episode_hide_values">
<item>unplayed</item>
<item>paused</item>
<item>played</item>
<item>queued</item>
<item>not_queued</item>
<item>downloaded</item>
<item>not_downloaded</item>
</string-array>
</resources>

View File

@ -39,6 +39,7 @@
<attr name="ic_settings" format="reference"/>
<attr name="ic_lock_open" format="reference"/>
<attr name="ic_lock_closed" format="reference"/>
<attr name="ic_filter" format="reference"/>
<!-- Used in itemdescription -->
<attr name="non_transparent_background" format="reference"/>

View File

@ -91,6 +91,15 @@
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded.</string>
<string name="feed_remover_msg">Removing feed</string>
<string name="load_complete_feed">Refresh complete feed</string>
<string name="hide_episodes_title">Hide episodes</string>
<string name="hide_unplayed_episodes_label">Unplayed</string>
<string name="hide_paused_episodes_label">Paused</string>
<string name="hide_played_episodes_label">Played</string>
<string name="hide_queued_episodes_label">Queued</string>
<string name="hide_not_queued_episodes_label">Not queued</string>
<string name="hide_downloaded_episodes_label">Downloaded</string>
<string name="hide_not_downloaded_episodes_label">Not downloaded</string>
<string name="filtered_label">Filtered</string>
<!-- actions on feeditems -->
<string name="download_label">Download</string>

View File

@ -44,6 +44,7 @@
<item name="attr/ic_settings">@drawable/ic_settings_grey600_24dp</item>
<item name="attr/ic_lock_open">@drawable/ic_lock_open_grey600_24dp</item>
<item name="attr/ic_lock_closed">@drawable/ic_lock_closed_grey600_24dp</item>
<item name="attr/ic_filter">@drawable/ic_filter_grey600_24dp</item>
</style>
<style name="Theme.AntennaPod.Dark" parent="@style/Theme.AppCompat">
@ -88,6 +89,7 @@
<item name="attr/ic_settings">@drawable/ic_settings_white_24dp</item>
<item name="attr/ic_lock_open">@drawable/ic_lock_open_white_24dp</item>
<item name="attr/ic_lock_closed">@drawable/ic_lock_closed_white_24dp</item>
<item name="attr/ic_filter">@drawable/ic_filter_white_24dp</item>
</style>
<style name="Theme.AntennaPod.Light.NoTitle" parent="@style/Theme.AppCompat.Light.NoActionBar">
@ -135,6 +137,7 @@
<item name="attr/ic_settings">@drawable/ic_settings_grey600_24dp</item>
<item name="attr/ic_lock_open">@drawable/ic_lock_open_grey600_24dp</item>
<item name="attr/ic_lock_closed">@drawable/ic_lock_closed_grey600_24dp</item>
<item name="attr/ic_filter">@drawable/ic_filter_grey600_24dp</item>
</style>
<style name="Theme.AntennaPod.Dark.NoTitle" parent="@style/Theme.AppCompat.NoActionBar">
@ -181,6 +184,7 @@
<item name="attr/ic_settings">@drawable/ic_settings_white_24dp</item>
<item name="attr/ic_lock_open">@drawable/ic_lock_open_white_24dp</item>
<item name="attr/ic_lock_closed">@drawable/ic_lock_closed_white_24dp</item>
<item name="attr/ic_filter">@drawable/ic_filter_white_24dp</item>
</style>
<style name="Theme.AntennaPod.VideoPlayer" parent="@style/Theme.AntennaPod.Dark">