summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java351
1 files changed, 159 insertions, 192 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
index 0ac33f8fb..cf159b4a1 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -1,14 +1,17 @@
package de.danoeh.antennapod.fragment;
-import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
+import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -22,22 +25,21 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
-import com.mobeta.android.dslv.DragSortListView;
-
+import java.util.Collections;
import java.util.List;
-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.QueueListAdapter;
+import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.FeedItemEvent;
+import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
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.event.QueueEvent;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
@@ -47,12 +49,13 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.IntList;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.QueueSorter;
-import de.danoeh.antennapod.core.util.gui.FeedItemUndoToken;
-import de.danoeh.antennapod.core.util.gui.UndoBarController;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
+import de.danoeh.antennapod.view.DividerItemDecoration;
import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
@@ -71,28 +74,22 @@ public class QueueFragment extends Fragment {
EventDistributor.PLAYER_STATUS_UPDATE;
private TextView infoBar;
- private DragSortListView listView;
- private QueueListAdapter listAdapter;
+ private RecyclerView recyclerView;
+ private QueueRecyclerAdapter recyclerAdapter;
private TextView txtvEmpty;
private ProgressBar progLoading;
private ContextMenu contextMenu;
private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
- private UndoBarController<FeedItemUndoToken> undoBarController;
-
private List<FeedItem> queue;
private List<Downloader> downloaderList;
- private boolean itemsLoaded = false;
- private boolean viewsCreated = false;
private boolean isUpdatingFeeds = false;
private static final String PREFS = "QueueFragment";
- private static final String PREF_KEY_LIST_TOP = "list_top";
- private static final String PREF_KEY_LIST_SELECTION = "list_selection";
-
- private AtomicReference<Activity> activity = new AtomicReference<Activity>();
+ private static final String PREF_SCROLL_POSITION = "scroll_position";
+ private static final String PREF_SCROLL_OFFSET = "scroll_offset";
private DownloadObserver downloadObserver = null;
@@ -102,6 +99,8 @@ public class QueueFragment extends Fragment {
private boolean blockDownloadObserverUpdate = false;
private Subscription subscription;
+ private LinearLayoutManager layoutManager;
+ private ItemTouchHelper itemTouchHelper;
@Override
@@ -115,19 +114,18 @@ public class QueueFragment extends Fragment {
public void onResume() {
super.onResume();
loadItems();
+ EventDistributor.getInstance().register(contentUpdate);
+ EventBus.getDefault().register(this);
}
@Override
public void onStart() {
super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- EventBus.getDefault().register(this);
- this.activity.set((MainActivity) getActivity());
if (downloadObserver != null) {
downloadObserver.setActivity(getActivity());
downloadObserver.onResume();
}
- if (viewsCreated && itemsLoaded) {
+ if (queue != null) {
onFragmentLoaded();
}
}
@@ -136,66 +134,90 @@ public class QueueFragment extends Fragment {
public void onPause() {
super.onPause();
saveScrollPosition();
- }
-
- @Override
- public void onStop() {
- super.onStop();
EventDistributor.getInstance().unregister(contentUpdate);
EventBus.getDefault().unregister(this);
if(subscription != null) {
subscription.unsubscribe();
}
- if(undoBarController.isShowing()) {
- undoBarController.close();
- }
}
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity.set((MainActivity) activity);
+ public void onEventMainThread(QueueEvent event) {
+ Log.d(TAG, "onEvent(" + event + ")");
+ switch(event.action) {
+ case ADDED:
+ queue.add(event.position, event.item);
+ recyclerAdapter.notifyItemInserted(event.position);
+ break;
+ case SET_QUEUE:
+ queue = event.items;
+ recyclerAdapter.notifyDataSetChanged();
+ break;
+ case REMOVED:
+ int position = FeedItemUtil.indexOfItemWithId(queue, event.item.getId());
+ queue.remove(position);
+ recyclerAdapter.notifyItemRemoved(position);
+ break;
+ case CLEARED:
+ queue.clear();
+ recyclerAdapter.notifyDataSetChanged();
+ break;
+ case SORTED:
+ queue = event.items;
+ recyclerAdapter.notifyDataSetChanged();
+ break;
+ case MOVED:
+ // ItemTouchHelper already handled everything
+ break;
+ }
}
- public void onEventMainThread(QueueEvent event) {
+ public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
- if(event.action == QueueEvent.Action.REMOVED) {
- undoBarController.showUndoBar(false, getString(R.string.removed_from_queue),
- new FeedItemUndoToken(event.item, event.position));
+ IntList positions = new IntList();
+ for(int i=0, size = event.items.size(); i < size; i++) {
+ FeedItem item = event.items.get(i);
+ int pos = FeedItemUtil.indexOfItemWithId(queue, item.getId());
+ if(pos >= 0) {
+ queue.remove(pos);
+ queue.add(pos, item);
+ recyclerAdapter.notifyItemChanged(pos);
+ }
}
- loadItems();
}
private void saveScrollPosition() {
+ int firstItem = layoutManager.findFirstVisibleItemPosition();
+ View firstItemView = layoutManager.findViewByPosition(firstItem);
+ float topOffset;
+ if(firstItemView == null) {
+ topOffset = 0;
+ } else {
+ topOffset = firstItemView.getTop();
+ }
+
SharedPreferences prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
- View v = listView.getChildAt(0);
- int top = (v == null) ? 0 : (v.getTop() - listView.getPaddingTop());
- editor.putInt(PREF_KEY_LIST_SELECTION, listView.getFirstVisiblePosition());
- editor.putInt(PREF_KEY_LIST_TOP, top);
+ editor.putInt(PREF_SCROLL_POSITION, firstItem);
+ editor.putFloat(PREF_SCROLL_OFFSET, topOffset);
editor.commit();
}
private void restoreScrollPosition() {
SharedPreferences prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
- int listSelection = prefs.getInt(PREF_KEY_LIST_SELECTION, 0);
- int top = prefs.getInt(PREF_KEY_LIST_TOP, 0);
- if(listSelection > 0 || top > 0) {
- listView.setSelectionFromTop(listSelection, top);
+ int position = prefs.getInt(PREF_SCROLL_POSITION, 0);
+ float offset = prefs.getFloat(PREF_SCROLL_OFFSET, 0.0f);
+ if (position > 0 || offset > 0) {
+ layoutManager.scrollToPositionWithOffset(position, (int) offset);
// restore once, then forget
SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_KEY_LIST_SELECTION, 0);
- editor.putInt(PREF_KEY_LIST_TOP, 0);
+ editor.putInt(PREF_SCROLL_POSITION, 0);
+ editor.putFloat(PREF_SCROLL_OFFSET, 0.0f);
editor.commit();
}
}
private void resetViewState() {
- unregisterForContextMenu(listView);
- listAdapter = null;
- activity.set(null);
- undoBarController = null;
- viewsCreated = false;
+ unregisterForContextMenu(recyclerView);
blockDownloadObserverUpdate = false;
if (downloadObserver != null) {
downloadObserver.onPause();
@@ -208,17 +230,14 @@ public class QueueFragment extends Fragment {
resetViewState();
}
- private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = new MenuItemUtils.UpdateRefreshMenuItemChecker() {
- @Override
- public boolean isRefreshing() {
- return DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
- }
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = () -> {
+ return DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
};
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
- if (itemsLoaded) {
+ if (queue != null) {
inflater.inflate(R.menu.queue, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
@@ -251,14 +270,9 @@ public class QueueFragment extends Fragment {
switch (item.getItemId()) {
case R.id.queue_lock:
boolean locked = !UserPreferences.isQueueLocked();
- if(locked) {
- listView.setDragEnabled(false);
- } else {
- listView.setDragEnabled(true);
- }
UserPreferences.setQueueLocked(locked);
getActivity().supportInvalidateOptionsMenu();
- listAdapter.setLocked(locked);
+ recyclerAdapter.setLocked(locked);
return true;
case R.id.refresh_item:
List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
@@ -322,28 +336,6 @@ public class QueueFragment extends Fragment {
};
@Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItem item = itemAccess.getItem(adapterInfo.position);
-
- MenuInflater inflater = getActivity().getMenuInflater();
- inflater.inflate(R.menu.queue_context, menu);
-
- if (item != null) {
- menu.setHeaderTitle(item.getTitle());
- }
-
- contextMenu = menu;
- lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- LongList queueIds = new LongList(queue.size());
- for(FeedItem queueItem : queue) {
- queueIds.add(queueItem.getId());
- }
- FeedItemMenuHandler.onPrepareMenu(getActivity(), contextMenuInterface, item, true, queueIds);
- }
-
- @Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
if(menuInfo == null) {
@@ -373,112 +365,86 @@ public class QueueFragment extends Fragment {
View root = inflater.inflate(R.layout.queue_fragment, container, false);
infoBar = (TextView) root.findViewById(R.id.info_bar);
- listView = (DragSortListView) root.findViewById(android.R.id.list);
- txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
- progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
- listView.setEmptyView(txtvEmpty);
+ recyclerView = (RecyclerView) root.findViewById(R.id.recyclerView);
+ layoutManager = new LinearLayoutManager(getActivity());
+ recyclerView.setLayoutManager(layoutManager);
+ RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(getActivity(), null);
+ recyclerView.addItemDecoration(itemDecoration);
+ recyclerView.setHasFixedSize(true);
- if(UserPreferences.isQueueLocked()) {
- listView.setDragEnabled(false);
- } else {
- listView.setDragEnabled(true);
- }
+ itemTouchHelper = new ItemTouchHelper(
+ new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT) {
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- FeedItem item = (FeedItem) listAdapter.getItem(position - listView.getHeaderViewsCount());
- if (item != null) {
- ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
- }
- }
- });
-
- listView.setDragSortListener(new DragSortListView.DragSortListener() {
- @Override
- public void drag(int from, int to) {
- Log.d(TAG, "drag");
- blockDownloadObserverUpdate = true;
- }
-
- @Override
- public void drop(int from, int to) {
- Log.d(TAG, "drop");
- blockDownloadObserverUpdate = false;
- if(subscription != null) {
- subscription.unsubscribe();
+ @Override
+ public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
+ int from = viewHolder.getAdapterPosition();
+ int to = target.getAdapterPosition();
+ Log.d(TAG, "move(" + from + ", " + to + ")");
+ Collections.swap(queue, from, to);
+ recyclerAdapter.notifyItemMoved(from, to);
+ DBWriter.moveQueueItem(from, to, true);
+ return true;
}
- final FeedItem item = queue.remove(from);
- queue.add(to, item);
- listAdapter.notifyDataSetChanged();
- DBWriter.moveQueueItem(from, to, true);
- }
- @Override
- public void remove(int which) {
- Log.d(TAG, "remove(" + which + ")");
- if(subscription != null) {
- subscription.unsubscribe();
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ final int position = viewHolder.getAdapterPosition();
+ Log.d(TAG, "remove(" + position + ")");
+ final FeedItem item = queue.get(position);
+ final boolean isRead = item.isPlayed();
+ DBWriter.markItemPlayed(FeedItem.PLAYED, item.getId());
+ DBWriter.removeQueueItem(getActivity(), item, true);
+ Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label), Snackbar.LENGTH_LONG);
+ snackbar.setAction(getString(R.string.undo), v -> {
+ DBWriter.addQueueItemAt(getActivity(), item.getId(), position, false);
+ if(false == isRead) {
+ DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
+ }
+ });
+ snackbar.show();
}
- FeedItem item = (FeedItem) listView.getAdapter().getItem(which);
- DBWriter.removeQueueItem(getActivity(), item, true);
- }
- });
-
- undoBarController = new UndoBarController<FeedItemUndoToken>(root.findViewById(R.id.undobar),
- new UndoBarController.UndoListener<FeedItemUndoToken>() {
- private final Context context = getActivity();
-
- @Override
- public void onUndo(FeedItemUndoToken token) {
- if (token != null) {
- long itemId = token.getFeedItemId();
- int position = token.getPosition();
- DBWriter.addQueueItemAt(context, itemId, position, false);
+ @Override
+ public boolean isLongPressDragEnabled() {
+ return false == UserPreferences.isQueueLocked();
}
- }
- @Override
- public void onHide(FeedItemUndoToken token) {
- if (token != null && context != null) {
- long itemId = token.getFeedItemId();
- FeedItem item = DBReader.getFeedItem(itemId);
- if(item != null) {
- FeedMedia media = item.getMedia();
- if (media != null && media.hasAlmostEnded() && item.getFeed().getPreferences().getCurrentAutoDelete()) {
- DBWriter.deleteFeedMediaOfItem(context, media.getId());
- }
- }
+ @Override
+ public boolean isItemViewSwipeEnabled() {
+ return false == UserPreferences.isQueueLocked();
}
}
+ );
+ itemTouchHelper.attachToRecyclerView(recyclerView);
- });
-
- registerForContextMenu(listView);
-
- if (!itemsLoaded) {
- progLoading.setVisibility(View.VISIBLE);
- txtvEmpty.setVisibility(View.GONE);
- }
-
- viewsCreated = true;
-
- if (itemsLoaded && activity.get() != null) {
- onFragmentLoaded();
- }
+ txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
+ txtvEmpty.setVisibility(View.GONE);
+ progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
+ progLoading.setVisibility(View.VISIBLE);
return root;
}
private void onFragmentLoaded() {
- if (listAdapter == null) {
- listAdapter = new QueueListAdapter(activity.get(), itemAccess, new DefaultActionButtonCallback(activity.get()));
- listView.setAdapter(listAdapter);
- downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
+ if (recyclerAdapter == null) {
+ MainActivity activity = (MainActivity) getActivity();
+ recyclerAdapter = new QueueRecyclerAdapter(activity, itemAccess,
+ new DefaultActionButtonCallback(activity), itemTouchHelper);
+ recyclerView.setAdapter(recyclerAdapter);
+ downloadObserver = new DownloadObserver(activity, new Handler(), downloadObserverCallback);
downloadObserver.onResume();
}
- listAdapter.notifyDataSetChanged();
+ if(queue == null || queue.size() == 0) {
+ recyclerView.setVisibility(View.GONE);
+ txtvEmpty.setVisibility(View.VISIBLE);
+ } else {
+ txtvEmpty.setVisibility(View.GONE);
+ recyclerView.setVisibility(View.VISIBLE);
+ }
+ recyclerAdapter.notifyDataSetChanged();
restoreScrollPosition();
@@ -505,21 +471,21 @@ public class QueueFragment extends Fragment {
@Override
public void onContentChanged(List<Downloader> downloaderList) {
QueueFragment.this.downloaderList = downloaderList;
- if (listAdapter != null && !blockDownloadObserverUpdate) {
- listAdapter.notifyDataSetChanged();
+ if (recyclerAdapter != null && !blockDownloadObserverUpdate) {
+ recyclerAdapter.notifyDataSetChanged();
}
}
};
- private QueueListAdapter.ItemAccess itemAccess = new QueueListAdapter.ItemAccess() {
+ private QueueRecyclerAdapter.ItemAccess itemAccess = new QueueRecyclerAdapter.ItemAccess() {
@Override
public int getCount() {
- return (itemsLoaded) ? queue.size() : 0;
+ return queue != null ? queue.size() : 0;
}
@Override
public FeedItem getItem(int position) {
- return (itemsLoaded) ? queue.get(position) : null;
+ return queue != null ? queue.get(position) : null;
}
@Override
@@ -561,6 +527,11 @@ public class QueueFragment extends Fragment {
}
return 0;
}
+
+ @Override
+ public LongList getQueueIds() {
+ return queue != null ? LongList.of(FeedItemUtil.getIds(queue)) : new LongList(0);
+ }
};
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@@ -579,23 +550,19 @@ public class QueueFragment extends Fragment {
if(subscription != null) {
subscription.unsubscribe();
}
- if (viewsCreated && !itemsLoaded) {
- listView.setVisibility(View.GONE);
+ if (queue == null) {
+ recyclerView.setVisibility(View.GONE);
txtvEmpty.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
subscription = Observable.defer(() -> Observable.just(DBReader.getQueue()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> {
- listView.setVisibility(View.VISIBLE);
- progLoading.setVisibility(View.GONE);
- if(result != null) {
- queue = result;
- itemsLoaded = true;
- if (viewsCreated && activity.get() != null) {
- onFragmentLoaded();
- }
+ .subscribe(items -> {
+ if(items != null) {
+ progLoading.setVisibility(View.GONE);
+ queue = items;
+ onFragmentLoaded();
}
}, error -> {
Log.e(TAG, Log.getStackTraceString(error));