280 lines
13 KiB
Java
280 lines
13 KiB
Java
package de.danoeh.antennapod.ui.episodeslist;
|
|
|
|
import android.os.Build;
|
|
import android.text.Layout;
|
|
import android.text.format.Formatter;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
import android.widget.ProgressBar;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.cardview.widget.CardView;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import com.google.android.material.elevation.SurfaceColors;
|
|
|
|
import de.danoeh.antennapod.R;
|
|
import de.danoeh.antennapod.activity.MainActivity;
|
|
import de.danoeh.antennapod.ui.CoverLoader;
|
|
import de.danoeh.antennapod.actionbutton.ItemActionButton;
|
|
import de.danoeh.antennapod.playback.service.PlaybackStatus;
|
|
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
|
|
import de.danoeh.antennapod.ui.common.DateFormatter;
|
|
import de.danoeh.antennapod.model.feed.FeedItem;
|
|
import de.danoeh.antennapod.model.feed.FeedMedia;
|
|
import de.danoeh.antennapod.model.playback.MediaType;
|
|
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
|
|
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
|
import de.danoeh.antennapod.ui.common.Converter;
|
|
import de.danoeh.antennapod.net.common.NetworkUtils;
|
|
import de.danoeh.antennapod.model.playback.Playable;
|
|
import de.danoeh.antennapod.ui.common.CircularProgressBar;
|
|
import de.danoeh.antennapod.ui.common.ThemeUtils;
|
|
import de.danoeh.antennapod.ui.episodes.ImageResourceUtils;
|
|
|
|
/**
|
|
* Holds the view which shows FeedItems.
|
|
*/
|
|
public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
|
|
private static final String TAG = "EpisodeItemViewHolder";
|
|
|
|
private final View container;
|
|
public final ImageView dragHandle;
|
|
public final TextView placeholder;
|
|
public 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 ImageView isInbox;
|
|
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;
|
|
private final View leftPadding;
|
|
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);
|
|
isInbox = itemView.findViewById(R.id.statusInbox);
|
|
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);
|
|
leftPadding = itemView.findViewById(R.id.left_padding);
|
|
itemView.setTag(this);
|
|
}
|
|
|
|
public void bind(FeedItem item) {
|
|
this.item = item;
|
|
placeholder.setText(item.getFeed().getTitle());
|
|
title.setText(item.getTitle());
|
|
if (item.isPlayed()) {
|
|
leftPadding.setContentDescription(item.getTitle() + ". " + activity.getString(R.string.is_played));
|
|
} else {
|
|
leftPadding.setContentDescription(item.getTitle());
|
|
}
|
|
pubDate.setText(DateFormatter.formatAbbrev(activity, item.getPubDate()));
|
|
pubDate.setContentDescription(DateFormatter.formatForAccessibility(item.getPubDate()));
|
|
isInbox.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);
|
|
container.setAlpha(item.isPlayed() ? 0.5f : 1.0f);
|
|
|
|
ItemActionButton actionButton = ItemActionButton.forItem(item);
|
|
actionButton.configure(secondaryActionButton, secondaryActionIcon, activity);
|
|
secondaryActionButton.setFocusable(false);
|
|
|
|
if (item.getMedia() != null) {
|
|
bind(item.getMedia());
|
|
} else {
|
|
secondaryActionProgress.setPercentage(0, item);
|
|
secondaryActionProgress.setIndeterminate(false);
|
|
isVideo.setVisibility(View.GONE);
|
|
progressBar.setVisibility(View.GONE);
|
|
duration.setVisibility(View.GONE);
|
|
position.setVisibility(View.GONE);
|
|
itemView.setBackgroundResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.selectableItemBackground));
|
|
}
|
|
|
|
if (coverHolder.getVisibility() == View.VISIBLE) {
|
|
new CoverLoader()
|
|
.withUri(ImageResourceUtils.getEpisodeListImageLocation(item))
|
|
.withFallbackUri(item.getFeed().getImageUrl())
|
|
.withPlaceholderView(placeholder)
|
|
.withCoverView(cover)
|
|
.load();
|
|
}
|
|
}
|
|
|
|
private void bind(FeedMedia media) {
|
|
isVideo.setVisibility(media.getMediaType() == MediaType.VIDEO ? View.VISIBLE : View.GONE);
|
|
duration.setVisibility(media.getDuration() > 0 ? View.VISIBLE : View.GONE);
|
|
|
|
if (PlaybackStatus.isCurrentlyPlaying(media)) {
|
|
float density = activity.getResources().getDisplayMetrics().density;
|
|
itemView.setBackgroundColor(SurfaceColors.getColorForElevation(activity, 8 * density));
|
|
} else {
|
|
itemView.setBackgroundResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.selectableItemBackground));
|
|
}
|
|
|
|
if (DownloadServiceInterface.get().isDownloadingEpisode(media.getDownloadUrl())) {
|
|
float percent = 0.01f * DownloadServiceInterface.get().getProgress(media.getDownloadUrl());
|
|
secondaryActionProgress.setPercentage(Math.max(percent, 0.01f), item);
|
|
secondaryActionProgress.setIndeterminate(
|
|
DownloadServiceInterface.get().isEpisodeQueued(media.getDownloadUrl()));
|
|
} else if (media.isDownloaded()) {
|
|
secondaryActionProgress.setPercentage(1, item); // Do not animate 100% -> 0%
|
|
secondaryActionProgress.setIndeterminate(false);
|
|
} else {
|
|
secondaryActionProgress.setPercentage(0, item); // Animate X% -> 0%
|
|
secondaryActionProgress.setIndeterminate(false);
|
|
}
|
|
|
|
duration.setText(Converter.getDurationStringLong(media.getDuration()));
|
|
duration.setContentDescription(activity.getString(R.string.chapter_duration,
|
|
Converter.getDurationStringLocalized(activity, media.getDuration())));
|
|
if (PlaybackStatus.isPlaying(item.getMedia()) || item.isInProgress()) {
|
|
int progress = (int) (100.0 * media.getPosition() / media.getDuration());
|
|
int remainingTime = Math.max(media.getDuration() - media.getPosition(), 0);
|
|
progressBar.setProgress(progress);
|
|
position.setText(Converter.getDurationStringLong(media.getPosition()));
|
|
position.setContentDescription(activity.getString(R.string.position,
|
|
Converter.getDurationStringLocalized(activity, media.getPosition())));
|
|
progressBar.setVisibility(View.VISIBLE);
|
|
position.setVisibility(View.VISIBLE);
|
|
if (UserPreferences.shouldShowRemainingTime()) {
|
|
duration.setText(((remainingTime > 0) ? "-" : "") + Converter.getDurationStringLong(remainingTime));
|
|
duration.setContentDescription(activity.getString(R.string.chapter_duration,
|
|
Converter.getDurationStringLocalized(activity, (media.getDuration() - media.getPosition()))));
|
|
}
|
|
} else {
|
|
progressBar.setVisibility(View.GONE);
|
|
position.setVisibility(View.GONE);
|
|
}
|
|
|
|
if (media.getSize() > 0) {
|
|
size.setText(Formatter.formatShortFileSize(activity, media.getSize()));
|
|
} else if (NetworkUtils.isEpisodeHeadDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
|
|
size.setText("");
|
|
MediaSizeLoader.getFeedMediaSizeObservable(media).subscribe(
|
|
sizeValue -> {
|
|
if (sizeValue > 0) {
|
|
size.setText(Formatter.formatShortFileSize(activity, sizeValue));
|
|
} else {
|
|
size.setText("");
|
|
}
|
|
}, error -> {
|
|
size.setText("");
|
|
Log.e(TAG, Log.getStackTraceString(error));
|
|
});
|
|
} else {
|
|
size.setText("");
|
|
}
|
|
}
|
|
|
|
public void bindDummy() {
|
|
item = new FeedItem();
|
|
container.setAlpha(0.1f);
|
|
secondaryActionIcon.setImageDrawable(null);
|
|
isInbox.setVisibility(View.VISIBLE);
|
|
isVideo.setVisibility(View.GONE);
|
|
isFavorite.setVisibility(View.GONE);
|
|
isInQueue.setVisibility(View.GONE);
|
|
title.setText("███████");
|
|
pubDate.setText("████");
|
|
duration.setText("████");
|
|
secondaryActionProgress.setPercentage(0, null);
|
|
secondaryActionProgress.setIndeterminate(false);
|
|
progressBar.setVisibility(View.GONE);
|
|
position.setVisibility(View.GONE);
|
|
dragHandle.setVisibility(View.GONE);
|
|
size.setText("");
|
|
itemView.setBackgroundResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.selectableItemBackground));
|
|
placeholder.setText("");
|
|
if (coverHolder.getVisibility() == View.VISIBLE) {
|
|
new CoverLoader()
|
|
.withResource(R.color.medium_gray)
|
|
.withPlaceholderView(placeholder)
|
|
.withCoverView(cover)
|
|
.load();
|
|
}
|
|
}
|
|
|
|
private void updateDuration(PlaybackPositionEvent event) {
|
|
if (getFeedItem().getMedia() != null) {
|
|
getFeedItem().getMedia().setPosition(event.getPosition());
|
|
getFeedItem().getMedia().setDuration(event.getDuration());
|
|
}
|
|
int currentPosition = event.getPosition();
|
|
int timeDuration = event.getDuration();
|
|
int remainingTime = Math.max(timeDuration - currentPosition, 0);
|
|
Log.d(TAG, "currentPosition " + Converter.getDurationStringLong(currentPosition));
|
|
if (currentPosition == Playable.INVALID_TIME || timeDuration == Playable.INVALID_TIME) {
|
|
Log.w(TAG, "Could not react to position observer update because of invalid time");
|
|
return;
|
|
}
|
|
if (UserPreferences.shouldShowRemainingTime()) {
|
|
duration.setText(((remainingTime > 0) ? "-" : "") + Converter.getDurationStringLong(remainingTime));
|
|
} else {
|
|
duration.setText(Converter.getDurationStringLong(timeDuration));
|
|
}
|
|
}
|
|
|
|
public FeedItem getFeedItem() {
|
|
return item;
|
|
}
|
|
|
|
public boolean isCurrentlyPlayingItem() {
|
|
return item.getMedia() != null && PlaybackStatus.isCurrentlyPlaying(item.getMedia());
|
|
}
|
|
|
|
public void notifyPlaybackPositionUpdated(PlaybackPositionEvent event) {
|
|
progressBar.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
|
|
position.setText(Converter.getDurationStringLong(event.getPosition()));
|
|
updateDuration(event);
|
|
duration.setVisibility(View.VISIBLE); // Even if the duration was previously unknown, it is now known
|
|
}
|
|
|
|
/**
|
|
* Hides the separator dot between icons and text if there are no icons.
|
|
*/
|
|
public void hideSeparatorIfNecessary() {
|
|
boolean hasIcons = isInbox.getVisibility() == View.VISIBLE
|
|
|| isInQueue.getVisibility() == View.VISIBLE
|
|
|| isVideo.getVisibility() == View.VISIBLE
|
|
|| isFavorite.getVisibility() == View.VISIBLE
|
|
|| isInbox.getVisibility() == View.VISIBLE;
|
|
separatorIcons.setVisibility(hasIcons ? View.VISIBLE : View.GONE);
|
|
}
|
|
}
|