summaryrefslogtreecommitdiff
path: root/app/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java74
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java300
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java84
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java274
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java102
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java73
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java227
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java320
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java123
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java76
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java46
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java31
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java48
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java19
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java87
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/DownloadItemViewHolder.java41
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java213
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedComponentViewHolder.java15
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedViewHolder.java62
25 files changed, 812 insertions, 1444 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
deleted file mode 100644
index 315b3a173..000000000
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.util.Log;
-import android.view.View;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.joanzapata.iconify.Iconify;
-
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.NetworkUtils;
-
-/**
- * Utility methods for adapters
- */
-class AdapterUtils {
-
- private static final String TAG = AdapterUtils.class.getSimpleName();
-
- private AdapterUtils() {
-
- }
-
- /**
- * Updates the contents of the TextView that shows the current playback position and the ProgressBar.
- */
- static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) {
- FeedMedia media = item.getMedia();
- episodeProgress.setVisibility(View.GONE);
- if (media == null) {
- txtvPos.setVisibility(View.GONE);
- return;
- } else {
- txtvPos.setVisibility(View.VISIBLE);
- }
-
- FeedItem.State state = item.getState();
- if (state == FeedItem.State.PLAYING
- || state == FeedItem.State.IN_PROGRESS) {
- if (media.getDuration() > 0) {
- episodeProgress.setVisibility(View.VISIBLE);
- episodeProgress.setProgress((int) (((double) media
- .getPosition()) / media.getDuration() * 100));
- txtvPos.setText(Converter.getDurationStringLong(media.getDuration()
- - media.getPosition()));
- }
- } else if (!media.isDownloaded()) {
- if (media.getSize() > 0) {
- txtvPos.setText(Converter.byteToString(media.getSize()));
- } else if(NetworkUtils.isEpisodeHeadDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
- txtvPos.setText("{fa-spinner}");
- Iconify.addIcons(txtvPos);
- NetworkUtils.getFeedMediaSizeObservable(media)
- .subscribe(
- size -> {
- if (size > 0) {
- txtvPos.setText(Converter.byteToString(size));
- } else {
- txtvPos.setText("");
- }
- }, error -> {
- txtvPos.setText("");
- Log.e(TAG, Log.getStackTraceString(error));
- });
- } else {
- txtvPos.setText("");
- }
- } else {
- txtvPos.setText(Converter.getDurationStringLong(media.getDuration()));
- }
- }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
index d0e0eac9e..71c872de2 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -1,204 +1,73 @@
package de.danoeh.antennapod.adapter;
-import android.os.Build;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.ItemTouchHelper;
-import android.text.Layout;
-import android.util.Log;
import android.view.ContextMenu;
-import android.view.LayoutInflater;
import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.joanzapata.iconify.Iconify;
-
-import java.lang.ref.WeakReference;
-import java.util.List;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
-import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
-import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
-import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.core.util.NetworkUtils;
-import de.danoeh.antennapod.core.util.ThemeUtils;
-import de.danoeh.antennapod.fragment.ItemFragment;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.fragment.ItemPagerFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
/**
- * List adapter for the list of new episodes
+ * List adapter for the list of new episodes.
*/
-public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesRecycleAdapter.Holder> {
-
- private static final String TAG = AllEpisodesRecycleAdapter.class.getSimpleName();
+public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<EpisodeItemViewHolder>
+ implements View.OnCreateContextMenuListener {
private final WeakReference<MainActivity> mainActivityRef;
- private final ItemAccess itemAccess;
- private final boolean showOnlyNewEpisodes;
+ private List<FeedItem> episodes = new ArrayList<>();
private FeedItem selectedItem;
- private final int playingBackGroundColor;
- private final int normalBackGroundColor;
-
- public AllEpisodesRecycleAdapter(MainActivity mainActivity,
- ItemAccess itemAccess,
- boolean showOnlyNewEpisodes) {
+ public AllEpisodesRecycleAdapter(MainActivity mainActivity) {
super();
this.mainActivityRef = new WeakReference<>(mainActivity);
- this.itemAccess = itemAccess;
- this.showOnlyNewEpisodes = showOnlyNewEpisodes;
+ }
- playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
- normalBackGroundColor = ContextCompat.getColor(mainActivity, android.R.color.transparent);
+ public void updateItems(List<FeedItem> items) {
+ episodes = items;
+ notifyDataSetChanged();
}
+ @NonNull
@Override
- public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.new_episodes_listitem, parent, false);
- Holder holder = new Holder(view);
- holder.container = view.findViewById(R.id.container);
- holder.content = view.findViewById(R.id.content);
- holder.placeholder = view.findViewById(R.id.txtvPlaceholder);
- holder.title = view.findViewById(R.id.txtvTitle);
- if(Build.VERSION.SDK_INT >= 23) {
- holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- }
- holder.pubDate = view
- .findViewById(R.id.txtvPublished);
- holder.statusUnread = view.findViewById(R.id.statusUnread);
- holder.butSecondary = view
- .findViewById(R.id.butSecondaryAction);
- holder.queueStatus = view
- .findViewById(R.id.imgvInPlaylist);
- holder.progress = view
- .findViewById(R.id.pbar_progress);
- holder.cover = view.findViewById(R.id.imgvCover);
- holder.txtvDuration = view.findViewById(R.id.txtvDuration);
- holder.item = null;
- holder.mainActivityRef = mainActivityRef;
- // so we can grab this later
- view.setTag(holder);
-
- return holder;
+ public EpisodeItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ EpisodeItemViewHolder viewHolder = new EpisodeItemViewHolder(mainActivityRef.get(), parent);
+ viewHolder.dragHandle.setVisibility(View.GONE);
+ return viewHolder;
}
@Override
- public void onBindViewHolder(final Holder holder, int position) {
- final FeedItem item = itemAccess.getItem(position);
- if (item == null) return;
+ public void onBindViewHolder(EpisodeItemViewHolder holder, int pos) {
+ FeedItem item = episodes.get(pos);
+ holder.bind(item);
holder.itemView.setOnLongClickListener(v -> {
- this.selectedItem = item;
+ selectedItem = item;
return false;
});
- holder.item = item;
- holder.placeholder.setVisibility(View.VISIBLE);
- holder.placeholder.setText(item.getFeed().getTitle());
- holder.title.setText(item.getTitle());
- String pubDateStr = DateUtils.formatAbbrev(mainActivityRef.get(), item.getPubDate());
- holder.pubDate.setText(pubDateStr);
- if (showOnlyNewEpisodes || !item.isNew()) {
- holder.statusUnread.setVisibility(View.INVISIBLE);
- } else {
- holder.statusUnread.setVisibility(View.VISIBLE);
- }
- if(item.isPlayed()) {
- holder.content.setAlpha(0.5f);
- } else {
- holder.content.setAlpha(1.0f);
- }
-
- FeedMedia media = item.getMedia();
- if (media != null) {
- final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
-
- if (media.getDuration() > 0) {
- holder.txtvDuration.setText(Converter.getDurationStringLong(media.getDuration()));
- } else if (media.getSize() > 0) {
- holder.txtvDuration.setText(Converter.byteToString(media.getSize()));
- } else if(NetworkUtils.isEpisodeHeadDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
- holder.txtvDuration.setText("{fa-spinner}");
- Iconify.addIcons(holder.txtvDuration);
- NetworkUtils.getFeedMediaSizeObservable(media)
- .subscribe(
- size -> {
- if (size > 0) {
- holder.txtvDuration.setText(Converter.byteToString(size));
- } else {
- holder.txtvDuration.setText("");
- }
- }, error -> {
- holder.txtvDuration.setText("");
- Log.e(TAG, Log.getStackTraceString(error));
- });
- } else {
- holder.txtvDuration.setText("");
- }
-
- FeedItem.State state = item.getState();
- if (isDownloadingMedia) {
- holder.progress.setVisibility(View.VISIBLE);
- // item is being downloaded
- holder.progress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
- } else if (state == FeedItem.State.PLAYING
- || state == FeedItem.State.IN_PROGRESS) {
- if (media.getDuration() > 0) {
- int progress = (int) (100.0 * media.getPosition() / media.getDuration());
- holder.progress.setProgress(progress);
- holder.progress.setVisibility(View.VISIBLE);
- }
- } else {
- holder.progress.setVisibility(View.INVISIBLE);
+ holder.itemView.setOnClickListener(v -> {
+ MainActivity activity = mainActivityRef.get();
+ if (activity != null) {
+ long[] ids = FeedItemUtil.getIds(episodes);
+ int position = ArrayUtils.indexOf(ids, item.getId());
+ activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
}
-
- if (media.isCurrentlyPlaying()) {
- holder.container.setBackgroundColor(playingBackGroundColor);
- } else {
- holder.container.setBackgroundColor(normalBackGroundColor);
- }
- } else {
- holder.progress.setVisibility(View.INVISIBLE);
- holder.txtvDuration.setVisibility(View.GONE);
- }
-
- boolean isInQueue = itemAccess.isInQueue(item);
- if (isInQueue) {
- holder.queueStatus.setVisibility(View.VISIBLE);
- } else {
- holder.queueStatus.setVisibility(View.INVISIBLE);
- }
-
- ItemActionButton actionButton = ItemActionButton.forItem(item, isInQueue, true);
- actionButton.configure(holder.butSecondary, mainActivityRef.get());
-
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(item);
-
- new CoverLoader(mainActivityRef.get())
- .withUri(ImageResourceUtils.getImageLocation(item))
- .withFallbackUri(item.getFeed().getImageLocation())
- .withPlaceholderView(holder.placeholder)
- .withCoverView(holder.cover)
- .load();
+ });
+ holder.itemView.setOnCreateContextMenuListener(this);
+ holder.hideSeparatorIfNecessary();
}
@Nullable
@@ -208,98 +77,21 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
@Override
public long getItemId(int position) {
- FeedItem item = itemAccess.getItem(position);
+ FeedItem item = episodes.get(position);
return item != null ? item.getId() : RecyclerView.NO_POSITION;
}
@Override
public int getItemCount() {
- return itemAccess.getCount();
+ return episodes.size();
}
- public class Holder extends RecyclerView.ViewHolder
- implements View.OnClickListener,
- View.OnCreateContextMenuListener,
- ItemTouchHelperViewHolder {
- LinearLayout content;
- FrameLayout container;
- TextView placeholder;
- TextView title;
- TextView pubDate;
- View statusUnread;
- ImageView queueStatus;
- ImageView cover;
- ProgressBar progress;
- TextView txtvDuration;
- ImageButton butSecondary;
- FeedItem item;
- WeakReference<MainActivity> mainActivityRef;
-
- public Holder(View itemView) {
- super(itemView);
- itemView.setOnClickListener(this);
- itemView.setOnCreateContextMenuListener(this);
- }
-
- @Override
- public void onClick(View v) {
- MainActivity mainActivity = mainActivityRef.get();
- if (mainActivity != null) {
- LongList itemIds = itemAccess.getItemsIds();
- long[] ids = itemIds.toArray();
- mainActivity.loadChildFragment(ItemPagerFragment.newInstance(ids, itemIds.indexOf(item.getId())));
- }
- }
-
- @Override
- public void onItemSelected() {
- itemView.setAlpha(0.5f);
- }
-
- @Override
- public void onItemClear() {
- itemView.setAlpha(1.0f);
- }
-
- public FeedItem getFeedItem() { return item; }
-
- @Override
- public void onCreateContextMenu(final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- FeedItem item = itemAccess.getItem(getAdapterPosition());
-
- MenuInflater inflater = mainActivityRef.get().getMenuInflater();
- inflater.inflate(R.menu.feeditemlist_context, menu);
-
- if (item != null) {
- menu.setHeaderTitle(item.getTitle());
- }
- FeedItemMenuHandler.onPrepareMenu(menu, item);
- }
-
- public boolean isCurrentlyPlayingItem() {
- return item.getMedia() != null && item.getMedia().isCurrentlyPlaying();
- }
-
- public void notifyPlaybackPositionUpdated(PlaybackPositionEvent event) {
- progress.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
- }
-
- }
-
- public interface ItemAccess {
-
- int getCount();
-
- FeedItem getItem(int position);
-
- LongList getItemsIds();
-
- int getItemDownloadProgressPercent(FeedItem item);
-
- boolean isInQueue(FeedItem item);
-
- LongList getQueueIds();
-
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ MenuInflater inflater = mainActivityRef.get().getMenuInflater();
+ inflater.inflate(R.menu.feeditemlist_context, menu);
+ menu.setHeaderTitle(selectedItem.getTitle());
+ FeedItemMenuHandler.onPrepareMenu(menu, selectedItem, R.id.skip_episode_item);
}
/**
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
index 143071146..3e84e090a 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
@@ -1,36 +1,26 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-import android.text.Layout;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
-import android.text.util.Linkify;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
-import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.TextView;
-
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.playback.Playable;
public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
-
private static final String TAG = "ChapterListAdapter";
private Playable media;
-
- private int defaultTextColor;
private final Callback callback;
private int currentChapterIndex = -1;
@@ -59,11 +49,11 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
convertView = inflater.inflate(R.layout.simplechapter_item, parent, false);
holder.view = convertView;
holder.title = convertView.findViewById(R.id.txtvTitle);
- defaultTextColor = holder.title.getTextColors().getDefaultColor();
holder.start = convertView.findViewById(R.id.txtvStart);
holder.link = convertView.findViewById(R.id.txtvLink);
holder.duration = convertView.findViewById(R.id.txtvDuration);
- holder.butPlayChapter = convertView.findViewById(R.id.butPlayChapter);
+ holder.secondaryActionButton = convertView.findViewById(R.id.secondaryActionButton);
+ holder.secondaryActionIcon = convertView.findViewById(R.id.secondaryActionIcon);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
@@ -83,60 +73,15 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
holder.duration.setText(getContext().getString(R.string.chapter_duration,
Converter.getDurationStringLong((int) duration)));
- if (sc.getLink() != null) {
+ if (sc.getLink() == null) {
+ holder.link.setVisibility(View.GONE);
+ } else {
holder.link.setVisibility(View.VISIBLE);
holder.link.setText(sc.getLink());
- Linkify.addLinks(holder.link, Linkify.WEB_URLS);
- } else {
- holder.link.setVisibility(View.GONE);
+ holder.link.setOnClickListener(v -> IntentUtils.openInBrowser(getContext(), sc.getLink()));
}
- holder.link.setMovementMethod(null);
- holder.link.setOnTouchListener((v, event) -> {
- // from
- // http://stackoverflow.com/questions/7236840/android-textview-linkify-intercepts-with-parent-view-gestures
- TextView widget = (TextView) v;
- Object text = widget.getText();
- if (text instanceof Spanned) {
- Spannable buffer = (Spannable) text;
-
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP
- || action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off,
- ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
- Selection.setSelection(buffer,
- buffer.getSpanStart(link[0]),
- buffer.getSpanEnd(link[0]));
- }
- return true;
- }
- }
-
- }
-
- return false;
-
- });
- holder.butPlayChapter.setOnClickListener(v -> {
+ holder.secondaryActionIcon.setImageResource(ThemeUtils.getDrawableFromAttr(getContext(), R.attr.av_play));
+ holder.secondaryActionButton.setOnClickListener(v -> {
if (callback != null) {
callback.onPlayChapterButtonClicked(position);
}
@@ -147,8 +92,6 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
holder.view.setBackgroundColor(playingBackGroundColor);
} else {
holder.view.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
- holder.title.setTextColor(defaultTextColor);
- holder.start.setTextColor(defaultTextColor);
}
return convertView;
@@ -160,7 +103,8 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
TextView start;
TextView link;
TextView duration;
- ImageButton butPlayChapter;
+ View secondaryActionButton;
+ ImageView secondaryActionIcon;
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
index 4d66fd486..9206cebea 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
@@ -26,171 +26,139 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.ThemeUtils;
+import de.danoeh.antennapod.view.viewholder.DownloadItemViewHolder;
+import de.danoeh.antennapod.view.viewholder.FeedViewHolder;
-/** Displays a list of DownloadStatus entries. */
+/**
+ * Displays a list of DownloadStatus entries.
+ */
public class DownloadLogAdapter extends BaseAdapter {
+ private static final String TAG = "DownloadLogAdapter";
- private static final String TAG = "DownloadLogAdapter";
-
- private final Context context;
-
+ private final Context context;
private final ItemAccess itemAccess;
- public DownloadLogAdapter(Context context, ItemAccess itemAccess) {
- super();
+ public DownloadLogAdapter(Context context, ItemAccess itemAccess) {
+ super();
this.itemAccess = itemAccess;
- this.context = context;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- DownloadStatus status = getItem(position);
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.downloadlog_item, parent, false);
- holder.icon = convertView.findViewById(R.id.txtvIcon);
- holder.retry = convertView.findViewById(R.id.btnRetry);
- holder.date = convertView.findViewById(R.id.txtvDate);
- holder.title = convertView.findViewById(R.id.txtvTitle);
- if(Build.VERSION.SDK_INT >= 23) {
- holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- }
- holder.type = convertView.findViewById(R.id.txtvType);
- holder.reason = convertView.findViewById(R.id.txtvReason);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
- if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
- holder.type.setText(R.string.download_type_feed);
- } else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- holder.type.setText(R.string.download_type_media);
- }
- if (status.getTitle() != null) {
- holder.title.setText(status.getTitle());
- } else {
- holder.title.setText(R.string.download_log_title_unknown);
- }
- holder.date.setText(DateUtils.getRelativeTimeSpanString(
- status.getCompletionDate().getTime(),
- System.currentTimeMillis(), 0, 0));
- if (status.isSuccessful()) {
- holder.icon.setTextColor(ContextCompat.getColor(convertView.getContext(),
- R.color.download_success_green));
- holder.icon.setText("{fa-check-circle}");
- holder.retry.setVisibility(View.GONE);
- holder.reason.setVisibility(View.GONE);
- } else {
- holder.icon.setTextColor(ContextCompat.getColor(convertView.getContext(),
- R.color.download_failed_red));
- holder.icon.setText("{fa-times-circle}");
- String reasonText = status.getReason().getErrorString(context);
- if (status.getReasonDetailed() != null) {
- reasonText += ": " + status.getReasonDetailed();
- }
- holder.reason.setText(reasonText);
- holder.reason.setVisibility(View.VISIBLE);
- if(!newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
- holder.retry.setVisibility(View.VISIBLE);
- holder.retry.setOnClickListener(clickListener);
- ButtonHolder btnHolder;
- if(holder.retry.getTag() != null) {
- btnHolder = (ButtonHolder) holder.retry.getTag();
- } else {
- btnHolder = new ButtonHolder();
- }
- btnHolder.typeId = status.getFeedfileType();
- btnHolder.id = status.getFeedfileId();
- holder.retry.setTag(btnHolder);
- } else {
- holder.retry.setVisibility(View.GONE);
- holder.retry.setOnClickListener(null);
- holder.retry.setTag(null);
- }
- }
-
- return convertView;
- }
-
- private final View.OnClickListener clickListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ButtonHolder holder = (ButtonHolder) v.getTag();
- if(holder.typeId == Feed.FEEDFILETYPE_FEED) {
- Feed feed = DBReader.getFeed(holder.id);
- if (feed != null) {
- try {
- DBTasks.forceRefreshFeed(context, feed);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- } else {
- Log.wtf(TAG, "Could not find feed for feed id: " + holder.id);
- }
- } else if(holder.typeId == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- FeedMedia media = DBReader.getFeedMedia(holder.id);
- if (media != null) {
- try {
- DownloadRequester.getInstance().downloadMedia(context, media.getItem());
- Toast.makeText(context, R.string.status_downloading_label, Toast.LENGTH_SHORT).show();
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DownloadRequestErrorDialogCreator.newRequestErrorDialog(context, e.getMessage());
- }
- } else {
- Log.wtf(TAG, "Could not find media for id: " + holder.id);
- }
- } else {
- Log.wtf(TAG, "Unexpected type id: " + holder.typeId);
- }
- v.setVisibility(View.GONE);
- }
- };
-
- private boolean newerWasSuccessful(int position, int feedTypeId, long id) {
- for (int i = 0; i < position; i++) {
- DownloadStatus status = getItem(i);
- if (status.getFeedfileType() == feedTypeId && status.getFeedfileId() == id &&
- status.isSuccessful()) return true;
- }
- return false;
- }
-
- static class Holder {
- IconTextView icon;
- IconButton retry;
- TextView title;
- TextView type;
- TextView date;
- TextView reason;
- }
-
- static class ButtonHolder {
- int typeId;
- long id;
- }
-
- @Override
- public int getCount() {
+ this.context = context;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ DownloadItemViewHolder holder;
+ if (convertView == null) {
+ holder = new DownloadItemViewHolder(context, parent);
+ } else {
+ holder = (DownloadItemViewHolder) convertView.getTag();
+ }
+
+ DownloadStatus status = getItem(position);
+ if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
+ holder.type.setText(R.string.download_type_feed);
+ } else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+ holder.type.setText(R.string.download_type_media);
+ }
+
+ if (status.getTitle() != null) {
+ holder.title.setText(status.getTitle());
+ } else {
+ holder.title.setText(R.string.download_log_title_unknown);
+ }
+ holder.date.setText(DateUtils.getRelativeTimeSpanString(status.getCompletionDate().getTime(),
+ System.currentTimeMillis(), 0, 0));
+
+ if (status.isSuccessful()) {
+ holder.icon.setTextColor(ContextCompat.getColor(context, R.color.download_success_green));
+ holder.icon.setText("{fa-check-circle}");
+ holder.secondaryActionButton.setVisibility(View.INVISIBLE);
+ holder.reason.setVisibility(View.GONE);
+ } else {
+ holder.icon.setTextColor(ContextCompat.getColor(context, R.color.download_failed_red));
+ holder.icon.setText("{fa-times-circle}");
+ String reasonText = status.getReason().getErrorString(context);
+ if (status.getReasonDetailed() != null) {
+ reasonText += ": " + status.getReasonDetailed();
+ }
+ holder.reason.setText(reasonText);
+ holder.reason.setVisibility(View.VISIBLE);
+
+ if (newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
+ holder.secondaryActionButton.setVisibility(View.INVISIBLE);
+ holder.secondaryActionButton.setOnClickListener(null);
+ holder.secondaryActionButton.setTag(null);
+ } else {
+ holder.secondaryActionIcon.setImageResource(
+ ThemeUtils.getDrawableFromAttr(context, R.attr.navigation_refresh));
+ holder.secondaryActionButton.setVisibility(View.VISIBLE);
+
+ if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
+ holder.secondaryActionButton.setOnClickListener(v -> {
+ holder.secondaryActionButton.setVisibility(View.INVISIBLE);
+ Feed feed = DBReader.getFeed(status.getFeedfileId());
+ if (feed == null) {
+ Log.e(TAG, "Could not find feed for feed id: " + status.getFeedfileId());
+ return;
+ }
+ try {
+ DBTasks.forceRefreshFeed(context, feed);
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ }
+ });
+ } else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+ holder.secondaryActionButton.setOnClickListener(v -> {
+ holder.secondaryActionButton.setVisibility(View.INVISIBLE);
+ FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId());
+ if (media == null) {
+ Log.e(TAG, "Could not find feed media for feed id: " + status.getFeedfileId());
+ return;
+ }
+ try {
+ DownloadRequester.getInstance().downloadMedia(context, media.getItem());
+ Toast.makeText(context, R.string.status_downloading_label, Toast.LENGTH_SHORT).show();
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ DownloadRequestErrorDialogCreator.newRequestErrorDialog(context, e.getMessage());
+ }
+ });
+ }
+ }
+ }
+
+ return holder.itemView;
+ }
+
+ private boolean newerWasSuccessful(int position, int feedTypeId, long id) {
+ for (int i = 0; i < position; i++) {
+ DownloadStatus status = getItem(i);
+ if (status.getFeedfileType() == feedTypeId && status.getFeedfileId() == id && status.isSuccessful()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getCount() {
return itemAccess.getCount();
- }
+ }
- @Override
- public DownloadStatus getItem(int position) {
+ @Override
+ public DownloadStatus getItem(int position) {
return itemAccess.getItem(position);
- }
+ }
- @Override
- public long getItemId(int position) {
- return position;
- }
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
public interface ItemAccess {
- int getCount();
- DownloadStatus getItem(int position);
+ int getCount();
+
+ DownloadStatus getItem(int position);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
index b083908a8..307dabf14 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -1,37 +1,25 @@
package de.danoeh.antennapod.adapter;
-import android.content.Context;
-import android.os.Build;
-import android.text.Layout;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.bumptech.glide.Glide;
-
-import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.glide.ApGlideSettings;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
-import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
+import de.danoeh.antennapod.core.util.ThemeUtils;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
/**
- * Shows a list of downloaded episodes
+ * Shows a list of downloaded episodes.
*/
public class DownloadedEpisodesListAdapter extends BaseAdapter {
- private final Context context;
+ private final MainActivity activity;
private final ItemAccess itemAccess;
- public DownloadedEpisodesListAdapter(Context context, ItemAccess itemAccess) {
+ public DownloadedEpisodesListAdapter(MainActivity activity, ItemAccess itemAccess) {
super();
- this.context = context;
+ this.activity = activity;
this.itemAccess = itemAccess;
}
@@ -52,77 +40,21 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = getItem(position);
- if (item == null) return null;
-
+ EpisodeItemViewHolder holder;
if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.downloaded_episodeslist_item,
- parent, false);
- holder.imageView = convertView.findViewById(R.id.imgvImage);
- holder.title = convertView.findViewById(R.id.txtvTitle);
- if(Build.VERSION.SDK_INT >= 23) {
- holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- }
- holder.txtvSize = convertView.findViewById(R.id.txtvSize);
- holder.queueStatus = convertView.findViewById(R.id.imgvInPlaylist);
- holder.pubDate = convertView
- .findViewById(R.id.txtvPublished);
- holder.butSecondary = convertView
- .findViewById(R.id.butSecondaryAction);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- Glide.with(context)
- .load(ImageResourceUtils.getImageLocation(item))
- .apply(new RequestOptions()
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate())
- .into(holder.imageView);
-
- if(item.isPlayed()) {
- convertView.setAlpha(0.5f);
+ holder = new EpisodeItemViewHolder(activity, parent);
} else {
- convertView.setAlpha(1.0f);
+ holder = (EpisodeItemViewHolder) convertView.getTag();
}
- holder.title.setText(item.getTitle());
- holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize()));
- holder.queueStatus.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE);
- String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
- holder.pubDate.setText(pubDateStr);
-
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(item);
- holder.butSecondary.setOnClickListener(secondaryActionListener);
-
- return convertView;
- }
-
- private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FeedItem item = (FeedItem) v.getTag();
- itemAccess.onFeedItemSecondaryAction(item);
- }
- };
-
+ final FeedItem item = getItem(position);
+ holder.bind(item);
+ holder.dragHandle.setVisibility(View.GONE);
+ holder.secondaryActionIcon.setImageResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.content_discard));
+ holder.secondaryActionButton.setOnClickListener(v -> itemAccess.onFeedItemSecondaryAction(item));
+ holder.hideSeparatorIfNecessary();
- static class Holder {
- ImageView imageView;
- TextView title;
- TextView txtvSize;
- ImageView queueStatus;
- TextView pubDate;
- ImageButton butSecondary;
+ return holder.itemView;
}
public interface ItemAccess {
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
index b0ee87b7e..fd9b76b9c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
@@ -5,23 +5,25 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.ImageButton;
-import android.widget.ProgressBar;
+import android.widget.ImageView;
import android.widget.TextView;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.ThemeUtils;
+import de.danoeh.antennapod.view.CircularProgressBar;
public class DownloadlistAdapter extends BaseAdapter {
private final ItemAccess itemAccess;
private final Context context;
- public DownloadlistAdapter(Context context,
- ItemAccess itemAccess) {
+ public DownloadlistAdapter(Context context, ItemAccess itemAccess) {
super();
this.context = context;
this.itemAccess = itemAccess;
@@ -47,47 +49,44 @@ public class DownloadlistAdapter extends BaseAdapter {
Holder holder;
Downloader downloader = getItem(position);
DownloadRequest request = downloader.getDownloadRequest();
- // Inflate layout
if (convertView == null) {
holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.downloadlist_item, parent, false);
holder.title = convertView.findViewById(R.id.txtvTitle);
- holder.downloaded = convertView
- .findViewById(R.id.txtvDownloaded);
- holder.percent = convertView
- .findViewById(R.id.txtvPercent);
- holder.progbar = convertView
- .findViewById(R.id.progProgress);
- holder.butSecondary = convertView
- .findViewById(R.id.butSecondaryAction);
-
+ holder.status = convertView.findViewById(R.id.txtvStatus);
+ holder.secondaryActionButton = convertView.findViewById(R.id.secondaryActionButton);
+ holder.secondaryActionIcon = convertView.findViewById(R.id.secondaryActionIcon);
+ holder.secondaryActionProgress = convertView.findViewById(R.id.secondaryActionProgress);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.title.setText(request.getTitle());
-
- holder.progbar.setIndeterminate(request.getSoFar() <= 0);
-
- String strDownloaded = Converter.byteToString(request.getSoFar());
- if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) {
- strDownloaded += " / " + Converter.byteToString(request.getSize());
- holder.percent.setText(request.getProgressPercent() + "%");
- holder.progbar.setProgress(request.getProgressPercent());
- holder.percent.setVisibility(View.VISIBLE);
+ holder.secondaryActionIcon.setImageResource(ThemeUtils.getDrawableFromAttr(context, R.attr.navigation_cancel));
+ holder.secondaryActionButton.setTag(downloader);
+ holder.secondaryActionButton.setOnClickListener(butSecondaryListener);
+ holder.secondaryActionProgress.setPercentage(0, request);
+
+ String status = "";
+ if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
+ status += context.getString(R.string.download_type_feed);
+ } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+ status += context.getString(R.string.download_type_media);
+ }
+ status += " · ";
+ if (request.getSoFar() <= 0) {
+ status += context.getString(R.string.download_queued);
} else {
- holder.progbar.setProgress(0);
- holder.percent.setVisibility(View.INVISIBLE);
+ status += Converter.byteToString(request.getSoFar());
+ if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) {
+ status += " / " + Converter.byteToString(request.getSize());
+ holder.secondaryActionProgress.setPercentage(
+ 0.01f * Math.max(1, request.getProgressPercent()), request);
+ }
}
-
- holder.downloaded.setText(strDownloaded);
-
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(downloader);
- holder.butSecondary.setOnClickListener(butSecondaryListener);
+ holder.status.setText(status);
return convertView;
}
@@ -102,10 +101,10 @@ public class DownloadlistAdapter extends BaseAdapter {
static class Holder {
TextView title;
- TextView downloaded;
- TextView percent;
- ProgressBar progbar;
- ImageButton butSecondary;
+ TextView status;
+ View secondaryActionButton;
+ ImageView secondaryActionIcon;
+ CircularProgressBar secondaryActionProgress;
}
public interface ItemAccess {
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 6a88a39ce..a5cfcb3e7 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -1,33 +1,17 @@
package de.danoeh.antennapod.adapter;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Build;
-import androidx.core.content.ContextCompat;
-import android.text.Layout;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Adapter;
import android.widget.BaseAdapter;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
+import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedComponent;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.feed.MediaType;
-import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
-import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.core.util.ThemeUtils;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
+import de.danoeh.antennapod.view.viewholder.FeedComponentViewHolder;
+import de.danoeh.antennapod.view.viewholder.FeedViewHolder;
/**
* List adapter for items of feeds that the user has already subscribed to.
@@ -35,27 +19,19 @@ import de.danoeh.antennapod.core.util.ThemeUtils;
public class FeedItemlistAdapter extends BaseAdapter {
private final ItemAccess itemAccess;
- private final Context context;
- private final boolean showFeedtitle;
- /** true if played items should be made partially transparent */
+ private final MainActivity activity;
private final boolean makePlayedItemsTransparent;
- private final int playingBackGroundColor;
- private final int normalBackGroundColor;
+ private final boolean showIcons;
private int currentlyPlayingItem = -1;
- public FeedItemlistAdapter(Context context,
- ItemAccess itemAccess,
- boolean showFeedtitle,
- boolean makePlayedItemsTransparent) {
+ public FeedItemlistAdapter(MainActivity activity, ItemAccess itemAccess,
+ boolean showIcons, boolean makePlayedItemsTransparent) {
super();
- this.context = context;
+ this.activity = activity;
this.itemAccess = itemAccess;
- this.showFeedtitle = showFeedtitle;
+ this.showIcons = showIcons;
this.makePlayedItemsTransparent = makePlayedItemsTransparent;
-
- playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background);
- normalBackGroundColor = ContextCompat.getColor(context, android.R.color.transparent);
}
@Override
@@ -70,135 +46,56 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
@Override
- public FeedItem getItem(int position) {
+ public FeedComponent getItem(int position) {
return itemAccess.getItem(position);
}
@Override
- @SuppressWarnings("ResourceType")
public View getView(final int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = getItem(position);
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.feeditemlist_item, parent, false);
- holder.container = convertView
- .findViewById(R.id.container);
- holder.title = convertView.findViewById(R.id.txtvItemname);
- if(Build.VERSION.SDK_INT >= 23) {
- holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- }
- holder.lenSize = convertView
- .findViewById(R.id.txtvLenSize);
- holder.butAction = convertView
- .findViewById(R.id.butSecondaryAction);
- holder.published = convertView
- .findViewById(R.id.txtvPublished);
- holder.inPlaylist = convertView
- .findViewById(R.id.imgvInPlaylist);
- holder.type = convertView.findViewById(R.id.imgvType);
- holder.statusUnread = convertView
- .findViewById(R.id.statusUnread);
- holder.episodeProgress = convertView
- .findViewById(R.id.pbar_episode_progress);
-
- convertView.setTag(holder);
+ final FeedComponent item = getItem(position);
+ if (item instanceof Feed) {
+ return getView((Feed) item, convertView, parent);
} else {
- holder = (Holder) convertView.getTag();
- }
-
- if (!(getItemViewType(position) == Adapter.IGNORE_ITEM_VIEW_TYPE)) {
- convertView.setVisibility(View.VISIBLE);
-
- StringBuilder buffer = new StringBuilder(item.getTitle());
- if (showFeedtitle) {
- buffer.append(" (");
- buffer.append(item.getFeed().getTitle());
- buffer.append(")");
+ final FeedItem feeditem = (FeedItem) item;
+ if (feeditem.getMedia() != null && feeditem.getMedia().isCurrentlyPlaying()) {
+ currentlyPlayingItem = position;
}
- holder.title.setText(buffer.toString());
+ return getView(feeditem, convertView, parent);
+ }
+ }
- if(item.isNew()) {
- holder.statusUnread.setVisibility(View.VISIBLE);
- } else {
- holder.statusUnread.setVisibility(View.INVISIBLE);
- }
- if(item.isPlayed() && makePlayedItemsTransparent) {
- convertView.setAlpha(0.5f);
- } else {
- convertView.setAlpha(1.0f);
- }
+ private View getView(Feed item, View convertView, ViewGroup parent) {
+ FeedViewHolder holder;
+ if (convertView == null || !(convertView.getTag() instanceof FeedViewHolder)) {
+ holder = new FeedViewHolder(activity, parent);
+ } else {
+ holder = (FeedViewHolder) convertView.getTag();
+ }
+ holder.bind(item);
+ return holder.itemView;
+ }
- String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
- holder.published.setText(pubDateStr);
-
- boolean isInQueue = item.isTagged(FeedItem.TAG_QUEUE);
-
- FeedMedia media = item.getMedia();
- if (media == null) {
- holder.episodeProgress.setVisibility(View.INVISIBLE);
- holder.inPlaylist.setVisibility(View.INVISIBLE);
- holder.type.setVisibility(View.INVISIBLE);
- holder.lenSize.setVisibility(View.INVISIBLE);
- } else {
-
- AdapterUtils.updateEpisodePlaybackProgress(item, holder.lenSize, holder.episodeProgress);
-
- if (isInQueue) {
- holder.inPlaylist.setVisibility(View.VISIBLE);
- } else {
- holder.inPlaylist.setVisibility(View.INVISIBLE);
- }
-
- if (DownloadRequester.getInstance().isDownloadingFile(item.getMedia())) {
- holder.episodeProgress.setVisibility(View.VISIBLE);
- holder.episodeProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
- } else {
- if(media.getPosition() == 0) {
- holder.episodeProgress.setVisibility(View.INVISIBLE);
- }
- }
-
- TypedArray typeDrawables = context.obtainStyledAttributes(
- new int[]{R.attr.type_audio, R.attr.type_video});
- final int[] labels = new int[]{R.string.media_type_audio_label, R.string.media_type_video_label};
-
- MediaType mediaType = item.getMedia().getMediaType();
- if (mediaType == MediaType.AUDIO) {
- holder.type.setImageDrawable(typeDrawables.getDrawable(0));
- holder.type.setContentDescription(context.getString(labels[0]));
- holder.type.setVisibility(View.VISIBLE);
- } else if (mediaType == MediaType.VIDEO) {
- holder.type.setImageDrawable(typeDrawables.getDrawable(1));
- holder.type.setContentDescription(context.getString(labels[1]));
- holder.type.setVisibility(View.VISIBLE);
- } else {
- holder.type.setImageBitmap(null);
- holder.type.setVisibility(View.GONE);
- }
- typeDrawables.recycle();
-
- if (media.isCurrentlyPlaying()) {
- holder.container.setBackgroundColor(playingBackGroundColor);
- currentlyPlayingItem = position;
- } else {
- holder.container.setBackgroundColor(normalBackGroundColor);
- }
- }
+ private View getView(final FeedItem item, View convertView, ViewGroup parent) {
+ EpisodeItemViewHolder holder;
+ if (convertView == null || !(convertView.getTag() instanceof EpisodeItemViewHolder)) {
+ holder = new EpisodeItemViewHolder(activity, parent);
+ } else {
+ holder = (EpisodeItemViewHolder) convertView.getTag();
+ }
- ItemActionButton actionButton = ItemActionButton.forItem(item, isInQueue, true);
- actionButton.configure(holder.butAction, context);
+ if (!showIcons) {
+ holder.coverHolder.setVisibility(View.GONE);
+ }
- holder.butAction.setFocusable(false);
- holder.butAction.setTag(item);
+ holder.bind(item);
+ holder.dragHandle.setVisibility(View.GONE);
- } else {
- convertView.setVisibility(View.GONE);
+ if (!makePlayedItemsTransparent) {
+ holder.itemView.setAlpha(1.0f);
}
- return convertView;
+
+ holder.hideSeparatorIfNecessary();
+ return holder.itemView;
}
public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event, ListView listView) {
@@ -208,35 +105,15 @@ public class FeedItemlistAdapter extends BaseAdapter {
if (view == null) {
return;
}
- Holder holder = (Holder) view.getTag();
- holder.episodeProgress.setVisibility(View.VISIBLE);
- holder.episodeProgress.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
- holder.lenSize.setText(Converter.getDurationStringLong(event.getDuration() - event.getPosition()));
+ EpisodeItemViewHolder holder = (EpisodeItemViewHolder) view.getTag();
+ holder.notifyPlaybackPositionUpdated(event);
}
}
- static class Holder {
- LinearLayout container;
- TextView title;
- TextView published;
- TextView lenSize;
- ImageView type;
- ImageView inPlaylist;
- ImageButton butAction;
- View statusUnread;
- ProgressBar episodeProgress;
- }
-
public interface ItemAccess {
-
- int getItemDownloadProgressPercent(FeedItem item);
-
int getCount();
- FeedItem getItem(int position);
-
- LongList getQueueIds();
-
+ FeedComponent getItem(int position);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
index 681dee380..456f45fd2 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -1,56 +1,34 @@
package de.danoeh.antennapod.adapter;
-import android.os.Build;
-import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-import androidx.core.view.MotionEventCompat;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.ItemTouchHelper;
-import android.text.Layout;
-import android.text.TextUtils;
+import android.annotation.SuppressLint;
import android.util.Log;
import android.view.ContextMenu;
-import android.view.LayoutInflater;
import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.joanzapata.iconify.Iconify;
-
-import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
-import de.danoeh.antennapod.fragment.ItemPagerFragment;
-import org.apache.commons.lang3.ArrayUtils;
-
-import java.lang.ref.WeakReference;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.view.MotionEventCompat;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
-import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.core.util.NetworkUtils;
-import de.danoeh.antennapod.core.util.ThemeUtils;
+import de.danoeh.antennapod.fragment.ItemPagerFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.lang.ref.WeakReference;
/**
* List adapter for the queue.
*/
-public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdapter.ViewHolder> {
-
- private static final String TAG = QueueRecyclerAdapter.class.getSimpleName();
+public class QueueRecyclerAdapter extends RecyclerView.Adapter<EpisodeItemViewHolder> implements View.OnCreateContextMenuListener {
+ private static final String TAG = "QueueRecyclerAdapter";
private final WeakReference<MainActivity> mainActivity;
private final ItemAccess itemAccess;
@@ -60,9 +38,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
private FeedItem selectedItem;
- private final int playingBackGroundColor;
- private final int normalBackGroundColor;
-
public QueueRecyclerAdapter(MainActivity mainActivity,
ItemAccess itemAccess,
ItemTouchHelper itemTouchHelper) {
@@ -71,9 +46,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
this.itemAccess = itemAccess;
this.itemTouchHelper = itemTouchHelper;
locked = UserPreferences.isQueueLocked();
-
- playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
- normalBackGroundColor = ContextCompat.getColor(mainActivity, android.R.color.transparent);
}
public void setLocked(boolean locked) {
@@ -81,20 +53,49 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
notifyDataSetChanged();
}
+ @NonNull
@Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.queue_listitem, parent, false);
- return new ViewHolder(view);
+ public EpisodeItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new EpisodeItemViewHolder(mainActivity.get(), parent);
}
@Override
- public void onBindViewHolder(ViewHolder holder, int pos) {
+ @SuppressLint("ClickableViewAccessibility")
+ public void onBindViewHolder(EpisodeItemViewHolder holder, int pos) {
FeedItem item = itemAccess.getItem(pos);
holder.bind(item);
+ holder.dragHandle.setVisibility(locked ? View.GONE : View.VISIBLE);
holder.itemView.setOnLongClickListener(v -> {
selectedItem = item;
return false;
});
+ holder.itemView.setOnClickListener(v -> {
+ MainActivity activity = mainActivity.get();
+ if (activity != null) {
+ long[] ids = itemAccess.getQueueIds().toArray();
+ int position = ArrayUtils.indexOf(ids, item.getId());
+ activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
+ }
+ });
+
+ View.OnTouchListener startDragTouchListener = (v1, event) -> {
+ if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+ Log.d(TAG, "startDrag()");
+ itemTouchHelper.startDrag(holder);
+ }
+ return false;
+ };
+ if (!locked) {
+ holder.dragHandle.setOnTouchListener(startDragTouchListener);
+ holder.coverHolder.setOnTouchListener(startDragTouchListener);
+ } else {
+ holder.dragHandle.setOnTouchListener(null);
+ holder.coverHolder.setOnTouchListener(null);
+ }
+
+ holder.itemView.setOnCreateContextMenuListener(this);
+ holder.isInQueue.setVisibility(View.GONE);
+ holder.hideSeparatorIfNecessary();
}
@Nullable
@@ -112,211 +113,30 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
return itemAccess.getCount();
}
- public class ViewHolder extends RecyclerView.ViewHolder
- implements View.OnClickListener,
- View.OnCreateContextMenuListener,
- ItemTouchHelperViewHolder {
-
- private final FrameLayout container;
- private final ImageView dragHandle;
- private final TextView placeholder;
- private final ImageView cover;
- private final TextView title;
- private final TextView pubDate;
- private final TextView progressLeft;
- private final TextView progressRight;
- private final ProgressBar progressBar;
- private final ImageButton butSecondary;
-
- private FeedItem item;
-
- public ViewHolder(View v) {
- super(v);
- container = v.findViewById(R.id.container);
- dragHandle = v.findViewById(R.id.drag_handle);
- placeholder = v.findViewById(R.id.txtvPlaceholder);
- cover = v.findViewById(R.id.imgvCover);
- title = v.findViewById(R.id.txtvTitle);
- if(Build.VERSION.SDK_INT >= 23) {
- title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- }
- pubDate = v.findViewById(R.id.txtvPubDate);
- progressLeft = v.findViewById(R.id.txtvProgressLeft);
- progressRight = v.findViewById(R.id.txtvProgressRight);
- butSecondary = v.findViewById(R.id.butSecondaryAction);
- progressBar = v.findViewById(R.id.progressBar);
- v.setTag(this);
- v.setOnClickListener(this);
- v.setOnCreateContextMenuListener(this);
- dragHandle.setOnTouchListener((v1, event) -> {
- if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
- Log.d(TAG, "startDrag()");
- itemTouchHelper.startDrag(ViewHolder.this);
- }
- return false;
- });
- }
-
- @Override
- public void onClick(View v) {
- MainActivity activity = mainActivity.get();
- if (activity != null) {
- long[] ids = itemAccess.getQueueIds().toArray();
- int position = ArrayUtils.indexOf(ids, item.getId());
- activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
- }
- }
-
- @Override
- public void onCreateContextMenu(final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- FeedItem item = itemAccess.getItem(getAdapterPosition());
-
- MenuInflater inflater = mainActivity.get().getMenuInflater();
- inflater.inflate(R.menu.queue_context, menu); // queue-specific menu items
- inflater.inflate(R.menu.feeditemlist_context, menu); // generic menu items for item feeds
-
- if (item != null) {
- menu.setHeaderTitle(item.getTitle());
- }
-
- FeedItemMenuHandler.onPrepareMenu(menu, item,
- R.id.skip_episode_item); // Skip Episode is not useful in Queue, so hide it.
- // Queue-specific menu preparation
- final boolean keepSorted = UserPreferences.isQueueKeepSorted();
- final LongList queueAccess = itemAccess.getQueueIds();
- if (queueAccess.size() == 0 || queueAccess.get(0) == item.getId() || keepSorted) {
- menu.findItem(R.id.move_to_top_item).setVisible(false);
- }
- if (queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == item.getId() || keepSorted) {
- menu.findItem(R.id.move_to_bottom_item).setVisible(false);
- }
- }
-
- @Override
- public void onItemSelected() {
- itemView.setAlpha(0.5f);
- }
-
- @Override
- public void onItemClear() {
- itemView.setAlpha(1.0f);
- }
-
- public void bind(FeedItem item) {
- this.item = item;
- if(locked) {
- dragHandle.setVisibility(View.GONE);
- } else {
- dragHandle.setVisibility(View.VISIBLE);
- }
-
- placeholder.setText(item.getFeed().getTitle());
-
- title.setText(item.getTitle());
- FeedMedia media = item.getMedia();
-
- title.setText(item.getTitle());
- String pubDateStr = DateUtils.formatAbbrev(mainActivity.get(), item.getPubDate());
- int index = 0;
- if(countMatches(pubDateStr, ' ') == 1 || countMatches(pubDateStr, ' ') == 2) {
- index = pubDateStr.lastIndexOf(' ');
- } else if(countMatches(pubDateStr, '.') == 2) {
- index = pubDateStr.lastIndexOf('.');
- } else if(countMatches(pubDateStr, '-') == 2) {
- index = pubDateStr.lastIndexOf('-');
- } else if(countMatches(pubDateStr, '/') == 2) {
- index = pubDateStr.lastIndexOf('/');
- }
- if(index > 0) {
- pubDateStr = pubDateStr.substring(0, index+1).trim() + "\n" + pubDateStr.substring(index+1);
- }
- pubDate.setText(pubDateStr);
-
- if (media != null) {
- final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
- FeedItem.State state = item.getState();
- if (isDownloadingMedia) {
- progressLeft.setText(Converter.byteToString(itemAccess.getItemDownloadedBytes(item)));
- if(itemAccess.getItemDownloadSize(item) > 0) {
- progressRight.setText(Converter.byteToString(itemAccess.getItemDownloadSize(item)));
- } else {
- progressRight.setText(Converter.byteToString(media.getSize()));
- }
- progressBar.setProgress(itemAccess.getItemDownloadProgressPercent(item));
- progressBar.setVisibility(View.VISIBLE);
- } else if (state == FeedItem.State.PLAYING
- || state == FeedItem.State.IN_PROGRESS) {
- if (media.getDuration() > 0) {
- int progress = (int) (100.0 * media.getPosition() / media.getDuration());
- progressBar.setProgress(progress);
- progressBar.setVisibility(View.VISIBLE);
- progressLeft.setText(Converter
- .getDurationStringLong(media.getPosition()));
- progressRight.setText(Converter.getDurationStringLong(media.getDuration()));
- }
- } else {
- if(media.getSize() > 0) {
- progressLeft.setText(Converter.byteToString(media.getSize()));
- } else if(NetworkUtils.isEpisodeHeadDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
- progressLeft.setText("{fa-spinner}");
- Iconify.addIcons(progressLeft);
- NetworkUtils.getFeedMediaSizeObservable(media)
- .subscribe(
- size -> {
- if (size > 0) {
- progressLeft.setText(Converter.byteToString(size));
- } else {
- progressLeft.setText("");
- }
- }, error -> {
- progressLeft.setText("");
- Log.e(TAG, Log.getStackTraceString(error));
- });
- } else {
- progressLeft.setText("");
- }
- progressRight.setText(Converter.getDurationStringLong(media.getDuration()));
- progressBar.setVisibility(View.INVISIBLE);
- }
-
- if(media.isCurrentlyPlaying()) {
- container.setBackgroundColor(playingBackGroundColor);
- } else {
- container.setBackgroundColor(normalBackGroundColor);
- }
- }
-
- ItemActionButton actionButton = ItemActionButton.forItem(item, true, true);
- actionButton.configure(butSecondary, mainActivity.get());
-
- butSecondary.setFocusable(false);
- butSecondary.setTag(item);
-
- new CoverLoader(mainActivity.get())
- .withUri(ImageResourceUtils.getImageLocation(item))
- .withFallbackUri(item.getFeed().getImageLocation())
- .withPlaceholderView(placeholder)
- .withCoverView(cover)
- .load();
- }
-
- public boolean isCurrentlyPlayingItem() {
- return item.getMedia() != null && item.getMedia().isCurrentlyPlaying();
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ MenuInflater inflater = mainActivity.get().getMenuInflater();
+ inflater.inflate(R.menu.queue_context, menu); // queue-specific menu items
+ inflater.inflate(R.menu.feeditemlist_context, menu); // generic menu items for item feeds
+
+ menu.setHeaderTitle(selectedItem.getTitle());
+ FeedItemMenuHandler.onPrepareMenu(menu, selectedItem, R.id.skip_episode_item);
+ // Queue-specific menu preparation
+ final boolean keepSorted = UserPreferences.isQueueKeepSorted();
+ final LongList queueAccess = itemAccess.getQueueIds();
+ if (queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId() || keepSorted) {
+ menu.findItem(R.id.move_to_top_item).setVisible(false);
}
-
- public void notifyPlaybackPositionUpdated(PlaybackPositionEvent event) {
- progressBar.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
- progressLeft.setText(Converter.getDurationStringLong(event.getPosition()));
- progressRight.setText(Converter.getDurationStringLong(event.getDuration()));
+ if (queueAccess.size() == 0 || queueAccess.get(queueAccess.size() - 1) == selectedItem.getId() || keepSorted) {
+ menu.findItem(R.id.move_to_bottom_item).setVisible(false);
}
}
public interface ItemAccess {
FeedItem getItem(int position);
+
int getCount();
- long getItemDownloadedBytes(FeedItem item);
- long getItemDownloadSize(FeedItem item);
- int getItemDownloadProgressPercent(FeedItem item);
+
LongList getQueueIds();
}
@@ -341,18 +161,4 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
*/
void onItemClear();
}
-
- // Oh Xiaomi, I hate you so much. How did you manage to fuck this up?
- private static int countMatches(final CharSequence str, final char ch) {
- if (TextUtils.isEmpty(str)) {
- return 0;
- }
- int count = 0;
- for (int i = 0; i < str.length(); i++) {
- if (ch == str.charAt(i)) {
- count++;
- }
- }
- return count;
- }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
deleted file mode 100644
index d1615b410..000000000
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.os.Build;
-import android.text.Layout;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.request.RequestOptions;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedComponent;
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.glide.ApGlideSettings;
-
-/**
- * List adapter for search activity.
- */
-public class SearchlistAdapter extends BaseAdapter {
-
- private final Context context;
- private final ItemAccess itemAccess;
-
-
- public SearchlistAdapter(Context context, ItemAccess itemAccess) {
- this.context = context;
- this.itemAccess = itemAccess;
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public FeedComponent getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return 0;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final Holder holder;
- FeedComponent component = getItem(position);
-
- // Inflate Layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.searchlist_item, parent, false);
- holder.title = convertView.findViewById(R.id.txtvTitle);
- if(Build.VERSION.SDK_INT >= 23) {
- holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- }
- holder.cover = convertView
- .findViewById(R.id.imgvFeedimage);
- holder.subtitle = convertView
- .findViewById(R.id.txtvSubtitle);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
- if (component.getClass() == Feed.class) {
- final Feed feed = (Feed) component;
- holder.title.setText(feed.getTitle());
- holder.subtitle.setVisibility(View.GONE);
-
- Glide.with(context)
- .load(feed.getImageLocation())
- .apply(new RequestOptions()
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate())
- .into(holder.cover);
-
- } else if (component.getClass() == FeedItem.class) {
- final FeedItem item = (FeedItem) component;
- holder.title.setText(item.getTitle());
- holder.subtitle.setVisibility(View.VISIBLE);
-
- convertView.setAlpha(item.isPlayed() ? 0.5f : 1.0f);
-
- Glide.with(context)
- .load(item.getFeed().getImageLocation())
- .apply(new RequestOptions()
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate())
- .into(holder.cover);
-
- }
-
- return convertView;
- }
-
- static class Holder {
- ImageView cover;
- TextView title;
- TextView subtitle;
- }
-
- public interface ItemAccess {
- int getCount();
-
- FeedComponent getItem(int position);
- }
-
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java
index ffc73c5fb..47eab7d05 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.content.res.TypedArray;
+import android.widget.ImageView;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
@@ -54,14 +55,13 @@ public abstract class ItemActionButton {
}
}
- public void configure(@NonNull ImageButton button, Context context) {
- TypedArray drawables = context.obtainStyledAttributes(new int[]{getDrawable()});
-
+ public void configure(@NonNull View button, @NonNull ImageView icon, Context context) {
button.setVisibility(getVisibility());
button.setContentDescription(context.getString(getLabel()));
- button.setImageDrawable(drawables.getDrawable(0));
button.setOnClickListener((view) -> onClick(context));
+ TypedArray drawables = context.obtainStyledAttributes(new int[]{getDrawable()});
+ icon.setImageDrawable(drawables.getDrawable(0));
drawables.recycle();
}
}
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 e4276b3b9..edcc566f2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -39,11 +39,6 @@ public class AllEpisodesFragment extends EpisodesListFragment {
}
@Override
- protected boolean showOnlyNewEpisodes() {
- return false;
- }
-
- @Override
protected String getPrefName() {
return PREF_NAME;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
index 7f70daaec..101c5da27 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -52,7 +52,7 @@ public class CompletedDownloadsFragment extends ListFragment {
addVerticalPadding();
addEmptyView();
- listAdapter = new DownloadedEpisodesListAdapter(getActivity(), itemAccess);
+ listAdapter = new DownloadedEpisodesListAdapter((MainActivity) getActivity(), itemAccess);
setListAdapter(listAdapter);
setListShown(false);
EventBus.getDefault().register(this);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
index 89cf3b07f..6176ca410 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java
@@ -28,6 +28,7 @@ import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
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.view.viewholder.EpisodeItemViewHolder;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -43,14 +44,11 @@ import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemUtil;
-import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
@@ -82,8 +80,6 @@ public abstract class EpisodesListFragment extends Fragment {
@NonNull
List<FeedItem> episodes = new ArrayList<>();
- @NonNull
- private List<Downloader> downloaderList = new ArrayList<>();
private boolean isUpdatingFeeds;
boolean isMenuInvalidationAllowed = false;
@@ -92,10 +88,6 @@ public abstract class EpisodesListFragment extends Fragment {
private LinearLayoutManager layoutManager;
protected TextView txtvInformation;
- boolean showOnlyNewEpisodes() {
- return false;
- }
-
String getPrefName() {
return DEFAULT_PREF_NAME;
}
@@ -347,10 +339,10 @@ public abstract class EpisodesListFragment extends Fragment {
}
protected void onFragmentLoaded(List<FeedItem> episodes) {
- listAdapter.notifyDataSetChanged();
-
if (episodes.size() == 0) {
createRecycleAdapter(recyclerView, emptyView);
+ } else {
+ listAdapter.updateItems(episodes);
}
restoreScrollPosition();
@@ -363,66 +355,13 @@ public abstract class EpisodesListFragment extends Fragment {
*/
private void createRecycleAdapter(RecyclerView recyclerView, EmptyViewHandler emptyViewHandler) {
MainActivity mainActivity = (MainActivity) getActivity();
- listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
+ listAdapter = new AllEpisodesRecycleAdapter(mainActivity);
listAdapter.setHasStableIds(true);
+ listAdapter.updateItems(episodes);
recyclerView.setAdapter(listAdapter);
emptyViewHandler.updateAdapter(listAdapter);
}
- private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
-
- @Override
- public int getCount() {
- return episodes.size();
- }
-
- @Override
- public FeedItem getItem(int position) {
- if (0 <= position && position < episodes.size()) {
- return episodes.get(position);
- }
- return null;
- }
-
- @Override
- public LongList getItemsIds() {
- LongList ids = new LongList(episodes.size());
- for (FeedItem episode : episodes) {
- ids.add(episode.getId());
- }
- return ids;
- }
-
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- for (Downloader downloader : downloaderList) {
- DownloadRequest downloadRequest = downloader.getDownloadRequest();
- if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloadRequest.getFeedfileId() == item.getMedia().getId()) {
- return downloadRequest.getProgressPercent();
- }
- }
- return 0;
- }
-
- @Override
- public boolean isInQueue(FeedItem item) {
- return item != null && item.isTagged(FeedItem.TAG_QUEUE);
- }
-
- @Override
- public LongList getQueueIds() {
- LongList queueIds = new LongList();
- for (FeedItem item : episodes) {
- if (item.isTagged(FeedItem.TAG_QUEUE)) {
- queueIds.add(item.getId());
- }
- }
- return queueIds;
- }
-
- };
-
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
@@ -444,8 +383,7 @@ public abstract class EpisodesListFragment extends Fragment {
public void onEventMainThread(PlaybackPositionEvent event) {
if (listAdapter != null) {
for (int i = 0; i < listAdapter.getItemCount(); i++) {
- AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)
- recyclerView.findViewHolderForAdapterPosition(i);
+ EpisodeItemViewHolder holder = (EpisodeItemViewHolder) recyclerView.findViewHolderForAdapterPosition(i);
if (holder != null && holder.isCurrentlyPlayingItem()) {
holder.notifyPlaybackPositionUpdated(event);
break;
@@ -462,7 +400,7 @@ public abstract class EpisodesListFragment extends Fragment {
public void onEventMainThread(DownloadEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
- downloaderList = update.downloaders;
+ List<Downloader> downloaderList = update.downloaders;
if (isMenuInvalidationAllowed && event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
requireActivity().invalidateOptionsMenu();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
index 87a555cfd..4953ccc6c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -10,12 +10,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
import org.greenrobot.eventbus.Subscribe;
import java.util.List;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -31,11 +31,6 @@ public class FavoriteEpisodesFragment extends EpisodesListFragment {
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
@Override
- protected boolean showOnlyNewEpisodes() {
- return true;
- }
-
- @Override
protected String getPrefName() {
return PREF_NAME;
}
@@ -63,8 +58,8 @@ public class FavoriteEpisodesFragment extends EpisodesListFragment {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
- AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
- Log.d(TAG, String.format("remove(%s)", holder.getItemId()));
+ EpisodeItemViewHolder holder = (EpisodeItemViewHolder) viewHolder;
+ Log.d(TAG, String.format("remove(%s)", holder.getFeedItem().getId()));
if (disposable != null) {
disposable.dispose();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
index 9c04886f6..b9afa6d57 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
@@ -89,25 +89,18 @@ public class FeedItemlistFragment extends ListFragment {
private static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id";
private FeedItemlistAdapter adapter;
- private ContextMenu contextMenu;
private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
+ private MoreContentListFooterUtil listFooter;
private long feedID;
private Feed feed;
-
private boolean headerCreated = false;
-
- private List<Downloader> downloaderList;
-
- private MoreContentListFooterUtil listFooter;
-
private boolean isUpdatingFeed;
private TextView txtvTitle;
private IconTextView txtvFailure;
private ImageView imgvBackground;
private ImageView imgvCover;
-
private TextView txtvInformation;
private Disposable disposable;
@@ -296,7 +289,7 @@ public class FeedItemlistFragment extends ListFragment {
AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
// because of addHeaderView(), positions are increased by 1!
- FeedItem item = itemAccess.getItem(adapterInfo.position-1);
+ FeedItem item = (FeedItem) itemAccess.getItem(adapterInfo.position - 1);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.feeditemlist_context, menu);
@@ -305,7 +298,6 @@ public class FeedItemlistFragment extends ListFragment {
menu.setHeaderTitle(item.getTitle());
}
- contextMenu = menu;
lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
FeedItemMenuHandler.onPrepareMenu(menu, item);
}
@@ -313,11 +305,11 @@ public class FeedItemlistFragment extends ListFragment {
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
- if(menuInfo == null) {
+ if (menuInfo == null) {
menuInfo = lastMenuInfo;
}
// because of addHeaderView(), positions are increased by 1!
- FeedItem selectedItem = itemAccess.getItem(menuInfo.position-1);
+ FeedItem selectedItem = feed.getItemAtIndex(menuInfo.position - 1);
if (selectedItem == null) {
Log.i(TAG, "Selected item at position " + menuInfo.position + " was null, ignoring selection");
@@ -366,7 +358,6 @@ public class FeedItemlistFragment extends ListFragment {
public void onEventMainThread(DownloadEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
- downloaderList = update.downloaders;
if (event.hasChangedFeedUpdateStatus(isUpdatingFeed)) {
updateProgressBarVisibility();
}
@@ -424,7 +415,7 @@ public class FeedItemlistFragment extends ListFragment {
setListAdapter(null);
setupHeaderView();
setupFooterView();
- adapter = new FeedItemlistAdapter(getActivity(), itemAccess, false, true);
+ adapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, false, true);
setListAdapter(adapter);
}
refreshHeaderView();
@@ -575,39 +566,12 @@ public class FeedItemlistFragment extends ListFragment {
}
@Override
- public LongList getQueueIds() {
- LongList queueIds = new LongList();
- if(feed == null) {
- return queueIds;
- }
- for(FeedItem item : feed.getItems()) {
- if(item.isTagged(FeedItem.TAG_QUEUE)) {
- queueIds.add(item.getId());
- }
- }
- return queueIds;
- }
-
- @Override
public int getCount() {
return (feed != null) ? feed.getNumOfItems() : 0;
}
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
};
-
private void loadItems() {
if(disposable != null) {
disposable.dispose();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
index bd3fd06b0..33e686a90 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -16,6 +16,7 @@ import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
/**
* Like 'EpisodesFragment' except that it only shows new episodes and
@@ -27,11 +28,6 @@ public class NewEpisodesFragment extends EpisodesListFragment {
private static final String PREF_NAME = "PrefNewEpisodesFragment";
@Override
- protected boolean showOnlyNewEpisodes() {
- return true;
- }
-
- @Override
protected String getPrefName() {
return PREF_NAME;
}
@@ -63,7 +59,7 @@ public class NewEpisodesFragment extends EpisodesListFragment {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
- AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
+ EpisodeItemViewHolder holder = (EpisodeItemViewHolder) viewHolder;
FeedItemMenuHandler.removeNewFlagWithUndo(NewEpisodesFragment.this, holder.getFeedItem());
}
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 a97e3dae8..923a6325c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -73,7 +73,7 @@ public class PlaybackHistoryFragment extends ListFragment {
// played items shoudln't be transparent for this fragment since, *all* items
// in this fragment will, by definition, be played. So it serves no purpose and can make
// it harder to read.
- adapter = new FeedItemlistAdapter(getActivity(), itemAccess, true, false);
+ adapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, true, false);
setListAdapter(adapter);
}
@@ -93,7 +93,7 @@ public class PlaybackHistoryFragment extends ListFragment {
}
}
- @Subscribe(sticky = true)
+ @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
@@ -181,19 +181,6 @@ public class PlaybackHistoryFragment extends ListFragment {
private final FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
@Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
-
- @Override
public int getCount() {
return (playbackHistory != null) ? playbackHistory.size() : 0;
}
@@ -206,20 +193,6 @@ public class PlaybackHistoryFragment extends ListFragment {
return null;
}
}
-
- @Override
- public LongList getQueueIds() {
- LongList queueIds = new LongList();
- if(playbackHistory == null) {
- return queueIds;
- }
- for (FeedItem item : playbackHistory) {
- if (item.isTagged(FeedItem.TAG_QUEUE)) {
- queueIds.add(item.getId());
- }
- }
- return queueIds;
- }
};
private void loadItems() {
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 c13ddc3b1..36c837a25 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -27,6 +27,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator;
import com.google.android.material.snackbar.Snackbar;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
+import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -45,11 +46,9 @@ import de.danoeh.antennapod.core.event.PlayerStatusEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadService;
-import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester;
@@ -84,7 +83,6 @@ public class QueueFragment extends Fragment {
private ProgressBar progLoading;
private List<FeedItem> queue;
- private List<Downloader> downloaderList;
private boolean isUpdatingFeeds = false;
@@ -196,7 +194,6 @@ public class QueueFragment extends Fragment {
public void onEventMainThread(DownloadEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
- downloaderList = update.downloaders;
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
getActivity().invalidateOptionsMenu();
}
@@ -214,7 +211,7 @@ public class QueueFragment extends Fragment {
public void onEventMainThread(PlaybackPositionEvent event) {
if (recyclerAdapter != null) {
for (int i = 0; i < recyclerAdapter.getItemCount(); i++) {
- QueueRecyclerAdapter.ViewHolder holder = (QueueRecyclerAdapter.ViewHolder)
+ EpisodeItemViewHolder holder = (EpisodeItemViewHolder)
recyclerView.findViewHolderForAdapterPosition(i);
if (holder != null && holder.isCurrentlyPlayingItem()) {
holder.notifyPlaybackPositionUpdated(event);
@@ -510,7 +507,6 @@ public class QueueFragment extends Fragment {
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
- recyclerView.setHasFixedSize(true);
registerForContextMenu(recyclerView);
itemTouchHelper = new ItemTouchHelper(
@@ -693,46 +689,6 @@ public class QueueFragment extends Fragment {
}
@Override
- public long getItemDownloadedBytes(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- Log.d(TAG, "downloaded bytes: " + downloader.getDownloadRequest().getSoFar());
- return downloader.getDownloadRequest().getSoFar();
- }
- }
- }
- return 0;
- }
-
- @Override
- public long getItemDownloadSize(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- Log.d(TAG, "downloaded size: " + downloader.getDownloadRequest().getSize());
- return downloader.getDownloadRequest().getSize();
- }
- }
- }
- return 0;
- }
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
-
- @Override
public LongList getQueueIds() {
return queue != null ? LongList.of(FeedItemUtil.getIds(queue)) : new LongList(0);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
index 7e8823c27..1bfbd2d78 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
@@ -104,11 +104,12 @@ public class RunningDownloadsFragment extends ListFragment {
DownloadRequest downloadRequest = downloader.getDownloadRequest();
DownloadRequester.getInstance().cancelDownload(getActivity(), downloadRequest.getSource());
- if(downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA &&
- UserPreferences.isEnableAutodownload()) {
+ if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
+ && UserPreferences.isEnableAutodownload()) {
FeedMedia media = DBReader.getFeedMedia(downloadRequest.getFeedfileId());
DBWriter.setFeedItemAutoDownload(media.getItem(), false);
- Toast.makeText(getActivity(), R.string.download_canceled_autodownload_enabled_msg, Toast.LENGTH_SHORT).show();
+ Toast.makeText(getActivity(), R.string.download_canceled_autodownload_enabled_msg,
+ Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), R.string.download_canceled_msg, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
index c640554ff..7d284835d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -20,7 +20,8 @@ import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.SearchlistAdapter;
+import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
+import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedComponent;
@@ -33,8 +34,10 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import java.util.ArrayList;
import java.util.List;
+
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
/**
* Performs a search operation on all feeds or one specific feed and displays the search result.
@@ -45,7 +48,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
private static final String ARG_QUERY = "query";
private static final String ARG_FEED = "feed";
- private SearchlistAdapter searchAdapter;
+ private FeedItemlistAdapter searchAdapter;
private List<FeedComponent> searchResults = new ArrayList<>();
private Disposable disposable;
private ProgressBar progressBar;
@@ -105,7 +108,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
View layout = inflater.inflate(R.layout.search_fragment, container, false);
ListView listView = layout.findViewById(R.id.listview);
progressBar = layout.findViewById(R.id.progressBar);
- searchAdapter = new SearchlistAdapter(getActivity(), itemAccess);
+ searchAdapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, true, true);
listView.setAdapter(searchAdapter);
listView.setOnItemClickListener(this);
@@ -164,6 +167,14 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
search();
}
+ @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(DownloadEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if (searchAdapter != null) {
+ searchAdapter.notifyDataSetChanged();
+ }
+ }
+
private void onSearchResults(List<FeedComponent> results) {
progressBar.setVisibility(View.GONE);
searchResults = results;
@@ -172,7 +183,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
emptyViewHandler.setMessage(getString(R.string.no_results_for_query, query));
}
- private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() {
+ private final FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
@Override
public int getCount() {
return searchResults.size();
diff --git a/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java b/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java
new file mode 100644
index 000000000..4b3c51cfc
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java
@@ -0,0 +1,87 @@
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+import androidx.annotation.Nullable;
+
+public class CircularProgressBar extends View {
+ private static final float EPSILON = 0.005f;
+
+ private final Paint paintBackground = new Paint();
+ private final Paint paintProgress = new Paint();
+ private float percentage = 0;
+ private float targetPercentage = 0;
+ private Object tag = null;
+
+ public CircularProgressBar(Context context) {
+ super(context);
+ setup();
+ }
+
+ public CircularProgressBar(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ setup();
+ }
+
+ public CircularProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setup();
+ }
+
+ private void setup() {
+ paintBackground.setAntiAlias(true);
+ paintBackground.setStyle(Paint.Style.STROKE);
+
+ paintProgress.setAntiAlias(true);
+ paintProgress.setStyle(Paint.Style.STROKE);
+ paintProgress.setStrokeCap(Paint.Cap.ROUND);
+
+ int[] colorAttrs = new int[] { android.R.attr.textColorPrimary, android.R.attr.textColorSecondary };
+ TypedArray a = getContext().obtainStyledAttributes(colorAttrs);
+ paintProgress.setColor(a.getColor(0, 0xffffffff));
+ paintBackground.setColor(a.getColor(1, 0xffffffff));
+ a.recycle();
+ }
+
+ /**
+ * Sets the percentage to be displayed.
+ * @param percentage Number from 0 to 1
+ * @param tag When the tag is the same as last time calling setPercentage, the update is animated
+ */
+ public void setPercentage(float percentage, Object tag) {
+ targetPercentage = percentage;
+
+ if (tag == null || !tag.equals(this.tag)) {
+ // Do not animate
+ this.percentage = percentage;
+ this.tag = tag;
+ }
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ float padding = getHeight() * 0.06f;
+ paintBackground.setStrokeWidth(getHeight() * 0.02f);
+ paintProgress.setStrokeWidth(padding);
+ RectF bounds = new RectF(padding, padding, getWidth() - padding, getHeight() - padding);
+ canvas.drawArc(bounds, 0, 360, false, paintBackground);
+
+ if (percentage > EPSILON && 1 - percentage > EPSILON) {
+ canvas.drawArc(bounds, -90, percentage * 360, false, paintProgress);
+ }
+
+ if (Math.abs(percentage - targetPercentage) > EPSILON) {
+ float delta = Math.min(0.02f, Math.abs(targetPercentage - percentage));
+ percentage += delta * ((targetPercentage - percentage) > 0 ? 1f : -1f);
+ invalidate();
+ }
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/DownloadItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/DownloadItemViewHolder.java
new file mode 100644
index 000000000..d48db196f
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/DownloadItemViewHolder.java
@@ -0,0 +1,41 @@
+package de.danoeh.antennapod.view.viewholder;
+
+import android.content.Context;
+import android.os.Build;
+import android.text.Layout;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import androidx.recyclerview.widget.RecyclerView;
+import com.joanzapata.iconify.widget.IconTextView;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.view.CircularProgressBar;
+
+public class DownloadItemViewHolder extends RecyclerView.ViewHolder {
+ public final View secondaryActionButton;
+ public final ImageView secondaryActionIcon;
+ public final CircularProgressBar secondaryActionProgress;
+ public final IconTextView icon;
+ public final TextView title;
+ public final TextView type;
+ public final TextView date;
+ public final TextView reason;
+
+ public DownloadItemViewHolder(Context context, ViewGroup parent) {
+ super(LayoutInflater.from(context).inflate(R.layout.downloadlog_item, parent, false));
+ date = itemView.findViewById(R.id.txtvDate);
+ type = itemView.findViewById(R.id.txtvType);
+ icon = itemView.findViewById(R.id.txtvIcon);
+ reason = itemView.findViewById(R.id.txtvReason);
+ secondaryActionProgress = itemView.findViewById(R.id.secondaryActionProgress);
+ secondaryActionButton = itemView.findViewById(R.id.secondaryActionButton);
+ secondaryActionIcon = itemView.findViewById(R.id.secondaryActionIcon);
+ title = itemView.findViewById(R.id.txtvTitle);
+ if (Build.VERSION.SDK_INT >= 23) {
+ title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
+ itemView.setTag(this);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
new file mode 100644
index 000000000..369574190
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
@@ -0,0 +1,213 @@
+package de.danoeh.antennapod.view.viewholder;
+
+import android.graphics.Color;
+import android.os.Build;
+import android.text.Layout;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import androidx.cardview.widget.CardView;
+import androidx.recyclerview.widget.RecyclerView;
+import com.joanzapata.iconify.Iconify;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.adapter.CoverLoader;
+import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
+import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.feed.MediaType;
+import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
+import de.danoeh.antennapod.core.service.download.DownloadRequest;
+import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.core.util.ThemeUtils;
+import de.danoeh.antennapod.view.CircularProgressBar;
+
+/**
+ * Holds the view which shows FeedItems.
+ */
+public class EpisodeItemViewHolder extends FeedComponentViewHolder
+ implements QueueRecyclerAdapter.ItemTouchHelperViewHolder {
+ private static final String TAG = "EpisodeItemViewHolder";
+
+ private final View container;
+ public final ImageView dragHandle;
+ private final TextView placeholder;
+ private final ImageView cover;
+ private final TextView title;
+ private final TextView pubDate;
+ private final TextView position;
+ private final TextView duration;
+ private final TextView size;
+ public final TextView isNew;
+ public final ImageView isInQueue;
+ private final ImageView isVideo;
+ public final ImageView isFavorite;
+ private final ProgressBar progressBar;
+ public final View secondaryActionButton;
+ public final ImageView secondaryActionIcon;
+ private final CircularProgressBar secondaryActionProgress;
+ private final TextView separatorIcons;
+ public final CardView coverHolder;
+
+ private final MainActivity activity;
+ private FeedItem item;
+
+ public EpisodeItemViewHolder(MainActivity activity, ViewGroup parent) {
+ super(LayoutInflater.from(activity).inflate(R.layout.feeditemlist_item, parent, false));
+ this.activity = activity;
+ container = itemView.findViewById(R.id.container);
+ dragHandle = itemView.findViewById(R.id.drag_handle);
+ placeholder = itemView.findViewById(R.id.txtvPlaceholder);
+ cover = itemView.findViewById(R.id.imgvCover);
+ title = itemView.findViewById(R.id.txtvTitle);
+ if (Build.VERSION.SDK_INT >= 23) {
+ title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
+ pubDate = itemView.findViewById(R.id.txtvPubDate);
+ position = itemView.findViewById(R.id.txtvPosition);
+ duration = itemView.findViewById(R.id.txtvDuration);
+ progressBar = itemView.findViewById(R.id.progressBar);
+ isInQueue = itemView.findViewById(R.id.ivInPlaylist);
+ isVideo = itemView.findViewById(R.id.ivIsVideo);
+ isNew = itemView.findViewById(R.id.statusUnread);
+ isFavorite = itemView.findViewById(R.id.isFavorite);
+ size = itemView.findViewById(R.id.size);
+ separatorIcons = itemView.findViewById(R.id.separatorIcons);
+ secondaryActionProgress = itemView.findViewById(R.id.secondaryActionProgress);
+ secondaryActionButton = itemView.findViewById(R.id.secondaryActionButton);
+ secondaryActionIcon = itemView.findViewById(R.id.secondaryActionIcon);
+ coverHolder = itemView.findViewById(R.id.coverHolder);
+ itemView.setTag(this);
+ }
+
+ @Override
+ public void onItemSelected() {
+ itemView.setAlpha(0.5f);
+ }
+
+ @Override
+ public void onItemClear() {
+ itemView.setAlpha(1.0f);
+ }
+
+ public void bind(FeedItem item) {
+ this.item = item;
+ placeholder.setText(item.getFeed().getTitle());
+ title.setText(item.getTitle());
+ pubDate.setText(DateUtils.formatAbbrev(activity, item.getPubDate()));
+ isNew.setVisibility(item.isNew() ? View.VISIBLE : View.GONE);
+ isFavorite.setVisibility(item.isTagged(FeedItem.TAG_FAVORITE) ? View.VISIBLE : View.GONE);
+ isInQueue.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE);
+ itemView.setAlpha(item.isPlayed() ? 0.5f : 1.0f);
+
+ ItemActionButton actionButton = ItemActionButton.forItem(item, true, true);
+ actionButton.configure(secondaryActionButton, secondaryActionIcon, activity);
+ secondaryActionButton.setFocusable(false);
+
+ if (item.getMedia() != null) {
+ bind(item.getMedia());
+ } else {
+ secondaryActionProgress.setPercentage(0, item);
+ }
+
+ if (coverHolder.getVisibility() == View.VISIBLE) {
+ new CoverLoader(activity)
+ .withUri(ImageResourceUtils.getImageLocation(item))
+ .withFallbackUri(item.getFeed().getImageLocation())
+ .withPlaceholderView(placeholder)
+ .withCoverView(cover)
+ .load();
+ }
+ }
+
+ private void bind(FeedMedia media) {
+ isVideo.setVisibility(media.getMediaType() == MediaType.VIDEO ? View.VISIBLE : View.GONE);
+ duration.setText(Converter.getDurationStringLong(media.getDuration()));
+
+ if (media.isCurrentlyPlaying()) {
+ container.setBackgroundColor(ThemeUtils.getColorFromAttr(activity, R.attr.currently_playing_background));
+ } else {
+ container.setBackgroundResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.selectableItemBackground));
+ }
+
+ if (DownloadRequester.getInstance().isDownloadingFile(media)) {
+ final DownloadRequest downloadRequest = DownloadRequester.getInstance().getRequestFor(media);
+ float percent = 0.01f * downloadRequest.getProgressPercent();
+ secondaryActionProgress.setPercentage(Math.max(percent, 0.01f), item);
+ } else if (media.isDownloaded()) {
+ secondaryActionProgress.setPercentage(1, item); // Do not animate 100% -> 0%
+ } else {
+ secondaryActionProgress.setPercentage(0, item); // Animate X% -> 0%
+ }
+
+ if (media.getDuration() > 0
+ && (item.getState() == FeedItem.State.PLAYING || item.getState() == FeedItem.State.IN_PROGRESS)) {
+ int progress = (int) (100.0 * media.getPosition() / media.getDuration());
+ progressBar.setProgress(progress);
+ position.setText(Converter.getDurationStringLong(media.getPosition()));
+ duration.setText(Converter.getDurationStringLong(media.getDuration()));
+ progressBar.setVisibility(View.VISIBLE);
+ position.setVisibility(View.VISIBLE);
+ } else {
+ progressBar.setVisibility(View.GONE);
+ position.setVisibility(View.GONE);
+ }
+
+ if (media.getSize() > 0) {
+ size.setText(Converter.byteToString(media.getSize()));
+ } else if (NetworkUtils.isEpisodeHeadDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
+ size.setText("{fa-spinner}");
+ Iconify.addIcons(size);
+ NetworkUtils.getFeedMediaSizeObservable(media).subscribe(
+ sizeValue -> {
+ if (sizeValue > 0) {
+ size.setText(Converter.byteToString(sizeValue));
+ } else {
+ size.setText("");
+ }
+ }, error -> {
+ size.setText("");
+ Log.e(TAG, Log.getStackTraceString(error));
+ });
+ } else {
+ size.setText("");
+ }
+ }
+
+ public FeedItem getFeedItem() {
+ return item;
+ }
+
+ public boolean isCurrentlyPlayingItem() {
+ return item.getMedia() != null && item.getMedia().isCurrentlyPlaying();
+ }
+
+ public void notifyPlaybackPositionUpdated(PlaybackPositionEvent event) {
+ progressBar.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
+ position.setText(Converter.getDurationStringLong(event.getPosition()));
+ duration.setText(Converter.getDurationStringLong(event.getDuration()));
+ }
+
+ /**
+ * Hides the separator dot between icons and text if there are no icons.
+ */
+ public void hideSeparatorIfNecessary() {
+ boolean hasIcons = isNew.getVisibility() == View.VISIBLE
+ || isInQueue.getVisibility() == View.VISIBLE
+ || isVideo.getVisibility() == View.VISIBLE
+ || isFavorite.getVisibility() == View.VISIBLE
+ || isNew.getVisibility() == View.VISIBLE;
+ separatorIcons.setVisibility(hasIcons ? View.VISIBLE : View.GONE);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedComponentViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedComponentViewHolder.java
new file mode 100644
index 000000000..f55ea9bc8
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedComponentViewHolder.java
@@ -0,0 +1,15 @@
+package de.danoeh.antennapod.view.viewholder;
+
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Holds the view which shows FeedComponents.
+ */
+public class FeedComponentViewHolder extends RecyclerView.ViewHolder {
+
+ public FeedComponentViewHolder(@NonNull View itemView) {
+ super(itemView);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedViewHolder.java
new file mode 100644
index 000000000..83250bbfa
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/FeedViewHolder.java
@@ -0,0 +1,62 @@
+package de.danoeh.antennapod.view.viewholder;
+
+import android.os.Build;
+import android.text.Layout;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import androidx.cardview.widget.CardView;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.adapter.CoverLoader;
+import de.danoeh.antennapod.core.feed.Feed;
+
+/**
+ * Holds the view which shows feeds.
+ */
+public class FeedViewHolder extends FeedComponentViewHolder {
+ private static final String TAG = "FeedViewHolder";
+
+ private final TextView placeholder;
+ private final ImageView cover;
+ private final TextView title;
+ public final CardView coverHolder;
+
+ private final MainActivity activity;
+ private Feed feed;
+
+ public FeedViewHolder(MainActivity activity, ViewGroup parent) {
+ super(LayoutInflater.from(activity).inflate(R.layout.feeditemlist_item, parent, false));
+ this.activity = activity;
+ placeholder = itemView.findViewById(R.id.txtvPlaceholder);
+ cover = itemView.findViewById(R.id.imgvCover);
+ coverHolder = itemView.findViewById(R.id.coverHolder);
+ title = itemView.findViewById(R.id.txtvTitle);
+ if (Build.VERSION.SDK_INT >= 23) {
+ title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
+
+ itemView.findViewById(R.id.secondaryActionButton).setVisibility(View.GONE);
+ itemView.findViewById(R.id.status).setVisibility(View.GONE);
+ itemView.findViewById(R.id.progress).setVisibility(View.GONE);
+ itemView.findViewById(R.id.drag_handle).setVisibility(View.GONE);
+ itemView.setTag(this);
+ }
+
+ public void bind(Feed feed) {
+ this.feed = feed;
+ placeholder.setText(feed.getTitle());
+ title.setText(feed.getTitle());
+
+ if (coverHolder.getVisibility() == View.VISIBLE) {
+ new CoverLoader(activity)
+ .withUri(feed.getImageLocation())
+ .withPlaceholderView(placeholder)
+ .withCoverView(cover)
+ .load();
+ }
+ }
+
+}