Redone new indicator

This commit is contained in:
Martin Fietz 2015-05-11 17:14:42 +02:00
parent c829a4e9b2
commit 4561f16f11
14 changed files with 132 additions and 64 deletions

View File

@ -301,7 +301,7 @@ public class DBReaderTest extends InstrumentationTestCase {
}
}
public void testGetUnreadItemIds() {
public void testGetNewItemIds() {
final Context context = getInstrumentation().getTargetContext();
final int numItems = 10;
@ -310,10 +310,11 @@ public class DBReaderTest extends InstrumentationTestCase {
for (int i = 0; i < unread.size(); i++) {
unreadIds[i] = unread.get(i).getId();
}
long[] unreadSaved = DBReader.getUnreadItemIds(context);
LongList unreadSaved = DBReader.getNewItemIds(context);
assertNotNull(unreadSaved);
assertTrue(unread.size() == unreadSaved.length);
for (long savedId : unreadSaved) {
assertTrue(unread.size() == unreadSaved.size());
for(int i=0; i < unreadSaved.size(); i++) {
long savedId = unreadSaved.get(i);
boolean found = false;
for (long id : unreadIds) {
if (id == savedId) {

View File

@ -22,19 +22,22 @@ import de.danoeh.antennapod.core.util.Converter;
/**
* List adapter for the list of new episodes
*/
public class NewEpisodesListAdapter extends BaseAdapter {
public class AllEpisodesListAdapter extends BaseAdapter {
private final Context context;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
private final boolean showOnlyNewEpisodes;
public NewEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) {
public AllEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback,
boolean showOnlyNewEpisodes) {
super();
this.context = context;
this.itemAccess = itemAccess;
this.actionButtonUtils = new ActionButtonUtils(context);
this.actionButtonCallback = actionButtonCallback;
this.showOnlyNewEpisodes = showOnlyNewEpisodes;
}
@Override
@ -88,7 +91,7 @@ public class NewEpisodesListAdapter extends BaseAdapter {
holder.title.setText(item.getTitle());
holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
if (item.isRead()) {
if (showOnlyNewEpisodes || item.isRead() || false == itemAccess.isNew(item)) {
holder.statusUnread.setVisibility(View.INVISIBLE);
} else {
holder.statusUnread.setVisibility(View.VISIBLE);
@ -175,5 +178,8 @@ public class NewEpisodesListAdapter extends BaseAdapter {
int getItemDownloadProgressPercent(FeedItem item);
boolean isInQueue(FeedItem item);
boolean isNew(FeedItem item);
}
}

View File

@ -110,7 +110,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
holder.title.setText(buffer.toString());
if(item.isRead()) {
if(false == item.isRead() && itemAccess.isNew(item)) {
holder.statusUnread.setVisibility(View.VISIBLE);
} else {
holder.statusUnread.setVisibility(View.INVISIBLE);
}
@ -214,6 +216,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
FeedItem getItem(int position);
boolean isNew(FeedItem item);
}
}

View File

@ -142,6 +142,12 @@ public class StorageCallbacksImpl implements StorageCallbacks {
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);
}
}
}

View File

@ -29,7 +29,7 @@ import java.util.concurrent.atomic.AtomicReference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.NewEpisodesListAdapter;
import de.danoeh.antennapod.adapter.AllEpisodesListAdapter;
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.feed.EventDistributor;
@ -64,12 +64,13 @@ public class AllEpisodesFragment extends Fragment {
private String prefName;
protected DragSortListView listView;
private NewEpisodesListAdapter listAdapter;
private AllEpisodesListAdapter listAdapter;
private TextView txtvEmpty;
private ProgressBar progLoading;
private List<FeedItem> episodes;
private LongList queueAccess;
private LongList queuedItemsIds;
private LongList newItemsIds;
private List<Downloader> downloaderList;
private boolean itemsLoaded = false;
@ -308,7 +309,8 @@ public class AllEpisodesFragment extends Fragment {
private void onFragmentLoaded() {
if (listAdapter == null) {
listAdapter = new NewEpisodesListAdapter(activity.get(), itemAccess, new DefaultActionButtonCallback(activity.get()));
listAdapter = new AllEpisodesListAdapter(activity.get(), itemAccess,
new DefaultActionButtonCallback(activity.get()), showOnlyNewEpisodes);
listView.setAdapter(listAdapter);
listView.setEmptyView(txtvEmpty);
downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
@ -337,7 +339,7 @@ public class AllEpisodesFragment extends Fragment {
}
};
private NewEpisodesListAdapter.ItemAccess itemAccess = new NewEpisodesListAdapter.ItemAccess() {
private AllEpisodesListAdapter.ItemAccess itemAccess = new AllEpisodesListAdapter.ItemAccess() {
@Override
public int getCount() {
@ -371,7 +373,17 @@ public class AllEpisodesFragment extends Fragment {
@Override
public boolean isInQueue(FeedItem item) {
if (itemsLoaded) {
return queueAccess.contains(item.getId());
return queuedItemsIds.contains(item.getId());
} else {
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;
}
@ -436,12 +448,14 @@ public class AllEpisodesFragment extends Fragment {
if(showOnlyNewEpisodes) {
return new Object[] {
DBReader.getNewItemsList(context),
DBReader.getQueueIDList(context)
DBReader.getQueueIDList(context),
null // see ItemAccess.isNew
};
} else {
return new Object[]{
DBReader.getRecentlyPublishedEpisodes(context, RECENT_EPISODES_LIMIT),
DBReader.getQueueIDList(context)
DBReader.getQueueIDList(context),
DBReader.getNewItemIds(context)
};
}
} else {
@ -457,7 +471,8 @@ public class AllEpisodesFragment extends Fragment {
if (lists != null) {
episodes = (List<FeedItem>) lists[0];
queueAccess = (LongList) lists[1];
queuedItemsIds = (LongList) lists[1];
newItemsIds = (LongList) lists[2];
itemsLoaded = true;
if (viewsCreated && activity.get() != null) {
onFragmentLoaded();

View File

@ -9,8 +9,8 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ListFragment;
import android.support.v4.util.Pair;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.util.Log;
@ -85,7 +85,9 @@ public class ItemlistFragment extends ListFragment {
private long feedID;
private Feed feed;
private LongList queue;
private LongList queuedItemsIds;
private LongList newItemsIds;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
@ -299,7 +301,7 @@ public class ItemlistFragment extends ListFragment {
}
contextMenu = menu;
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, false, queue);
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, false, queuedItemsIds);
}
@Override
@ -547,7 +549,12 @@ public class ItemlistFragment extends ListFragment {
@Override
public boolean isInQueue(FeedItem item) {
return (queue != null) && queue.contains(item.getId());
return (queuedItemsIds != null) && queuedItemsIds.contains(item.getId());
}
@Override
public boolean isNew(FeedItem item) {
return (newItemsIds != null) && newItemsIds.contains(item.getId());
}
@Override
@ -580,9 +587,9 @@ public class ItemlistFragment extends ListFragment {
}
}
private class ItemLoader extends AsyncTask<Long, Void, Pair<Feed,LongList>> {
private class ItemLoader extends AsyncTask<Long, Void, Object[]> {
@Override
protected Pair<Feed,LongList> doInBackground(Long... params) {
protected Object[] doInBackground(Long... params) {
long feedID = params[0];
Context context = getActivity();
if (context != null) {
@ -591,19 +598,21 @@ public class ItemlistFragment extends ListFragment {
FeedItemFilter filter = feed.getItemFilter();
feed.setItems(filter.filter(context, feed.getItems()));
}
LongList queue = DBReader.getQueueIDList(context);
return Pair.create(feed, queue);
LongList queuedItemsIds = DBReader.getQueueIDList(context);
LongList newItemsIds = DBReader.getNewItemIds(context);
return new Object[] { feed, queuedItemsIds, newItemsIds };
} else {
return null;
}
}
@Override
protected void onPostExecute(Pair<Feed,LongList> res) {
protected void onPostExecute(Object[] res) {
super.onPostExecute(res);
if (res != null) {
feed = res.first;
queue = res.second;
feed = (Feed) res[0];
queuedItemsIds = (LongList) res[1];
newItemsIds = res[2] == null ? null : (LongList) res[2];
itemsLoaded = true;
if (viewsCreated) {
onFragmentLoaded();

View File

@ -225,6 +225,11 @@ public class PlaybackHistoryFragment extends ListFragment {
return (queue != null) ? queue.contains(item.getId()) : false;
}
@Override
public boolean isNew(FeedItem item) {
return false;
}
@Override
public int getItemDownloadProgressPercent(FeedItem item) {
if (downloaderList != null) {

View File

@ -88,7 +88,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.share_link_item, false);
}
if (!(state == FeedItem.State.NEW || state == FeedItem.State.IN_PROGRESS)) {
if (!(state == FeedItem.State.UNREAD || state == FeedItem.State.IN_PROGRESS)) {
mi.setItemVisibility(R.id.mark_read_item, false);
}
if (!(state == FeedItem.State.IN_PROGRESS || state == FeedItem.State.READ)) {

View File

@ -179,7 +179,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
*/
public boolean hasNewItems(boolean enableEpisodeFilter) {
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (item.getState() == FeedItem.State.UNREAD) {
if (item.getMedia() != null) {
return true;
}

View File

@ -239,7 +239,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
}
public boolean isRead() {
return read || isInProgress();
return read;
}
public void setRead(boolean read) {
@ -330,7 +330,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
}
public enum State {
NEW, IN_PROGRESS, READ, PLAYING
UNREAD, IN_PROGRESS, READ, PLAYING
}
public State getState() {
@ -342,7 +342,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
return State.IN_PROGRESS;
}
}
return (isRead() ? State.READ : State.NEW);
return (isRead() ? State.READ : State.UNREAD);
}
public long getFeedId() {

View File

@ -178,8 +178,7 @@ public final class DBReader {
*/
public static List<FeedItem> getFeedItemList(Context context,
final Feed feed) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Extracting Feeditems of feed " + feed.getTitle());
Log.d(TAG, "Extracting Feeditems of feed " + feed.getTitle());
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
@ -319,7 +318,7 @@ public final class DBReader {
new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS)),
cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_IS_PAGED) > 0,
cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_NEXT_PAGE_LINK),
cursor.getString(cursor.getColumnIndex(PodDBAdapter.KEY_HIDE))
cursor.getString(cursor.getColumnIndex(PodDBAdapter.KEY_HIDE)),
cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_LAST_UPDATE_FAILED) > 0
);
@ -521,15 +520,16 @@ public final class DBReader {
* @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred
* over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used.
*/
public static long[] getUnreadItemIds(Context context) {
public static LongList getNewItemIds(Context context) {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
Cursor cursor = adapter.getUnreadItemIdsCursor();
long[] itemIds = new long[cursor.getCount()];
Cursor cursor = adapter.getNewItemIdsCursor();
LongList itemIds = new LongList(cursor.getCount());
int i = 0;
if (cursor.moveToFirst()) {
do {
itemIds[i] = cursor.getLong(PodDBAdapter.KEY_ID_INDEX);
long id = cursor.getLong(PodDBAdapter.KEY_ID_INDEX);
itemIds.add(id);
i++;
} while (cursor.moveToNext());
}

View File

@ -455,14 +455,6 @@ public final class DBTasks {
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter(context));
}
/**
* Adds all FeedItem objects whose 'read'-attribute is false to the queue in a separate thread.
*/
public static void enqueueAllNewItems(final Context context) {
long[] unreadItems = DBReader.getUnreadItemIds(context);
DBWriter.addQueueItem(context, unreadItems);
}
/**
* Returns the successor of a FeedItem in the queue.
*

View File

@ -408,16 +408,11 @@ public class DBWriter {
if(addToFront){
queue.add(0, item);
}else{
} else {
queue.add(item);
}
queueModified = true;
if (!item.isRead()) {
item.setRead(true);
itemsToSave.add(item);
unreadItemsModified = true;
}
}
}
}
@ -425,11 +420,6 @@ public class DBWriter {
adapter.setQueue(queue);
EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue));
}
if (unreadItemsModified) {
adapter.setFeedItemlist(itemsToSave);
EventDistributor.getInstance()
.sendUnreadItemsUpdateBroadcast();
}
}
adapter.close();
DBTasks.autodownloadUndownloadedItems(context);

View File

@ -227,6 +227,28 @@ public class PodDBAdapter {
+ " TEXT," + KEY_START + " INTEGER," + KEY_FEEDITEM + " INTEGER,"
+ KEY_LINK + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)";
// SQL Statements for creating indexes
public static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_FEED + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_FEED + ")";
public static final String CREATE_INDEX_FEEDITEMS_IMAGE = "CREATE INDEX "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_IMAGE + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_IMAGE + ")";
public static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " ("
+ KEY_FEEDITEM + ")";
public static final String CREATE_INDEX_FEEDMEDIA_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_FEED_MEDIA + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_FEED_MEDIA + " ("
+ KEY_FEEDITEM + ")";
public static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_SIMPLECHAPTERS + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_SIMPLECHAPTERS + " ("
+ KEY_FEEDITEM + ")";
private SQLiteDatabase db;
private final Context context;
private PodDBHelper helper;
@ -1063,10 +1085,21 @@ public class PodDBAdapter {
return c;
}
public final Cursor getUnreadItemIdsCursor() {
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, new String[]{KEY_ID},
KEY_READ + "=0", null, null, null, KEY_PUBDATE + " DESC");
return c;
public final Cursor getNewItemIdsCursor() {
final String query = "SELECT " + TABLE_NAME_FEED_ITEMS + "." + 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
return db.rawQuery(query, null);
}
/**
@ -1085,7 +1118,8 @@ public class PodDBAdapter {
+ 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
+ TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL" // not in queue
+ " ORDER BY " + KEY_PUBDATE + " DESC";
Cursor c = db.rawQuery(query, null);
return c;
}
@ -1425,6 +1459,12 @@ public class PodDBAdapter {
db.execSQL(CREATE_TABLE_DOWNLOAD_LOG);
db.execSQL(CREATE_TABLE_QUEUE);
db.execSQL(CREATE_TABLE_SIMPLECHAPTERS);
db.execSQL(CREATE_INDEX_FEEDITEMS_FEED);
db.execSQL(CREATE_INDEX_FEEDITEMS_IMAGE);
db.execSQL(CREATE_INDEX_FEEDMEDIA_FEEDITEM);
db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM);
db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
}
@Override