diff options
author | ByteHamster <ByteHamster@users.noreply.github.com> | 2022-08-07 20:53:11 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-07 20:53:11 +0200 |
commit | 440b20487b9c48ddc1e20ba008262689916e8eaa (patch) | |
tree | 38bbf41a708080b3b42d9a45e723138534f64f56 | |
parent | d58debbf580dee6ea9728aeedac29db4524e7e2d (diff) | |
parent | e65fe6244b2131ce55c82d3ffb226521a9d8318e (diff) | |
download | AntennaPod-440b20487b9c48ddc1e20ba008262689916e8eaa.zip |
Merge pull request #6001 from ByteHamster/remove-favorite-tab
Remove favorites tab from episodes screen
21 files changed, 265 insertions, 592 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java b/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java index 3c32407a5..c68e13438 100644 --- a/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java +++ b/app/src/androidTest/java/de/test/antennapod/dialogs/ShareDialogTest.java @@ -8,7 +8,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.fragment.EpisodesFragment; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.test.antennapod.EspressoTestUtils; import de.test.antennapod.ui.UITestUtils; import org.hamcrest.Matcher; @@ -48,7 +48,7 @@ public class ShareDialogTest { context = InstrumentationRegistry.getInstrumentation().getTargetContext(); EspressoTestUtils.clearPreferences(); EspressoTestUtils.clearDatabase(); - EspressoTestUtils.setLastNavFragment(EpisodesFragment.TAG); + EspressoTestUtils.setLastNavFragment(AllEpisodesFragment.TAG); UITestUtils uiTestUtils = new UITestUtils(context); uiTestUtils.setup(); uiTestUtils.addLocalFeedData(true); @@ -57,8 +57,6 @@ public class ShareDialogTest { openNavDrawer(); onDrawerItem(withText(R.string.episodes_label)).perform(click()); - onView(isRoot()).perform(waitForView(withText(R.string.all_episodes_short_label), 1000)); - onView(withText(R.string.all_episodes_short_label)).perform(click()); Matcher<View> allEpisodesMatcher; allEpisodesMatcher = Matchers.allOf(withId(android.R.id.list), isDisplayed(), hasMinimumChildCount(2)); diff --git a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java index 67a660ae1..78cf59907 100644 --- a/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java +++ b/app/src/androidTest/java/de/test/antennapod/playback/PlaybackTest.java @@ -251,11 +251,9 @@ public class PlaybackTest { protected void startLocalPlayback() { openNavDrawer(); onDrawerItem(withText(R.string.episodes_label)).perform(click()); - onView(isRoot()).perform(waitForView(withText(R.string.all_episodes_short_label), 1000)); - onView(withText(R.string.all_episodes_short_label)).perform(click()); final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10, FeedItemFilter.unfiltered()); - Matcher<View> allEpisodesMatcher = allOf(withId(android.R.id.list), isDisplayed(), hasMinimumChildCount(2)); + Matcher<View> allEpisodesMatcher = allOf(withId(R.id.recyclerView), isDisplayed(), hasMinimumChildCount(2)); onView(isRoot()).perform(waitForView(allEpisodesMatcher, 1000)); onView(allEpisodesMatcher).perform(actionOnItemAtPosition(0, clickChildViewWithId(R.id.secondaryActionButton))); diff --git a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java index 98d983a02..97c199e26 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/NavigationDrawerTest.java @@ -11,7 +11,7 @@ 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.EpisodesFragment; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.NavDrawerFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; @@ -148,7 +148,7 @@ public class NavigationDrawerTest { List<String> hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(2, hidden.size()); - assertTrue(hidden.contains(EpisodesFragment.TAG)); + assertTrue(hidden.contains(AllEpisodesFragment.TAG)); assertTrue(hidden.contains(PlaybackHistoryFragment.TAG)); } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index ef5719d6f..b8f2faa63 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -28,7 +28,7 @@ import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm; import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm; import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm; import de.danoeh.antennapod.core.storage.ExceptFavoriteCleanupAlgorithm; -import de.danoeh.antennapod.fragment.EpisodesFragment; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.test.antennapod.EspressoTestUtils; @@ -521,7 +521,7 @@ public class PreferencesTest { Awaitility.await().atMost(1000, MILLISECONDS) .until(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE); Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getBackButtonGoToPage().equals(EpisodesFragment.TAG)); + .until(() -> UserPreferences.getBackButtonGoToPage().equals(AllEpisodesFragment.TAG)); clickPreference(R.string.pref_back_button_behavior_title); onView(withText(R.string.back_button_go_to_page)).perform(click()); onView(withText(R.string.subscriptions_label)).perform(click()); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index fe5d8733a..837dcd731 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -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.AllEpisodesFragment; import de.danoeh.antennapod.fragment.CompletedDownloadsFragment; import de.danoeh.antennapod.playback.cast.CastEnabledActivity; import org.apache.commons.lang3.ArrayUtils; @@ -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.EpisodesFragment; import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.fragment.FeedItemlistFragment; import de.danoeh.antennapod.fragment.NavDrawerFragment; @@ -270,8 +270,8 @@ public class MainActivity extends CastEnabledActivity { case InboxFragment.TAG: fragment = new InboxFragment(); break; - case EpisodesFragment.TAG: - fragment = new EpisodesFragment(); + case AllEpisodesFragment.TAG: + fragment = new AllEpisodesFragment(); break; case CompletedDownloadsFragment.TAG: fragment = new CompletedDownloadsFragment(); @@ -606,7 +606,7 @@ public class MainActivity extends CastEnabledActivity { loadFragment(PlaybackHistoryFragment.TAG, null); break; case "EPISODES": - loadFragment(EpisodesFragment.TAG, null); + loadFragment(AllEpisodesFragment.TAG, null); break; case "QUEUE": loadFragment(QueueFragment.TAG, null); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index aaf914ebc..c0fc07ff6 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -24,6 +24,7 @@ import com.bumptech.glide.request.RequestOptions; import com.joanzapata.iconify.Iconify; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.CompletedDownloadsFragment; import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.model.feed.Feed; @@ -31,7 +32,6 @@ 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.EpisodesFragment; import de.danoeh.antennapod.fragment.NavDrawerFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; @@ -116,7 +116,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder> return R.drawable.ic_playlist_play; case InboxFragment.TAG: return R.drawable.ic_inbox; - case EpisodesFragment.TAG: + case AllEpisodesFragment.TAG: return R.drawable.ic_feed; case CompletedDownloadsFragment.TAG: return R.drawable.ic_download; diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SwipeActionsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SwipeActionsDialog.java index da4cfc1c0..fd0a32e03 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SwipeActionsDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SwipeActionsDialog.java @@ -22,8 +22,8 @@ import de.danoeh.antennapod.databinding.SwipeactionsDialogBinding; import de.danoeh.antennapod.databinding.SwipeactionsPickerBinding; import de.danoeh.antennapod.databinding.SwipeactionsPickerItemBinding; import de.danoeh.antennapod.databinding.SwipeactionsRowBinding; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.CompletedDownloadsFragment; -import de.danoeh.antennapod.fragment.EpisodesFragment; import de.danoeh.antennapod.fragment.FeedItemlistFragment; import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.fragment.QueueFragment; @@ -62,7 +62,7 @@ public class SwipeActionsDialog { forFragment = context.getString(R.string.inbox_label); keys = Stream.of(keys).filter(a -> !a.getId().equals(SwipeAction.TOGGLE_PLAYED)).toList(); break; - case EpisodesFragment.TAG: + case AllEpisodesFragment.TAG: forFragment = context.getString(R.string.episodes_label); break; case CompletedDownloadsFragment.TAG: diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index 46a648e57..36e02929a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -3,37 +3,51 @@ package de.danoeh.antennapod.fragment; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; -import android.view.Menu; +import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import com.joanzapata.iconify.Iconify; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.dialog.AllEpisodesFilterDialog; -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 java.util.List; +import java.util.Collections; /** - * Like 'EpisodesFragment' except that it only shows new episodes and - * supports swiping to mark as read. + * Shows all episodes (possibly filtered by user). */ 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 FeedItemFilter feedItemFilter = new FeedItemFilter(""); + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final View root = super.onCreateView(inflater, container, savedInstanceState); + toolbar.inflateMenu(R.menu.episodes); + toolbar.setTitle(R.string.episodes_label); + updateToolbar(); + updateFilterUi(); + speedDialView.removeActionItemById(R.id.mark_unread_batch); + speedDialView.removeActionItemById(R.id.remove_from_queue_batch); + speedDialView.removeActionItemById(R.id.delete_batch); + return root; + } @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + protected FeedItemFilter getFilter() { SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - feedItemFilter = new FeedItemFilter(prefs.getString(PREF_FILTER, "")); + return new FeedItemFilter(prefs.getString(PREF_FILTER, "")); + } + + @Override + protected String getFragmentTag() { + return TAG; } @Override @@ -42,12 +56,16 @@ public class AllEpisodesFragment extends EpisodesListFragment { } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onMenuItemClick(MenuItem item) { if (super.onOptionsItemSelected(item)) { 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(getFilter().showIsFavorite + ? Collections.emptySet() : Collections.singleton(FeedItemFilter.IS_FAVORITE))); return true; } return false; @@ -55,58 +73,23 @@ public class AllEpisodesFragment extends EpisodesListFragment { @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; loadItems(); } - @Override - public void onPrepareOptionsMenu(@NonNull Menu menu) { - super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.filter_items).setVisible(true); - } - - @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); + emptyView.setMessage(R.string.no_all_episodes_filtered_label); } else { txtvInformation.setVisibility(View.GONE); + emptyView.setMessage(R.string.no_all_episodes_label); } } - - @Override - protected boolean shouldUpdatedItemRemainInList(FeedItem item) { - SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - FeedItemFilter feedItemFilter = new FeedItemFilter(prefs.getString(PREF_FILTER, "")); - - if (feedItemFilter.isShowDownloaded() && (!item.hasMedia() || !item.getMedia().isDownloaded())) { - return false; - } - - return true; - } - - @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); - } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java deleted file mode 100644 index 951d42d73..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ /dev/null @@ -1,121 +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.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; - -public class EpisodesFragment extends PagedToolbarFragment { - - public static final String TAG = "EpisodesFragment"; - private static final String PREF_LAST_TAB_POSITION = "tab_position"; - private static final String KEY_UP_ARROW = "up_arrow"; - - private static final int POS_ALL_EPISODES = 0; - private static final int POS_FAV_EPISODES = 1; - private static final int TOTAL_COUNT = 2; - - private TabLayout tabLayout; - private boolean displayUpArrow; - - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setRetainInstance(true); - } - - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - View rootView = inflater.inflate(R.layout.pager_fragment, container, false); - Toolbar toolbar = rootView.findViewById(R.id.toolbar); - toolbar.setTitle(R.string.episodes_label); - toolbar.inflateMenu(R.menu.episodes); - displayUpArrow = getParentFragmentManager().getBackStackEntryCount() != 0; - if (savedInstanceState != null) { - displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW); - } - ((MainActivity) getActivity()).setupToolbarToggle(toolbar, displayUpArrow); - - ViewPager2 viewPager = rootView.findViewById(R.id.viewpager); - viewPager.setAdapter(new EpisodesPagerAdapter(this)); - viewPager.setOffscreenPageLimit(2); - super.setupPagedToolbar(toolbar, viewPager); - - // Give the TabLayout the ViewPager - tabLayout = rootView.findViewById(R.id.sliding_tabs); - - new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> { - switch (position) { - case POS_ALL_EPISODES: - tab.setText(R.string.all_episodes_short_label); - break; - case POS_FAV_EPISODES: - tab.setText(R.string.favorite_episodes_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 rootView; - } - - @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(); - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - outState.putBoolean(KEY_UP_ARROW, displayUpArrow); - super.onSaveInstanceState(outState); - } - - static class EpisodesPagerAdapter extends FragmentStateAdapter { - - EpisodesPagerAdapter(@NonNull Fragment fragment) { - super(fragment); - } - - @NonNull - @Override - public Fragment createFragment(int position) { - switch (position) { - case POS_ALL_EPISODES: - return new AllEpisodesFragment(); - default: - case POS_FAV_EPISODES: - return new FavoriteEpisodesFragment(); - } - } - - @Override - public int getItemCount() { - return TOTAL_COUNT; - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java index 03dbc6ae4..f581a16f5 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -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,57 +14,63 @@ 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.adapter.EpisodeItemListAdapter; -import de.danoeh.antennapod.adapter.SelectableAdapter; -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.fragment.actions.EpisodeMultiSelectActionHandler; -import de.danoeh.antennapod.ui.common.PagedToolbarFragment; -import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; -import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; -import io.reactivex.Completable; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -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.adapter.EpisodeItemListAdapter; 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.menuhandler.MenuItemUtils; import de.danoeh.antennapod.core.service.download.DownloadService; -import de.danoeh.antennapod.core.storage.DBWriter; +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.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.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; + +import java.util.ArrayList; +import java.util.List; /** * 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); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java deleted file mode 100644 index 30eec8780..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ /dev/null @@ -1,109 +0,0 @@ -package de.danoeh.antennapod.fragment; - -import android.os.Bundle; -import android.view.Menu; -import androidx.annotation.NonNull; -import com.google.android.material.snackbar.Snackbar; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.ItemTouchHelper; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.model.feed.FeedItemFilter; -import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; -import org.greenrobot.eventbus.Subscribe; - -import java.util.List; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.event.FavoritesEvent; -import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; - -/** - * Like 'EpisodesFragment' except that it only shows favorite episodes and - * supports swiping to remove from favorites. - */ -public class FavoriteEpisodesFragment extends EpisodesListFragment { - - private static final String TAG = "FavoriteEpisodesFrag"; - private static final String PREF_NAME = "PrefFavoriteEpisodesFragment"; - - @Override - protected String getPrefName() { - return PREF_NAME; - } - - @Subscribe - public void onEvent(FavoritesEvent event) { - Log.d(TAG, String.format("onEvent() called with: event = [%s]", event)); - loadItems(); - } - - @Override - public void onPrepareOptionsMenu(@NonNull Menu menu) { - super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.filter_items).setVisible(false); - } - - @NonNull - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View root = super.onCreateView(inflater, container, savedInstanceState); - emptyView.setIcon(R.drawable.ic_star); - emptyView.setTitle(R.string.no_fav_episodes_head_label); - emptyView.setMessage(R.string.no_fav_episodes_label); - - ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, - ItemTouchHelper.LEFT) { - @Override - public boolean onMove(@NonNull RecyclerView recyclerView, - @NonNull RecyclerView.ViewHolder viewHolder, - @NonNull RecyclerView.ViewHolder target) { - return false; - } - - @Override - public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int swipeDir) { - EpisodeItemViewHolder holder = (EpisodeItemViewHolder) viewHolder; - Log.d(TAG, String.format("remove(%s)", holder.getFeedItem().getId())); - - if (disposable != null) { - disposable.dispose(); - } - FeedItem item = holder.getFeedItem(); - if (item != null) { - DBWriter.removeFavoriteItem(item); - - ((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.removed_item, Snackbar.LENGTH_LONG) - .setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item)); - } - } - }; - - ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); - itemTouchHelper.attachToRecyclerView(recyclerView); - return root; - } - - @NonNull - @Override - protected List<FeedItem> loadData() { - return DBReader.getFavoriteItemsList(0, page * EPISODES_PER_PAGE); - } - - @NonNull - @Override - protected List<FeedItem> loadMoreData(int page) { - return DBReader.getFavoriteItemsList((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE); - } - - @Override - protected int loadTotalItemCount() { - return DBReader.getTotalEpisodeCount(new FeedItemFilter(FeedItemFilter.IS_FAVORITE)); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java index 77d0c4555..d5dd51e93 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java @@ -273,7 +273,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem new RenameItemDialog(getActivity(), feed).show(); return true; } else if (itemId == R.id.remove_feed) { - ((MainActivity) getActivity()).loadFragment(EpisodesFragment.TAG, null); + ((MainActivity) getActivity()).loadFragment(AllEpisodesFragment.TAG, null); RemoveFeedDialog.show(getContext(), feed); return true; } else if (itemId == R.id.action_search) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java index 0ff0bd24a..6e5db0963 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/InboxFragment.java @@ -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; - - @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); + 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); - - 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); + return root; } @Override - public void onStart() { - super.onStart(); - if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) { - updateToolbar(); - } + protected FeedItemFilter getFilter() { + return new FeedItemFilter(FeedItemFilter.NEW); } - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - super.onEventMainThread(event); - if (event.hasChangedFeedUpdateStatus(isUpdatingFeeds)) { - updateToolbar(); - } + @Override + protected String getFragmentTag() { + return TAG; } @Override - public boolean onMenuItemClick(MenuItem item) { - return super.onOptionsItemSelected(item); + protected String getPrefName() { + return PREF_NAME; } @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - outState.putBoolean(KEY_UP_ARROW, displayUpArrow); - super.onSaveInstanceState(outState); + public boolean onMenuItemClick(MenuItem 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 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 diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java index 1561a984d..95f08a838 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java @@ -67,7 +67,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS public static final String[] NAV_DRAWER_TAGS = { QueueFragment.TAG, InboxFragment.TAG, - EpisodesFragment.TAG, + AllEpisodesFragment.TAG, SubscriptionFragment.TAG, CompletedDownloadsFragment.TAG, PlaybackHistoryFragment.TAG, @@ -173,7 +173,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS new RenameItemDialog(getActivity(), feed).show(); return true; } else if (itemId == R.id.remove_feed) { - ((MainActivity) getActivity()).loadFragment(EpisodesFragment.TAG, null); + ((MainActivity) getActivity()).loadFragment(AllEpisodesFragment.TAG, null); RemoveFeedDialog.show(getContext(), feed); return true; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index a22edbc76..3e9b2b5c7 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -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; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setRetainInstance(true); - } + @NonNull @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); + swipeActions.detach(); + return root; + } - return historyContainer; + @Override + protected FeedItemFilter getFilter() { + return FeedItemFilter.unfiltered(); } @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - outState.putBoolean(KEY_UP_ARROW, displayUpArrow); - super.onSaveInstanceState(outState); + protected String getFragmentTag() { + return TAG; } - public void refreshToolbarState() { - boolean hasHistory = episodes != null && !episodes.isEmpty(); - toolbar.getMenu().findItem(R.id.clear_history_item).setVisible(hasHistory); + @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; } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onHistoryUpdated(PlaybackHistoryEvent event) { - loadItems(); - refreshToolbarState(); - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onPlayerStatusChanged(PlayerStatusEvent event) { - loadItems(); - refreshToolbarState(); + @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()); } - @Override @Subscribe(threadMode = ThreadMode.MAIN) - public void onUnreadItemsChanged(UnreadItemsUpdateEvent event) { + public void onHistoryUpdated(PlaybackHistoryEvent 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 diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/swipeactions/SwipeActions.java b/app/src/main/java/de/danoeh/antennapod/fragment/swipeactions/SwipeActions.java index be35f6503..afb79e497 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/swipeactions/SwipeActions.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/swipeactions/SwipeActions.java @@ -21,8 +21,8 @@ import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.dialog.SwipeActionsDialog; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.CompletedDownloadsFragment; -import de.danoeh.antennapod.fragment.EpisodesFragment; import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.model.feed.FeedItem; @@ -106,7 +106,7 @@ public class SwipeActions extends ItemTouchHelper.SimpleCallback implements Life defaultActions = SwipeAction.DELETE + "," + SwipeAction.DELETE; break; default: - case EpisodesFragment.TAG: + case AllEpisodesFragment.TAG: defaultActions = SwipeAction.MARK_FAV + "," + SwipeAction.START_DOWNLOAD; break; } diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/episodes_list_fragment.xml index c1e7e6434..39a0c260a 100644 --- a/app/src/main/res/layout/all_episodes_fragment.xml +++ b/app/src/main/res/layout/episodes_list_fragment.xml @@ -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" diff --git a/app/src/main/res/layout/list_container_fragment.xml b/app/src/main/res/layout/list_container_fragment.xml deleted file mode 100644 index 1b6debb13..000000000 --- a/app/src/main/res/layout/list_container_fragment.xml +++ /dev/null @@ -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> diff --git a/app/src/main/res/menu/episodes.xml b/app/src/main/res/menu/episodes.xml index 4e6da923b..2841fc12f 100644 --- a/app/src/main/res/menu/episodes.xml +++ b/app/src/main/res/menu/episodes.xml @@ -21,7 +21,13 @@ android:icon="@drawable/ic_filter" android:menuCategory="container" android:title="@string/filter" - android:visible="false" - custom:showAsAction="ifRoom"/> + custom:showAsAction="always"/> + + <item + android:id="@+id/action_favorites" + android:icon="@drawable/ic_star_border" + android:menuCategory="container" + android:title="@string/favorite_episodes_label" + custom:showAsAction="always"/> </menu> diff --git a/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java b/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java index c9989e60a..460177d56 100644 --- a/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java +++ b/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java @@ -72,7 +72,36 @@ public class FeedItemFilter implements Serializable { return properties.clone(); } - public boolean isShowDownloaded() { - return showDownloaded; + public boolean matches(FeedItem item) { + if (showNew && !item.isNew()) { + return false; + } else if (showPlayed && !item.isPlayed()) { + return false; + } else if (showUnplayed && item.isPlayed()) { + return false; + } else if (showPaused && !item.isInProgress()) { + return false; + } else if (showNotPaused && item.isInProgress()) { + return false; + } else if (showNew && !item.isNew()) { + return false; + } else if (showQueued && !item.isTagged(FeedItem.TAG_QUEUE)) { + return false; + } else if (showNotQueued && item.isTagged(FeedItem.TAG_QUEUE)) { + return false; + } else if (showDownloaded && !item.isDownloaded()) { + return false; + } else if (showNotDownloaded && item.isDownloaded()) { + return false; + } else if (showHasMedia && !item.hasMedia()) { + return false; + } else if (showNoMedia && item.hasMedia()) { + return false; + } else if (showIsFavorite && !item.isTagged(FeedItem.TAG_FAVORITE)) { + return false; + } else if (showNotFavorite && item.isTagged(FeedItem.TAG_FAVORITE)) { + return false; + } + return true; } } diff --git a/ui/i18n/src/main/res/values/strings.xml b/ui/i18n/src/main/res/values/strings.xml index 0242f75a2..35ccc9677 100644 --- a/ui/i18n/src/main/res/values/strings.xml +++ b/ui/i18n/src/main/res/values/strings.xml @@ -11,7 +11,6 @@ <string name="add_feed_label">Add Podcast</string> <string name="episodes_label">Episodes</string> <string name="queue_label">Queue</string> - <string name="all_episodes_short_label">All</string> <string name="inbox_label">Inbox</string> <string name="favorite_episodes_label">Favorites</string> <string name="settings_label">Settings</string> @@ -233,7 +232,6 @@ <string name="visit_website_label">Visit Website</string> <string name="skip_episode_label">Skip episode</string> <string name="reset_position">Reset Playback Position</string> - <string name="removed_item">Item removed</string> <string name="no_items_selected">No items selected</string> <!-- Download messages and labels --> @@ -339,10 +337,9 @@ <string name="no_history_label">After you listen to an episode, it will appear here.</string> <string name="no_all_episodes_head_label">No Episodes</string> <string name="no_all_episodes_label">When you add a podcast, the episodes will be shown here.</string> + <string name="no_all_episodes_filtered_label">Try clearing the filter to see more episodes.</string> <string name="no_inbox_head_label">No episodes in the inbox</string> <string name="no_inbox_label">When new episodes arrive, they will be shown here. You can then decide if you are interested in them or not.</string> - <string name="no_fav_episodes_head_label">No favorite episodes</string> - <string name="no_fav_episodes_label">You can add episodes to the favorites by long-pressing them.</string> <string name="no_subscriptions_head_label">No subscriptions</string> <string name="no_subscriptions_label">To subscribe to a podcast, press the plus icon below.</string> |