summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java23
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java21
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java16
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java18
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java34
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java5
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java70
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java68
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/StorageCallbacksImpl.java185
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java4
-rw-r--r--app/src/main/res/menu/nav_feed_context.xml19
-rw-r--r--app/src/main/res/xml/preferences.xml27
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java27
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java43
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java139
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java72
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java79
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java76
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java304
-rw-r--r--core/src/main/res/values/arrays.xml22
-rw-r--r--core/src/main/res/values/strings.xml15
44 files changed, 720 insertions, 688 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java
index 52067c971..738ec488f 100644
--- a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java
@@ -2,15 +2,9 @@ package de.test.antennapod.handler;
import android.content.Context;
import android.test.InstrumentationTestCase;
-import de.danoeh.antennapod.core.feed.*;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
-import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
-import de.test.antennapod.util.syndication.feedgenerator.AtomGenerator;
-import de.test.antennapod.util.syndication.feedgenerator.FeedGenerator;
-import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
+
import org.xml.sax.SAXException;
-import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -19,6 +13,19 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import javax.xml.parsers.ParserConfigurationException;
+
+import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedImage;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
+import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
+import de.test.antennapod.util.syndication.feedgenerator.AtomGenerator;
+import de.test.antennapod.util.syndication.feedgenerator.FeedGenerator;
+import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
+
/**
* Tests for FeedHandler
*/
@@ -162,7 +169,7 @@ public class FeedHandlerTest extends InstrumentationTestCase {
for (int i = 0; i < numItems; i++) {
FeedItem item = new FeedItem(0, "item-" + i, "http://example.com/item-" + i,
- "http://example.com/items/" + i, new Date(i*60000), false, feed);
+ "http://example.com/items/" + i, new Date(i*60000), FeedItem.UNPLAYED, feed);
feed.getItems().add(item);
if (withFeedMedia) {
item.setMedia(new FeedMedia(0, item, 4711, 0, 100, "audio/mp3", null, "http://example.com/media-" + i,
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
index aac4c245a..9281cb319 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
@@ -3,15 +3,9 @@ package de.test.antennapod.service.playback;
import android.content.Context;
import android.media.RemoteControlClient;
import android.test.InstrumentationTestCase;
-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.service.playback.PlaybackServiceMediaPlayer;
-import de.danoeh.antennapod.core.service.playback.PlayerStatus;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import de.danoeh.antennapod.core.util.playback.Playable;
-import de.test.antennapod.util.service.download.HTTPBin;
+
import junit.framework.AssertionFailedError;
+
import org.apache.commons.io.IOUtils;
import java.io.File;
@@ -23,6 +17,15 @@ import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+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.service.playback.PlaybackServiceMediaPlayer;
+import de.danoeh.antennapod.core.service.playback.PlayerStatus;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import de.danoeh.antennapod.core.util.playback.Playable;
+import de.test.antennapod.util.service.download.HTTPBin;
+
/**
* Test class for PlaybackServiceMediaPlayer
*/
@@ -114,7 +117,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final Context c = getInstrumentation().getTargetContext();
Feed f = new Feed(0, new Date(), "f", "l", "d", null, null, null, null, "i", null, null, "l", false);
f.setItems(new ArrayList<FeedItem>());
- FeedItem i = new FeedItem(0, "t", "i", "l", new Date(), false, f);
+ FeedItem i = new FeedItem(0, "t", "i", "l", new Date(), FeedItem.UNPLAYED, f);
f.getItems().add(i);
FeedMedia media = new FeedMedia(0, i, 0, 0, 0, "audio/wav", fileUrl, downloadUrl, fileUrl != null, null, 0);
i.setMedia(media);
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
index d74128c2f..edb576249 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
@@ -51,7 +51,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase {
Feed f = new Feed(0, new Date(), "title", "link", "d", null, null, null, null, "id", null, "null", "url", false);
f.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- f.getItems().add(new FeedItem(0, pref + i, pref + i, "link", new Date(), true, f));
+ f.getItems().add(new FeedItem(0, pref + i, pref + i, "link", new Date(), FeedItem.PLAYED, f));
}
PodDBAdapter adapter = new PodDBAdapter(c);
adapter.open();
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
index 95d2ce58a..1b77baea0 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
@@ -277,7 +277,7 @@ public class DBReaderTest extends InstrumentationTestCase {
int i = random.nextInt(numItems);
if (!unread.contains(items.get(i))) {
FeedItem item = items.get(i);
- item.setRead(false);
+ item.setPlayed(false);
unread.add(item);
}
}
@@ -297,7 +297,7 @@ public class DBReaderTest extends InstrumentationTestCase {
assertNotNull(unreadSaved);
assertTrue(unread.size() == unreadSaved.size());
for (FeedItem item : unreadSaved) {
- assertFalse(item.isRead());
+ assertFalse(item.isPlayed());
}
}
@@ -310,11 +310,11 @@ public class DBReaderTest extends InstrumentationTestCase {
for (int i = 0; i < unread.size(); i++) {
unreadIds[i] = unread.get(i).getId();
}
- LongList unreadSaved = DBReader.getNewItemIds(context);
+ List<FeedItem> unreadSaved = DBReader.getUnreadItemsList(context);
assertNotNull(unreadSaved);
assertTrue(unread.size() == unreadSaved.size());
for(int i=0; i < unreadSaved.size(); i++) {
- long savedId = unreadSaved.get(i);
+ long savedId = unreadSaved.get(i).getId();
boolean found = false;
for (long id : unreadIds) {
if (id == savedId) {
@@ -385,13 +385,13 @@ public class DBReaderTest extends InstrumentationTestCase {
final int NUM_FEEDS = 10;
final int NUM_ITEMS = 10;
final int NUM_QUEUE = 1;
- final int NUM_UNREAD = 2;
+ final int NUM_NEW = 2;
List<Feed> feeds = DBTestUtils.saveFeedlist(context, NUM_FEEDS, NUM_ITEMS, true);
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
- for (int i = 0; i < NUM_UNREAD; i++) {
+ for (int i = 0; i < NUM_NEW; i++) {
FeedItem item = feeds.get(0).getItems().get(i);
- item.setRead(false);
+ item.setNew();
adapter.setSingleFeedItem(item);
}
List<FeedItem> queue = new ArrayList<FeedItem>();
@@ -405,7 +405,7 @@ public class DBReaderTest extends InstrumentationTestCase {
DBReader.NavDrawerData navDrawerData = DBReader.getNavDrawerData(context);
assertEquals(NUM_FEEDS, navDrawerData.feeds.size());
- assertEquals(NUM_UNREAD, navDrawerData.numNewItems);
+ assertEquals(NUM_NEW, navDrawerData.numNewItems);
assertEquals(NUM_QUEUE, navDrawerData.queueSize);
}
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
index 356933367..a176ef69a 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
@@ -78,7 +78,7 @@ public class DBTasksTest extends InstrumentationTestCase {
feed.setItems(items);
List<File> files = new ArrayList<File>();
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
File f = new File(destFolder, "file " + i);
assertTrue(f.createNewFile());
@@ -116,7 +116,7 @@ public class DBTasksTest extends InstrumentationTestCase {
feed.setItems(items);
List<File> files = new ArrayList<File>();
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), false, feed);
+ FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.UNPLAYED, feed);
File f = new File(destFolder, "file " + i);
assertTrue(f.createNewFile());
@@ -151,7 +151,7 @@ public class DBTasksTest extends InstrumentationTestCase {
feed.setItems(items);
List<File> files = new ArrayList<File>();
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
File f = new File(destFolder, "file " + i);
assertTrue(f.createNewFile());
@@ -208,14 +208,14 @@ public class DBTasksTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- feed.getItems().add(new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(), false, feed));
+ feed.getItems().add(new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(), FeedItem.UNPLAYED, feed));
}
Feed newFeed = DBTasks.updateFeed(context, feed)[0];
assertTrue(newFeed == feed);
assertTrue(feed.getId() != 0);
for (FeedItem item : feed.getItems()) {
- assertFalse(item.isRead());
+ assertFalse(item.isPlayed());
assertTrue(item.getId() != 0);
}
}
@@ -242,7 +242,7 @@ public class DBTasksTest extends InstrumentationTestCase {
final Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS_OLD; i++) {
- feed.getItems().add(new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(i), true, feed));
+ feed.getItems().add(new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(i), FeedItem.PLAYED, feed));
}
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
@@ -261,7 +261,7 @@ public class DBTasksTest extends InstrumentationTestCase {
}
for (int i = NUM_ITEMS_OLD; i < NUM_ITEMS_NEW + NUM_ITEMS_OLD; i++) {
- feed.getItems().add(0, new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(i), true, feed));
+ feed.getItems().add(0, new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(i), FeedItem.PLAYED, feed));
}
final Feed newFeed = DBTasks.updateFeed(context, feed)[0];
@@ -285,7 +285,7 @@ public class DBTasksTest extends InstrumentationTestCase {
FeedItem item = newFeed.getItems().get(i);
assertTrue(item.getFeed() == newFeed);
assertTrue(item.getId() == itemIDs.get(i));
- assertTrue(item.isRead());
+ assertTrue(item.isPlayed());
assertTrue(item.getPubDate().getTime() >= lastDate.getTime());
lastDate = item.getPubDate();
}
@@ -293,7 +293,7 @@ public class DBTasksTest extends InstrumentationTestCase {
FeedItem item = newFeed.getItems().get(i);
assertTrue(item.getFeed() == newFeed);
assertTrue(item.getId() != 0);
- assertFalse(item.isRead());
+ assertFalse(item.isPlayed());
assertTrue(item.getPubDate().getTime() >= lastDate.getTime());
lastDate = item.getPubDate();
}
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
index 4f33cd798..c6f702f3d 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
@@ -51,7 +51,7 @@ public class DBTestUtils {
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(),
- true, f, withChapters);
+ FeedItem.PLAYED, f, withChapters);
if (withMedia) {
FeedMedia media = new FeedMedia(item, "url" + j, 1, "audio/mp3");
item.setMedia(media);
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
index f3b0c9165..c5fa2f131 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
@@ -65,7 +65,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
List<FeedItem> items = new ArrayList<FeedItem>();
feed.setItems(items);
- FeedItem item = new FeedItem(0, "Item", "Item", "url", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "Item", "Item", "url", new Date(), FeedItem.PLAYED, feed);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", dest.getAbsolutePath(), "download_url", true, null, 0);
item.setMedia(media);
@@ -104,7 +104,7 @@ public class DBWriterTest extends InstrumentationTestCase {
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed, true);
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed, true);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
@@ -171,7 +171,7 @@ public class DBWriterTest extends InstrumentationTestCase {
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
@@ -268,7 +268,7 @@ public class DBWriterTest extends InstrumentationTestCase {
// create items
for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
}
@@ -320,7 +320,7 @@ public class DBWriterTest extends InstrumentationTestCase {
// create items with images
for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
File itemImageFile = new File(destFolder, "item-image-" + i);
FeedImage itemImage = new FeedImage(0, "item-image" + i, itemImageFile.getAbsolutePath(), "url", true);
@@ -378,7 +378,7 @@ public class DBWriterTest extends InstrumentationTestCase {
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
@@ -450,7 +450,7 @@ public class DBWriterTest extends InstrumentationTestCase {
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
@@ -496,7 +496,7 @@ public class DBWriterTest extends InstrumentationTestCase {
final Context context = getInstrumentation().getTargetContext();
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
- FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
FeedMedia media = new FeedMedia(0, item, 10, 0, 1, "mime", null, "url", false, playbackCompletionDate, 0);
feed.getItems().add(item);
item.setMedia(media);
@@ -543,7 +543,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
}
@@ -569,7 +569,7 @@ public class DBWriterTest extends InstrumentationTestCase {
final Context context = getInstrumentation().getTargetContext();
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
- FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
PodDBAdapter adapter = new PodDBAdapter(context);
@@ -593,7 +593,7 @@ public class DBWriterTest extends InstrumentationTestCase {
final Context context = getInstrumentation().getTargetContext();
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
- FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
PodDBAdapter adapter = new PodDBAdapter(context);
@@ -661,7 +661,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
}
@@ -707,7 +707,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), true, feed);
+ FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.PLAYED, feed);
feed.getItems().add(item);
}
@@ -754,7 +754,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), false, feed);
+ FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.UNPLAYED, feed);
feed.getItems().add(item);
}
@@ -771,7 +771,7 @@ public class DBWriterTest extends InstrumentationTestCase {
DBWriter.markFeedRead(context, feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
List<FeedItem> loadedItems = DBReader.getFeedItemList(context, feed);
for (FeedItem item : loadedItems) {
- assertTrue(item.isRead());
+ assertTrue(item.isPlayed());
}
}
@@ -781,7 +781,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
for (int i = 0; i < NUM_ITEMS; i++) {
- FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), false, feed);
+ FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.UNPLAYED, feed);
feed.getItems().add(item);
}
@@ -798,7 +798,7 @@ public class DBWriterTest extends InstrumentationTestCase {
DBWriter.markAllItemsRead(context).get(TIMEOUT, TimeUnit.SECONDS);
List<FeedItem> loadedItems = DBReader.getFeedItemList(context, feed);
for (FeedItem item : loadedItems) {
- assertTrue(item.isRead());
+ assertTrue(item.isPlayed());
}
}
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
index 613826932..7bbc6e462 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
@@ -111,6 +111,9 @@ public class UITestUtils {
private File newMediaFile(String name) throws IOException {
File mediaFile = new File(hostedMediaDir, name);
+ if(mediaFile.exists()) {
+ mediaFile.delete();
+ }
Assert.assertFalse(mediaFile.exists());
InputStream in = context.getAssets().open("testfile.mp3");
@@ -142,7 +145,7 @@ public class UITestUtils {
List<FeedItem> items = new ArrayList<FeedItem>();
for (int j = 0; j < NUM_ITEMS_PER_FEED; j++) {
FeedItem item = new FeedItem(j, "Feed " + (i+1) + ": Item " + (j+1), "item" + j,
- "http://example.com/feed" + i + "/item/" + j, new Date(), false, feed);
+ "http://example.com/feed" + i + "/item/" + j, new Date(), FeedItem.UNPLAYED, feed);
items.add(item);
File mediaFile = newMediaFile("feed-" + i + "-episode-" + j + ".mp3");
diff --git a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
index 2c56b71cc..7e535e12c 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
@@ -31,7 +31,7 @@ public class TimelineTest extends InstrumentationTestCase {
}
private Playable newTestPlayable(List<Chapter> chapters, String shownotes) {
- FeedItem item = new FeedItem(0, "Item", "item-id", "http://example.com/item", new Date(), true, null);
+ FeedItem item = new FeedItem(0, "Item", "item-id", "http://example.com/item", new Date(), FeedItem.PLAYED, null);
item.setChapters(chapters);
item.setContentEncoded(shownotes);
FeedMedia media = new FeedMedia(item, "http://example.com/episode", 100, "audio/mp3");
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
index b59f6ba35..cae29db4b 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.activity;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -13,6 +14,8 @@ import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
+import android.view.ContextMenu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
@@ -31,6 +34,8 @@ import org.apache.commons.lang3.StringUtils;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.ChapterListAdapter;
import de.danoeh.antennapod.adapter.NavListAdapter;
+import de.danoeh.antennapod.core.asynctask.FeedRemover;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
@@ -39,6 +44,7 @@ import de.danoeh.antennapod.core.feed.SimpleChapter;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
@@ -430,6 +436,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
drawerLayout.closeDrawer(navDrawer);
}
});
+ registerForContextMenu(navList);
drawerToggle.syncState();
findViewById(R.id.nav_settings).setOnClickListener(new View.OnClickListener() {
@@ -634,6 +641,65 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
}
}
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ if(v.getId() != R.id.nav_list) {
+ return;
+ }
+ AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ int position = adapterInfo.position;
+ if(position < navAdapter.getSubscriptionOffset()) {
+ return;
+ }
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.nav_feed_context, menu);
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ menu.setHeaderTitle(feed.getTitle());
+ // episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
+ if(menuInfo.targetView.getParent() instanceof ListView == false
+ || ((ListView)menuInfo.targetView.getParent()).getId() != R.id.nav_list) {
+ return false;
+ }
+ int position = menuInfo.position;
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ switch(item.getItemId()) {
+ case R.id.mark_all_seen_item:
+ DBWriter.markFeedSeen(this, feed.getId());
+ return true;
+ case R.id.mark_all_read_item:
+ DBWriter.markFeedRead(this, feed.getId());
+ return true;
+ case R.id.remove_item:
+ final FeedRemover remover = new FeedRemover(this, feed) {
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ }
+ };
+ ConfirmationDialog conDialog = new ConfirmationDialog(this,
+ R.string.remove_feed_label,
+ R.string.feed_delete_confirmation_msg) {
+ @Override
+ public void onConfirmButtonPressed(
+ DialogInterface dialog) {
+ dialog.dismiss();
+ remover.executeAsync();
+ }
+ };
+ conDialog.createNewDialog().show();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+
private DBReader.NavDrawerData navDrawerData;
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
@@ -708,8 +774,8 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
}
@Override
- public int getNumberOfUnreadFeedItems(long feedId) {
- return (navDrawerData != null) ? navDrawerData.numUnreadFeedItems.get(feedId) : 0;
+ public int getFeedCounter(long feedId) {
+ return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
};
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
index 5b80b8f9d..acb56dcb4 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -20,6 +20,8 @@ import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
+import android.view.ContextMenu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
@@ -32,12 +34,15 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.NavListAdapter;
+import de.danoeh.antennapod.core.asynctask.FeedRemover;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.QueueEvent;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.AllEpisodesFragment;
@@ -140,6 +145,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
navList.setAdapter(navAdapter);
navList.setOnItemClickListener(navListClickListener);
navList.setOnItemLongClickListener(newListLongClickListener);
+ registerForContextMenu(navList);
navAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
@@ -493,6 +499,64 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
}
}
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ if(v.getId() != R.id.nav_list) {
+ return;
+ }
+ AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ int position = adapterInfo.position;
+ if(position < navAdapter.getSubscriptionOffset()) {
+ return;
+ }
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.nav_feed_context, menu);
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ menu.setHeaderTitle(feed.getTitle());
+ // episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
+ if(menuInfo.targetView.getParent() instanceof ListView == false
+ || ((ListView)menuInfo.targetView.getParent()).getId() != R.id.nav_list) {
+ return false;
+ }
+ int position = menuInfo.position;
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ switch(item.getItemId()) {
+ case R.id.mark_all_seen_item:
+ DBWriter.markFeedSeen(this, feed.getId());
+ return true;
+ case R.id.mark_all_read_item:
+ DBWriter.markFeedRead(this, feed.getId());
+ return true;
+ case R.id.remove_item:
+ final FeedRemover remover = new FeedRemover(this, feed) {
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ }
+ };
+ ConfirmationDialog conDialog = new ConfirmationDialog(this,
+ R.string.remove_feed_label,
+ R.string.feed_delete_confirmation_msg) {
+ @Override
+ public void onConfirmButtonPressed(
+ DialogInterface dialog) {
+ dialog.dismiss();
+ remover.executeAsync();
+ }
+ };
+ conDialog.createNewDialog().show();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
private DBReader.NavDrawerData navDrawerData;
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
private int selectedNavListIndex = 0;
@@ -532,8 +596,8 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
}
@Override
- public int getNumberOfUnreadFeedItems(long feedId) {
- return (navDrawerData != null) ? navDrawerData.numUnreadFeedItems.get(feedId) : 0;
+ public int getFeedCounter(long feedId) {
+ return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
};
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
index 8e347a819..aca2b359a 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
@@ -88,7 +88,7 @@ public class ActionButtonUtils {
butSecondary.setContentDescription(context.getString(labels[0]));
}
} else {
- if (item.isRead()) {
+ if (item.isPlayed()) {
butSecondary.setVisibility(View.INVISIBLE);
} else {
butSecondary.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java
index d96326053..bc3d3abbc 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java
@@ -91,7 +91,7 @@ public class AllEpisodesListAdapter extends BaseAdapter {
holder.title.setText(item.getTitle());
holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
- if (showOnlyNewEpisodes || item.isRead() || false == itemAccess.isNew(item)) {
+ if (showOnlyNewEpisodes || false == item.isNew()) {
holder.statusUnread.setVisibility(View.INVISIBLE);
} else {
holder.statusUnread.setVisibility(View.VISIBLE);
@@ -179,7 +179,5 @@ public class AllEpisodesListAdapter extends BaseAdapter {
boolean isInQueue(FeedItem item);
- boolean isNew(FeedItem item);
-
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
index 4d6279560..c34d90a30 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
@@ -95,7 +95,7 @@ public class DefaultActionButtonCallback implements ActionButtonCallback {
}
}
} else {
- if (!item.isRead()) {
+ if (!item.isPlayed()) {
DBWriter.markItemRead(context, item, true, true);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
index b39e23d42..1ecc45210 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -112,12 +112,12 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
holder.title.setText(buffer.toString());
- if(false == item.isRead() && itemAccess.isNew(item)) {
+ if(item.isNew()) {
holder.statusUnread.setVisibility(View.VISIBLE);
} else {
holder.statusUnread.setVisibility(View.INVISIBLE);
}
- if(item.isRead()) {
+ if(item.isPlayed()) {
ViewHelper.setAlpha(convertView, 0.5f);
} else {
ViewHelper.setAlpha(convertView, 1.0f);
@@ -221,8 +221,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
FeedItem getItem(int position);
- boolean isNew(FeedItem item);
-
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
index 0d2d5cfa0..444d08da9 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -276,10 +276,10 @@ public class NavListAdapter extends BaseAdapter
p.addRule(RelativeLayout.LEFT_OF, R.id.txtvCount);
holder.failure.setVisibility(View.GONE);
}
- int feedUnreadItems = itemAccess.getNumberOfUnreadFeedItems(feed.getId());
- if(feedUnreadItems > 0) {
+ int counter = itemAccess.getFeedCounter(feed.getId());
+ if(counter > 0) {
holder.count.setVisibility(View.VISIBLE);
- holder.count.setText(String.valueOf(feedUnreadItems));
+ holder.count.setText(String.valueOf(counter));
holder.count.setTypeface(holder.title.getTypeface());
} else {
holder.count.setVisibility(View.GONE);
@@ -306,7 +306,7 @@ public class NavListAdapter extends BaseAdapter
int getSelectedItemIndex();
int getQueueSize();
int getNumberOfNewItems();
- int getNumberOfUnreadFeedItems(long feedId);
+ int getFeedCounter(long feedId);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
index 10666aa36..932b9d22f 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
@@ -14,7 +14,6 @@ public class ClientConfigurator {
ClientConfig.downloadServiceCallbacks = new DownloadServiceCallbacksImpl();
ClientConfig.gpodnetCallbacks = new GpodnetCallbacksImpl();
ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl();
- ClientConfig.storageCallbacks = new StorageCallbacksImpl();
ClientConfig.flattrCallbacks = new FlattrCallbacksImpl();
ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/StorageCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/StorageCallbacksImpl.java
deleted file mode 100644
index d8fab34c8..000000000
--- a/app/src/main/java/de/danoeh/antennapod/config/StorageCallbacksImpl.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package de.danoeh.antennapod.config;
-
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.media.MediaMetadataRetriever;
-import android.util.Log;
-
-import de.danoeh.antennapod.core.StorageCallbacks;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
-public class StorageCallbacksImpl implements StorageCallbacks {
-
- @Override
- public int getDatabaseVersion() {
- return 16;
- }
-
- @Override
- public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
- Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
- + newVersion + ".");
- if (oldVersion <= 1) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
- + PodDBAdapter.KEY_TYPE + " TEXT");
- }
- if (oldVersion <= 2) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + PodDBAdapter.KEY_LINK + " TEXT");
- }
- if (oldVersion <= 3) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_ITEM_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 4) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
- + PodDBAdapter.KEY_FEED_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 5) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + PodDBAdapter.KEY_REASON_DETAILED + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE + " TEXT");
- }
- if (oldVersion <= 6) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + PodDBAdapter.KEY_CHAPTER_TYPE + " INTEGER");
- }
- if (oldVersion <= 7) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE
- + " INTEGER");
- }
- if (oldVersion <= 8) {
- final int KEY_ID_POSITION = 0;
- final int KEY_MEDIA_POSITION = 1;
-
- // Add feeditem column to feedmedia table
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_FEEDITEM
- + " INTEGER");
- Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
- new String[]{PodDBAdapter.KEY_ID, PodDBAdapter.KEY_MEDIA}, "? > 0",
- new String[]{PodDBAdapter.KEY_MEDIA}, null, null, null);
- if (feeditemCursor.moveToFirst()) {
- db.beginTransaction();
- ContentValues contentValues = new ContentValues();
- do {
- long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
- contentValues.put(PodDBAdapter.KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
- db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, PodDBAdapter.KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
- contentValues.clear();
- } while (feeditemCursor.moveToNext());
- db.setTransactionSuccessful();
- db.endTransaction();
- }
- feeditemCursor.close();
- }
- if (oldVersion <= 9) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD
- + " INTEGER DEFAULT 1");
- }
- if (oldVersion <= 10) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_FLATTR_STATUS
- + " INTEGER");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_FLATTR_STATUS
- + " INTEGER");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_PLAYED_DURATION
- + " INTEGER");
- }
- if (oldVersion <= 11) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_USERNAME
- + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_PASSWORD
- + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE
- + " INTEGER");
- }
- if (oldVersion <= 12) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_NEXT_PAGE_LINK + " TEXT");
- }
- if (oldVersion <= 13) {
- // remove duplicate rows in "Chapters" table that were created because of a bug.
- db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
- "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
- PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
- PodDBAdapter.KEY_ID,
- PodDBAdapter.KEY_ID,
- PodDBAdapter.KEY_ID,
- PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
- PodDBAdapter.KEY_TITLE,
- PodDBAdapter.KEY_START,
- PodDBAdapter.KEY_FEEDITEM,
- PodDBAdapter.KEY_LINK,
- PodDBAdapter.KEY_CHAPTER_TYPE));
- }
- if(oldVersion <= 14) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD + " INTEGER");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " SET " + PodDBAdapter.KEY_AUTO_DOWNLOAD + " = "
- + "(SELECT " + PodDBAdapter.KEY_AUTO_DOWNLOAD
- + " 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");
-
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
-
- // create indexes
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE);
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM);
- db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM);
- db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
- }
- if(oldVersion <= 15) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0"
- + " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=0");
- Cursor c = db.rawQuery("SELECT " + PodDBAdapter.KEY_FILE_URL
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=1 "
- + " AND " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=-1", null);
- if(c.moveToFirst()) {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- do {
- String fileUrl = c.getString(0);
- try {
- mmr.setDataSource(fileUrl);
- byte[] image = mmr.getEmbeddedPicture();
- if (image != null) {
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=1"
- + " WHERE " + PodDBAdapter.KEY_FILE_URL + "='"+ fileUrl + "'");
- } else {
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0"
- + " WHERE " + PodDBAdapter.KEY_FILE_URL + "='"+ fileUrl + "'");
- }
- } catch(Exception e) {
- e.printStackTrace();
- }
- } while(c.moveToNext());
- }
- c.close();
- }
- }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index 1ca5b831c..8a4a4efbf 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -5,8 +5,6 @@ import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -316,7 +314,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkPlayed(boolean isPlayed) {
for (FeedItem episode : episodes) {
- if(episode.isRead() == isPlayed) {
+ if(episode.isPlayed() == isPlayed) {
if(!checkedIds.contains(episode.getId())) {
checkedIds.add(episode.getId());
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
index e48b175e8..b4c4f1822 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -76,7 +76,6 @@ public class AllEpisodesFragment extends Fragment {
private List<FeedItem> episodes;
private LongList queuedItemsIds;
- private LongList newItemsIds;
private List<Downloader> downloaderList;
private boolean itemsLoaded = false;
@@ -432,18 +431,6 @@ public class AllEpisodesFragment extends Fragment {
return false;
}
}
-
- @Override
- public boolean isNew(FeedItem item) {
- if (itemsLoaded) {
- // should actually never be called in NewEpisodesFragment, but better safe than sorry
- return showOnlyNewEpisodes || newItemsIds.contains(item.getId());
- } else {
- return false;
- }
- }
-
-
};
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@@ -508,8 +495,7 @@ public class AllEpisodesFragment extends Fragment {
} else {
return new Object[]{
DBReader.getRecentlyPublishedEpisodes(context, RECENT_EPISODES_LIMIT),
- DBReader.getQueueIDList(context),
- DBReader.getNewItemIds(context)
+ DBReader.getQueueIDList(context)
};
}
} else {
@@ -526,7 +512,6 @@ public class AllEpisodesFragment extends Fragment {
if (lists != null) {
episodes = (List<FeedItem>) lists[0];
queuedItemsIds = (LongList) lists[1];
- newItemsIds = (LongList) lists[2];
itemsLoaded = true;
if (viewsCreated && activity.get() != null) {
onFragmentLoaded();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
index 6e3b37133..e0ed3d02c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -355,7 +355,7 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.navigation_accept,
R.attr.location_web_site});
- if (!item.isRead()) {
+ if (!item.isPlayed()) {
butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(0), null, null, null);
butAction1.setText(getActivity().getString(R.string.mark_read_label));
butAction1.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
index 797e5fb82..5862e248b 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -92,8 +92,6 @@ public class ItemlistFragment extends ListFragment {
private long feedID;
private Feed feed;
private LongList queuedItemsIds;
- private LongList newItemsIds;
-
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
@@ -580,11 +578,6 @@ public class ItemlistFragment extends ListFragment {
}
@Override
- public boolean isNew(FeedItem item) {
- return (newItemsIds != null) && newItemsIds.contains(item.getId());
- }
-
- @Override
public int getItemDownloadProgressPercent(FeedItem item) {
if (downloaderList != null) {
for (Downloader downloader : downloaderList) {
@@ -626,8 +619,7 @@ public class ItemlistFragment extends ListFragment {
feed.setItems(filter.filter(context, feed.getItems()));
}
LongList queuedItemsIds = DBReader.getQueueIDList(context);
- LongList newItemsIds = DBReader.getNewItemIds(context);
- return new Object[] { feed, queuedItemsIds, newItemsIds };
+ return new Object[] { feed, queuedItemsIds };
} else {
return null;
}
@@ -639,7 +631,6 @@ public class ItemlistFragment extends ListFragment {
if (res != null) {
feed = (Feed) res[0];
queuedItemsIds = (LongList) res[1];
- newItemsIds = res[2] == null ? null : (LongList) res[2];
itemsLoaded = true;
if (viewsCreated) {
onFragmentLoaded();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
index fc8bf2fbb..67f454fa0 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -219,11 +219,6 @@ public class PlaybackHistoryFragment extends ListFragment {
}
@Override
- public boolean isNew(FeedItem item) {
- return false;
- }
-
- @Override
public int getItemDownloadProgressPercent(FeedItem item) {
if (downloaderList != null) {
for (Downloader downloader : downloaderList) {
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
index e3285fd53..3e2fdf24f 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -154,7 +154,7 @@ public class FeedItemMenuHandler {
DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId());
break;
case R.id.mark_read_item:
- selectedItem.setRead(true);
+ selectedItem.setPlayed(true);
DBWriter.markItemRead(context, selectedItem, true, false);
if(GpodnetPreferences.loggedIn()) {
FeedMedia media = selectedItem.getMedia();
@@ -172,7 +172,7 @@ public class FeedItemMenuHandler {
}
break;
case R.id.mark_unread_item:
- selectedItem.setRead(false);
+ selectedItem.setPlayed(false);
DBWriter.markItemRead(context, selectedItem, false, false);
if(GpodnetPreferences.loggedIn()) {
GpodnetEpisodeAction actionNew = new GpodnetEpisodeAction.Builder(selectedItem, Action.NEW)
diff --git a/app/src/main/res/menu/nav_feed_context.xml b/app/src/main/res/menu/nav_feed_context.xml
new file mode 100644
index 000000000..4bf067d25
--- /dev/null
+++ b/app/src/main/res/menu/nav_feed_context.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/mark_all_seen_item"
+ android:menuCategory="container"
+ android:title="@string/mark_all_seen_label" />
+
+ <item
+ android:id="@+id/mark_all_read_item"
+ android:menuCategory="container"
+ android:title="@string/mark_all_read_label" />
+
+ <item
+ android:id="@+id/remove_item"
+ android:menuCategory="container"
+ android:title="@string/remove_feed_label" />
+
+</menu>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 04699bac1..9f93662de 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -9,10 +9,29 @@
android:key="prefTheme"
android:summary="@string/pref_set_theme_sum"
android:defaultValue="0"/>
- <Preference
- android:key="prefHiddenDrawerItems"
- android:summary="@string/pref_nav_drawer_items_sum"
- android:title="@string/pref_nav_drawer_items_title" />
+ <PreferenceScreen
+ android:key="prefDrawerSettings"
+ android:summary="@string/pref_nav_drawer_sum"
+ android:title="@string/pref_nav_drawer_title">
+ <Preference
+ android:key="prefHiddenDrawerItems"
+ android:summary="@string/pref_nav_drawer_items_sum"
+ android:title="@string/pref_nav_drawer_items_title" />
+ <ListPreference
+ android:entryValues="@array/nav_drawer_feed_order_values"
+ android:entries="@array/nav_drawer_feed_order_options"
+ android:title="@string/pref_nav_drawer_feed_order_title"
+ android:key="prefDrawerFeedOrder"
+ android:summary="@string/pref_nav_drawer_feed_order_sum"
+ android:defaultValue="0"/>
+ <ListPreference
+ android:entryValues="@array/nav_drawer_feed_counter_values"
+ android:entries="@array/nav_drawer_feed_counter_options"
+ android:title="@string/pref_nav_drawer_feed_counter_title"
+ android:key="prefDrawerFeedIndicator"
+ android:summary="@string/pref_nav_drawer_feed_counter_sum"
+ android:defaultValue="0"/>
+ </PreferenceScreen>
<CheckBoxPreference
android:defaultValue="false"
android:enabled="true"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
index 1a2671555..6619e706b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -21,7 +21,5 @@ public class ClientConfig {
public static FlattrCallbacks flattrCallbacks;
- public static StorageCallbacks storageCallbacks;
-
public static DBTasksCallbacks dbTasksCallbacks;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java
deleted file mode 100644
index 5d1a0fffc..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.danoeh.antennapod.core;
-
-import android.database.sqlite.SQLiteDatabase;
-
-/**
- * Callbacks for the classes in the storage package of the core module.
- */
-public interface StorageCallbacks {
-
- /**
- * Returns the current version of the database.
- *
- * @return The non-negative version number of the database.
- */
- public int getDatabaseVersion();
-
- /**
- * Upgrades the given database from an old version to a newer version.
- *
- * @param db The database that is supposed to be upgraded.
- * @param oldVersion The old version of the database.
- * @param newVersion The version that the database is supposed to be upgraded to.
- */
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
-
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
index 29ba721fe..25b3a9ae6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
@@ -177,10 +177,21 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
*/
public boolean hasNewItems() {
for (FeedItem item : items) {
- if (item.getState() == FeedItem.State.UNREAD) {
- if (item.getMedia() != null) {
- return true;
- }
+ if (item.isNew()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if at least one item in the itemlist is unread.
+ *
+ */
+ public boolean hasUnplayedItems() {
+ for (FeedItem item : items) {
+ if (false == item.isNew() && false == item.isPlayed()) {
+ return true;
}
}
return false;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
index 1168c60e4..96a6c2ba1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
@@ -44,7 +44,11 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
private Feed feed;
private long feedId;
- private boolean read;
+ private int state;
+ public final static int NEW = -1;
+ public final static int UNPLAYED = 0;
+ public final static int PLAYED = 1;
+
private String paymentLink;
private FlattrStatus flattrStatus;
@@ -66,7 +70,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
private boolean autoDownload = true;
public FeedItem() {
- this.read = true;
+ this.state = UNPLAYED;
this.flattrStatus = new FlattrStatus();
this.hasChapters = false;
}
@@ -75,7 +79,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
* This constructor is used by DBReader.
* */
public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId,
- FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, boolean read,
+ FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state,
String itemIdentifier, boolean autoDownload) {
this.id = id;
this.title = title;
@@ -86,7 +90,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
this.flattrStatus = flattrStatus;
this.hasChapters = hasChapters;
this.image = image;
- this.read = read;
+ this.state = state;
this.itemIdentifier = itemIdentifier;
this.autoDownload = autoDownload;
}
@@ -94,13 +98,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
/**
* This constructor should be used for creating test objects.
*/
- public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed) {
+ public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed) {
this.id = id;
this.title = title;
this.itemIdentifier = itemIdentifier;
this.link = link;
this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null;
- this.read = read;
+ this.state = state;
this.feed = feed;
this.flattrStatus = new FlattrStatus();
this.hasChapters = false;
@@ -109,13 +113,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
/**
* This constructor should be used for creating test objects involving chapter marks.
*/
- public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed, boolean hasChapters) {
+ public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed, boolean hasChapters) {
this.id = id;
this.title = title;
this.itemIdentifier = itemIdentifier;
this.link = link;
this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null;
- this.read = read;
+ this.state = state;
this.feed = feed;
this.flattrStatus = new FlattrStatus();
this.hasChapters = hasChapters;
@@ -238,12 +242,25 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
this.feed = feed;
}
- public boolean isRead() {
- return read;
+ public boolean isNew() {
+ return state == NEW;
+ }
+
+
+ public void setNew() {
+ state = NEW;
+ }
+
+ public boolean isPlayed() {
+ return state == PLAYED;
}
- public void setRead(boolean read) {
- this.read = read;
+ public void setPlayed(boolean played) {
+ if(played) {
+ state = PLAYED;
+ } else {
+ state = UNPLAYED;
+ }
}
private boolean isInProgress() {
@@ -342,7 +359,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
return State.IN_PROGRESS;
}
}
- return (isRead() ? State.READ : State.UNREAD);
+ return (isPlayed() ? State.READ : State.UNREAD);
}
public long getFeedId() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
index 4ad084b39..2fd5666c8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
@@ -61,9 +61,9 @@ public class FeedItemFilter {
}
List<FeedItem> result = new ArrayList<FeedItem>();
for(FeedItem item : items) {
- if(hideUnplayed && false == item.isRead()) continue;
+ if(hideUnplayed && false == item.isPlayed()) continue;
if(hidePaused && item.getState() == FeedItem.State.IN_PROGRESS) continue;
- if(hidePlayed && item.isRead()) continue;
+ if(hidePlayed && item.isPlayed()) continue;
boolean isQueued = DBReader.getQueueIDList(context).contains(item.getId());
if(hideQueued && isQueued) continue;
if(hideNotQueued && false == isQueued) continue;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
index b4cca505c..33dd9d636 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
@@ -186,6 +186,9 @@ public class FeedMedia extends FeedFile implements Playable {
public void setPosition(int position) {
this.position = position;
+ if(position > 0 && item.isNew()) {
+ this.item.setPlayed(false);
+ }
}
public long getSize() {
@@ -365,14 +368,16 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void saveCurrentPosition(SharedPreferences pref, int newPosition) {
- setPosition(newPosition);
DBWriter.setFeedMediaPlaybackInformation(ClientConfig.applicationCallbacks.getApplicationInstance(), this);
+ if(item.isNew()) {
+ DBWriter.markItemRead(ClientConfig.applicationCallbacks.getApplicationInstance(), false, item.getId());
+ }
+ setPosition(newPosition);
}
@Override
public void onPlaybackStart() {
}
-
@Override
public void onPlaybackCompleted() {
@@ -447,6 +452,9 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void setDownloaded(boolean downloaded) {
super.setDownloaded(downloaded);
+ if(downloaded) {
+ item.setPlayed(false);
+ }
}
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java
index c8497f509..97d086e5b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java
@@ -8,7 +8,7 @@ import java.util.List;
public class QueueEvent {
public enum Action {
- ADDED, ADDED_ITEMS, REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED
+ ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED
}
public final Action action;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
index d96d25fc2..c9bfe2153 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
@@ -43,6 +43,8 @@ public class UserPreferences {
// User Interface
public static final String PREF_THEME = "prefTheme";
public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems";
+ public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder";
+ public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedCounter";
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify";
public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
@@ -85,6 +87,12 @@ public class UserPreferences {
// Constants
private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
+ public static int FEED_ORDER_UNPLAYED_EPISODES = 0;
+ public static int FEED_ORDER_ALPHABETICAL = 1;
+ public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0;
+ public static int FEED_COUNTER_SHOW_NEW = 1;
+ public static int FEED_COUNTER_SHOW_UNPLAYED = 2;
+ public static int FEED_COUNTER_SHOW_NONE = 3;
private static Context context;
private static SharedPreferences prefs;
@@ -128,6 +136,16 @@ public class UserPreferences {
return new ArrayList<String>(Arrays.asList(StringUtils.split(hiddenItems, ',')));
}
+ public static int getFeedOrder() {
+ String value = prefs.getString(PREF_DRAWER_FEED_ORDER, "0");
+ return Integer.valueOf(value);
+ }
+
+ public static int getFeedCounter() {
+ String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "0");
+ return Integer.valueOf(value);
+ }
+
/**
* Returns notification priority.
*
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index 238cad763..7fb878680 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -815,7 +815,7 @@ public class DownloadService extends Service {
e.printStackTrace();
}
}
- if (!item.isRead() && item.hasMedia() && !item.getMedia().isDownloaded()) {
+ if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) {
newMediaFiles.add(item.getMedia().getId());
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
index f647fd537..a07705e69 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
@@ -28,7 +28,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
List<FeedItem> delete;
for (FeedItem item : downloadedItems) {
if (item.hasMedia() && item.getMedia().isDownloaded()
- && !queue.contains(item.getId()) && item.isRead()) {
+ && !queue.contains(item.getId()) && item.isPlayed()) {
candidates.add(item);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java
deleted file mode 100644
index 420bbc09d..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package de.danoeh.antennapod.core.storage;
-
-import android.content.Context;
-import android.util.Log;
-
-import org.apache.commons.io.FileUtils;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-import de.danoeh.antennapod.core.feed.FeedItem;
-
-/**
- * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPodSP apps.
- */
-public class APSPCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
- private static final String TAG = "APSPCleanupAlgorithm";
-
- final int numberOfNewAutomaticallyDownloadedEpisodes;
-
- public APSPCleanupAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
- this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
- }
-
- /**
- * Performs an automatic cleanup. Episodes that have been downloaded first will also be deleted first.
- * The episode that is currently playing as well as the n most recent episodes (the exact value is determined
- * by AppPreferences.numberOfNewAutomaticallyDownloadedEpisodes) will never be deleted.
- *
- * @param context
- * @param episodeSize The maximum amount of space that should be freed by this method
- * @return The number of episodes that have been deleted
- */
- @Override
- public int performCleanup(Context context, Integer episodeSize) {
- Log.i(TAG, String.format("performAutoCleanup(%d)", episodeSize));
- if (episodeSize <= 0) {
- return 0;
- }
-
- List<FeedItem> candidates = getAutoCleanupCandidates(context);
- List<FeedItem> deleteList = new ArrayList<FeedItem>();
- long deletedEpisodesSize = 0;
- Collections.sort(candidates, new Comparator<FeedItem>() {
- @Override
- public int compare(FeedItem lhs, FeedItem rhs) {
- File lFile = new File(lhs.getMedia().getFile_url());
- File rFile = new File(rhs.getMedia().getFile_url());
- if (!lFile.exists() || !rFile.exists()) {
- return 0;
- }
- if (FileUtils.isFileOlder(lFile, rFile)) {
- return -1;
- } else {
- return 1;
- }
- }
- });
- // listened episodes will be deleted first
- Iterator<FeedItem> it = candidates.iterator();
- if (it.hasNext()) {
- for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
- if (!i.getMedia().isPlaying() && i.getMedia().getPlaybackCompletionDate() != null) {
- it.remove();
- deleteList.add(i);
- deletedEpisodesSize += i.getMedia().getSize();
- }
- }
- }
-
- // delete unlistened old episodes if necessary
- it = candidates.iterator();
- if (it.hasNext()) {
- for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
- if (!i.getMedia().isPlaying()) {
- it.remove();
- deleteList.add(i);
- deletedEpisodesSize += i.getMedia().getSize();
- }
- }
- }
- for (FeedItem item : deleteList) {
- try {
- DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- Log.i(TAG, String.format("performAutoCleanup(%d) deleted %d episodes and freed %d bytes of memory",
- episodeSize, deleteList.size(), deletedEpisodesSize));
- return deleteList.size();
- }
-
- @Override
- public Integer getDefaultCleanupParameter(Context context) {
- return 0;
- }
-
- @Override
- public Integer getPerformCleanupParameter(Context context, List<FeedItem> items) {
- int episodeSize = 0;
- for (FeedItem item : items) {
- if (item.hasMedia() && !item.getMedia().isDownloaded()) {
- episodeSize += item.getMedia().getSize();
- }
- }
- return episodeSize;
- }
-
- /**
- * Returns list of FeedItems that have been downloaded, but are not one of the
- * [numberOfNewAutomaticallyDownloadedEpisodes] most recent items.
- */
- private List<FeedItem> getAutoCleanupCandidates(Context context) {
- List<FeedItem> downloaded = new ArrayList<FeedItem>(DBReader.getDownloadedItems(context));
- List<FeedItem> recent = new ArrayList<FeedItem>(DBReader.getRecentlyPublishedEpisodes(context,
- numberOfNewAutomaticallyDownloadedEpisodes));
- for (FeedItem r : recent) {
- if (r.hasMedia() && r.getMedia().isDownloaded()) {
- for (int i = 0; i < downloaded.size(); i++) {
- if (downloaded.get(i).getId() == r.getId()) {
- downloaded.remove(i);
- break;
- }
- }
- }
- }
-
- return downloaded;
-
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java
deleted file mode 100644
index f760ec0ce..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package de.danoeh.antennapod.core.storage;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.util.NetworkUtils;
-
-/**
- * Implements the automatic download algorithm used by AntennaPodSP apps.
- */
-public class APSPDownloadAlgorithm implements AutomaticDownloadAlgorithm {
- private static final String TAG = "APSPDownloadAlgorithm";
-
- private final int numberOfNewAutomaticallyDownloadedEpisodes;
-
- public APSPDownloadAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
- this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
- }
-
- /**
- * Downloads the most recent episodes automatically. The exact number of
- * episodes that will be downloaded can be set in the AppPreferences.
- *
- * @param context Used for accessing the DB.
- * @return A Runnable that will be submitted to an ExecutorService.
- */
- @Override
- public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) {
- return new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Performing auto-dl of undownloaded episodes");
- if (NetworkUtils.autodownloadNetworkAvailable(context)
- && UserPreferences.isEnableAutodownload()) {
-
- Arrays.sort(mediaIds);
- List<FeedItem> itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context,
- numberOfNewAutomaticallyDownloadedEpisodes);
- Iterator<FeedItem> it = itemsToDownload.iterator();
-
- for (FeedItem item = it.next(); it.hasNext(); item = it.next()) {
- if (!item.hasMedia()
- || item.getMedia().isDownloaded()
- || Arrays.binarySearch(mediaIds, item.getMedia().getId()) < 0) {
- it.remove();
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Enqueueing " + itemsToDownload.size()
- + " items for automatic download");
- if (!itemsToDownload.isEmpty()) {
- try {
- DBTasks.downloadFeedItems(false, context,
- itemsToDownload.toArray(new FeedItem[itemsToDownload
- .size()]));
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- }
- }
- }
- };
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
index 95c033dc5..93aec54c8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
@@ -22,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.ID3Chapter;
import de.danoeh.antennapod.core.feed.SimpleChapter;
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.LongIntMap;
@@ -229,7 +230,7 @@ public final class DBReader {
new FlattrStatus(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)),
itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0,
image,
- (itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0),
+ itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ),
itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER),
itemlistCursor.getInt(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD)) > 0
);
@@ -481,8 +482,7 @@ public final class DBReader {
* Loads a list of FeedItems whose 'read'-attribute is set to false.
*
* @param context A context that is used for opening a database connection.
- * @return A list of FeedItems whose 'read'-attribute it set to false. If the FeedItems in the list are not used,
- * consider using {@link #getUnreadItemIds(android.content.Context)} instead.
+ * @return A list of FeedItems whose 'read'-attribute it set to false.
*/
public static List<FeedItem> getUnreadItemsList(Context context) {
if (BuildConfig.DEBUG)
@@ -1013,20 +1013,6 @@ public final class DBReader {
}
/**
- * Returns a map containing the number of unread items per feed
- *
- * @param context A context that is used for opening a database connection.
- * @return The number of unread items per feed.
- */
- public static LongIntMap getNumberOfUnreadFeedItems(final Context context, long... feedIds) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final LongIntMap result = adapter.getNumberOfUnreadFeedItems(feedIds);
- adapter.close();
- return result;
- }
-
- /**
* Searches the DB for a FeedImage of the given id.
*
* @param context A context that is used for opening a database connection.
@@ -1154,27 +1140,42 @@ public final class DBReader {
for(int i=0; i < feeds.size(); i++) {
feedIds[i] = feeds.get(i).getId();
}
- final LongIntMap numUnreadFeedItems = adapter.getNumberOfUnreadFeedItems(feedIds);
- Collections.sort(feeds, new Comparator<Feed>() {
- @Override
- public int compare(Feed lhs, Feed rhs) {
- long numUnreadLhs = numUnreadFeedItems.get(lhs.getId());
- Log.d(TAG, "feed with id " + lhs.getId() + " has " + numUnreadLhs + " unread items");
- long numUnreadRhs = numUnreadFeedItems.get(rhs.getId());
- Log.d(TAG, "feed with id " + rhs.getId() + " has " + numUnreadRhs + " unread items");
- if(numUnreadLhs > numUnreadRhs) {
- // reverse natural order: podcast with most unplayed episodes first
- return -1;
- } else if(numUnreadLhs == numUnreadRhs) {
+ final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
+
+ Comparator<Feed> comparator;
+ int feedOrder = UserPreferences.getFeedOrder();
+ if(feedOrder == UserPreferences.FEED_ORDER_UNPLAYED_EPISODES) {
+ comparator = new Comparator<Feed>() {
+ @Override
+ public int compare(Feed lhs, Feed rhs) {
+ long counterLhs = feedCounters.get(lhs.getId());
+ long counterRhs = feedCounters.get(rhs.getId());
+ if(counterLhs > counterRhs) {
+ // reverse natural order: podcast with most unplayed episodes first
+ return -1;
+ } else if(counterLhs == counterRhs) {
+ return lhs.getTitle().compareTo(rhs.getTitle());
+ } else {
+ return 1;
+ }
+ }
+ };
+ } else {
+ comparator = new Comparator<Feed>() {
+ @Override
+ public int compare(Feed lhs, Feed rhs) {
+ if(lhs.getTitle() == null) {
+ return 1;
+ }
return lhs.getTitle().compareTo(rhs.getTitle());
- } else {
- return 1;
}
- }
- });
+ };
+ }
+
+ Collections.sort(feeds, comparator);
int queueSize = adapter.getQueueSize();
int numNewItems = adapter.getNumberOfNewItems();
- NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numUnreadFeedItems);
+ NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters);
adapter.close();
return result;
}
@@ -1183,14 +1184,16 @@ public final class DBReader {
public List<Feed> feeds;
public int queueSize;
public int numNewItems;
- public LongIntMap numUnreadFeedItems;
+ public LongIntMap feedCounters;
- public NavDrawerData(List<Feed> feeds, int queueSize, int numNewItems,
- LongIntMap numUnreadFeedItems) {
+ public NavDrawerData(List<Feed> feeds,
+ int queueSize,
+ int numNewItems,
+ LongIntMap feedIndicatorValues) {
this.feeds = feeds;
this.queueSize = queueSize;
this.numNewItems = numNewItems;
- this.numUnreadFeedItems = numUnreadFeedItems;
+ this.feedCounters = feedIndicatorValues;
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
index 711cd773e..9273cf11e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
@@ -561,7 +561,7 @@ public final class DBTasks {
// all new feeds will have the most recent item marked as unplayed
FeedItem mostRecent = newFeed.getMostRecentItem();
if (mostRecent != null) {
- mostRecent.setRead(false);
+ mostRecent.setNew();
}
newFeedsList.add(newFeed);
@@ -572,16 +572,16 @@ public final class DBTasks {
Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator());
- final boolean markNewItemsAsUnread;
+ final boolean markNewItems;
if (newFeed.getPageNr() == savedFeed.getPageNr()) {
if (savedFeed.compareWithOther(newFeed)) {
Log.d(TAG, "Feed has updated attribute values. Updating old feed's attributes");
savedFeed.updateFromOther(newFeed);
}
- markNewItemsAsUnread = true;
+ markNewItems = true;
} else {
Log.d(TAG, "New feed has a higher page number. Merging without marking as unread");
- markNewItemsAsUnread = false;
+ markNewItems = false;
savedFeed.setNextPageLink(newFeed.getNextPageLink());
}
if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) {
@@ -599,8 +599,8 @@ public final class DBTasks {
item.setFeed(savedFeed);
item.setAutoDownload(savedFeed.getPreferences().getAutoDownload());
savedFeed.getItems().add(i, item);
- if (markNewItemsAsUnread) {
- item.setRead(false);
+ if (markNewItems) {
+ item.setNew();
}
} else {
oldItem.updateFromOther(item);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index e103007e3..acdcf5f85 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -13,10 +13,10 @@ import org.shredzone.flattr4j.model.Flattr;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
@@ -185,13 +185,15 @@ public class DBWriter {
}
// delete stored media files and mark them as read
List<FeedItem> queue = DBReader.getQueue(context);
- boolean queueWasModified = false;
+ List<FeedItem> removed = new ArrayList<>();
if (feed.getItems() == null) {
DBReader.getFeedItemList(context, feed);
}
for (FeedItem item : feed.getItems()) {
- queueWasModified |= queue.remove(item);
+ if(queue.remove(item)) {
+ removed.add(item);
+ }
if (item.getMedia() != null
&& item.getMedia().isDownloaded()) {
File mediaFile = new File(item.getMedia()
@@ -214,8 +216,10 @@ public class DBWriter {
}
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
- if (queueWasModified) {
+ if (removed.size() > 0) {
adapter.setQueue(queue);
+ EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED,
+ removed));
}
adapter.removeFeed(feed);
adapter.close();
@@ -352,7 +356,7 @@ public class DBWriter {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
final List<FeedItem> queue = DBReader.getQueue(context, adapter);
- FeedItem item = null;
+ FeedItem item;
if (queue != null) {
if (!itemListContains(queue, itemId)) {
@@ -361,6 +365,9 @@ public class DBWriter {
queue.add(index, item);
adapter.setQueue(queue);
EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index));
+ if(item.isNew()) {
+ DBWriter.markItemRead(context, false, item.getId());
+ }
}
}
}
@@ -380,7 +387,6 @@ public class DBWriter {
return addQueueItem(context, false, itemIds);
}
-
/**
* Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true.
* If a FeedItem is already in the queue, the FeedItem will not change its position in the queue.
@@ -398,35 +404,36 @@ public class DBWriter {
if (itemIds.length > 0) {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
- final List<FeedItem> queue = DBReader.getQueue(context,
- adapter);
+ final List<FeedItem> queue = DBReader.getQueue(context, adapter);
if (queue != null) {
boolean queueModified = false;
- boolean unreadItemsModified = false;
- List<FeedItem> itemsToSave = new LinkedList<FeedItem>();
+ LongList markAsUnplayedIds = new LongList();
for (int i = 0; i < itemIds.length; i++) {
if (!itemListContains(queue, itemIds[i])) {
- final FeedItem item = DBReader.getFeedItem(
- context, itemIds[i]);
+ final FeedItem item = DBReader.getFeedItem(context, itemIds[i]);
if (item != null) {
// add item to either front ot back of queue
boolean addToFront = UserPreferences.enqueueAtFront();
-
- if(addToFront){
- queue.add(0+i, item);
+ if (addToFront) {
+ queue.add(0 + i, item);
} else {
queue.add(item);
}
-
queueModified = true;
+ if(item.isNew()) {
+ markAsUnplayedIds.add(item.getId());
+ }
}
}
}
if (queueModified) {
adapter.setQueue(queue);
EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue));
+ if(markAsUnplayedIds.size() > 0) {
+ DBWriter.markItemRead(context, false, markAsUnplayedIds.toArray());
+ }
}
}
adapter.close();
@@ -616,7 +623,8 @@ public class DBWriter {
public void run() {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
- adapter.setFeedItemRead(read, itemIds);
+ int played = read ? FeedItem.PLAYED : FeedItem.UNPLAYED;
+ adapter.setFeedItemRead(played, itemIds);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
@@ -662,6 +670,35 @@ public class DBWriter {
* @param context A context that is used for opening a database connection.
* @param feedId ID of the Feed.
*/
+ public static Future<?> markFeedSeen(final Context context, final long feedId) {
+ return dbExec.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ final PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId);
+ long[] ids = new long[itemCursor.getCount()];
+ itemCursor.moveToFirst();
+ for (int i = 0; i < ids.length; i++) {
+ ids[i] = itemCursor.getLong(0);
+ itemCursor.moveToNext();
+ }
+ itemCursor.close();
+ adapter.setFeedItemRead(FeedItem.UNPLAYED, ids);
+ adapter.close();
+
+ EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
+ }
+ });
+ }
+
+ /**
+ * Sets the 'read'-attribute of all FeedItems of a specific Feed to true.
+ *
+ * @param context A context that is used for opening a database connection.
+ * @param feedId ID of the Feed.
+ */
public static Future<?> markFeedRead(final Context context, final long feedId) {
return dbExec.submit(new Runnable() {
@@ -677,13 +714,12 @@ public class DBWriter {
itemCursor.moveToNext();
}
itemCursor.close();
- adapter.setFeedItemRead(true, itemIds);
+ adapter.setFeedItemRead(FeedItem.PLAYED, itemIds);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
});
-
}
/**
@@ -706,7 +742,7 @@ public class DBWriter {
itemCursor.moveToNext();
}
itemCursor.close();
- adapter.setFeedItemRead(true, itemIds);
+ adapter.setFeedItemRead(FeedItem.PLAYED, itemIds);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
index ed3cb71e9..2be53047d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -9,6 +9,7 @@ import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
+import android.media.MediaMetadataRetriever;
import android.text.TextUtils;
import android.util.Log;
@@ -18,7 +19,6 @@ import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.Chapter;
@@ -28,13 +28,12 @@ import de.danoeh.antennapod.core.feed.FeedImage;
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.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
import de.greenrobot.event.EventBus;
-;
-
// TODO Remove media column from feeditem table
/**
@@ -369,8 +368,7 @@ public class PodDBAdapter {
private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) {
if (dbHelperSingleton == null) {
- dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null,
- ClientConfig.storageCallbacks.getDatabaseVersion());
+ dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null);
}
return dbHelperSingleton;
}
@@ -742,7 +740,13 @@ public class PodDBAdapter {
setFeed(item.getFeed());
}
values.put(KEY_FEED, item.getFeed().getId());
- values.put(KEY_READ, item.isRead());
+ if(item.isNew()) {
+ values.put(KEY_READ, FeedItem.NEW);
+ } else if(item.isPlayed()) {
+ values.put(KEY_READ, FeedItem.PLAYED);
+ } else {
+ values.put(KEY_READ, FeedItem.UNPLAYED);
+ }
values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters());
values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier());
values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong());
@@ -774,7 +778,7 @@ public class PodDBAdapter {
db.beginTransaction();
ContentValues values = new ContentValues();
- values.put(KEY_READ, read);
+ values.put(KEY_READ, read ? FeedItem.PLAYED : FeedItem.UNPLAYED);
db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)});
if (resetMediaPosition) {
@@ -787,7 +791,7 @@ public class PodDBAdapter {
db.endTransaction();
}
- public void setFeedItemRead(boolean read, long... itemIds) {
+ public void setFeedItemRead(int read, long... itemIds) {
db.beginTransaction();
ContentValues values = new ContentValues();
for (long id : itemIds) {
@@ -880,8 +884,7 @@ public class PodDBAdapter {
values.put(KEY_ID, i);
values.put(KEY_FEEDITEM, item.getId());
values.put(KEY_FEED, item.getFeed().getId());
- db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
+ db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
db.setTransactionSuccessful();
db.endTransaction();
@@ -1059,6 +1062,7 @@ public class PodDBAdapter {
/**
* Returns a cursor which contains all feed items in the queue. The returned
* cursor uses the FEEDITEM_SEL_FI_SMALL selection.
+ * cursor uses the FEEDITEM_SEL_FI_SMALL selection.
*/
public final Cursor getQueueCursor() {
Object[] args = (Object[]) new String[]{
@@ -1090,44 +1094,39 @@ public class PodDBAdapter {
*/
public final Cursor getUnreadItemsCursor() {
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_READ
- + "=0", null, null, null, KEY_PUBDATE + " DESC");
+ + "<" + FeedItem.PLAYED, null, null, null, KEY_PUBDATE + " DESC");
return c;
}
public final Cursor getNewItemIdsCursor() {
- final String query = "SELECT " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID
+ final String query = "SELECT " + KEY_ID
+ " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
+ + " WHERE " + KEY_READ + "=" + FeedItem.NEW;
return db.rawQuery(query, null);
}
/**
+ * Returns a cursor which contains all items of a feed that are considered new.
+ * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
+ */
+ public final Cursor getNewItemsIdsCursor(long feedId) {
+ final String query = "SELECT " + KEY_ID
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " WHERE " + KEY_FEED + "=" + feedId
+ + " AND " + KEY_READ + "=" + FeedItem.NEW
+ + " ORDER BY " + KEY_PUBDATE + " DESC";
+ Cursor c = db.rawQuery(query, null);
+ return c;
+ }
+
+ /**
* Returns a cursor which contains all feed items that are considered new.
* The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
*/
public final Cursor getNewItemsCursor() {
- final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL" // not in queue
+ final String query = "SELECT " + SEL_FI_SMALL_STR
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " WHERE " + KEY_READ + "=" + FeedItem.NEW
+ " ORDER BY " + KEY_PUBDATE + " DESC";
Cursor c = db.rawQuery(query, null);
return c;
@@ -1139,11 +1138,11 @@ public class PodDBAdapter {
}
public Cursor getDownloadedItemsCursor() {
- final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0";
+ final String query = "SELECT " + SEL_FI_SMALL_STR
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " INNER JOIN " + TABLE_NAME_FEED_MEDIA
+ + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
+ + " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0";
Cursor c = db.rawQuery(query, null);
return c;
}
@@ -1277,19 +1276,9 @@ public class PodDBAdapter {
}
public final int getNumberOfNewItems() {
- final String query = "SELECT COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ")"
- +" FROM " + TABLE_NAME_FEED_ITEMS
- + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT JOIN " + TABLE_NAME_QUEUE + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
+ final String query = "SELECT COUNT(" + KEY_ID + ")"
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " WHERE " + KEY_READ + "=" + FeedItem.NEW;
Cursor c = db.rawQuery(query, null);
int result = 0;
if (c.moveToFirst()) {
@@ -1299,7 +1288,20 @@ public class PodDBAdapter {
return result;
}
- public final LongIntMap getNumberOfUnreadFeedItems(long... feedIds) {
+ public final LongIntMap getFeedCounters(long... feedIds) {
+ int counter = UserPreferences.getFeedCounter();
+ String whereRead;
+ if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) {
+ whereRead = "(" + KEY_READ + "=" + FeedItem.NEW
+ + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")";
+ } else if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW) {
+ whereRead = KEY_READ + "=" + FeedItem.NEW;
+ } else if(counter == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) {
+ whereRead = KEY_READ + "=" + FeedItem.UNPLAYED;
+ } else {
+ return new LongIntMap(0);
+ }
+
// work around TextUtils.join wanting only boxed items
// and StringUtils.join() causing NoSuchMethodErrors on MIUI
StringBuilder builder = new StringBuilder();
@@ -1315,8 +1317,8 @@ public class PodDBAdapter {
final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count "
+ " FROM " + TABLE_NAME_FEED_ITEMS
+ " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") "
- + " AND " + KEY_READ + " = 0"
- + " GROUP BY " + KEY_FEED;
+ + " AND " + whereRead + " GROUP BY " + KEY_FEED;
+
Cursor c = db.rawQuery(query, null);
LongIntMap result = new LongIntMap(c.getCount());
if (c.moveToFirst()) {
@@ -1470,6 +1472,8 @@ public class PodDBAdapter {
*/
private static class PodDBHelper extends SQLiteOpenHelper {
+ private final static int VERSION = 17;
+
private Context context;
/**
@@ -1478,11 +1482,10 @@ public class PodDBAdapter {
* @param context Context to use
* @param name Name of the database
* @param factory to use for creating cursor objects
- * @param version number of the database
*/
public PodDBHelper(final Context context, final String name,
- final CursorFactory factory, final int version) {
- super(context, name, factory, version);
+ final CursorFactory factory) {
+ super(context, name, factory, VERSION);
this.context = context;
}
@@ -1508,7 +1511,188 @@ public class PodDBAdapter {
public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
final int newVersion) {
EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database)));
- ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion);
+ Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
+ + newVersion + ".");
+ if (oldVersion <= 1) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ + KEY_TYPE + " TEXT");
+ }
+ if (oldVersion <= 2) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ + " ADD COLUMN " + KEY_LINK + " TEXT");
+ }
+ if (oldVersion <= 3) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT");
+ }
+ if (oldVersion <= 4) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ + KEY_FEED_IDENTIFIER + " TEXT");
+ }
+ if (oldVersion <= 5) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ + " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ + " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT");
+ }
+ if (oldVersion <= 6) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ + " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER");
+ }
+ if (oldVersion <= 7) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_PLAYBACK_COMPLETION_DATE
+ + " INTEGER");
+ }
+ if (oldVersion <= 8) {
+ final int KEY_ID_POSITION = 0;
+ final int KEY_MEDIA_POSITION = 1;
+
+ // Add feeditem column to feedmedia table
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_FEEDITEM
+ + " INTEGER");
+ Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
+ new String[]{KEY_ID, KEY_MEDIA}, "? > 0",
+ new String[]{KEY_MEDIA}, null, null, null);
+ if (feeditemCursor.moveToFirst()) {
+ db.beginTransaction();
+ ContentValues contentValues = new ContentValues();
+ do {
+ long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
+ contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
+ db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
+ contentValues.clear();
+ } while (feeditemCursor.moveToNext());
+ db.setTransactionSuccessful();
+ db.endTransaction();
+ }
+ feeditemCursor.close();
+ }
+ if (oldVersion <= 9) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_AUTO_DOWNLOAD
+ + " INTEGER DEFAULT 1");
+ }
+ if (oldVersion <= 10) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_FLATTR_STATUS
+ + " INTEGER");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_FLATTR_STATUS
+ + " INTEGER");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_PLAYED_DURATION
+ + " INTEGER");
+ }
+ if (oldVersion <= 11) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_USERNAME
+ + " TEXT");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_PASSWORD
+ + " TEXT");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_IMAGE
+ + " INTEGER");
+ }
+ if (oldVersion <= 12) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_IS_PAGED + " INTEGER DEFAULT 0");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_NEXT_PAGE_LINK + " TEXT");
+ }
+ if (oldVersion <= 13) {
+ // remove duplicate rows in "Chapters" table that were created because of a bug.
+ db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
+ "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
+ PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
+ KEY_ID,
+ KEY_ID,
+ KEY_ID,
+ PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
+ KEY_TITLE,
+ KEY_START,
+ KEY_FEEDITEM,
+ KEY_LINK,
+ KEY_CHAPTER_TYPE));
+ }
+ if(oldVersion <= 14) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER");
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " SET " + KEY_AUTO_DOWNLOAD + " = "
+ + "(SELECT " + KEY_AUTO_DOWNLOAD
+ + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + KEY_ID
+ + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ")");
+
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_HIDE + " TEXT");
+
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
+
+ // create indexes
+ db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
+ }
+ if(oldVersion <= 15) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
+ + " WHERE " + KEY_DOWNLOADED + "=0");
+ Cursor c = db.rawQuery("SELECT " + KEY_FILE_URL
+ + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " WHERE " + KEY_DOWNLOADED + "=1 "
+ + " AND " + KEY_HAS_EMBEDDED_PICTURE + "=-1", null);
+ if(c.moveToFirst()) {
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever();
+ do {
+ String fileUrl = c.getString(0);
+ try {
+ mmr.setDataSource(fileUrl);
+ byte[] image = mmr.getEmbeddedPicture();
+ if (image != null) {
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=1"
+ + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'");
+ } else {
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
+ + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'");
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ } while(c.moveToNext());
+ }
+ c.close();
+ }
+ if(oldVersion <= 16) {
+ String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID
+ + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON "
+ + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
+ + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON "
+ + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
+ + " WHERE "
+ + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
+ + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
+ + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
+ + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
+ String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " SET " + KEY_READ + "=" + FeedItem.NEW
+ + " WHERE " + KEY_ID + " IN (" + selectNew + ")";
+ Log.d("Migration", "SQL: " + sql);
+ db.execSQL(sql);
+ }
EventBus.getDefault().post(ProgressEvent.end());
}
}
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index afcb31078..5fe5f24e8 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -126,6 +126,28 @@
<item>@string/add_feed_label</item>
</string-array>
+ <string-array name="nav_drawer_feed_order_options">
+ <item>@string/drawer_feed_order_unplayed_episodes</item>
+ <item>@string/drawer_feed_order_alphabetical</item>
+ </string-array>
+ <string-array name="nav_drawer_feed_order_values">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+
+ <string-array name="nav_drawer_feed_counter_options">
+ <item>@string/drawer_feed_counter_new_unplayed</item>
+ <item>@string/drawer_feed_counter_new</item>
+ <item>@string/drawer_feed_counter_unplayed</item>
+ <item>@string/drawer_feed_counter_none</item>
+ </string-array>
+ <string-array name="nav_drawer_feed_counter_values">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+
<string-array name="episode_hide_options">
<item>@string/hide_unplayed_episodes_label</item>
<item>@string/hide_paused_episodes_label</item>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 94c02a2d2..232ba238e 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -33,6 +33,12 @@
<string name="drawer_open">Open menu</string>
<string name="drawer_close">Close menu</string>
<string name="drawer_preferences">Drawer Preferences</string>
+ <string name="drawer_feed_order_unplayed_episodes">Sort by counter</string>
+ <string name="drawer_feed_order_alphabetical">Sort alphabetically</string>
+ <string name="drawer_feed_counter_new_unplayed">Number of new and unplayed episodes</string>
+ <string name="drawer_feed_counter_new">Number of new episodes</string>
+ <string name="drawer_feed_counter_unplayed">Number of unplayed episodes</string>
+ <string name="drawer_feed_counter_none">None</string>
<!-- Webview actions -->
<string name="open_in_browser_label">Open in Browser</string>
@@ -84,6 +90,7 @@
<string name="mark_all_read_msg">Marked all Episodes as played</string>
<string name="mark_all_read_confirmation_msg">Please confirm that you want to mark all episodes as being played.</string>
<string name="mark_all_read_feed_confirmation_msg">Please confirm that you want to mark all episodes in this feed as being played.</string>
+ <string name="mark_all_seen_label">Mark all as seen</string>
<string name="show_info_label">Show information</string>
<string name="remove_feed_label">Remove Podcast</string>
<string name="share_label">Share...</string>
@@ -279,8 +286,14 @@
<string name="pref_auto_flattr_sum">Configure automatic flattring</string>
<string name="user_interface_label">User Interface</string>
<string name="pref_set_theme_title">Select Theme</string>
- <string name="pref_nav_drawer_items_title">Change Navigation Drawer</string>
+ <string name="pref_nav_drawer_title">Customize Navigation Drawer</string>
+ <string name="pref_nav_drawer_sum">Customize the appearance of the navigation drawer.</string>
+ <string name="pref_nav_drawer_items_title">Set Navigation Drawer items</string>
<string name="pref_nav_drawer_items_sum">Change which items appear in the navigation drawer.</string>
+ <string name="pref_nav_drawer_feed_order_title">Set Subscription Order</string>
+ <string name="pref_nav_drawer_feed_order_sum">Change the order of your subscriptions</string>
+ <string name="pref_nav_drawer_feed_counter_title">Set Subscription Counter</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Change the information displayed by the subscription counter</string>
<string name="pref_set_theme_sum">Change the appearance of AntennaPod.</string>
<string name="pref_automatic_download_title">Automatic Download</string>
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>