diff options
64 files changed, 1245 insertions, 2226 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java index cc380813e..efd6070bb 100644 --- a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java @@ -228,7 +228,7 @@ public class PlaybackTest { final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10); Matcher<View> allEpisodesMatcher = allOf(withId(android.R.id.list), isDisplayed(), hasMinimumChildCount(2)); onView(isRoot()).perform(waitForView(allEpisodesMatcher, 1000)); - onView(allEpisodesMatcher).perform(actionOnItemAtPosition(0, clickChildViewWithId(R.id.butSecondaryAction))); + onView(allEpisodesMatcher).perform(actionOnItemAtPosition(0, clickChildViewWithId(R.id.secondaryActionButton))); FeedMedia media = episodes.get(0).getMedia(); Awaitility.await().atMost(1, TimeUnit.SECONDS).until( @@ -244,7 +244,7 @@ public class PlaybackTest { Matcher<View> queueMatcher = allOf(withId(R.id.recyclerView), isDisplayed(), hasMinimumChildCount(2)); onView(isRoot()).perform(waitForView(queueMatcher, 1000)); - onView(queueMatcher).perform(actionOnItemAtPosition(itemIdx, clickChildViewWithId(R.id.butSecondaryAction))); + onView(queueMatcher).perform(actionOnItemAtPosition(itemIdx, clickChildViewWithId(R.id.secondaryActionButton))); FeedMedia media = queue.get(itemIdx).getMedia(); Awaitility.await().atMost(1, TimeUnit.SECONDS).until( 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(); + } + } + +} diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml index 784e7a1c8..2ccfe2494 100644 --- a/app/src/main/res/layout/all_episodes_fragment.xml +++ b/app/src/main/res/layout/all_episodes_fragment.xml @@ -34,7 +34,7 @@ app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable" app:fastScrollVerticalTrackDrawable="@drawable/line_drawable" tools:itemCount="13" - tools:listitem="@layout/new_episodes_listitem" /> + tools:listitem="@layout/feeditemlist_item" /> <ProgressBar android:id="@+id/progLoading" diff --git a/app/src/main/res/layout/downloaded_episodeslist_item.xml b/app/src/main/res/layout/downloaded_episodeslist_item.xml deleted file mode 100644 index 3f8065466..000000000 --- a/app/src/main/res/layout/downloaded_episodeslist_item.xml +++ /dev/null @@ -1,102 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - tools:background="@android:color/darker_gray"> - - <ImageView - android:id="@+id/imgvImage" - android:layout_width="@dimen/thumbnail_length_downloaded_item" - android:layout_height="@dimen/thumbnail_length_downloaded_item" - android:layout_gravity="center_vertical" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:contentDescription="@string/cover_label" - android:scaleType="centerCrop" - tools:src="@drawable/ic_antenna" - tools:background="@android:color/holo_green_dark"/> - - - <LinearLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding" - android:layout_marginStart="@dimen/listitem_threeline_textleftpadding" - android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" - android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_weight="1" - android:orientation="vertical" - tools:background="@android:color/holo_red_dark"> - - <TextView - android:id="@+id/txtvTitle" - style="@style/AntennaPod.TextView.ListItemPrimaryTitle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="4dp" - tools:text="Downloaded episode title" - tools:background="@android:color/holo_green_dark"/> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - tools:background="@android:color/holo_red_dark" > - - <TextView - android:id="@+id/txtvSize" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - tools:text="23 MB" - tools:background="@android:color/holo_green_dark"/> - - <View - android:layout_width="0dip" - android:layout_height="1dip" - android:layout_weight="1" /> - - <ImageView - android:id="@+id/imgvInPlaylist" - android:layout_width="@dimen/enc_icons_size" - android:layout_height="@dimen/enc_icons_size" - android:contentDescription="@string/in_queue_label" - android:src="?attr/stat_playlist" - android:visibility="visible" - tools:src="@drawable/ic_list_white_24dp" - tools:background="@android:color/holo_red_light"/> - - <TextView - android:id="@+id/txtvPublished" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - tools:text="Jan 23" - tools:background="@android:color/holo_green_dark"/> - - </LinearLayout> - </LinearLayout> - - <include layout="@layout/vertical_list_divider"/> - - <ImageButton - android:id="@+id/butSecondaryAction" - android:layout_width="@dimen/listview_secondary_button_width" - android:layout_height="match_parent" - android:background="?attr/selectableItemBackground" - android:clickable="false" - android:contentDescription="@string/delete_episode_label" - android:focusable="false" - android:focusableInTouchMode="false" - android:src="?attr/content_discard" - tools:src="@drawable/ic_delete_white_24dp" - tools:background="@android:color/holo_green_dark" /> - -</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/downloadlist_item.xml b/app/src/main/res/layout/downloadlist_item.xml index 668ec817a..7a4c2fede 100644 --- a/app/src/main/res/layout/downloadlist_item.xml +++ b/app/src/main/res/layout/downloadlist_item.xml @@ -1,90 +1,39 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - tools:background="@android:color/darker_gray"> - - <LinearLayout - android:layout_width="0dp" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" - android:orientation="vertical"> + android:orientation="horizontal" + android:gravity="center_vertical" + android:baselineAligned="false" + android:descendantFocusability="blocksDescendants"> - <TextView - android:id="@+id/txtvTitle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:ellipsize="end" - android:lines="1" - android:textColor="?android:attr/textColorPrimary" - android:textSize="16sp" - tools:text="Download item title" - tools:background="@android:color/holo_green_dark" /> - - <ProgressBar - android:id="@+id/progProgress" - style="?android:attr/progressBarStyleHorizontal" - android:layout_width="match_parent" - android:layout_height="16dp" - android:layout_marginBottom="4dp" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginTop="4dp" - tools:background="@android:color/holo_blue_light" /> - - <RelativeLayout - android:layout_width="match_parent" + <LinearLayout + android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding"> - - <TextView - android:id="@+id/txtvDownloaded" - android:layout_width="wrap_content" + android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" + android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" + android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" + android:layout_marginLeft="16dp" + android:layout_marginStart="16dp" + android:layout_weight="1" + android:orientation="vertical"> + <TextView + android:id="@+id/txtvTitle" + style="@style/AntennaPod.TextView.ListItemPrimaryTitle" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:ellipsize="end" - android:lines="1" - android:textColor="?android:attr/textColorPrimary" - android:textSize="@dimen/text_size_small" - tools:text="21 MB / 42 MB" - tools:background="@android:color/holo_green_dark" /> - - <TextView - android:id="@+id/txtvPercent" + tools:text="@sample/episodes.json/data/title" + android:ellipsize="end"/> + <TextView + android:id="@+id/txtvStatus" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:ellipsize="end" - android:lines="1" - android:textColor="?android:attr/textColorPrimary" - android:textSize="@dimen/text_size_small" - tools:text="50%" - tools:background="@android:color/holo_green_dark" /> - </RelativeLayout> - + tools:text="Media file · 10MB / 20MB"/> </LinearLayout> - - <include layout="@layout/vertical_list_divider"/> - - <ImageButton - android:id="@+id/butSecondaryAction" - android:layout_width="@dimen/listview_secondary_button_width" - android:layout_height="match_parent" - android:background="?attr/selectableItemBackground" - android:clickable="false" - android:contentDescription="@string/cancel_download_label" - android:focusable="false" - android:focusableInTouchMode="false" - android:src="?attr/navigation_cancel" - tools:src="@drawable/ic_cancel_white_24dp" - tools:background="@android:color/holo_green_dark" /> + <include layout="@layout/secondary_action"/> </LinearLayout> diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml index 505102ea4..c8cbf15f6 100644 --- a/app/src/main/res/layout/downloadlog_item.xml +++ b/app/src/main/res/layout/downloadlog_item.xml @@ -1,97 +1,90 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="8dp" - android:paddingLeft="16dp" - android:paddingRight="16dp" - android:paddingBottom="8dp" - android:descendantFocusability="blocksDescendants" - tools:background="@android:color/darker_gray"> +<LinearLayout + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical" + android:baselineAligned="false" + android:descendantFocusability="blocksDescendants"> <com.joanzapata.iconify.widget.IconTextView - android:id="@+id/txtvIcon" - android:layout_width="48sp" - android:layout_height="48sp" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:textSize="48sp" - android:gravity="center" /> + android:id="@+id/txtvIcon" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" + android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" + android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding" + android:layout_marginStart="@dimen/listitem_threeline_textleftpadding" + android:textSize="40dp" + android:gravity="center" + tools:text="X"/> - <com.joanzapata.iconify.widget.IconButton - android:id="@+id/btnRetry" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@id/txtvIcon" - android:layout_alignLeft="@id/txtvIcon" - android:layout_alignStart="@id/txtvIcon" - android:layout_alignRight="@id/txtvIcon" - android:layout_alignEnd="@id/txtvIcon" - android:layout_marginTop="8dp" - android:text="{fa-repeat}" - tools:text="↻" /> + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" + android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" + android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" + android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" + android:layout_marginLeft="16dp" + android:layout_marginStart="16dp" + android:layout_weight="1" + android:orientation="vertical"> - <TextView - android:id="@+id/txtvType" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - android:layout_marginBottom="8dp" - tools:text="Media file" - tools:background="@android:color/holo_green_dark" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/status" + android:orientation="horizontal" + android:gravity="center_vertical"> - <TextView - android:id="@+id/txtvTitle" - style="@style/AntennaPod.TextView.ListItemPrimaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_toRightOf="@id/txtvIcon" - android:layout_toEndOf="@id/txtvIcon" - android:layout_toLeftOf="@id/txtvType" - android:layout_toStartOf="@id/txtvType" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - android:layout_marginBottom="8dp" - android:minLines="1" - android:maxLines="2" - tools:text="Download item title" - tools:background="@android:color/holo_blue_light" /> + <TextView + android:id="@+id/txtvType" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="Media file"/> + <TextView + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:layout_marginEnd="4dp" + android:layout_marginLeft="4dp" + android:layout_marginStart="4dp" + android:text="·" + tools:background="@android:color/holo_blue_light"/> + <TextView + android:id="@+id/txtvDate" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="January 23"/> - <TextView - android:id="@+id/txtvDate" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/txtvIcon" - android:layout_toEndOf="@id/txtvIcon" - android:layout_below="@id/txtvTitle" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - android:layout_marginBottom="8dp" - tools:text="January 23" - tools:background="@android:color/holo_green_dark" /> + </LinearLayout> + <TextView + android:id="@+id/txtvTitle" + style="@style/AntennaPod.TextView.ListItemPrimaryTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + tools:text="@sample/episodes.json/data/title" + android:ellipsize="end" + tools:background="@android:color/holo_blue_light"/> - <TextView - android:id="@+id/txtvReason" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@id/txtvDate" - android:layout_toRightOf="@id/txtvIcon" - android:layout_toEndOf="@id/txtvIcon" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - android:textColor="?android:attr/textColorTertiary" - android:textSize="@dimen/text_size_micro" - tools:text="@string/design_time_downloaded_log_failure_reason" - tools:background="@android:color/holo_green_dark" /> + <TextView + android:id="@+id/txtvReason" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="14sp" + android:textColor="?android:attr/textColorSecondary" + tools:text="@string/design_time_downloaded_log_failure_reason"/> + + </LinearLayout> + + <include layout="@layout/secondary_action"/> -</RelativeLayout>
\ No newline at end of file +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/feeditemlist_item.xml b/app/src/main/res/layout/feeditemlist_item.xml index adf0748eb..11656fefc 100644 --- a/app/src/main/res/layout/feeditemlist_item.xml +++ b/app/src/main/res/layout/feeditemlist_item.xml @@ -1,124 +1,203 @@ <?xml version="1.0" encoding="utf-8"?> - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - tools:background="@android:color/darker_gray"> - - <RelativeLayout - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" - android:layout_weight="1" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - tools:background="@android:color/holo_orange_dark"> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical" + android:baselineAligned="false"> - <TextView - android:id="@+id/statusUnread" - style="@style/AntennaPod.TextView.UnreadIndicator" + <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_alignParentTop="true" - android:layout_marginLeft="8dp" - android:layout_marginRight="8dp" - tools:text="NEW" - tools:background="@android:color/white" /> + android:layout_height="match_parent" + android:minWidth="16dp"> + <ImageView + android:id="@+id/drag_handle" + android:layout_width="36dp" + android:layout_height="match_parent" + android:contentDescription="@string/drag_handle_content_description" + android:scaleType="center" + android:src="?attr/dragview_background" + tools:src="@drawable/ic_drag_vertical_grey600_48dp" + tools:background="@android:color/holo_green_dark"/> - <TextView - android:id="@+id/txtvItemname" - style="@style/AntennaPod.TextView.ListItemPrimaryTitle" + </LinearLayout> + + <androidx.cardview.widget.CardView + android:layout_width="@dimen/thumbnail_length_queue_item" + android:layout_height="@dimen/thumbnail_length_queue_item" + android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" + android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" + android:layout_marginRight="@dimen/listitem_threeline_textleftpadding" + android:layout_marginEnd="@dimen/listitem_threeline_textleftpadding" + android:id="@+id/coverHolder" + app:cardCornerRadius="4dp" + app:cardElevation="0dp"> + + <RelativeLayout + android:layout_width="@dimen/thumbnail_length_queue_item" + android:layout_height="@dimen/thumbnail_length_queue_item"> + + <TextView + android:id="@+id/txtvPlaceholder" + android:layout_width="@dimen/thumbnail_length_queue_item" + android:layout_height="@dimen/thumbnail_length_queue_item" + android:layout_centerVertical="true" + android:gravity="center" + android:background="@color/light_gray" + android:maxLines="3" + android:padding="2dp" + android:ellipsize="end"/> + <ImageView + android:id="@+id/imgvCover" + android:layout_width="@dimen/thumbnail_length_queue_item" + android:layout_height="@dimen/thumbnail_length_queue_item" + android:layout_centerVertical="true" + android:contentDescription="@string/cover_label" + tools:src="@tools:sample/avatars"/> + + </RelativeLayout> + </androidx.cardview.widget.CardView> + + <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_alignParentTop="true" - android:layout_marginBottom="4dp" - android:layout_toLeftOf="@id/statusUnread" - android:layout_toStartOf="@id/statusUnread" - tools:text="Episode title" - tools:background="@android:color/holo_green_dark" /> + android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" + android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" + android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" + android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" + android:layout_weight="1" + tools:background="@android:color/holo_red_dark" + android:orientation="vertical"> - <TextView - android:id="@+id/txtvLenSize" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_below="@id/txtvItemname" - tools:text="00:42:23" - tools:background="@android:color/holo_green_dark" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/status" + android:orientation="horizontal" + android:gravity="center_vertical"> - <ImageView - android:id="@+id/imgvInPlaylist" - android:layout_width="@dimen/enc_icons_size" - android:layout_height="@dimen/enc_icons_size" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_below="@id/txtvItemname" - android:layout_marginRight="8dp" - android:layout_marginEnd="8dp" - android:contentDescription="@string/in_queue_label" - android:src="?attr/stat_playlist" - android:visibility="visible" - tools:src="@drawable/ic_list_white_24dp" - tools:background="@android:color/holo_red_light" /> + <TextView + android:text="@string/new_episodes_label" + style="@style/AntennaPod.TextView.UnreadIndicator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/statusUnread" + android:layout_marginRight="4dp" + android:layout_marginEnd="4dp" + tools:text="@sample/episodes.json/data/status_label"/> - <ImageView - android:id="@+id/imgvType" - android:layout_width="@dimen/enc_icons_size" - android:layout_height="@dimen/enc_icons_size" - android:layout_below="@id/txtvItemname" - android:layout_marginRight="8dp" - android:layout_marginEnd="8dp" - android:layout_toLeftOf="@id/imgvInPlaylist" - android:layout_toStartOf="@id/imgvInPlaylist" - tools:ignore="ContentDescription" - tools:src="@drawable/ic_hearing_white_18dp" - tools:background="@android:color/holo_red_light" /> + <ImageView + android:layout_width="14sp" + android:layout_height="14sp" + app:srcCompat="?attr/type_video" + tools:srcCompat="@drawable/ic_videocam_grey600_24dp" + android:id="@+id/ivIsVideo"/> + + <ImageView + android:layout_width="14sp" + android:layout_height="14sp" + app:srcCompat="?attr/ic_unfav" + tools:srcCompat="@drawable/ic_star_grey600_24dp" + android:id="@+id/isFavorite"/> + <ImageView + android:layout_width="14sp" + android:layout_height="14sp" + app:srcCompat="?attr/stat_playlist" + tools:srcCompat="@drawable/ic_list_grey600_24dp" + android:id="@+id/ivInPlaylist"/> + + <TextView + android:id="@+id/separatorIcons" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="4dp" + android:layout_marginStart="4dp" + android:layout_marginRight="4dp" + android:layout_marginEnd="4dp" + android:text="·" + tools:background="@android:color/holo_blue_light"/> + + <TextView + android:id="@+id/txtvPubDate" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:layout_marginEnd="4dp" + tools:text="@sample/episodes.json/data/published_at"/> + + <TextView + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:layout_marginEnd="4dp" + android:text="·" + tools:background="@android:color/holo_blue_light"/> + + <TextView + android:id="@+id/size" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_marginRight="4dp" + android:layout_marginEnd="4dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="10 MB"/> + + </LinearLayout> <TextView - android:id="@+id/txtvPublished" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@id/txtvItemname" - android:layout_marginRight="8dp" - android:layout_marginEnd="8dp" - android:layout_toLeftOf="@id/imgvType" - android:layout_toStartOf="@id/imgvType" - tools:text="Jan 23" - tools:background="@android:color/holo_green_dark" /> - - <ProgressBar - android:id="@+id/pbar_episode_progress" - style="?android:attr/progressBarStyleHorizontal" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_alignBottom="@id/txtvPublished" - android:layout_marginLeft="8dp" - android:layout_marginRight="8dp" - android:layout_toStartOf="@id/txtvPublished" - android:layout_toLeftOf="@id/txtvPublished" - android:layout_toEndOf="@id/txtvLenSize" - android:layout_toRightOf="@id/txtvLenSize" - android:layoutDirection="ltr" - android:indeterminate="false" - android:max="100" - android:progress="42" - tools:background="@android:color/holo_blue_light" /> - - </RelativeLayout> - - <include layout="@layout/vertical_list_divider"/> + android:id="@+id/txtvTitle" + style="@style/AntennaPod.TextView.ListItemPrimaryTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + tools:text="@sample/episodes.json/data/title" + android:ellipsize="end" + tools:background="@android:color/holo_blue_light"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/progress" + android:orientation="horizontal" + android:gravity="center_vertical"> + + <TextView + android:id="@+id/txtvPosition" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="0dp" + tools:text="00:42:23" + tools:background="@android:color/holo_blue_light"/> + + <ProgressBar + android:id="@+id/progressBar" + style="?attr/progressBarTheme" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="4dp" + android:max="100" + android:layout_margin="4dp" + tools:background="@android:color/holo_blue_light"/> + + <TextView + android:id="@+id/txtvDuration" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="0dp" + tools:text="@sample/episodes.json/data/duration" + tools:background="@android:color/holo_blue_light"/> + + </LinearLayout> + + </LinearLayout> <include layout="@layout/secondary_action"/> diff --git a/app/src/main/res/layout/new_episodes_listitem.xml b/app/src/main/res/layout/new_episodes_listitem.xml deleted file mode 100644 index 150d692e7..000000000 --- a/app/src/main/res/layout/new_episodes_listitem.xml +++ /dev/null @@ -1,147 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<FrameLayout - android:id="@+id/container" - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - -<LinearLayout - android:id="@+id/content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/selectableItemBackground" - android:orientation="horizontal" - android:gravity="center_vertical"> - - <RelativeLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - - <TextView - android:id="@+id/txtvPlaceholder" - android:layout_width="@dimen/thumbnail_length_itemlist" - android:layout_height="@dimen/thumbnail_length_itemlist" - android:layout_gravity="center_vertical" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:background="@color/light_gray" - android:ellipsize="end" - android:maxLines="3" - android:gravity="center"/> - - <ImageView - android:id="@+id/imgvCover" - android:layout_height="64dp" - android:layout_width="64dp" - android:layout_alignLeft="@id/txtvPlaceholder" - android:layout_alignStart="@id/txtvPlaceholder" - android:layout_alignTop="@id/txtvPlaceholder" - android:layout_alignRight="@id/txtvPlaceholder" - android:layout_alignEnd="@id/txtvPlaceholder" - android:layout_alignBottom="@id/txtvPlaceholder" - android:contentDescription="@string/cover_label" - tools:src="@tools:sample/avatars" /> - - </RelativeLayout> - - <RelativeLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding" - android:layout_marginStart="@dimen/listitem_threeline_textleftpadding" - android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" - android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:layout_weight="1"> - - - <TextView - android:id="@+id/statusUnread" - style="@style/AntennaPod.TextView.UnreadIndicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_alignParentTop="true" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - tools:text="@sample/episodes.json/data/status_label"/> - - <TextView - android:id="@+id/txtvTitle" - style="@style/AntennaPod.TextView.ListItemPrimaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_alignParentTop="true" - android:layout_toLeftOf="@id/statusUnread" - android:layout_toStartOf="@id/statusUnread" - tools:text="@sample/episodes.json/data/title" /> - - <RelativeLayout - android:id="@+id/bottom_bar" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_below="@id/txtvTitle" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true"> - - <TextView - android:id="@+id/txtvDuration" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - tools:text="@sample/episodes.json/data/duration" /> - - <ImageView - android:id="@+id/imgvInPlaylist" - android:layout_width="@dimen/enc_icons_size" - android:layout_height="@dimen/enc_icons_size" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - android:contentDescription="@string/in_queue_label" - android:src="?attr/stat_playlist" - tools:src="@sample/inplaylist" /> - - <TextView - android:id="@+id/txtvPublished" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_toLeftOf="@id/imgvInPlaylist" - android:layout_toStartOf="@id/imgvInPlaylist" - android:ellipsize="end" - tools:text="@sample/episodes.json/data/published_at" /> - - <ProgressBar - android:id="@+id/pbar_progress" - style="?attr/progressBarTheme" - android:layout_width="match_parent" - android:layout_height="4dp" - android:layout_below="@id/txtvDuration" - android:max="100" /> - - </RelativeLayout> - </RelativeLayout> - - <include layout="@layout/vertical_list_divider"/> - - <include layout="@layout/secondary_action" /> - -</LinearLayout> - -</FrameLayout> diff --git a/app/src/main/res/layout/queue_listitem.xml b/app/src/main/res/layout/queue_listitem.xml deleted file mode 100644 index 1dcc34bce..000000000 --- a/app/src/main/res/layout/queue_listitem.xml +++ /dev/null @@ -1,153 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<FrameLayout - android:id="@+id/container" - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - -<LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/selectableItemBackground" - android:orientation="horizontal" - android:gravity="center_vertical" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - tools:background="@android:color/darker_gray" > - - <ImageView - android:id="@+id/drag_handle" - android:layout_width="104dp" - android:layout_height="64dp" - android:layout_marginLeft="-16dp" - android:layout_marginStart="-16dp" - android:layout_marginRight="-72dp" - android:layout_marginEnd="-72dp" - android:contentDescription="@string/drag_handle_content_description" - android:scaleType="fitXY" - android:src="?attr/dragview_background" - tools:src="@drawable/ic_drag_vertical_grey600_48dp" - tools:background="@android:color/holo_green_dark" /> - - <RelativeLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp"> - <TextView - android:id="@+id/txtvPlaceholder" - android:layout_width="@dimen/thumbnail_length_queue_item" - android:layout_height="@dimen/thumbnail_length_queue_item" - android:layout_centerVertical="true" - android:gravity="center" - android:background="@color/light_gray" - android:maxLines="3" - android:ellipsize="end"/> - <ImageView - android:id="@+id/imgvCover" - android:layout_width="@dimen/thumbnail_length_queue_item" - android:layout_height="@dimen/thumbnail_length_queue_item" - android:layout_centerVertical="true" - android:contentDescription="@string/cover_label" - tools:src="@drawable/ic_antenna" - tools:background="@android:color/holo_green_dark"/> - </RelativeLayout> - - <RelativeLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding" - android:layout_marginStart="@dimen/listitem_threeline_textleftpadding" - android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" - android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:layout_weight="1" - tools:background="@android:color/holo_red_dark"> - - <!-- order is important, pubDate first! --> - <TextView - android:id="@+id/txtvPubDate" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:lines="2" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_alignParentTop="true" - android:layout_marginLeft="8dp" - android:layout_marginStart="8dp" - android:gravity="end|top" - android:text="Feb\n12" - tools:background="@android:color/holo_blue_light" /> - - <TextView - android:id="@+id/txtvTitle" - style="@style/AntennaPod.TextView.ListItemPrimaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toLeftOf="@id/txtvPubDate" - android:layout_toStartOf="@id/txtvPubDate" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_alignParentTop="true" - android:text="Queue item title" - android:ellipsize="end" - tools:background="@android:color/holo_blue_light" /> - - <RelativeLayout - android:id="@+id/bottom_bar" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_below="@id/txtvTitle" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true"> - - <TextView - android:id="@+id/txtvProgressLeft" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_marginBottom="0dp" - android:text="00:42:23" - tools:background="@android:color/holo_blue_light"/> - - <TextView - android:id="@+id/txtvProgressRight" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:layout_marginBottom="0dp" - tools:text="Jan 23" - tools:background="@android:color/holo_green_dark" /> - - <ProgressBar - android:id="@+id/progressBar" - style="?attr/progressBarTheme" - android:layout_width="match_parent" - android:layout_height="4dp" - android:layout_below="@id/txtvProgressLeft" - android:layoutDirection="ltr" - android:max="100" - tools:background="@android:color/holo_blue_light" /> - - - </RelativeLayout> - </RelativeLayout> - - <include layout="@layout/vertical_list_divider"/> - - <include layout="@layout/secondary_action"/> - -</LinearLayout> - -</FrameLayout> diff --git a/app/src/main/res/layout/search_fragment.xml b/app/src/main/res/layout/search_fragment.xml index 6f455a056..489c2d392 100644 --- a/app/src/main/res/layout/search_fragment.xml +++ b/app/src/main/res/layout/search_fragment.xml @@ -13,8 +13,5 @@ <ListView android:id="@+id/listview" android:layout_width="match_parent" - android:layout_height="match_parent" - android:clipToPadding="false" - android:paddingLeft="@dimen/list_vertical_padding" - android:paddingRight="@dimen/list_vertical_padding" /> + android:layout_height="match_parent" /> </FrameLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/secondary_action.xml b/app/src/main/res/layout/secondary_action.xml index 1f4d9e4e6..73ca174a6 100644 --- a/app/src/main/res/layout/secondary_action.xml +++ b/app/src/main/res/layout/secondary_action.xml @@ -1,12 +1,27 @@ <?xml version="1.0" encoding="utf-8"?> -<ImageButton xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/butSecondaryAction" - android:layout_width="@dimen/listview_secondary_button_width" - android:layout_height="match_parent" - android:background="?attr/selectableItemBackground" - android:clickable="false" - android:focusable="false" - android:focusableInTouchMode="false" - tools:ignore="ContentDescription" - tools:src="@sample/secondaryaction" /> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginRight="12dp" + android:layout_marginEnd="12dp" + android:id="@+id/secondaryActionButton" + android:background="?selectableItemBackgroundBorderless" + android:clickable="true" + android:focusable="false" + android:focusableInTouchMode="false" > + + <ImageView + android:id="@+id/secondaryActionIcon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center" + tools:ignore="ContentDescription" + tools:src="@sample/secondaryaction"/> + + <de.danoeh.antennapod.view.CircularProgressBar + android:id="@+id/secondaryActionProgress" + android:layout_width="40dp" + android:layout_gravity="center" + android:layout_height="40dp"/> +</FrameLayout> diff --git a/app/src/main/res/layout/simplechapter_item.xml b/app/src/main/res/layout/simplechapter_item.xml index 0d02eac1a..86927f32c 100644 --- a/app/src/main/res/layout/simplechapter_item.xml +++ b/app/src/main/res/layout/simplechapter_item.xml @@ -1,86 +1,64 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - tools:background="@android:color/darker_gray"> - - <TextView - android:id="@+id/txtvStart" - style="@style/AntennaPod.TextView.ListItemSecondaryTitle" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" android:gravity="center_vertical" - tools:text="Start" - tools:background="@android:color/holo_green_dark" /> + android:baselineAligned="false" + android:descendantFocusability="blocksDescendants"> <LinearLayout - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" - android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginEnd="@dimen/listitem_threeline_horizontalpadding" - android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" - android:layout_weight="1" - android:gravity="center_vertical" - android:orientation="vertical" - tools:background="@android:color/holo_red_dark"> + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" + android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" + android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" + android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" + android:layout_marginLeft="16dp" + android:layout_marginStart="16dp" + android:layout_weight="1" + android:orientation="vertical"> <TextView - android:id="@+id/txtvTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="4dp" - android:ellipsize="end" - android:maxLines="2" - android:textColor="?android:attr/textColorPrimary" - android:textSize="16sp" - tools:text="Chapter title" - tools:background="@android:color/holo_green_dark" /> + android:id="@+id/txtvStart" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="00:00:00"/> <TextView - android:id="@+id/txtvLink" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:focusable="false" - android:focusableInTouchMode="false" - android:maxLines="1" - android:visibility="gone" - tools:visibility="visible" - tools:text="Link" - tools:background="@android:color/holo_green_dark" /> + android:id="@+id/txtvTitle" + style="@style/AntennaPod.TextView.ListItemPrimaryTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + tools:text="@sample/episodes.json/data/title" + android:ellipsize="end"/> + + <TextView + android:id="@+id/txtvLink" + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" + android:focusable="false" + android:focusableInTouchMode="false" + android:visibility="gone" + android:background="?attr/selectableItemBackground" + tools:visibility="visible" + tools:text="https://example.com"/> <TextView android:id="@+id/txtvDuration" android:layout_width="wrap_content" android:layout_height="wrap_content" + style="@style/AntennaPod.TextView.ListItemSecondaryTitle" android:focusable="false" android:focusableInTouchMode="false" - android:maxLines="1" - tools:text="Duration" - tools:background="@android:color/holo_green_dark" /> - + tools:text="Duration: 00:00:00"/> </LinearLayout> - <include layout="@layout/vertical_list_divider" /> - - <ImageButton xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/butPlayChapter" - android:layout_width="@dimen/listview_secondary_button_width" - android:layout_height="match_parent" - android:background="?attr/selectableItemBackground" - android:clickable="false" - android:contentDescription="@string/chapters_label" - android:focusable="false" - android:focusableInTouchMode="false" - android:src="?attr/av_play" - tools:src="@drawable/ic_play_arrow_white_36dp" - tools:background="@android:color/holo_green_dark" /> + <include layout="@layout/secondary_action"/> -</LinearLayout>
\ No newline at end of file +</LinearLayout> diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java index 5d2c48679..7c998146d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.download.handler; import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.service.download.Downloader; +import de.danoeh.antennapod.core.storage.DownloadRequester; import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; @@ -23,6 +24,7 @@ public class PostDownloaderTask implements Runnable { runningDownloads.add(downloader); } } + DownloadRequester.getInstance().updateProgress(downloads); List<Downloader> list = Collections.unmodifiableList(runningDownloads); EventBus.getDefault().postSticky(DownloadEvent.refresh(list)); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 3d4ee443b..8bd9afe38 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.content.ContextCompat; +import de.danoeh.antennapod.core.service.download.Downloader; import org.apache.commons.io.FilenameUtils; import java.io.File; @@ -344,6 +345,16 @@ public class DownloadRequester implements DownloadStateProvider { } /** + * Get the downloader for this item. + */ + public synchronized DownloadRequest getRequestFor(FeedFile item) { + if (isDownloadingFile(item)) { + return downloads.get(item.getDownload_url()); + } + return null; + } + + /** * Checks if feedfile with the given download url is in the downloads list */ public synchronized boolean isDownloadingFile(String downloadUrl) { @@ -428,4 +439,13 @@ public class DownloadRequester implements DownloadStateProvider { } return filename; } + + public void updateProgress(List<Downloader> newDownloads) { + for (Downloader downloader : newDownloads) { + DownloadRequest request = downloader.getDownloadRequest(); + if (downloads.containsKey(request.getSource())) { + downloads.put(request.getSource(), request); + } + } + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index bbe8b26f1..77c8d3b7f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -35,11 +35,12 @@ public class FeedSearcher { final List<FeedComponent> result = new ArrayList<>(); try { FutureTask<List<FeedItem>> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query); - FutureTask<List<Feed>> feedSearchTask = DBTasks.searchFeeds(context, query); itemSearchTask.run(); - feedSearchTask.run(); - - result.addAll(feedSearchTask.get()); + if (selectedFeed == 0) { + FutureTask<List<Feed>> feedSearchTask = DBTasks.searchFeeds(context, query); + feedSearchTask.run(); + result.addAll(feedSearchTask.get()); + } result.addAll(itemSearchTask.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java index eabaaa828..44b31f0be 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java @@ -4,6 +4,7 @@ import android.content.Context; import androidx.annotation.AttrRes; import androidx.annotation.ColorInt; import android.util.TypedValue; +import androidx.annotation.DrawableRes; public class ThemeUtils { private ThemeUtils() { @@ -15,4 +16,10 @@ public class ThemeUtils { context.getTheme().resolveAttribute(attr, typedValue, true); return typedValue.data; } + + public static @DrawableRes int getDrawableFromAttr(Context context, @AttrRes int attr) { + TypedValue typedValue = new TypedValue(); + context.getTheme().resolveAttribute(attr, typedValue, true); + return typedValue.resourceId; + } } diff --git a/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png Binary files differdeleted file mode 100644 index 2452cfa92..000000000 --- a/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png Binary files differdeleted file mode 100644 index 96a06141a..000000000 --- a/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png Binary files differdeleted file mode 100644 index 4f1af39ab..000000000 --- a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png Binary files differdeleted file mode 100644 index abc338d51..000000000 --- a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png Binary files differdeleted file mode 100644 index ea44e3f07..000000000 --- a/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png Binary files differdeleted file mode 100644 index 78e98fe8d..000000000 --- a/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png Binary files differdeleted file mode 100644 index daa8e568e..000000000 --- a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png Binary files differdeleted file mode 100644 index a6b4ff0da..000000000 --- a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png Binary files differdeleted file mode 100644 index d014684e1..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png Binary files differdeleted file mode 100644 index 91adb4437..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png Binary files differdeleted file mode 100644 index 2039d9ce8..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png Binary files differdeleted file mode 100644 index 6dd240bca..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png Binary files differdeleted file mode 100644 index 19456de04..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png Binary files differdeleted file mode 100644 index 82de8bb65..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png Binary files differdeleted file mode 100644 index 16cdc31c1..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png Binary files differdeleted file mode 100644 index 695eb950e..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png +++ /dev/null diff --git a/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml b/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml new file mode 100644 index 000000000..40c893883 --- /dev/null +++ b/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml @@ -0,0 +1,8 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="24dp" + android:width="24dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <path android:fillColor="#FF757575" + android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/> +</vector> diff --git a/core/src/main/res/drawable/ic_videocam_white_24dp.xml b/core/src/main/res/drawable/ic_videocam_white_24dp.xml new file mode 100644 index 000000000..a8cfd71e3 --- /dev/null +++ b/core/src/main/res/drawable/ic_videocam_white_24dp.xml @@ -0,0 +1,8 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="24dp" + android:width="24dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <path android:fillColor="#FFFFFFFF" + android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/> +</vector> diff --git a/core/src/main/res/values-large/dimens.xml b/core/src/main/res/values-large/dimens.xml index 2d107eef0..27e269099 100644 --- a/core/src/main/res/values-large/dimens.xml +++ b/core/src/main/res/values-large/dimens.xml @@ -2,6 +2,4 @@ <resources> <dimen name="thumbnail_length">170dp</dimen> - <dimen name="thumbnail_length_queue_item">64dp</dimen> - <dimen name="thumbnail_length_downloaded_item">64dp</dimen> </resources>
\ No newline at end of file diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 53cf7b211..066594f3d 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -26,7 +26,6 @@ <attr name="social_share" format="reference"/> <attr name="stat_playlist" format="reference"/> <attr name="ic_folder" format="reference"/> - <attr name="type_audio" format="reference"/> <attr name="type_video" format="reference"/> <attr name="overlay_drawable" format="reference"/> <attr name="dragview_background" format="reference"/> diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index fea7da4a4..b162038cf 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -7,8 +7,8 @@ <color name="black">#000000</color> <color name="holo_blue_light">#33B5E5</color> <color name="holo_blue_dark">#0099CC</color> - <color name="download_success_green">#669900</color> - <color name="download_failed_red">#CC0000</color> + <color name="download_success_green">#248800</color> + <color name="download_failed_red">#B00020</color> <color name="status_progress">#E033B5E5</color> <color name="overlay_dark">#2C2C2C</color> <color name="overlay_light">#FFFFFF</color> diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index 02c398b62..34cbe1b72 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -10,8 +10,8 @@ <dimen name="text_size_navdrawer">16sp</dimen> <dimen name="text_size_medium">18sp</dimen> <dimen name="text_size_large">22sp</dimen> - <dimen name="thumbnail_length_itemlist">64dp</dimen> - <dimen name="thumbnail_length_queue_item">64dp</dimen> + <dimen name="thumbnail_length_itemlist">56dp</dimen> + <dimen name="thumbnail_length_queue_item">56dp</dimen> <dimen name="thumbnail_length_downloaded_item">64dp</dimen> <dimen name="thumbnail_length_onlinefeedview">100dp</dimen> <dimen name="feeditemlist_header_height">132dp</dimen> @@ -23,7 +23,7 @@ <dimen name="listitem_threeline_textleftpadding">16dp</dimen> <dimen name="listitem_threeline_textrightpadding">8dp</dimen> - <dimen name="listitem_threeline_verticalpadding">16dp</dimen> + <dimen name="listitem_threeline_verticalpadding">8dp</dimen> <dimen name="listitem_threeline_horizontalpadding">16dp</dimen> <dimen name="list_vertical_padding">8dp</dimen> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index e5d8247bc..8cb9f7b84 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -102,6 +102,7 @@ <string name="feed_volume_reduction_light">Light</string> <string name="feed_volume_reduction_heavy">Heavy</string> <string name="parallel_downloads_suffix">\u0020parallel downloads</string> + <string name="download_queued">Download queued</string> <string name="feed_auto_download_global">Global default</string> <string name="feed_auto_download_always">Always</string> <string name="feed_auto_download_never">Never</string> diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 5656ca0e9..33b736089 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -38,8 +38,7 @@ <item name="navigation_up">@drawable/navigation_up</item> <item name="social_share">@drawable/ic_share_grey600_24dp</item> <item name="stat_playlist">@drawable/ic_list_grey600_24dp</item> - <item name="type_audio">@drawable/ic_hearing_grey600_18dp</item> - <item name="type_video">@drawable/ic_remove_red_eye_grey600_18dp</item> + <item name="type_video">@drawable/ic_videocam_grey600_24dp</item> <item name="non_transparent_background">@color/white</item> <item name="overlay_background">@color/overlay_light</item> <item name="overlay_drawable">@drawable/overlay_drawable</item> @@ -127,8 +126,7 @@ <item name="navigation_up">@drawable/navigation_up_dark</item> <item name="social_share">@drawable/ic_share_white_24dp</item> <item name="stat_playlist">@drawable/ic_list_white_24dp</item> - <item name="type_audio">@drawable/ic_hearing_white_18dp</item> - <item name="type_video">@drawable/ic_remove_red_eye_white_18dp</item> + <item name="type_video">@drawable/ic_videocam_white_24dp</item> <item name="non_transparent_background">@color/black</item> <item name="overlay_background">@color/overlay_dark</item> <item name="overlay_drawable">@drawable/overlay_drawable_dark</item> @@ -291,7 +289,7 @@ <style name="AntennaPod.TextView.ListItemPrimaryTitle" parent="@android:style/TextAppearance.Small"> <item name="android:textSize">16sp</item> <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:lines">2</item> + <item name="android:maxLines">2</item> <item name="android:ellipsize">end</item> </style> |