mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2024-12-26 16:52:46 +01:00
Migrated download screen to RecyclerView
This commit is contained in:
parent
7db3da273a
commit
6066fef1f2
@ -1,67 +0,0 @@
|
|||||||
package de.danoeh.antennapod.adapter;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import de.danoeh.antennapod.R;
|
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
|
||||||
import de.danoeh.antennapod.core.util.ThemeUtils;
|
|
||||||
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a list of downloaded episodes.
|
|
||||||
*/
|
|
||||||
public class DownloadedEpisodesListAdapter extends BaseAdapter {
|
|
||||||
|
|
||||||
private final MainActivity activity;
|
|
||||||
private final ItemAccess itemAccess;
|
|
||||||
|
|
||||||
public DownloadedEpisodesListAdapter(MainActivity activity, ItemAccess itemAccess) {
|
|
||||||
super();
|
|
||||||
this.activity = activity;
|
|
||||||
this.itemAccess = itemAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return itemAccess.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FeedItem getItem(int position) {
|
|
||||||
return itemAccess.getItem(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int position) {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
EpisodeItemViewHolder holder;
|
|
||||||
if (convertView == null) {
|
|
||||||
holder = new EpisodeItemViewHolder(activity, parent);
|
|
||||||
} else {
|
|
||||||
holder = (EpisodeItemViewHolder) convertView.getTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
final FeedItem item = getItem(position);
|
|
||||||
holder.bind(item);
|
|
||||||
holder.dragHandle.setVisibility(View.GONE);
|
|
||||||
holder.secondaryActionIcon.setImageResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.ic_delete));
|
|
||||||
holder.secondaryActionButton.setOnClickListener(v -> itemAccess.onFeedItemSecondaryAction(item));
|
|
||||||
holder.hideSeparatorIfNecessary();
|
|
||||||
|
|
||||||
return holder.itemView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ItemAccess {
|
|
||||||
int getCount();
|
|
||||||
|
|
||||||
FeedItem getItem(int position);
|
|
||||||
|
|
||||||
void onFeedItemSecondaryAction(FeedItem item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +1,81 @@
|
|||||||
package de.danoeh.antennapod.fragment;
|
package de.danoeh.antennapod.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.ListFragment;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ListView;
|
import android.view.ViewGroup;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import java.util.ArrayList;
|
import androidx.annotation.Nullable;
|
||||||
import java.util.List;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
import de.danoeh.antennapod.adapter.DownloadedEpisodesListAdapter;
|
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
|
||||||
|
import de.danoeh.antennapod.adapter.actionbutton.DeleteActionButton;
|
||||||
import de.danoeh.antennapod.core.event.DownloadLogEvent;
|
import de.danoeh.antennapod.core.event.DownloadLogEvent;
|
||||||
|
import de.danoeh.antennapod.core.event.FeedItemEvent;
|
||||||
|
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
|
||||||
|
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
|
||||||
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
|
||||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||||
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
|
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
|
||||||
|
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
|
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_ADD_TO_QUEUE;
|
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_ADD_TO_QUEUE;
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
|
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays all running downloads and provides a button to delete them
|
* Displays all completed downloads and provides a button to delete them.
|
||||||
*/
|
*/
|
||||||
public class CompletedDownloadsFragment extends ListFragment {
|
public class CompletedDownloadsFragment extends Fragment {
|
||||||
|
|
||||||
private static final String TAG = CompletedDownloadsFragment.class.getSimpleName();
|
private static final String TAG = CompletedDownloadsFragment.class.getSimpleName();
|
||||||
|
|
||||||
private List<FeedItem> items = new ArrayList<>();
|
private List<FeedItem> items = new ArrayList<>();
|
||||||
private DownloadedEpisodesListAdapter listAdapter;
|
private CompletedDownloadsListAdapter adapter;
|
||||||
|
private RecyclerView recyclerView;
|
||||||
private Disposable disposable;
|
private Disposable disposable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
super.onViewCreated(view, savedInstanceState);
|
@Nullable Bundle savedInstanceState) {
|
||||||
setHasOptionsMenu(true);
|
View root = inflater.inflate(R.layout.simple_list_fragment, container, false);
|
||||||
addVerticalPadding();
|
Toolbar toolbar = root.findViewById(R.id.toolbar);
|
||||||
addEmptyView();
|
toolbar.setVisibility(View.GONE);
|
||||||
|
|
||||||
listAdapter = new DownloadedEpisodesListAdapter((MainActivity) getActivity(), itemAccess);
|
recyclerView = root.findViewById(R.id.recyclerView);
|
||||||
setListAdapter(listAdapter);
|
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
|
||||||
setListShown(false);
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
recyclerView.setHasFixedSize(true);
|
||||||
|
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
|
||||||
|
recyclerView.setVisibility(View.GONE);
|
||||||
|
adapter = new CompletedDownloadsListAdapter((MainActivity) getActivity());
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
addEmptyView();
|
||||||
EventBus.getDefault().register(this);
|
EventBus.getDefault().register(this);
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -67,6 +87,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
setHasOptionsMenu(true);
|
||||||
loadItems();
|
loadItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,14 +99,6 @@ public class CompletedDownloadsFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
|
||||||
super.onListItemClick(l, v, position, id);
|
|
||||||
position -= l.getHeaderViewsCount();
|
|
||||||
long[] ids = FeedItemUtil.getIds(items);
|
|
||||||
((MainActivity) requireActivity()).loadChildFragment(ItemPagerFragment.newInstance(ids, position));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
@ -103,41 +116,66 @@ public class CompletedDownloadsFragment extends ListFragment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||||
|
FeedItem selectedItem = adapter.getSelectedItem();
|
||||||
|
if (selectedItem == null) {
|
||||||
|
Log.i(TAG, "Selected item at current position was null, ignoring selection");
|
||||||
|
return super.onContextItemSelected(item);
|
||||||
|
}
|
||||||
|
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
||||||
|
}
|
||||||
|
|
||||||
private void addEmptyView() {
|
private void addEmptyView() {
|
||||||
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
|
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
|
||||||
emptyView.setIcon(R.attr.av_download);
|
emptyView.setIcon(R.attr.av_download);
|
||||||
emptyView.setTitle(R.string.no_comp_downloads_head_label);
|
emptyView.setTitle(R.string.no_comp_downloads_head_label);
|
||||||
emptyView.setMessage(R.string.no_comp_downloads_label);
|
emptyView.setMessage(R.string.no_comp_downloads_label);
|
||||||
emptyView.attachToListView(getListView());
|
emptyView.attachToRecyclerView(recyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addVerticalPadding() {
|
|
||||||
final ListView lv = getListView();
|
|
||||||
lv.setClipToPadding(false);
|
|
||||||
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
|
|
||||||
lv.setPadding(0, vertPadding, 0, vertPadding);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
@Override
|
public void onEventMainThread(FeedItemEvent event) {
|
||||||
public int getCount() {
|
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||||
return items.size();
|
if (items == null) {
|
||||||
|
return;
|
||||||
|
} else if (adapter == null) {
|
||||||
|
loadItems();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
for (int i = 0, size = event.items.size(); i < size; i++) {
|
||||||
@Override
|
FeedItem item = event.items.get(i);
|
||||||
public FeedItem getItem(int position) {
|
int pos = FeedItemUtil.indexOfItemWithId(items, item.getId());
|
||||||
if (0 <= position && position < items.size()) {
|
if (pos >= 0) {
|
||||||
return items.get(position);
|
items.remove(pos);
|
||||||
|
if (item.getMedia().isDownloaded()) {
|
||||||
|
items.add(pos, item);
|
||||||
|
adapter.notifyItemChanged(pos);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
adapter.notifyItemRemoved(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onFeedItemSecondaryAction(FeedItem item) {
|
public void onEventMainThread(PlaybackPositionEvent event) {
|
||||||
DBWriter.deleteFeedMediaOfItem(requireActivity(), item.getMedia().getId());
|
if (adapter != null) {
|
||||||
|
for (int i = 0; i < adapter.getItemCount(); i++) {
|
||||||
|
EpisodeItemViewHolder holder = (EpisodeItemViewHolder) recyclerView.findViewHolderForAdapterPosition(i);
|
||||||
|
if (holder != null && holder.isCurrentlyPlayingItem()) {
|
||||||
|
holder.notifyPlaybackPositionUpdated(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
public void onPlayerStatusChanged(PlayerStatusEvent event) {
|
||||||
|
loadItems();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onDownloadLogChanged(DownloadLogEvent event) {
|
public void onDownloadLogChanged(DownloadLogEvent event) {
|
||||||
@ -158,13 +196,22 @@ public class CompletedDownloadsFragment extends ListFragment {
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(result -> {
|
.subscribe(result -> {
|
||||||
items = result;
|
items = result;
|
||||||
onItemsLoaded();
|
adapter.updateItems(result);
|
||||||
|
requireActivity().invalidateOptionsMenu();
|
||||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onItemsLoaded() {
|
private static class CompletedDownloadsListAdapter extends EpisodeItemListAdapter {
|
||||||
setListShown(true);
|
|
||||||
listAdapter.notifyDataSetChanged();
|
public CompletedDownloadsListAdapter(MainActivity mainActivity) {
|
||||||
requireActivity().invalidateOptionsMenu();
|
super(mainActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(EpisodeItemViewHolder holder, int pos) {
|
||||||
|
super.onBindViewHolder(holder, pos);
|
||||||
|
DeleteActionButton actionButton = new DeleteActionButton(getItem(pos));
|
||||||
|
actionButton.configure(holder.secondaryActionButton, holder.secondaryActionIcon, getActivity());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user