Merge download log+running lists (#5134)

This commit is contained in:
ByteHamster 2021-04-29 21:40:41 +02:00 committed by GitHub
parent 02dba45d5c
commit d08a9c423e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 220 additions and 489 deletions

View File

@ -2,25 +2,32 @@ package de.danoeh.antennapod.adapter;
import android.app.Activity; import android.app.Activity;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.Log; import android.text.format.Formatter;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.util.Log;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.Toast; import android.widget.Toast;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.ListFragment;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.view.viewholder.DownloadItemViewHolder; import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.ui.common.ThemeUtils;
import de.danoeh.antennapod.view.viewholder.DownloadLogItemViewHolder;
import java.util.ArrayList;
import java.util.List;
/** /**
* Displays a list of DownloadStatus entries. * Displays a list of DownloadStatus entries.
@ -29,37 +36,62 @@ public class DownloadLogAdapter extends BaseAdapter {
private static final String TAG = "DownloadLogAdapter"; private static final String TAG = "DownloadLogAdapter";
private final Activity context; private final Activity context;
private final ItemAccess itemAccess; private final ListFragment listFragment;
private List<DownloadStatus> downloadLog = new ArrayList<>();
private List<Downloader> runningDownloads = new ArrayList<>();
public DownloadLogAdapter(Activity context, ItemAccess itemAccess) { public DownloadLogAdapter(Activity context, ListFragment listFragment) {
super(); super();
this.itemAccess = itemAccess;
this.context = context; this.context = context;
this.listFragment = listFragment;
}
public void setDownloadLog(List<DownloadStatus> downloadLog) {
this.downloadLog = downloadLog;
notifyDataSetChanged();
}
public void setRunningDownloads(List<Downloader> runningDownloads) {
this.runningDownloads = runningDownloads;
notifyDataSetChanged();
} }
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
DownloadItemViewHolder holder; DownloadLogItemViewHolder holder;
if (convertView == null) { if (convertView == null) {
holder = new DownloadItemViewHolder(context, parent); holder = new DownloadLogItemViewHolder(context, parent);
holder.itemView.setTag(holder);
} else { } else {
holder = (DownloadItemViewHolder) convertView.getTag(); holder = (DownloadLogItemViewHolder) convertView.getTag();
} }
DownloadStatus status = getItem(position); Object item = getItem(position);
if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { if (item instanceof DownloadStatus) {
holder.type.setText(R.string.download_type_feed); bind(holder, (DownloadStatus) item, position);
} else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { } else if (item instanceof Downloader) {
holder.type.setText(R.string.download_type_media); bind(holder, (Downloader) item, position);
} }
return holder.itemView;
}
private void bind(DownloadLogItemViewHolder holder, DownloadStatus status, int position) {
String statusText = "";
if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
statusText += context.getString(R.string.download_type_feed);
} else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
statusText += context.getString(R.string.download_type_media);
}
statusText += " · ";
statusText += DateUtils.getRelativeTimeSpanString(status.getCompletionDate().getTime(),
System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 0);
holder.status.setText(statusText);
if (status.getTitle() != null) { if (status.getTitle() != null) {
holder.title.setText(status.getTitle()); holder.title.setText(status.getTitle());
} else { } else {
holder.title.setText(R.string.download_log_title_unknown); holder.title.setText(R.string.download_log_title_unknown);
} }
holder.date.setText(DateUtils.getRelativeTimeSpanString(status.getCompletionDate().getTime(),
System.currentTimeMillis(), 0, 0));
if (status.isSuccessful()) { if (status.isSuccessful()) {
holder.icon.setTextColor(ContextCompat.getColor(context, R.color.download_success_green)); holder.icon.setTextColor(ContextCompat.getColor(context, R.color.download_success_green));
@ -76,7 +108,8 @@ public class DownloadLogAdapter extends BaseAdapter {
holder.reason.setVisibility(View.VISIBLE); holder.reason.setVisibility(View.VISIBLE);
holder.tapForDetails.setVisibility(View.VISIBLE); holder.tapForDetails.setVisibility(View.VISIBLE);
if (newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) { if (newerWasSuccessful(position - runningDownloads.size(),
status.getFeedfileType(), status.getFeedfileId())) {
holder.secondaryActionButton.setVisibility(View.INVISIBLE); holder.secondaryActionButton.setVisibility(View.INVISIBLE);
holder.secondaryActionButton.setOnClickListener(null); holder.secondaryActionButton.setOnClickListener(null);
holder.secondaryActionButton.setTag(null); holder.secondaryActionButton.setTag(null);
@ -118,13 +151,51 @@ public class DownloadLogAdapter extends BaseAdapter {
} }
} }
} }
return holder.itemView;
} }
private boolean newerWasSuccessful(int position, int feedTypeId, long id) { private void bind(DownloadLogItemViewHolder holder, Downloader downloader, int position) {
for (int i = 0; i < position; i++) { DownloadRequest request = downloader.getDownloadRequest();
DownloadStatus status = getItem(i); holder.title.setText(request.getTitle());
holder.secondaryActionIcon.setImageResource(R.drawable.ic_cancel);
holder.secondaryActionButton.setContentDescription(context.getString(R.string.cancel_download_label));
holder.secondaryActionButton.setVisibility(View.VISIBLE);
holder.secondaryActionButton.setTag(downloader);
holder.secondaryActionButton.setOnClickListener(v ->
listFragment.onListItemClick(null, holder.itemView, position, 0));
holder.reason.setVisibility(View.GONE);
holder.tapForDetails.setVisibility(View.GONE);
holder.icon.setTextColor(ThemeUtils.getColorFromAttr(context, R.attr.colorPrimary));
holder.icon.setText("{fa-arrow-circle-down}");
holder.icon.setContentDescription(context.getString(R.string.status_downloading_label));
boolean percentageWasSet = false;
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_pending);
} else {
status += Formatter.formatShortFileSize(context, request.getSoFar());
if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) {
status += " / " + Formatter.formatShortFileSize(context, request.getSize());
holder.secondaryActionProgress.setPercentage(
0.01f * Math.max(1, request.getProgressPercent()), request);
percentageWasSet = true;
}
}
if (!percentageWasSet) {
holder.secondaryActionProgress.setPercentage(0, request);
}
holder.status.setText(status);
}
private boolean newerWasSuccessful(int downloadStatusIndex, int feedTypeId, long id) {
for (int i = 0; i < downloadStatusIndex; i++) {
DownloadStatus status = downloadLog.get(i);
if (status.getFeedfileType() == feedTypeId && status.getFeedfileId() == id && status.isSuccessful()) { if (status.getFeedfileType() == feedTypeId && status.getFeedfileId() == id && status.isSuccessful()) {
return true; return true;
} }
@ -134,12 +205,17 @@ public class DownloadLogAdapter extends BaseAdapter {
@Override @Override
public int getCount() { public int getCount() {
return itemAccess.getCount(); return downloadLog.size() + runningDownloads.size();
} }
@Override @Override
public DownloadStatus getItem(int position) { public Object getItem(int position) {
return itemAccess.getItem(position); if (position < runningDownloads.size()) {
return runningDownloads.get(position);
} else if (position - runningDownloads.size() < downloadLog.size()) {
return downloadLog.get(position - runningDownloads.size());
}
return null;
} }
@Override @Override
@ -147,10 +223,4 @@ public class DownloadLogAdapter extends BaseAdapter {
return position; return position;
} }
public interface ItemAccess {
int getCount();
DownloadStatus getItem(int position);
}
} }

View File

@ -1,122 +0,0 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.text.format.Formatter;
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 de.danoeh.antennapod.R;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.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.ui.common.CircularProgressBar;
public class DownloadlistAdapter extends BaseAdapter {
private final ItemAccess itemAccess;
private final Context context;
public DownloadlistAdapter(Context context, ItemAccess itemAccess) {
super();
this.context = context;
this.itemAccess = itemAccess;
}
@Override
public int getCount() {
return itemAccess.getCount();
}
@Override
public Downloader getItem(int position) {
return itemAccess.getItem(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
Downloader downloader = getItem(position);
DownloadRequest request = downloader.getDownloadRequest();
if (convertView == null) {
holder = new Holder();
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.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.secondaryActionIcon.setImageResource(R.drawable.ic_cancel);
holder.secondaryActionButton.setContentDescription(context.getString(R.string.cancel_download_label));
holder.secondaryActionButton.setTag(downloader);
holder.secondaryActionButton.setOnClickListener(butSecondaryListener);
boolean percentageWasSet = false;
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_pending);
} else {
status += Formatter.formatShortFileSize(context, request.getSoFar());
if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) {
status += " / " + Formatter.formatShortFileSize(context, request.getSize());
holder.secondaryActionProgress.setPercentage(
0.01f * Math.max(1, request.getProgressPercent()), request);
percentageWasSet = true;
}
}
if (!percentageWasSet) {
holder.secondaryActionProgress.setPercentage(0, request);
}
holder.status.setText(status);
return convertView;
}
private final View.OnClickListener butSecondaryListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Downloader downloader = (Downloader) v.getTag();
itemAccess.onSecondaryActionClick(downloader);
}
};
static class Holder {
TextView title;
TextView status;
View secondaryActionButton;
ImageView secondaryActionIcon;
CircularProgressBar secondaryActionProgress;
}
public interface ItemAccess {
int getCount();
Downloader getItem(int position);
void onSecondaryActionClick(Downloader downloader);
}
}

View File

@ -21,7 +21,7 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks {
Intent intent = new Intent(context, MainActivity.class); Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG); intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG);
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_RUNNING); args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args); intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
return PendingIntent.getActivity(context, return PendingIntent.getActivity(context,
R.id.pending_intent_download_service_notification, intent, PendingIntent.FLAG_UPDATE_CURRENT); R.id.pending_intent_download_service_notification, intent, PendingIntent.FLAG_UPDATE_CURRENT);

View File

@ -5,36 +5,36 @@ import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.ListFragment;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList; import androidx.annotation.NonNull;
import java.util.List; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.ListFragment;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DownloadLogAdapter; import de.danoeh.antennapod.adapter.DownloadLogAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloadLogEvent; import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager; import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EmptyViewHandler;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@ -44,6 +44,9 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
/** /**
* Shows the download log * Shows the download log
*/ */
@ -52,6 +55,7 @@ public class DownloadLogFragment extends ListFragment {
private static final String TAG = "DownloadLogFragment"; private static final String TAG = "DownloadLogFragment";
private List<DownloadStatus> downloadLog = new ArrayList<>(); private List<DownloadStatus> downloadLog = new ArrayList<>();
private List<Downloader> runningDownloads = new ArrayList<>();
private DownloadLogAdapter adapter; private DownloadLogAdapter adapter;
private Disposable disposable; private Disposable disposable;
@ -60,7 +64,7 @@ public class DownloadLogFragment extends ListFragment {
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
loadItems(); loadDownloadLog();
} }
@Override @Override
@ -79,6 +83,7 @@ public class DownloadLogFragment extends ListFragment {
lv.setClipToPadding(false); lv.setClipToPadding(false);
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding); final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding); lv.setPadding(0, vertPadding, 0, vertPadding);
setListShown(true);
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setIcon(R.drawable.ic_download); emptyView.setIcon(R.drawable.ic_download);
@ -86,7 +91,7 @@ public class DownloadLogFragment extends ListFragment {
emptyView.setMessage(R.string.no_log_downloads_label); emptyView.setMessage(R.string.no_log_downloads_label);
emptyView.attachToListView(getListView()); emptyView.attachToListView(getListView());
adapter = new DownloadLogAdapter(getActivity(), itemAccess); adapter = new DownloadLogAdapter(getActivity(), this);
setListAdapter(adapter); setListAdapter(adapter);
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
} }
@ -97,17 +102,25 @@ public class DownloadLogFragment extends ListFragment {
super.onDestroyView(); super.onDestroyView();
} }
private void onFragmentLoaded() {
setListShown(true);
adapter.notifyDataSetChanged();
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
}
@Override @Override
public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) { public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id); super.onListItemClick(l, v, position, id);
DownloadStatus status = adapter.getItem(position); Object item = adapter.getItem(position);
if (item instanceof Downloader) {
DownloadRequest downloadRequest = ((Downloader) item).getDownloadRequest();
DownloadRequester.getInstance().cancelDownload(getActivity(), downloadRequest.getSource());
if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
&& UserPreferences.isEnableAutodownload()) {
FeedMedia media = DBReader.getFeedMedia(downloadRequest.getFeedfileId());
DBWriter.setFeedItemAutoDownload(media.getItem(), false);
((MainActivity) getActivity()).showSnackbarAbovePlayer(
R.string.download_canceled_autodownload_enabled_msg, Toast.LENGTH_SHORT);
}
} else if (item instanceof DownloadStatus) {
DownloadStatus status = (DownloadStatus) item;
String url = "unknown"; String url = "unknown";
String message = getString(R.string.download_successful); String message = getString(R.string.download_successful);
if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
@ -132,35 +145,21 @@ public class DownloadLogFragment extends ListFragment {
builder.setMessage(messageFull); builder.setMessage(messageFull);
builder.setPositiveButton(android.R.string.ok, null); builder.setPositiveButton(android.R.string.ok, null);
builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> { builder.setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> {
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) getContext()
.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(getString(R.string.download_error_details), messageFull); ClipData clip = ClipData.newPlainText(getString(R.string.download_error_details), messageFull);
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT); ((MainActivity) getActivity()).showSnackbarAbovePlayer(
R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT);
}); });
Dialog dialog = builder.show(); Dialog dialog = builder.show();
((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true); ((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true);
} }
private final DownloadLogAdapter.ItemAccess itemAccess = new DownloadLogAdapter.ItemAccess() {
@Override
public int getCount() {
return downloadLog.size();
} }
@Override
public DownloadStatus getItem(int position) {
if (0 <= position && position < downloadLog.size()) {
return downloadLog.get(position);
} else {
return null;
}
}
};
@Subscribe @Subscribe
public void onDownloadLogChanged(DownloadLogEvent event) { public void onDownloadLogChanged(DownloadLogEvent event) {
loadItems(); loadDownloadLog();
} }
@Override @Override
@ -172,21 +171,17 @@ public class DownloadLogFragment extends ListFragment {
@Override @Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) { public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (!super.onOptionsItemSelected(item)) { if (super.onOptionsItemSelected(item)) {
switch (item.getItemId()) { return true;
case R.id.clear_logs_item: } else if (item.getItemId() == R.id.clear_logs_item) {
DBWriter.clearDownloadLog(); DBWriter.clearDownloadLog();
return true; return true;
case R.id.refresh_item: } else if (item.getItemId() == R.id.refresh_item) {
AutoUpdateManager.runImmediate(requireContext()); AutoUpdateManager.runImmediate(requireContext());
return true; return true;
default: }
return false; return false;
} }
} else {
return true;
}
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN) @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(DownloadEvent event) { public void onEventMainThread(DownloadEvent event) {
@ -196,10 +191,18 @@ public class DownloadLogFragment extends ListFragment {
} }
} }
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
runningDownloads = update.downloaders;
adapter.setRunningDownloads(runningDownloads);
}
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
() -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds(); () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
private void loadItems() { private void loadDownloadLog() {
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
@ -209,7 +212,8 @@ public class DownloadLogFragment extends ListFragment {
.subscribe(result -> { .subscribe(result -> {
if (result != null) { if (result != null) {
downloadLog = result; downloadLog = result;
onFragmentLoaded(); adapter.setDownloadLog(downloadLog);
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
} }
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }

View File

@ -31,10 +31,9 @@ public class DownloadsFragment extends PagedToolbarFragment {
private static final String PREF_LAST_TAB_POSITION = "tab_position"; private static final String PREF_LAST_TAB_POSITION = "tab_position";
private static final String KEY_UP_ARROW = "up_arrow"; private static final String KEY_UP_ARROW = "up_arrow";
public static final int POS_RUNNING = 0; private static final int POS_COMPLETED = 0;
private static final int POS_COMPLETED = 1; public static final int POS_LOG = 1;
public static final int POS_LOG = 2; private static final int TOTAL_COUNT = 2;
private static final int TOTAL_COUNT = 3;
private ViewPager2 viewPager; private ViewPager2 viewPager;
private TabLayout tabLayout; private TabLayout tabLayout;
@ -64,9 +63,6 @@ public class DownloadsFragment extends PagedToolbarFragment {
tabLayout = root.findViewById(R.id.sliding_tabs); tabLayout = root.findViewById(R.id.sliding_tabs);
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> { new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
switch (position) { switch (position) {
case POS_RUNNING:
tab.setText(R.string.downloads_running_label);
break;
case POS_COMPLETED: case POS_COMPLETED:
tab.setText(R.string.downloads_completed_label); tab.setText(R.string.downloads_completed_label);
break; break;
@ -121,8 +117,6 @@ public class DownloadsFragment extends PagedToolbarFragment {
@Override @Override
public Fragment createFragment(int position) { public Fragment createFragment(int position) {
switch (position) { switch (position) {
case POS_RUNNING:
return new RunningDownloadsFragment();
case POS_COMPLETED: case POS_COMPLETED:
return new CompletedDownloadsFragment(); return new CompletedDownloadsFragment();
default: default:

View File

@ -1,154 +0,0 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;
import de.danoeh.antennapod.activity.MainActivity;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.DownloadlistAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
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.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
import org.greenrobot.eventbus.ThreadMode;
/**
* Displays all running downloads and provides actions to cancel them
*/
public class RunningDownloadsFragment extends ListFragment {
private static final String TAG = "RunningDownloadsFrag";
private DownloadlistAdapter adapter;
private List<Downloader> downloaderList = new ArrayList<>();
private boolean isUpdatingFeeds = false;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// add padding
final ListView lv = getListView();
lv.setClipToPadding(false);
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding);
adapter = new DownloadlistAdapter(getActivity(), itemAccess);
setListAdapter(adapter);
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setIcon(R.drawable.ic_download);
emptyView.setTitle(R.string.no_run_downloads_head_label);
emptyView.setMessage(R.string.no_run_downloads_label);
emptyView.attachToListView(getListView());
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Override
public void onDestroy() {
super.onDestroy();
setListAdapter(null);
}
@Override
public void onPrepareOptionsMenu(@NonNull Menu menu) {
menu.findItem(R.id.clear_logs_item).setVisible(false);
menu.findItem(R.id.episode_actions).setVisible(false);
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.refresh_item) {
AutoUpdateManager.runImmediate(requireContext());
return true;
}
return false;
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(DownloadEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
}
}
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
() -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
downloaderList = update.downloaders;
adapter.notifyDataSetChanged();
}
private final DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() {
@Override
public int getCount() {
return downloaderList.size();
}
@Override
public Downloader getItem(int position) {
if (0 <= position && position < downloaderList.size()) {
return downloaderList.get(position);
} else {
return null;
}
}
@Override
public void onSecondaryActionClick(Downloader downloader) {
DownloadRequest downloadRequest = downloader.getDownloadRequest();
DownloadRequester.getInstance().cancelDownload(getActivity(), downloadRequest.getSource());
if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
&& UserPreferences.isEnableAutodownload()) {
FeedMedia media = DBReader.getFeedMedia(downloadRequest.getFeedfileId());
DBWriter.setFeedItemAutoDownload(media.getItem(), false);
((MainActivity) getActivity()).showSnackbarAbovePlayer(
R.string.download_canceled_autodownload_enabled_msg, Toast.LENGTH_SHORT);
}
}
};
}

View File

@ -11,25 +11,26 @@ import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.joanzapata.iconify.widget.IconTextView; import com.joanzapata.iconify.widget.IconTextView;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.ui.common.CircularProgressBar;
public class DownloadItemViewHolder extends RecyclerView.ViewHolder { public class DownloadLogItemViewHolder extends RecyclerView.ViewHolder {
public final View secondaryActionButton; public final View secondaryActionButton;
public final ImageView secondaryActionIcon; public final ImageView secondaryActionIcon;
public final CircularProgressBar secondaryActionProgress;
public final IconTextView icon; public final IconTextView icon;
public final TextView title; public final TextView title;
public final TextView type; public final TextView status;
public final TextView date;
public final TextView reason; public final TextView reason;
public final TextView tapForDetails; public final TextView tapForDetails;
public DownloadItemViewHolder(Context context, ViewGroup parent) { public DownloadLogItemViewHolder(Context context, ViewGroup parent) {
super(LayoutInflater.from(context).inflate(R.layout.downloadlog_item, parent, false)); super(LayoutInflater.from(context).inflate(R.layout.downloadlog_item, parent, false));
date = itemView.findViewById(R.id.txtvDate); status = itemView.findViewById(R.id.status);
type = itemView.findViewById(R.id.txtvType);
icon = itemView.findViewById(R.id.txtvIcon); icon = itemView.findViewById(R.id.txtvIcon);
reason = itemView.findViewById(R.id.txtvReason); reason = itemView.findViewById(R.id.txtvReason);
tapForDetails = itemView.findViewById(R.id.txtvTapForDetails); tapForDetails = itemView.findViewById(R.id.txtvTapForDetails);
secondaryActionButton = itemView.findViewById(R.id.secondaryActionButton); secondaryActionButton = itemView.findViewById(R.id.secondaryActionButton);
secondaryActionProgress = itemView.findViewById(R.id.secondaryActionProgress);
secondaryActionIcon = itemView.findViewById(R.id.secondaryActionIcon); secondaryActionIcon = itemView.findViewById(R.id.secondaryActionIcon);
title = itemView.findViewById(R.id.txtvTitle); title = itemView.findViewById(R.id.txtvTitle);
if (Build.VERSION.SDK_INT >= 23) { if (Build.VERSION.SDK_INT >= 23) {

View File

@ -1,39 +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: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">
<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/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/txtvStatus"
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Media file · 10MB / 20MB"/>
</LinearLayout>
<include layout="@layout/secondary_action"/>
</LinearLayout>

View File

@ -10,19 +10,6 @@
android:baselineAligned="false" android:baselineAligned="false"
android:descendantFocusability="blocksDescendants"> android:descendantFocusability="blocksDescendants">
<com.joanzapata.iconify.widget.IconTextView
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"
tools:ignore="SpUsage"/>
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -38,49 +25,43 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/status"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center_vertical"> android:gravity="center_vertical">
<TextView <com.joanzapata.iconify.widget.IconTextView
android:id="@+id/txtvType"
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="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_marginEnd="4dp"
android:layout_marginLeft="4dp" android:padding="2dp"
android:layout_marginStart="4dp" android:id="@+id/txtvIcon"
android:text="·" android:textSize="18sp"
tools:background="@android:color/holo_blue_light"/> android:gravity="center"/>
<TextView
android:id="@+id/txtvDate"
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="January 23"/>
</LinearLayout>
<TextView <TextView
android:id="@+id/txtvTitle" android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.ListItemPrimaryTitle" style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="@sample/episodes.json/data/title" tools:text="@sample/episodes.json/data/title"
android:maxLines="1"
android:ellipsize="end" android:ellipsize="end"
tools:background="@android:color/holo_blue_light"/> tools:background="@android:color/holo_blue_light"/>
</LinearLayout>
<TextView
android:id="@+id/status"
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Media file - 01/01/1970"/>
<TextView <TextView
android:id="@+id/txtvReason" android:id="@+id/txtvReason"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="14sp" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:textColor="@color/download_failed_red"
tools:text="@string/design_time_downloaded_log_failure_reason"/> tools:text="@string/design_time_downloaded_log_failure_reason"/>
<TextView <TextView
@ -94,5 +75,4 @@
</LinearLayout> </LinearLayout>
<include layout="@layout/secondary_action"/> <include layout="@layout/secondary_action"/>
</LinearLayout> </LinearLayout>

View File

@ -19,7 +19,6 @@
<string name="settings_label">Settings</string> <string name="settings_label">Settings</string>
<string name="downloads_label">Downloads</string> <string name="downloads_label">Downloads</string>
<string name="open_autodownload_settings">Open Settings</string> <string name="open_autodownload_settings">Open Settings</string>
<string name="downloads_running_label">Running</string>
<string name="downloads_completed_label">Completed</string> <string name="downloads_completed_label">Completed</string>
<string name="downloads_log_label">Log</string> <string name="downloads_log_label">Log</string>
<string name="subscriptions_label">Subscriptions</string> <string name="subscriptions_label">Subscriptions</string>
@ -333,8 +332,6 @@
<string name="no_items_header_label">No queued episodes</string> <string name="no_items_header_label">No queued episodes</string>
<string name="no_items_label">Add an episode by downloading it, or long press an episode and select \"Add to queue\".</string> <string name="no_items_label">Add an episode by downloading it, or long press an episode and select \"Add to queue\".</string>
<string name="no_shownotes_label">This episode has no shownotes.</string> <string name="no_shownotes_label">This episode has no shownotes.</string>
<string name="no_run_downloads_head_label">No downloads running</string>
<string name="no_run_downloads_label">You can download episodes on the podcast details screen.</string>
<string name="no_comp_downloads_head_label">No downloaded episodes</string> <string name="no_comp_downloads_head_label">No downloaded episodes</string>
<string name="no_comp_downloads_label">You can download episodes on the podcast details screen.</string> <string name="no_comp_downloads_label">You can download episodes on the podcast details screen.</string>
<string name="no_log_downloads_head_label">No download log</string> <string name="no_log_downloads_head_label">No download log</string>