diff options
author | Tom Hennen <TomHennen@users.noreply.github.com> | 2015-07-07 18:58:41 -0400 |
---|---|---|
committer | Tom Hennen <TomHennen@users.noreply.github.com> | 2015-07-07 18:58:41 -0400 |
commit | 0d2f99a1a7a473fc6abf1b23ff8b712ab1fb7c62 (patch) | |
tree | f34ce94823ff6a7f49796dbc0cd89a93ec09766f | |
parent | 1f0a6a14bba0b4620d286d8217e53271e6edaca2 (diff) | |
parent | 9cae7c5bfbe252158ddfa6195519db2dbb0a950e (diff) | |
download | AntennaPod-0d2f99a1a7a473fc6abf1b23ff8b712ab1fb7c62.zip |
Merge pull request #994 from mfietz/redesign-new-state
Drawer: Feed context menu, counter and order
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> |