Move download logs to a button on the downloads page instead of a tab (#5866)

This commit is contained in:
ByteHamster 2022-05-06 22:52:02 +02:00 committed by GitHub
parent dfcc342c57
commit 01bddcc0a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 228 additions and 261 deletions

View File

@ -8,9 +8,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.NavDrawerFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
@ -154,7 +154,7 @@ public class NavigationDrawerTest {
@Test
public void testDrawerPreferencesUnhideSomeElements() {
List<String> hidden = Arrays.asList(PlaybackHistoryFragment.TAG, DownloadsFragment.TAG);
List<String> hidden = Arrays.asList(PlaybackHistoryFragment.TAG, CompletedDownloadsFragment.TAG);
UserPreferences.setHiddenDrawerItems(hidden);
activityRule.launchActivity(new Intent());
openNavDrawer();
@ -211,6 +211,6 @@ public class NavigationDrawerTest {
List<String> hidden = UserPreferences.getHiddenDrawerItems();
assertEquals(1, hidden.size());
assertTrue(hidden.contains(DownloadsFragment.TAG));
assertTrue(hidden.contains(CompletedDownloadsFragment.TAG));
}
}

View File

@ -37,6 +37,7 @@ import com.bumptech.glide.Glide;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
import de.danoeh.antennapod.playback.cast.CastEnabledActivity;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
@ -54,7 +55,6 @@ import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.AudioPlayerFragment;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.InboxFragment;
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
@ -274,8 +274,8 @@ public class MainActivity extends CastEnabledActivity {
case EpisodesFragment.TAG:
fragment = new EpisodesFragment();
break;
case DownloadsFragment.TAG:
fragment = new DownloadsFragment();
case CompletedDownloadsFragment.TAG:
fragment = new CompletedDownloadsFragment();
break;
case PlaybackHistoryFragment.TAG:
fragment = new PlaybackHistoryFragment();
@ -594,7 +594,7 @@ public class MainActivity extends CastEnabledActivity {
}
switch (feature) {
case "DOWNLOADS":
loadFragment(DownloadsFragment.TAG, null);
loadFragment(CompletedDownloadsFragment.TAG, null);
break;
case "HISTORY":
loadFragment(PlaybackHistoryFragment.TAG, null);

View File

@ -3,26 +3,24 @@ package de.danoeh.antennapod.adapter;
import android.app.Activity;
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.util.Log;
import android.widget.BaseAdapter;
import android.widget.Toast;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.ListFragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadRequestCreator;
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.model.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.DownloadErrorLabel;
import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
@ -39,14 +37,12 @@ public class DownloadLogAdapter extends BaseAdapter {
private static final String TAG = "DownloadLogAdapter";
private final Activity context;
private final ListFragment listFragment;
private List<DownloadStatus> downloadLog = new ArrayList<>();
private List<Downloader> runningDownloads = new ArrayList<>();
public DownloadLogAdapter(Activity context, ListFragment listFragment) {
public DownloadLogAdapter(Activity context) {
super();
this.context = context;
this.listFragment = listFragment;
}
public void setDownloadLog(List<DownloadStatus> downloadLog) {

View File

@ -25,13 +25,13 @@ import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
import de.danoeh.antennapod.fragment.InboxFragment;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.NavDrawerData;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.NavDrawerFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
@ -119,7 +119,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
return R.drawable.ic_inbox;
case EpisodesFragment.TAG:
return R.drawable.ic_feed;
case DownloadsFragment.TAG:
case CompletedDownloadsFragment.TAG:
return R.drawable.ic_download;
case PlaybackHistoryFragment.TAG:
return R.drawable.ic_history;
@ -257,7 +257,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
holder.count.setText(NumberFormat.getInstance().format(sum));
holder.count.setVisibility(View.VISIBLE);
}
} else if (tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) {
} else if (tag.equals(CompletedDownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) {
int epCacheSize = UserPreferences.getEpisodeCacheSize();
// don't count episodes that can be reclaimed
int spaceUsed = itemAccess.getNumberOfDownloadedItems()

View File

@ -4,14 +4,14 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.DownloadAuthenticationActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.DownloadServiceCallbacks;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.CompletedDownloadsFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
@ -20,10 +20,7 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks {
@Override
public PendingIntent getNotificationContentIntent(Context context) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG);
Bundle args = new Bundle();
args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, CompletedDownloadsFragment.TAG);
return PendingIntent.getActivity(context,
R.id.pending_intent_download_service_notification, intent,
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
@ -42,9 +39,9 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks {
@Override
public PendingIntent getReportNotificationContentIntent(Context context) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, CompletedDownloadsFragment.TAG);
Bundle args = new Bundle();
args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG);
args.putBoolean(CompletedDownloadsFragment.ARG_SHOW_LOGS, true);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
return PendingIntent.getActivity(context, R.id.pending_intent_download_service_report, intent,
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));

View File

@ -12,30 +12,28 @@ import android.widget.ProgressBar;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.util.ObjectsCompat;
import androidx.fragment.app.Fragment;
import com.google.android.material.snackbar.Snackbar;
import com.leinardi.android.speeddial.SpeedDialView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
import de.danoeh.antennapod.adapter.actionbutton.DeleteActionButton;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.ui.common.PagedToolbarFragment;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.view.EmptyViewHandler;
import de.danoeh.antennapod.view.EpisodeItemListRecyclerView;
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
@ -53,28 +51,38 @@ import java.util.List;
/**
* Displays all completed downloads and provides a button to delete them.
*/
public class CompletedDownloadsFragment extends Fragment implements
EpisodeItemListAdapter.OnSelectModeListener {
private static final String TAG = CompletedDownloadsFragment.class.getSimpleName();
public class CompletedDownloadsFragment extends Fragment
implements EpisodeItemListAdapter.OnSelectModeListener, Toolbar.OnMenuItemClickListener {
public static final String TAG = "DownloadsFragment";
public static final String ARG_SHOW_LOGS = "show_logs";
private static final String KEY_UP_ARROW = "up_arrow";
private long[] runningDownloads = new long[0];
private List<FeedItem> items = new ArrayList<>();
private CompletedDownloadsListAdapter adapter;
private EpisodeItemListRecyclerView recyclerView;
private ProgressBar progressBar;
private Disposable disposable;
private EmptyViewHandler emptyView;
private boolean displayUpArrow;
private boolean isUpdatingFeeds = false;
private SpeedDialView speedDialView;
private Toolbar toolbar;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.simple_list_fragment, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setVisibility(View.GONE);
toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.downloads_label);
toolbar.inflateMenu(R.menu.downloads_completed);
toolbar.setOnMenuItemClickListener(this);
refreshToolbarState();
displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0;
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
}
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
recyclerView = root.findViewById(R.id.recyclerView);
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
@ -82,6 +90,7 @@ public class CompletedDownloadsFragment extends Fragment implements
adapter.setOnSelectModeListener(this);
recyclerView.setAdapter(adapter);
progressBar = root.findViewById(R.id.progLoading);
progressBar.setVisibility(View.VISIBLE);
speedDialView = root.findViewById(R.id.fabSD);
speedDialView.setOverlayLayout(root.findViewById(R.id.fabSDOverlay));
@ -111,12 +120,21 @@ public class CompletedDownloadsFragment extends Fragment implements
adapter.endSelectMode();
return true;
});
if (getArguments() != null && getArguments().getBoolean(ARG_SHOW_LOGS, false)) {
new DownloadLogFragment().show(getChildFragmentManager(), null);
}
addEmptyView();
EventBus.getDefault().register(this);
return root;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
super.onSaveInstanceState(outState);
}
@Override
public void onDestroyView() {
EventBus.getDefault().unregister(this);
@ -145,10 +163,16 @@ public class CompletedDownloadsFragment extends Fragment implements
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.refresh_item) {
AutoUpdateManager.runImmediate(requireContext());
return true;
} else if (item.getItemId() == R.id.action_download_logs) {
new DownloadLogFragment().show(getChildFragmentManager(), null);
return true;
} else if (item.getItemId() == R.id.action_search) {
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance());
return true;
}
return false;
}
@ -157,7 +181,20 @@ public class CompletedDownloadsFragment extends Fragment implements
public void onEventMainThread(DownloadEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
refreshToolbarState();
}
if (!ObjectsCompat.equals(event.update.mediaIds, runningDownloads)) {
runningDownloads = event.update.mediaIds;
loadItems();
return; // Refreshed anyway
}
if (event.update.mediaIds.length > 0) {
for (long mediaId : event.update.mediaIds) {
int pos = FeedItemUtil.indexOfItemWithMediaId(items, mediaId);
if (pos >= 0) {
adapter.notifyItemChangedCompat(pos);
}
}
}
}
@ -223,6 +260,11 @@ public class CompletedDownloadsFragment extends Fragment implements
}
}
private void refreshToolbarState() {
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(),
R.id.refresh_item, updateRefreshMenuItemChecker);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPlayerStatusChanged(PlayerStatusEvent event) {
loadItems();
@ -242,15 +284,28 @@ public class CompletedDownloadsFragment extends Fragment implements
if (disposable != null) {
disposable.dispose();
}
progressBar.setVisibility(View.VISIBLE);
emptyView.hide();
disposable = Observable.fromCallable(DBReader::getDownloadedItems)
disposable = Observable.fromCallable(() -> {
List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
List<Long> mediaIds = new ArrayList<>();
if (runningDownloads == null) {
return downloadedItems;
}
for (long id : runningDownloads) {
if (FeedItemUtil.indexOfItemWithMediaId(downloadedItems, id) != -1) {
continue; // Already in list
}
mediaIds.add(id);
}
List<FeedItem> currentDownloads = DBReader.getFeedItemsWithMedia(mediaIds.toArray(new Long[0]));
currentDownloads.addAll(downloadedItems);
return currentDownloads;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
items = result;
adapter.updateItems(result);
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
progressBar.setVisibility(View.GONE);
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
@ -275,10 +330,12 @@ public class CompletedDownloadsFragment extends Fragment implements
@Override
public void afterBindViewHolder(EpisodeItemViewHolder holder, int pos) {
if (!inActionMode()) {
if (holder.getFeedItem().isDownloaded()) {
DeleteActionButton actionButton = new DeleteActionButton(getItem(pos));
actionButton.configure(holder.secondaryActionButton, holder.secondaryActionIcon, getActivity());
}
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

View File

@ -2,27 +2,27 @@ package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.view.ViewGroup;
import android.widget.AdapterView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.ListFragment;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.DownloadLogAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.model.download.DownloadStatus;
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.util.download.AutoUpdateManager;
import de.danoeh.antennapod.databinding.DownloadLogFragmentBinding;
import de.danoeh.antennapod.dialog.DownloadLogDetailsDialog;
import de.danoeh.antennapod.ui.common.PagedToolbarFragment;
import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.view.EmptyViewHandler;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -38,16 +38,15 @@ import java.util.List;
/**
* Shows the download log
*/
public class DownloadLogFragment extends ListFragment {
public class DownloadLogFragment extends BottomSheetDialogFragment
implements AdapterView.OnItemClickListener, Toolbar.OnMenuItemClickListener {
private static final String TAG = "DownloadLogFragment";
private List<DownloadStatus> downloadLog = new ArrayList<>();
private List<Downloader> runningDownloads = new ArrayList<>();
private DownloadLogAdapter adapter;
private Disposable disposable;
private boolean isUpdatingFeeds = false;
private DownloadLogFragmentBinding viewBinding;
@Override
public void onStart() {
@ -63,25 +62,25 @@ public class DownloadLogFragment extends ListFragment {
}
}
@Nullable
@Override
public void onViewCreated(@NonNull View view, @Nullable 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);
setListShown(true);
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
viewBinding = DownloadLogFragmentBinding.inflate(inflater);
viewBinding.toolbar.inflateMenu(R.menu.download_log);
viewBinding.toolbar.setOnMenuItemClickListener(this);
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setIcon(R.drawable.ic_download);
emptyView.setTitle(R.string.no_log_downloads_head_label);
emptyView.setMessage(R.string.no_log_downloads_label);
emptyView.attachToListView(getListView());
emptyView.attachToListView(viewBinding.list);
adapter = new DownloadLogAdapter(getActivity(), this);
setListAdapter(adapter);
adapter = new DownloadLogAdapter(getActivity());
viewBinding.list.setAdapter(adapter);
viewBinding.list.setOnItemClickListener(this);
EventBus.getDefault().register(this);
return viewBinding.getRoot();
}
@Override
@ -91,9 +90,7 @@ public class DownloadLogFragment extends ListFragment {
}
@Override
public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id);
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object item = adapter.getItem(position);
if (item instanceof DownloadStatus) {
new DownloadLogDetailsDialog(getContext(), (DownloadStatus) item).show();
@ -108,31 +105,19 @@ public class DownloadLogFragment extends ListFragment {
@Override
public void onPrepareOptionsMenu(@NonNull Menu menu) {
menu.findItem(R.id.clear_logs_item).setVisible(!downloadLog.isEmpty());
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
public boolean onMenuItemClick(MenuItem item) {
if (super.onOptionsItemSelected(item)) {
return true;
} else if (item.getItemId() == R.id.clear_logs_item) {
DBWriter.clearDownloadLog();
return true;
} else 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);
}
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
@ -141,9 +126,6 @@ public class DownloadLogFragment extends ListFragment {
adapter.setRunningDownloads(runningDownloads);
}
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
() -> DownloadService.isRunning && DownloadService.isDownloadingFeeds();
private void loadDownloadLog() {
if (disposable != null) {
disposable.dispose();
@ -155,7 +137,6 @@ public class DownloadLogFragment extends ListFragment {
if (result != null) {
downloadLog = result;
adapter.setDownloadLog(downloadLog);
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
}
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}

View File

@ -1,134 +0,0 @@
package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.ui.common.PagedToolbarFragment;
/**
* Shows the CompletedDownloadsFragment and the RunningDownloadsFragment.
*/
public class DownloadsFragment extends PagedToolbarFragment {
public static final String TAG = "DownloadsFragment";
public static final String ARG_SELECTED_TAB = "selected_tab";
private static final String PREF_LAST_TAB_POSITION = "tab_position";
private static final String KEY_UP_ARROW = "up_arrow";
private static final int POS_COMPLETED = 0;
public static final int POS_LOG = 1;
private static final int TOTAL_COUNT = 2;
private ViewPager2 viewPager;
private TabLayout tabLayout;
private boolean displayUpArrow;
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.pager_fragment, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.downloads_label);
toolbar.inflateMenu(R.menu.downloads);
displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0;
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
}
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
viewPager = root.findViewById(R.id.viewpager);
viewPager.setAdapter(new DownloadsPagerAdapter(this));
viewPager.setOffscreenPageLimit(2);
super.setupPagedToolbar(toolbar, viewPager);
// Give the TabLayout the ViewPager
tabLayout = root.findViewById(R.id.sliding_tabs);
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
switch (position) {
case POS_COMPLETED:
tab.setText(R.string.downloads_completed_label);
break;
case POS_LOG:
tab.setText(R.string.downloads_log_label);
break;
default:
break;
}
}).attach();
// restore our last position
SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE);
int lastPosition = prefs.getInt(PREF_LAST_TAB_POSITION, 0);
viewPager.setCurrentItem(lastPosition, false);
return root;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
super.onSaveInstanceState(outState);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getArguments() != null) {
int tab = getArguments().getInt(ARG_SELECTED_TAB);
viewPager.setCurrentItem(tab, false);
}
}
@Override
public void onPause() {
super.onPause();
// save our tab selection
SharedPreferences prefs = getActivity().getSharedPreferences(TAG, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(PREF_LAST_TAB_POSITION, tabLayout.getSelectedTabPosition());
editor.apply();
}
public static class DownloadsPagerAdapter extends FragmentStateAdapter {
DownloadsPagerAdapter(@NonNull Fragment fragment) {
super(fragment);
}
@NonNull
@Override
public Fragment createFragment(int position) {
switch (position) {
case POS_COMPLETED:
return new CompletedDownloadsFragment();
default:
case POS_LOG:
return new DownloadLogFragment();
}
}
@Override
public int getItemCount() {
return TOTAL_COUNT;
}
}
}

View File

@ -1,7 +1,6 @@
package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
@ -514,12 +513,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
downloadStatus -> new DownloadLogDetailsDialog(getContext(), downloadStatus).show(),
error -> error.printStackTrace(),
() -> {
Intent intent = new Intent(getContext(), MainActivity.class);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, DownloadsFragment.TAG);
Bundle args = new Bundle();
args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG);
intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
startActivity(intent);
((MainActivity) getActivity()).loadChildFragment(new DownloadLogFragment());
});
}

View File

@ -69,7 +69,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
InboxFragment.TAG,
EpisodesFragment.TAG,
SubscriptionFragment.TAG,
DownloadsFragment.TAG,
CompletedDownloadsFragment.TAG,
PlaybackHistoryFragment.TAG,
AddFeedFragment.TAG,
NavListAdapter.SUBSCRIPTION_LIST_TAG

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="300dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
app:title="@string/downloads_log_label" />
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="@dimen/list_vertical_padding"
android:layout_below="@id/toolbar" />
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
android:visibility="gone" />
</RelativeLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/clear_logs_item"
android:menuCategory="container"
android:title="@string/clear_history_label"
android:icon="@drawable/ic_delete"
app:showAsAction="always" />
</menu>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/clear_logs_item"
android:menuCategory="container"
android:title="@string/clear_history_label"
android:icon="@drawable/ic_delete"
android:visible="false"
app:showAsAction="ifRoom" />
<item
android:id="@+id/refresh_item"
android:title="@string/refresh_label"
android:menuCategory="container"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_refresh"/>
</menu>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search"
android:title="@string/search_label"
custom:showAsAction="always" />
<item
android:id="@+id/action_download_logs"
android:icon="@drawable/ic_history"
android:title="@string/downloads_log_label"
custom:showAsAction="always" />
<item
android:id="@+id/refresh_item"
android:title="@string/refresh_label"
android:menuCategory="container"
android:icon="@drawable/ic_refresh"
app:showAsAction="always" />
</menu>

View File

@ -775,6 +775,19 @@ public final class DBReader {
}
}
public static List<FeedItem> getFeedItemsWithMedia(Long[] mediaIds) {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
try (Cursor itemCursor = adapter.getFeedItemCursorByMediaIds(mediaIds)) {
List<FeedItem> items = extractItemlistFromCursor(adapter, itemCursor);
loadAdditionalFeedItemListData(items);
Collections.sort(items, new PlaybackCompletionDateComparator());
return items;
} finally {
adapter.close();
}
}
public static class MonthlyStatisticsItem {
public int year = 0;
public int month = 0;

View File

@ -1106,6 +1106,15 @@ public class PodDBAdapter {
return db.rawQuery(query, null);
}
public final Cursor getFeedItemCursorByMediaIds(final Long[] ids) {
if (ids.length > IN_OPERATOR_MAXIMUM) {
throw new IllegalArgumentException("number of IDs must not be larger than " + IN_OPERATOR_MAXIMUM);
}
final String query = SELECT_FEED_ITEMS_AND_MEDIA
+ " WHERE " + SELECT_KEY_MEDIA_ID + " IN (" + TextUtils.join(",", ids) + ")";
return db.rawQuery(query, null);
}
public final Cursor getFeedItemCursor(final String guid, final String episodeUrl) {
String escapedEpisodeUrl = DatabaseUtils.sqlEscapeString(episodeUrl);
String whereClauseCondition = TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOAD_URL + "=" + escapedEpisodeUrl;

View File

@ -18,8 +18,7 @@
<string name="settings_label">Settings</string>
<string name="downloads_label">Downloads</string>
<string name="open_autodownload_settings">Open Settings</string>
<string name="downloads_completed_label">Completed</string>
<string name="downloads_log_label">Log</string>
<string name="downloads_log_label">Download Log</string>
<string name="subscriptions_label">Subscriptions</string>
<string name="subscriptions_list_label">Subscriptions List</string>
<string name="cancel_download_label">Cancel Download</string>