diff options
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
14 files changed, 203 insertions, 201 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java index eafc4b0a6..f1946d9a8 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java @@ -273,17 +273,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR if (item != null) { menu.setHeaderTitle(item.getTitle()); } - - FeedItemMenuHandler.MenuInterface contextMenuInterface = (id, visible) -> { - if (menu == null) { - return; - } - MenuItem item1 = menu.findItem(id); - if (item1 != null) { - item1.setVisible(visible); - } - }; - FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item); + FeedItemMenuHandler.onPrepareMenu(menu, item); } public boolean isCurrentlyPlayingItem() { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java index 5ccec0ade..2a39321ef 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -179,26 +179,16 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap menu.setHeaderTitle(item.getTitle()); } - FeedItemMenuHandler.MenuInterface contextMenuInterface = (id, visible) -> { - if (menu == null) { - return; - } - MenuItem item1 = menu.findItem(id); - if (item1 != null) { - item1.setVisible(visible); - } - }; - - FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, + FeedItemMenuHandler.onPrepareMenu(menu, item, R.id.skip_episode_item); // Skip Episode is not useful in Queue, so hide it. // Queue-specific menu preparation final boolean keepSorted = UserPreferences.isQueueKeepSorted(); final LongList queueAccess = itemAccess.getQueueIds(); if (queueAccess.size() == 0 || queueAccess.get(0) == item.getId() || keepSorted) { - contextMenuInterface.setItemVisibility(R.id.move_to_top_item, false); + menu.findItem(R.id.move_to_top_item).setVisible(false); } if (queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == item.getId() || keepSorted) { - contextMenuInterface.setItemVisibility(R.id.move_to_bottom_item, false); + menu.findItem(R.id.move_to_bottom_item).setVisible(false); } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MarkAsPlayedActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MarkAsPlayedActionButton.java index 354ded73d..71ac07c47 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MarkAsPlayedActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MarkAsPlayedActionButton.java @@ -18,7 +18,7 @@ class MarkAsPlayedActionButton extends ItemActionButton { @Override @StringRes public int getLabel() { - return R.string.mark_read_label; + return (item.hasMedia() ? R.string.mark_read_label : R.string.mark_read_no_media_label); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index d583c0e1e..34b102ca8 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -116,7 +116,7 @@ public class EpisodesApplyActionFragment extends Fragment { public static EpisodesApplyActionFragment newInstance(List<FeedItem> items, int actions) { EpisodesApplyActionFragment f = new EpisodesApplyActionFragment(); f.episodes.addAll(items); - for(FeedItem episode : items) { + for (FeedItem episode : items) { f.idMap.put(episode.getId(), episode); } f.actions = actions; @@ -411,7 +411,7 @@ public class EpisodesApplyActionFragment extends Fragment { private void refreshTitles() { titles.clear(); - for(FeedItem episode : episodes) { + for (FeedItem episode : episodes) { titles.add(episode.getTitle()); } mAdapter.notifyDataSetChanged(); @@ -457,8 +457,15 @@ public class EpisodesApplyActionFragment extends Fragment { } private void queueChecked() { - DBWriter.addQueueItem(getActivity(), true, checkedIds.toArray()); - close(R.plurals.added_to_queue_batch_label, checkedIds.size()); + // Check if an episode actually contains any media files before adding it to queue + LongList toQueue = new LongList(checkedIds.size()); + for (FeedItem episode : episodes) { + if (checkedIds.contains(episode.getId()) && episode.hasMedia()) { + toQueue.add(episode.getId()); + } + } + DBWriter.addQueueItem(getActivity(), true, toQueue.toArray()); + close(R.plurals.added_to_queue_batch_label, toQueue.size()); } private void removeFromQueueChecked() { @@ -479,7 +486,7 @@ public class EpisodesApplyActionFragment extends Fragment { private void downloadChecked() { // download the check episodes in the same order as they are currently displayed List<FeedItem> toDownload = new ArrayList<>(checkedIds.size()); - for(FeedItem episode : episodes) { + for (FeedItem episode : episodes) { if(checkedIds.contains(episode.getId()) && episode.hasMedia()) { toDownload.add(episode); } @@ -494,7 +501,7 @@ public class EpisodesApplyActionFragment extends Fragment { } private void deleteChecked() { - for(long id : checkedIds.toArray()) { + for (long id : checkedIds.toArray()) { FeedItem episode = idMap.get(id); if(episode.hasMedia()) { DBWriter.deleteFeedMediaOfItem(getActivity(), episode.getMedia().getId()); 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 fdb74fa64..e4276b3b9 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -3,26 +3,18 @@ package de.danoeh.antennapod.fragment; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.util.Log; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; 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.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedItemFilter; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.dialog.FilterDialog; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -33,16 +25,18 @@ import java.util.Set; * supports swiping to mark as read. */ public class AllEpisodesFragment extends EpisodesListFragment { - public static final String TAG = "AllEpisodesFragment"; private static final String PREF_NAME = "PrefAllEpisodesFragment"; private static final String PREF_FILTER = "filter"; - private static final int EPISODES_PER_PAGE = 150; - private static final int VISIBLE_EPISODES_SCROLL_THRESHOLD = 5; - private static int page = 1; + private static FeedItemFilter feedItemFilter = new FeedItemFilter(""); - 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, "")); + } @Override protected boolean showOnlyNewEpisodes() { @@ -69,53 +63,6 @@ public class AllEpisodesFragment extends EpisodesListFragment { } } - @NonNull - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View root = super.onCreateView(inflater, container, savedInstanceState); - - SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - feedItemFilter = new FeedItemFilter(prefs.getString(PREF_FILTER, "")); - - recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - - /* Total number of episodes after last load */ - private int previousTotalEpisodes = 0; - - /* True if loading more episodes is still in progress */ - private boolean isLoadingMore = true; - - @Override - public void onScrolled(RecyclerView recyclerView, int deltaX, int deltaY) { - super.onScrolled(recyclerView, deltaX, deltaY); - - int visibleEpisodeCount = recyclerView.getChildCount(); - int totalEpisodeCount = recyclerView.getLayoutManager().getItemCount(); - int firstVisibleEpisode = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); - - /* Determine if loading more episodes has finished */ - if (isLoadingMore) { - if (totalEpisodeCount > previousTotalEpisodes) { - isLoadingMore = false; - previousTotalEpisodes = totalEpisodeCount; - } - } - - /* Determine if the user scrolled to the bottom and loading more episodes is not already in progress */ - if (!isLoadingMore && (totalEpisodeCount - visibleEpisodeCount) - <= (firstVisibleEpisode + VISIBLE_EPISODES_SCROLL_THRESHOLD)) { - - /* The end of the list has been reached. Load more data. */ - page++; - loadMoreItems(); - isLoadingMore = true; - } - } - }); - - return root; - } - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); @@ -136,20 +83,6 @@ public class AllEpisodesFragment extends EpisodesListFragment { } } - private void loadMoreItems() { - if (disposable != null) { - disposable.dispose(); - } - disposable = Observable.fromCallable(this::loadMoreData) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(data -> { - progLoading.setVisibility(View.GONE); - episodes.addAll(data); - onFragmentLoaded(episodes); - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } - private void showFilterDialog() { FilterDialog filterDialog = new FilterDialog(getContext(), feedItemFilter) { @Override @@ -167,10 +100,13 @@ public class AllEpisodesFragment extends EpisodesListFragment { @NonNull @Override protected List<FeedItem> loadData() { - return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE)); + return feedItemFilter.filter(DBReader.getRecentlyPublishedEpisodes(0, page * EPISODES_PER_PAGE)); } - List<FeedItem> loadMoreData() { - return feedItemFilter.filter( DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE)); + @NonNull + @Override + protected List<FeedItem> loadMoreData() { + return feedItemFilter.filter(DBReader.getRecentlyPublishedEpisodes((page - 1) * EPISODES_PER_PAGE, + EPISODES_PER_PAGE)); } } 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 5dbb703b7..b6d6dd9bb 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -70,9 +70,14 @@ public abstract class EpisodesListFragment extends Fragment { private static final String PREF_SCROLL_POSITION = "scroll_position"; private static final String PREF_SCROLL_OFFSET = "scroll_offset"; + protected static final int EPISODES_PER_PAGE = 150; + private static final int VISIBLE_EPISODES_SCROLL_THRESHOLD = 5; + protected int page = 1; + RecyclerView recyclerView; AllEpisodesRecycleAdapter listAdapter; ProgressBar progLoading; + View loadingMore; EmptyViewHandler emptyView; @NonNull @@ -264,6 +269,7 @@ public abstract class EpisodesListFragment extends Fragment { recyclerView.setHasFixedSize(true); recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build()); recyclerView.setVisibility(View.GONE); + setupLoadMoreScrollListener(); RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { @@ -272,6 +278,7 @@ public abstract class EpisodesListFragment extends Fragment { progLoading = root.findViewById(R.id.progLoading); progLoading.setVisibility(View.VISIBLE); + loadingMore = root.findViewById(R.id.loadingMore); emptyView = new EmptyViewHandler(getContext()); emptyView.attachToRecyclerView(recyclerView); @@ -285,6 +292,60 @@ public abstract class EpisodesListFragment extends Fragment { return root; } + private void setupLoadMoreScrollListener() { + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + + /* Total number of episodes after last load */ + private int previousTotalEpisodes = 0; + + /* True if loading more episodes is still in progress */ + private boolean isLoadingMore = true; + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int deltaX, int deltaY) { + super.onScrolled(recyclerView, deltaX, deltaY); + + int visibleEpisodeCount = recyclerView.getChildCount(); + int totalEpisodeCount = recyclerView.getLayoutManager().getItemCount(); + int firstVisibleEpisode = layoutManager.findFirstVisibleItemPosition(); + + /* Determine if loading more episodes has finished */ + if (isLoadingMore) { + if (totalEpisodeCount > previousTotalEpisodes) { + isLoadingMore = false; + previousTotalEpisodes = totalEpisodeCount; + } + } + + /* Determine if the user scrolled to the bottom and loading more episodes is not already in progress */ + if (!isLoadingMore && (totalEpisodeCount - visibleEpisodeCount) + <= (firstVisibleEpisode + VISIBLE_EPISODES_SCROLL_THRESHOLD)) { + + /* The end of the list has been reached. Load more data. */ + page++; + loadMoreItems(); + isLoadingMore = true; + } + } + }); + } + + private void loadMoreItems() { + if (disposable != null) { + disposable.dispose(); + } + loadingMore.setVisibility(View.VISIBLE); + disposable = Observable.fromCallable(this::loadMoreData) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(data -> { + loadingMore.setVisibility(View.GONE); + progLoading.setVisibility(View.GONE); + episodes.addAll(data); + onFragmentLoaded(episodes); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); + } + protected void onFragmentLoaded(List<FeedItem> episodes) { listAdapter.notifyDataSetChanged(); @@ -453,4 +514,7 @@ public abstract class EpisodesListFragment extends Fragment { @NonNull protected abstract List<FeedItem> loadData(); + + @NonNull + protected abstract List<FeedItem> loadMoreData(); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java index f73735658..87a555cfd 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java @@ -88,6 +88,12 @@ public class FavoriteEpisodesFragment extends EpisodesListFragment { @NonNull @Override protected List<FeedItem> loadData() { - return DBReader.getFavoriteItemsList(); + return DBReader.getFavoriteItemsList(0, page * EPISODES_PER_PAGE); + } + + @NonNull + @Override + protected List<FeedItem> loadMoreData() { + return DBReader.getFavoriteItemsList((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE); } } 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 94aa7291e..081f4d604 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java @@ -290,19 +290,6 @@ public class FeedItemlistFragment extends ListFragment { } } - private final FeedItemMenuHandler.MenuInterface contextMenuInterface = new FeedItemMenuHandler.MenuInterface() { - @Override - public void setItemVisibility(int id, boolean visible) { - if(contextMenu == null) { - return; - } - MenuItem item = contextMenu.findItem(id); - if (item != null) { - item.setVisible(visible); - } - } - }; - @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); @@ -320,7 +307,7 @@ public class FeedItemlistFragment extends ListFragment { contextMenu = menu; lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo; - FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item); + FeedItemMenuHandler.onPrepareMenu(menu, item); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index 2806f48ba..7a3d034f1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -308,7 +308,11 @@ public class ItemFragment extends Fragment { if (media == null) { if (!item.isPlayed()) { butAction1Icon = R.attr.navigation_accept; - butAction1Text = R.string.mark_read_label; + if (item.hasMedia()) { + butAction1Text = R.string.mark_read_label; + } else { + butAction1Text = R.string.mark_read_no_media_label; + } } if (item.getLink() != null) { butAction2Icon = R.attr.location_web_site; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java index 20188a8a6..b9e961535 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java @@ -140,19 +140,14 @@ public class ItemPagerFragment extends Fragment { } inflater.inflate(R.menu.feeditem_options, menu); - FeedItemMenuHandler.MenuInterface popupMenuInterface = (id, visible) -> { - MenuItem item = menu.findItem(id); - if (item != null) { - item.setVisible(visible); + if (menu != null && item != null) { + if (item.hasMedia()) { + FeedItemMenuHandler.onPrepareMenu(menu, item); + } else { + // these are already available via button1 and button2 + FeedItemMenuHandler.onPrepareMenu(menu, item, + R.id.mark_read_item, R.id.visit_website_item); } - }; - - if (item.hasMedia()) { - FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item); - } else { - // these are already available via button1 and button2 - FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, - R.id.mark_read_item, R.id.visit_website_item); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index 2bfdd040b..bd3fd06b0 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -104,6 +104,12 @@ public class NewEpisodesFragment extends EpisodesListFragment { @NonNull @Override protected List<FeedItem> loadData() { - return DBReader.getNewItemsList(); + return DBReader.getNewItemsList(0, page * EPISODES_PER_PAGE); + } + + @NonNull + @Override + protected List<FeedItem> loadMoreData() { + return DBReader.getNewItemsList((page - 1) * EPISODES_PER_PAGE, EPISODES_PER_PAGE); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index 46e8789d4..83c16a9ff 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -550,7 +550,8 @@ public class QueueFragment extends Fragment { final boolean isRead = item.isPlayed(); DBWriter.markItemPlayed(FeedItem.PLAYED, false, item.getId()); DBWriter.removeQueueItem(getActivity(), true, item); - Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label), Snackbar.LENGTH_LONG); + Snackbar snackbar = Snackbar.make + (root, getString(item.hasMedia() ? R.string.marked_as_read_label: R.string.marked_as_read_no_media_label), Snackbar.LENGTH_LONG); snackbar.setAction(getString(R.string.undo), v -> { DBWriter.addQueueItemAt(getActivity(), item.getId(), position, false); if(!isRead) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java index 191999cf7..0acfe60bf 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java @@ -33,19 +33,6 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat { } private void setupInterfaceScreen() { - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - // disable expanded notification option on unsupported android versions - findPreference(PREF_EXPANDED_NOTIFICATION).setEnabled(false); - findPreference(PREF_EXPANDED_NOTIFICATION).setOnPreferenceClickListener( - preference -> { - Toast toast = Toast.makeText(getActivity(), - R.string.pref_expand_notify_unsupport_toast, Toast.LENGTH_SHORT); - toast.show(); - return true; - } - ); - } findPreference(UserPreferences.PREF_THEME) .setOnPreferenceChangeListener( (preference, newValue) -> { diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java index 2f3459beb..4d3e1ff72 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -6,6 +6,8 @@ import androidx.annotation.NonNull; import com.google.android.material.snackbar.Snackbar; import androidx.fragment.app.Fragment; import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; @@ -32,107 +34,134 @@ public class FeedItemMenuHandler { } /** - * Used by the MenuHandler to access different types of menus through one - * interface - */ - public interface MenuInterface { - /** - * Implementations of this method should call findItem(id) on their - * menu-object and call setVisibility(visibility) on the returned - * MenuItem object. - */ - void setItemVisibility(int id, boolean visible); - } - - /** * This method should be called in the prepare-methods of menus. It changes * the visibility of the menu items depending on a FeedItem's attributes. * - * @param mi An instance of MenuInterface that the method uses to change a - * MenuItem's visibility + * @param menu An instance of Menu * @param selectedItem The FeedItem for which the menu is supposed to be prepared * @return Returns true if selectedItem is not null. */ - public static boolean onPrepareMenu(MenuInterface mi, + public static boolean onPrepareMenu(Menu menu, FeedItem selectedItem) { - if (selectedItem == null) { + if (menu == null || selectedItem == null) { return false; } boolean hasMedia = selectedItem.getMedia() != null; boolean isPlaying = hasMedia && selectedItem.getState() == FeedItem.State.PLAYING; if (!isPlaying) { - mi.setItemVisibility(R.id.skip_episode_item, false); + setItemVisibility(menu, R.id.skip_episode_item, false); } - boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE); if (!isInQueue) { - mi.setItemVisibility(R.id.remove_from_queue_item, false); + setItemVisibility(menu, R.id.remove_from_queue_item, false); } if (!(!isInQueue && selectedItem.getMedia() != null)) { - mi.setItemVisibility(R.id.add_to_queue_item, false); + setItemVisibility(menu, R.id.add_to_queue_item, false); } - if (!ShareUtils.hasLinkToShare(selectedItem)) { - mi.setItemVisibility(R.id.visit_website_item, false); - mi.setItemVisibility(R.id.share_link_item, false); - mi.setItemVisibility(R.id.share_link_with_position_item, false); + setItemVisibility(menu, R.id.visit_website_item, false); + setItemVisibility(menu, R.id.share_link_item, false); + setItemVisibility(menu, R.id.share_link_with_position_item, false); } if (!hasMedia || selectedItem.getMedia().getDownload_url() == null) { - mi.setItemVisibility(R.id.share_download_url_item, false); - mi.setItemVisibility(R.id.share_download_url_with_position_item, false); + setItemVisibility(menu, R.id.share_download_url_item, false); + setItemVisibility(menu, R.id.share_download_url_with_position_item, false); } if(!hasMedia || selectedItem.getMedia().getPosition() <= 0) { - mi.setItemVisibility(R.id.share_link_with_position_item, false); - mi.setItemVisibility(R.id.share_download_url_with_position_item, false); + setItemVisibility(menu, R.id.share_download_url_with_position_item, false); + setItemVisibility(menu, R.id.share_link_with_position_item, false); } boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists(); - mi.setItemVisibility(R.id.share_file, fileDownloaded); + setItemVisibility(menu, R.id.share_file, fileDownloaded); - mi.setItemVisibility(R.id.remove_new_flag_item, selectedItem.isNew()); + setItemVisibility(menu, R.id.remove_new_flag_item, selectedItem.isNew()); if (selectedItem.isPlayed()) { - mi.setItemVisibility(R.id.mark_read_item, false); + setItemVisibility(menu, R.id.mark_read_item, false); } else { - mi.setItemVisibility(R.id.mark_unread_item, false); + setItemVisibility(menu, R.id.mark_unread_item, false); } - if(selectedItem.getMedia() == null || selectedItem.getMedia().getPosition() == 0) { - mi.setItemVisibility(R.id.reset_position, false); + if (selectedItem.getMedia() == null || selectedItem.getMedia().getPosition() == 0) { + setItemVisibility(menu, R.id.reset_position, false); } if(!UserPreferences.isEnableAutodownload() || fileDownloaded) { - mi.setItemVisibility(R.id.activate_auto_download, false); - mi.setItemVisibility(R.id.deactivate_auto_download, false); - } else if(selectedItem.getAutoDownload()) { - mi.setItemVisibility(R.id.activate_auto_download, false); + setItemVisibility(menu, R.id.activate_auto_download, false); + setItemVisibility(menu, R.id.deactivate_auto_download, false); + } else if (selectedItem.getAutoDownload()) { + setItemVisibility(menu, R.id.activate_auto_download, false); } else { - mi.setItemVisibility(R.id.deactivate_auto_download, false); + setItemVisibility(menu, R.id.deactivate_auto_download, false); + } + + // Display proper strings when item has no media + if (!hasMedia && !selectedItem.isPlayed()) { + setItemTitle(menu, R.id.mark_read_item, R.string.mark_read_no_media_label); + } + + if (!hasMedia && selectedItem.isPlayed()) { + setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label_no_media); } boolean isFavorite = selectedItem.isTagged(FeedItem.TAG_FAVORITE); - mi.setItemVisibility(R.id.add_to_favorites_item, !isFavorite); - mi.setItemVisibility(R.id.remove_from_favorites_item, isFavorite); + setItemVisibility(menu, R.id.add_to_favorites_item, !isFavorite); + setItemVisibility(menu, R.id.remove_from_favorites_item, isFavorite); - mi.setItemVisibility(R.id.remove_item, fileDownloaded); + setItemVisibility(menu, R.id.remove_item, fileDownloaded); return true; } /** + * Used to set the viability of a menu item. + * This method also does some null-checking so that neither menu nor the menu item are null + * in order to prevent nullpointer exceptions. + * @param menu The menu that should be used + * @param menuId The id of the menu item that will be used + * @param visibility The new visibility status of given menu item + * */ + private static void setItemVisibility(Menu menu, int menuId, boolean visibility) { + if (menu == null) { + return; + } + MenuItem item = menu.findItem(menuId); + if (item != null) { + item.setVisible(visibility); + } + } + + /** + * This method allows to replace to String of a menu item with a different one. + * @param menu Menu item that should be used + * @param id The id of the string that is going to be replaced. + * @param noMedia The id of the new String that is going to be used. + * */ + public static void setItemTitle(Menu menu, int id, int noMedia){ + MenuItem item = menu.findItem(id); + if (item != null) { + item.setTitle(noMedia); + } + } + + /** * The same method as onPrepareMenu(MenuInterface, FeedItem, boolean, QueueAccess), but lets the * caller also specify a list of menu items that should not be shown. * * @param excludeIds Menu item that should be excluded * @return true if selectedItem is not null. */ - public static boolean onPrepareMenu(MenuInterface mi, + public static boolean onPrepareMenu(Menu menu, FeedItem selectedItem, int... excludeIds) { - boolean rc = onPrepareMenu(mi, selectedItem); + if (menu == null || selectedItem == null ) { + return false; + } + boolean rc = onPrepareMenu(menu, selectedItem); if (rc && excludeIds != null) { for (int id : excludeIds) { - mi.setItemVisibility(id, false); + setItemVisibility(menu, id, false); } } return rc; @@ -161,7 +190,7 @@ public class FeedItemMenuHandler { case R.id.mark_read_item: selectedItem.setPlayed(true); DBWriter.markItemPlayed(selectedItem, FeedItem.PLAYED, true); - if(GpodnetPreferences.loggedIn()) { + if (GpodnetPreferences.loggedIn()) { FeedMedia media = selectedItem.getMedia(); // not all items have media, Gpodder only cares about those that do if (media != null) { @@ -179,7 +208,7 @@ public class FeedItemMenuHandler { case R.id.mark_unread_item: selectedItem.setPlayed(false); DBWriter.markItemPlayed(selectedItem, FeedItem.UNPLAYED, false); - if(GpodnetPreferences.loggedIn() && selectedItem.getMedia() != null) { + if (GpodnetPreferences.loggedIn() && selectedItem.getMedia() != null) { GpodnetEpisodeAction actionNew = new GpodnetEpisodeAction.Builder(selectedItem, Action.NEW) .currentDeviceId() .currentTimestamp() |