Move common code of list fragments to EpisodesListFragment
This commit is contained in:
parent
5887a86cec
commit
0f5f4d9e35
|
@ -7,80 +7,47 @@ import android.view.LayoutInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.event.DownloadEvent;
|
||||
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.dialog.AllEpisodesFilterDialog;
|
||||
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Shows all episodes (possibly filtered by user).
|
||||
*/
|
||||
public class AllEpisodesFragment extends EpisodesListFragment implements Toolbar.OnMenuItemClickListener {
|
||||
public class AllEpisodesFragment extends EpisodesListFragment {
|
||||
public static final String TAG = "EpisodesFragment";
|
||||
private static final String PREF_NAME = "PrefAllEpisodesFragment";
|
||||
private static final String PREF_FILTER = "filter";
|
||||
private static final String KEY_UP_ARROW = "up_arrow";
|
||||
private Toolbar toolbar;
|
||||
private boolean displayUpArrow;
|
||||
private volatile boolean isUpdatingFeeds;
|
||||
private SwipeActions swipeActions;
|
||||
|
||||
private FeedItemFilter feedItemFilter = new FeedItemFilter("");
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||
feedItemFilter = new FeedItemFilter(prefs.getString(PREF_FILTER, ""));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View appEpisodesContainer = View.inflate(getContext(), R.layout.list_container_fragment, null);
|
||||
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
((FrameLayout) appEpisodesContainer.findViewById(R.id.listContent)).addView(root);
|
||||
|
||||
toolbar = appEpisodesContainer.findViewById(R.id.toolbar);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
final View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
toolbar.inflateMenu(R.menu.episodes);
|
||||
toolbar.setTitle(R.string.episodes_label);
|
||||
toolbar.setOnLongClickListener(v -> {
|
||||
recyclerView.scrollToPosition(5);
|
||||
recyclerView.post(() -> recyclerView.smoothScrollToPosition(0));
|
||||
return false;
|
||||
});
|
||||
updateToolbar();
|
||||
displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0;
|
||||
if (savedInstanceState != null) {
|
||||
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
|
||||
}
|
||||
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
|
||||
|
||||
swipeActions = new SwipeActions(this, TAG).attachTo(recyclerView);
|
||||
swipeActions.setFilter(feedItemFilter);
|
||||
|
||||
updateFilterUi();
|
||||
speedDialView.removeActionItemById(R.id.mark_unread_batch);
|
||||
speedDialView.removeActionItemById(R.id.remove_from_queue_batch);
|
||||
speedDialView.removeActionItemById(R.id.delete_batch);
|
||||
return appEpisodesContainer;
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FeedItemFilter getFilter() {
|
||||
SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||
return new FeedItemFilter(prefs.getString(PREF_FILTER, ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFragmentTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,10 +61,10 @@ public class AllEpisodesFragment extends EpisodesListFragment implements Toolbar
|
|||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.filter_items) {
|
||||
AllEpisodesFilterDialog.newInstance(feedItemFilter).show(getChildFragmentManager(), null);
|
||||
AllEpisodesFilterDialog.newInstance(getFilter()).show(getChildFragmentManager(), null);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_favorites) {
|
||||
onFilterChanged(new AllEpisodesFilterDialog.AllEpisodesFilterChangedEvent(feedItemFilter.showIsFavorite
|
||||
onFilterChanged(new AllEpisodesFilterDialog.AllEpisodesFilterChangedEvent(getFilter().showIsFavorite
|
||||
? Collections.emptySet() : Collections.singleton(FeedItemFilter.IS_FAVORITE)));
|
||||
return true;
|
||||
}
|
||||
|
@ -106,19 +73,16 @@ public class AllEpisodesFragment extends EpisodesListFragment implements Toolbar
|
|||
|
||||
@Subscribe
|
||||
public void onFilterChanged(AllEpisodesFilterDialog.AllEpisodesFilterChangedEvent event) {
|
||||
feedItemFilter = new FeedItemFilter(event.filterValues.toArray(new String[0]));
|
||||
SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||
prefs.edit().putString(PREF_FILTER, StringUtils.join(event.filterValues, ",")).apply();
|
||||
updateFilterUi();
|
||||
page = 1;
|
||||
swipeActions.setFilter(feedItemFilter);
|
||||
loadItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFragmentLoaded(List<FeedItem> episodes) {
|
||||
super.onFragmentLoaded(episodes);
|
||||
|
||||
if (feedItemFilter.getValues().length > 0) {
|
||||
private void updateFilterUi() {
|
||||
swipeActions.setFilter(getFilter());
|
||||
if (getFilter().getValues().length > 0) {
|
||||
txtvInformation.setText("{md-info-outline} " + this.getString(R.string.filtered_label));
|
||||
Iconify.addIcons(txtvInformation);
|
||||
txtvInformation.setVisibility(View.VISIBLE);
|
||||
|
@ -126,57 +90,4 @@ public class AllEpisodesFragment extends EpisodesListFragment implements Toolbar
|
|||
txtvInformation.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
|
||||
() -> DownloadService.isRunning && DownloadService.isDownloadingFeeds();
|
||||
|
||||
private void updateToolbar() {
|
||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(),
|
||||
R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||
toolbar.getMenu().findItem(R.id.filter_items).setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
|
||||
updateToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(DownloadEvent event) {
|
||||
super.onEventMainThread(event);
|
||||
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
|
||||
updateToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
|
||||
return feedItemFilter.matches(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected List<FeedItem> loadData() {
|
||||
return DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE, feedItemFilter);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected List<FeedItem> loadMoreData(int page) {
|
||||
return DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE, feedItemFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int loadTotalItemCount() {
|
||||
return DBReader.getTotalEpisodeCount(feedItemFilter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,11 @@ package de.danoeh.antennapod.fragment;
|
|||
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.KeyEvent;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -21,22 +14,44 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
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.SelectableAdapter;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.event.DownloadEvent;
|
||||
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.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.FeedListUpdateEvent;
|
||||
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.event.playback.PlaybackPositionEvent;
|
||||
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
|
||||
import de.danoeh.antennapod.ui.common.PagedToolbarFragment;
|
||||
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||
import de.danoeh.antennapod.view.EpisodeItemListRecyclerView;
|
||||
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
@ -44,34 +59,18 @@ import org.greenrobot.eventbus.ThreadMode;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.event.DownloadEvent;
|
||||
import de.danoeh.antennapod.core.event.DownloaderUpdate;
|
||||
import de.danoeh.antennapod.event.FeedItemEvent;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Shows unread or recently published episodes
|
||||
*/
|
||||
public abstract class EpisodesListFragment extends Fragment implements EpisodeItemListAdapter.OnSelectModeListener {
|
||||
|
||||
public abstract class EpisodesListFragment extends Fragment
|
||||
implements EpisodeItemListAdapter.OnSelectModeListener, Toolbar.OnMenuItemClickListener {
|
||||
public static final String TAG = "EpisodesListFragment";
|
||||
private static final String KEY_UP_ARROW = "up_arrow";
|
||||
protected static final int EPISODES_PER_PAGE = 150;
|
||||
protected int page = 1;
|
||||
protected boolean isLoadingMore = false;
|
||||
protected boolean hasMoreItems = true;
|
||||
private boolean displayUpArrow;
|
||||
|
||||
EpisodeItemListRecyclerView recyclerView;
|
||||
EpisodeItemListAdapter listAdapter;
|
||||
|
@ -79,6 +78,8 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
View loadingMoreView;
|
||||
EmptyViewHandler emptyView;
|
||||
SpeedDialView speedDialView;
|
||||
Toolbar toolbar;
|
||||
SwipeActions swipeActions;
|
||||
|
||||
@NonNull
|
||||
List<FeedItem> episodes = new ArrayList<>();
|
||||
|
@ -87,9 +88,6 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
protected Disposable disposable;
|
||||
protected TextView txtvInformation;
|
||||
|
||||
String getPrefName() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
@ -137,21 +135,6 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
if (itemId == R.id.refresh_item) {
|
||||
AutoUpdateManager.runImmediate(requireContext());
|
||||
return true;
|
||||
} else if (itemId == R.id.remove_all_inbox_item) {
|
||||
ConfirmationDialog removeAllNewFlagsConfirmationDialog = new ConfirmationDialog(getActivity(),
|
||||
R.string.remove_all_inbox_label,
|
||||
R.string.remove_all_inbox_confirmation_msg) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
DBWriter.removeAllNewFlags();
|
||||
((MainActivity) getActivity()).showSnackbarAbovePlayer(
|
||||
R.string.removed_all_inbox_msg, Toast.LENGTH_SHORT);
|
||||
}
|
||||
};
|
||||
removeAllNewFlagsConfirmationDialog.createNewDialog().show();
|
||||
return true;
|
||||
} else if (itemId == R.id.action_search) {
|
||||
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance());
|
||||
return true;
|
||||
|
@ -180,13 +163,28 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View root = inflater.inflate(R.layout.all_episodes_fragment, container, false);
|
||||
View root = inflater.inflate(R.layout.episodes_list_fragment, container, false);
|
||||
txtvInformation = root.findViewById(R.id.txtvInformation);
|
||||
toolbar = root.findViewById(R.id.toolbar);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
toolbar.setOnLongClickListener(v -> {
|
||||
recyclerView.scrollToPosition(5);
|
||||
recyclerView.post(() -> recyclerView.smoothScrollToPosition(0));
|
||||
return false;
|
||||
});
|
||||
displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0;
|
||||
if (savedInstanceState != null) {
|
||||
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
|
||||
}
|
||||
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
|
||||
|
||||
recyclerView = root.findViewById(android.R.id.list);
|
||||
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
|
||||
setupLoadMoreScrollListener();
|
||||
|
||||
swipeActions = new SwipeActions(this, getFragmentTag()).attachTo(recyclerView);
|
||||
swipeActions.setFilter(getFilter());
|
||||
|
||||
RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
|
||||
if (animator instanceof SimpleItemAnimator) {
|
||||
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
|
||||
|
@ -308,7 +306,7 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
hasMoreItems = false;
|
||||
}
|
||||
episodes.addAll(data);
|
||||
onFragmentLoaded(episodes);
|
||||
updateAdapterWithNewItems();
|
||||
if (listAdapter.shouldSelectLazyLoadedItems()) {
|
||||
listAdapter.setSelected(episodes.size() - data.size(), episodes.size(), true);
|
||||
}
|
||||
|
@ -320,7 +318,7 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
});
|
||||
}
|
||||
|
||||
protected void onFragmentLoaded(List<FeedItem> episodes) {
|
||||
protected void updateAdapterWithNewItems() {
|
||||
boolean restoreScrollPosition = listAdapter.getItemCount() == 0;
|
||||
if (episodes.size() == 0) {
|
||||
createRecycleAdapter(recyclerView, emptyView);
|
||||
|
@ -330,10 +328,6 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
if (restoreScrollPosition) {
|
||||
recyclerView.restoreScrollPosition(getPrefName());
|
||||
}
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()
|
||||
&& getParentFragment() instanceof PagedToolbarFragment) {
|
||||
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -385,7 +379,7 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
|
||||
if (pos >= 0) {
|
||||
episodes.remove(pos);
|
||||
if (shouldUpdatedItemRemainInList(item)) {
|
||||
if (getFilter().matches(item)) {
|
||||
episodes.add(pos, item);
|
||||
listAdapter.notifyItemChangedCompat(pos);
|
||||
} else {
|
||||
|
@ -425,16 +419,12 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(DownloadEvent event) {
|
||||
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||
DownloaderUpdate update = event.update;
|
||||
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds) && getParentFragment() instanceof PagedToolbarFragment) {
|
||||
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
|
||||
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
|
||||
updateToolbar();
|
||||
}
|
||||
if (update.mediaIds.length > 0) {
|
||||
for (long mediaId : update.mediaIds) {
|
||||
|
@ -448,9 +438,8 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
|
||||
private void updateUi() {
|
||||
loadItems();
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()
|
||||
&& getParentFragment() instanceof PagedToolbarFragment) {
|
||||
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
|
||||
updateToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,32 +470,41 @@ public abstract class EpisodesListFragment extends Fragment implements EpisodeIt
|
|||
loadingMoreView.setVisibility(View.GONE);
|
||||
hasMoreItems = true;
|
||||
episodes = data.first;
|
||||
listAdapter.notifyDataSetChanged();
|
||||
listAdapter.setTotalNumberOfItems(data.second);
|
||||
onFragmentLoaded(episodes);
|
||||
if (getParentFragment() instanceof PagedToolbarFragment) {
|
||||
((PagedToolbarFragment) getParentFragment()).invalidateOptionsMenuIfActive(this);
|
||||
}
|
||||
updateAdapterWithNewItems();
|
||||
updateToolbar();
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract List<FeedItem> loadData();
|
||||
protected List<FeedItem> loadData() {
|
||||
return DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE, getFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a new page of data as defined by {@link #page} and {@link #EPISODES_PER_PAGE}.
|
||||
* If the number of items returned is less than {@link #EPISODES_PER_PAGE},
|
||||
* it will be assumed that the underlying data is exhausted
|
||||
* and this method will not be called again.
|
||||
*
|
||||
* @return The items from the next page of data
|
||||
*/
|
||||
@NonNull
|
||||
protected abstract List<FeedItem> loadMoreData(int page);
|
||||
protected List<FeedItem> loadMoreData(int page) {
|
||||
return DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE, getFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of items that would be returned if {@link #loadMoreData} was called often enough.
|
||||
*/
|
||||
protected int loadTotalItemCount() {
|
||||
return SelectableAdapter.COUNT_AUTOMATICALLY;
|
||||
return DBReader.getTotalEpisodeCount(getFilter());
|
||||
}
|
||||
|
||||
protected abstract FeedItemFilter getFilter();
|
||||
|
||||
protected abstract String getFragmentTag();
|
||||
|
||||
protected abstract String getPrefName();
|
||||
|
||||
protected void updateToolbar() {
|
||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(),
|
||||
R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,116 +1,84 @@
|
|||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.event.DownloadEvent;
|
||||
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Like 'EpisodesFragment' except that it only shows new episodes and
|
||||
* supports swiping to mark as read.
|
||||
*/
|
||||
public class InboxFragment extends EpisodesListFragment implements Toolbar.OnMenuItemClickListener {
|
||||
public class InboxFragment extends EpisodesListFragment {
|
||||
public static final String TAG = "NewEpisodesFragment";
|
||||
private static final String PREF_NAME = "PrefNewEpisodesFragment";
|
||||
private static final String KEY_UP_ARROW = "up_arrow";
|
||||
|
||||
private Toolbar toolbar;
|
||||
private boolean displayUpArrow;
|
||||
private volatile boolean isUpdatingFeeds;
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
final View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
toolbar.inflateMenu(R.menu.inbox);
|
||||
toolbar.setTitle(R.string.inbox_label);
|
||||
updateToolbar();
|
||||
emptyView.setIcon(R.drawable.ic_inbox);
|
||||
emptyView.setTitle(R.string.no_inbox_head_label);
|
||||
emptyView.setMessage(R.string.no_inbox_label);
|
||||
speedDialView.removeActionItemById(R.id.mark_unread_batch);
|
||||
speedDialView.removeActionItemById(R.id.remove_from_queue_batch);
|
||||
speedDialView.removeActionItemById(R.id.delete_batch);
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FeedItemFilter getFilter() {
|
||||
return new FeedItemFilter(FeedItemFilter.NEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFragmentTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPrefName() {
|
||||
return PREF_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
|
||||
return item.isNew();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View inboxContainer = View.inflate(getContext(), R.layout.list_container_fragment, null);
|
||||
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
((FrameLayout) inboxContainer.findViewById(R.id.listContent)).addView(root);
|
||||
emptyView.setTitle(R.string.no_inbox_head_label);
|
||||
emptyView.setMessage(R.string.no_inbox_label);
|
||||
|
||||
toolbar = inboxContainer.findViewById(R.id.toolbar);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
toolbar.inflateMenu(R.menu.inbox);
|
||||
toolbar.setOnLongClickListener(v -> {
|
||||
recyclerView.scrollToPosition(5);
|
||||
recyclerView.post(() -> recyclerView.smoothScrollToPosition(0));
|
||||
return false;
|
||||
});
|
||||
displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0;
|
||||
if (savedInstanceState != null) {
|
||||
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
|
||||
}
|
||||
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
|
||||
|
||||
SwipeActions swipeActions = new SwipeActions(this, TAG).attachTo(recyclerView);
|
||||
swipeActions.setFilter(new FeedItemFilter(FeedItemFilter.NEW));
|
||||
|
||||
speedDialView.removeActionItemById(R.id.mark_unread_batch);
|
||||
speedDialView.removeActionItemById(R.id.remove_from_queue_batch);
|
||||
speedDialView.removeActionItemById(R.id.delete_batch);
|
||||
return inboxContainer;
|
||||
}
|
||||
|
||||
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
|
||||
() -> DownloadService.isRunning && DownloadService.isDownloadingFeeds();
|
||||
|
||||
private void updateToolbar() {
|
||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(),
|
||||
R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
|
||||
updateToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(DownloadEvent event) {
|
||||
super.onEventMainThread(event);
|
||||
if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) {
|
||||
updateToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return super.onOptionsItemSelected(item);
|
||||
if (super.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.remove_all_inbox_item) {
|
||||
ConfirmationDialog removeAllNewFlagsConfirmationDialog = new ConfirmationDialog(getActivity(),
|
||||
R.string.remove_all_inbox_label,
|
||||
R.string.remove_all_inbox_confirmation_msg) {
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
|
||||
super.onSaveInstanceState(outState);
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
DBWriter.removeAllNewFlags();
|
||||
((MainActivity) getActivity()).showSnackbarAbovePlayer(
|
||||
R.string.removed_all_inbox_msg, Toast.LENGTH_SHORT);
|
||||
}
|
||||
};
|
||||
removeAllNewFlagsConfirmationDialog.createNewDialog().show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -1,92 +1,59 @@
|
|||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
|
||||
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.event.playback.PlaybackHistoryEvent;
|
||||
import de.danoeh.antennapod.event.PlayerStatusEvent;
|
||||
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.event.playback.PlaybackHistoryEvent;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlaybackHistoryFragment extends EpisodesListFragment implements Toolbar.OnMenuItemClickListener {
|
||||
public class PlaybackHistoryFragment extends EpisodesListFragment {
|
||||
public static final String TAG = "PlaybackHistoryFragment";
|
||||
private static final String KEY_UP_ARROW = "up_arrow";
|
||||
|
||||
private Toolbar toolbar;
|
||||
private boolean displayUpArrow;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View historyContainer = View.inflate(getContext(), R.layout.list_container_fragment, null);
|
||||
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
((FrameLayout) historyContainer.findViewById(R.id.listContent)).addView(root);
|
||||
|
||||
toolbar = historyContainer.findViewById(R.id.toolbar);
|
||||
toolbar.setTitle(R.string.playback_history_label);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
toolbar.setOnLongClickListener(v -> {
|
||||
recyclerView.scrollToPosition(5);
|
||||
recyclerView.post(() -> recyclerView.smoothScrollToPosition(0));
|
||||
return false;
|
||||
});
|
||||
displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0;
|
||||
if (savedInstanceState != null) {
|
||||
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
|
||||
}
|
||||
((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
final View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
toolbar.inflateMenu(R.menu.playback_history);
|
||||
refreshToolbarState();
|
||||
|
||||
listAdapter = new PlaybackHistoryListAdapter((MainActivity) getActivity());
|
||||
recyclerView.setAdapter(listAdapter);
|
||||
|
||||
toolbar.setTitle(R.string.playback_history_label);
|
||||
updateToolbar();
|
||||
emptyView.setIcon(R.drawable.ic_history);
|
||||
emptyView.setTitle(R.string.no_history_head_label);
|
||||
emptyView.setMessage(R.string.no_history_label);
|
||||
|
||||
return historyContainer;
|
||||
swipeActions.detach();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putBoolean(KEY_UP_ARROW, displayUpArrow);
|
||||
super.onSaveInstanceState(outState);
|
||||
protected FeedItemFilter getFilter() {
|
||||
return FeedItemFilter.unfiltered();
|
||||
}
|
||||
|
||||
public void refreshToolbarState() {
|
||||
boolean hasHistory = episodes != null && !episodes.isEmpty();
|
||||
toolbar.getMenu().findItem(R.id.clear_history_item).setVisible(hasHistory);
|
||||
@Override
|
||||
protected String getFragmentTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPrefName() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (super.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.clear_history_item) {
|
||||
DBWriter.clearPlaybackHistory();
|
||||
return true;
|
||||
|
@ -94,43 +61,16 @@ public class PlaybackHistoryFragment extends EpisodesListFragment implements Too
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateToolbar() {
|
||||
// Not calling super, as we do not have a refresh button that could be updated
|
||||
toolbar.getMenu().findItem(R.id.clear_history_item).setVisible(!episodes.isEmpty());
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onHistoryUpdated(PlaybackHistoryEvent event) {
|
||||
loadItems();
|
||||
refreshToolbarState();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onPlayerStatusChanged(PlayerStatusEvent event) {
|
||||
loadItems();
|
||||
refreshToolbarState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onUnreadItemsChanged(UnreadItemsUpdateEvent event) {
|
||||
loadItems();
|
||||
refreshToolbarState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFragmentLoaded(List<FeedItem> episodes) {
|
||||
super.onFragmentLoaded(episodes);
|
||||
listAdapter.notifyDataSetChanged();
|
||||
refreshToolbarState();
|
||||
}
|
||||
|
||||
private class PlaybackHistoryListAdapter extends EpisodeItemListAdapter {
|
||||
|
||||
public PlaybackHistoryListAdapter(MainActivity mainActivity) {
|
||||
super(mainActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
MenuItemUtils.setOnClickListeners(menu, PlaybackHistoryFragment.this::onContextItemSelected);
|
||||
}
|
||||
updateToolbar();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -6,11 +6,20 @@
|
|||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="?attr/actionBarTheme" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvInformation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:visibility="gone"
|
|
@ -1,23 +0,0 @@
|
|||
<?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">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="?attr/actionBarTheme"
|
||||
app:title="@string/inbox_label" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/listContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/toolbar" />
|
||||
|
||||
</RelativeLayout>
|
|
@ -21,7 +21,6 @@
|
|||
android:icon="@drawable/ic_filter"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/filter"
|
||||
android:visible="false"
|
||||
custom:showAsAction="always"/>
|
||||
|
||||
<item
|
||||
|
|
|
@ -72,10 +72,6 @@ public class FeedItemFilter implements Serializable {
|
|||
return properties.clone();
|
||||
}
|
||||
|
||||
public boolean isShowDownloaded() {
|
||||
return showDownloaded;
|
||||
}
|
||||
|
||||
public boolean matches(FeedItem item) {
|
||||
if (showNew && !item.isNew()) {
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue