Only show relevant actions on multi-select (#7424)

This commit is contained in:
ByteHamster 2024-09-26 22:48:48 +02:00 committed by GitHub
parent 7309f8e8b2
commit 7b2ebd8ab0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 150 additions and 103 deletions

View File

@ -47,7 +47,7 @@ public abstract class SelectableAdapter<T extends RecyclerView.ViewHolder> exten
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
updateTitle();
onSelectedItemsUpdated();
toggleSelectAllIcon(menu.findItem(R.id.select_toggle), false);
return false;
}
@ -59,7 +59,7 @@ public abstract class SelectableAdapter<T extends RecyclerView.ViewHolder> exten
shouldSelectLazyLoadedItems = selectAll;
setSelected(0, getItemCount(), selectAll);
toggleSelectAllIcon(item, selectAll);
updateTitle();
onSelectedItemsUpdated();
return true;
}
return false;
@ -74,7 +74,7 @@ public abstract class SelectableAdapter<T extends RecyclerView.ViewHolder> exten
notifyDataSetChanged();
}
});
updateTitle();
onSelectedItemsUpdated();
if (onSelectModeListener != null) {
onSelectModeListener.onStartSelectMode();
@ -109,7 +109,7 @@ public abstract class SelectableAdapter<T extends RecyclerView.ViewHolder> exten
} else {
selectedIds.remove(getItemId(pos));
}
updateTitle();
onSelectedItemsUpdated();
}
/**
@ -154,7 +154,7 @@ public abstract class SelectableAdapter<T extends RecyclerView.ViewHolder> exten
}
}
protected void updateTitle() {
protected void onSelectedItemsUpdated() {
if (actionMode == null) {
return;
}

View File

@ -20,6 +20,7 @@ import de.danoeh.antennapod.ui.common.ThemeUtils;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import de.danoeh.antennapod.R;
@ -53,7 +54,7 @@ public class EpisodeItemListAdapter extends SelectableAdapter<EpisodeItemViewHol
public void updateItems(List<FeedItem> items) {
episodes = items;
notifyDataSetChanged();
updateTitle();
onSelectedItemsUpdated();
}
@Override
@ -209,7 +210,7 @@ public class EpisodeItemListAdapter extends SelectableAdapter<EpisodeItemViewHol
}
inflater.inflate(R.menu.feeditemlist_context, menu);
menu.setHeaderTitle(longPressedItem.getTitle());
FeedItemMenuHandler.onPrepareMenu(menu, longPressedItem, R.id.skip_episode_item);
FeedItemMenuHandler.onPrepareMenu(menu, Collections.singletonList(longPressedItem), R.id.skip_episode_item);
}
}

View File

@ -28,19 +28,19 @@ public class EpisodeMultiSelectActionHandler {
}
public void handleAction(List<FeedItem> items) {
if (actionId == R.id.add_to_queue_batch) {
if (actionId == R.id.add_to_queue_item) {
queueChecked(items);
} else if (actionId == R.id.remove_from_queue_batch) {
} else if (actionId == R.id.remove_from_queue_item) {
removeFromQueueChecked(items);
} else if (actionId == R.id.remove_from_inbox_batch) {
} else if (actionId == R.id.remove_inbox_item) {
removeFromInboxChecked(items);
} else if (actionId == R.id.mark_read_batch) {
} else if (actionId == R.id.mark_read_item) {
markedCheckedPlayed(items);
} else if (actionId == R.id.mark_unread_batch) {
} else if (actionId == R.id.mark_unread_item) {
markedCheckedUnplayed(items);
} else if (actionId == R.id.download_batch) {
} else if (actionId == R.id.download_item) {
downloadChecked(items);
} else if (actionId == R.id.delete_batch) {
} else if (actionId == R.id.remove_item) {
LocalDeleteModal.showLocalFeedDeleteWarningIfNecessary(activity, items, () -> deleteChecked(items));
} else {
Log.e(TAG, "Unrecognized speed dial action item. Do nothing. id=" + actionId);
@ -112,6 +112,9 @@ public class EpisodeMultiSelectActionHandler {
}
private void showMessage(@PluralsRes int msgId, int numItems) {
if (numItems == 1) {
return;
}
totalNumItems += numItems;
activity.runOnUiThread(() -> {
String text = activity.getResources().getQuantityString(msgId, totalNumItems, totalNumItems);

View File

@ -177,7 +177,7 @@ public abstract class EpisodesListFragment extends Fragment
swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
swipeRefreshLayout.setOnRefreshListener(() -> FeedUpdateManager.getInstance().runOnceOrAsk(requireContext()));
listAdapter = new EpisodeItemListAdapter((MainActivity) getActivity()) {
listAdapter = new EpisodeItemListAdapter(getActivity()) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
@ -186,6 +186,13 @@ public abstract class EpisodesListFragment extends Fragment
}
MenuItemUtils.setOnClickListeners(menu, EpisodesListFragment.this::onContextItemSelected);
}
@Override
protected void onSelectedItemsUpdated() {
super.onSelectedItemsUpdated();
FeedItemMenuHandler.onPrepareMenu(floatingSelectMenu.getMenu(), getSelectedItems());
floatingSelectMenu.updateItemVisibility();
}
};
listAdapter.setOnSelectModeListener(this);
recyclerView.setAdapter(listAdapter);
@ -211,9 +218,9 @@ public abstract class EpisodesListFragment extends Fragment
int confirmationString = 0;
if (listAdapter.getSelectedItems().size() >= 25 || listAdapter.shouldSelectLazyLoadedItems()) {
// Should ask for confirmation
if (menuItem.getItemId() == R.id.mark_read_batch) {
if (menuItem.getItemId() == R.id.mark_read_item) {
confirmationString = R.string.multi_select_mark_played_confirmation;
} else if (menuItem.getItemId() == R.id.mark_unread_batch) {
} else if (menuItem.getItemId() == R.id.mark_unread_item) {
confirmationString = R.string.multi_select_mark_unplayed_confirmation;
}
}

View File

@ -13,6 +13,7 @@ import androidx.fragment.app.Fragment;
import com.google.android.material.snackbar.Snackbar;
import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@ -47,50 +48,88 @@ public class FeedItemMenuHandler {
* 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 menu An instance of Menu
* @param selectedItem The FeedItem for which the menu is supposed to be prepared
* @param menu An instance of Menu
* @param selectedItems The FeedItem for which the menu is supposed to be prepared
* @param excludeIds Menu item that should be excluded
* @return Returns true if selectedItem is not null.
*/
public static boolean onPrepareMenu(Menu menu, FeedItem selectedItem) {
if (menu == null || selectedItem == null) {
public static boolean onPrepareMenu(Menu menu, List<FeedItem> selectedItems, int... excludeIds) {
if (menu == null || selectedItems == null) {
return false;
}
final boolean hasMedia = selectedItem.getMedia() != null;
final boolean isPlaying = hasMedia && PlaybackStatus.isPlaying(selectedItem.getMedia());
final boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
final boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists();
final boolean isLocalFile = hasMedia && selectedItem.getFeed().isLocalFeed();
final boolean isFavorite = selectedItem.isTagged(FeedItem.TAG_FAVORITE);
final boolean hasTranscript = selectedItem.hasTranscript();
boolean canSkip = false;
boolean canRemoveFromQueue = false;
boolean canAddToQueue = false;
boolean canVisitWebsite = selectedItems.size() == 1;
boolean canShare = selectedItems.size() == 1;
boolean canRemoveFromInbox = false;
boolean canMarkPlayed = false;
boolean canMarkUnplayed = false;
boolean canResetPosition = false;
boolean canDelete = false;
boolean canDownload = false;
boolean canAddFavorite = false;
boolean canRemoveFavorite = false;
boolean canShowTranscript = selectedItems.size() == 1;
setItemVisibility(menu, R.id.skip_episode_item, isPlaying);
setItemVisibility(menu, R.id.remove_from_queue_item, isInQueue);
setItemVisibility(menu, R.id.add_to_queue_item, !isInQueue && selectedItem.getMedia() != null);
setItemVisibility(menu, R.id.visit_website_item, !selectedItem.getFeed().isLocalFeed()
&& ShareUtils.hasLinkToShare(selectedItem));
setItemVisibility(menu, R.id.share_item, !selectedItem.getFeed().isLocalFeed());
setItemVisibility(menu, R.id.remove_inbox_item, selectedItem.isNew());
setItemVisibility(menu, R.id.mark_read_item, !selectedItem.isPlayed());
setItemVisibility(menu, R.id.mark_unread_item, selectedItem.isPlayed());
setItemVisibility(menu, R.id.reset_position, hasMedia && selectedItem.getMedia().getPosition() != 0);
// Display proper strings when item has no media
if (hasMedia) {
setItemTitle(menu, R.id.mark_read_item, R.string.mark_read_label);
setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label);
} else {
setItemTitle(menu, R.id.mark_read_item, R.string.mark_read_no_media_label);
setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label_no_media);
for (FeedItem item : selectedItems) {
boolean hasMedia = item.getMedia() != null;
canSkip |= hasMedia && PlaybackStatus.isPlaying(item.getMedia());
canRemoveFromQueue |= item.isTagged(FeedItem.TAG_QUEUE);
canAddToQueue |= hasMedia && !item.isTagged(FeedItem.TAG_QUEUE);
canVisitWebsite |= !item.getFeed().isLocalFeed() && ShareUtils.hasLinkToShare(item);
canShare |= !item.getFeed().isLocalFeed();
canRemoveFromInbox |= item.isNew();
canMarkPlayed |= !item.isPlayed();
canMarkUnplayed |= item.isPlayed();
canResetPosition |= hasMedia && item.getMedia().getPosition() != 0;
canDelete |= hasMedia && item.getMedia().isDownloaded();
canDownload |= hasMedia && !item.getMedia().isDownloaded() && !item.getFeed().isLocalFeed();
canAddFavorite |= !item.isTagged(FeedItem.TAG_FAVORITE);
canRemoveFavorite |= item.isTagged(FeedItem.TAG_FAVORITE);
canShowTranscript |= item.hasTranscript();
}
setItemVisibility(menu, R.id.add_to_favorites_item, !isFavorite);
setItemVisibility(menu, R.id.remove_from_favorites_item, isFavorite);
setItemVisibility(menu, R.id.remove_item, fileDownloaded || isLocalFile);
setItemVisibility(menu, R.id.transcript_item, hasTranscript);
if (selectedItems.size() > 1) {
canVisitWebsite = false;
canShare = false;
canShowTranscript = false;
}
if (selectedItem.getFeed().getState() != Feed.STATE_SUBSCRIBED) {
setItemVisibility(menu, R.id.skip_episode_item, canSkip);
setItemVisibility(menu, R.id.remove_from_queue_item, canRemoveFromQueue);
setItemVisibility(menu, R.id.add_to_queue_item, canAddToQueue);
setItemVisibility(menu, R.id.visit_website_item, canVisitWebsite);
setItemVisibility(menu, R.id.share_item, canShare);
setItemVisibility(menu, R.id.remove_inbox_item, canRemoveFromInbox);
setItemVisibility(menu, R.id.mark_read_item, canMarkPlayed);
setItemVisibility(menu, R.id.mark_unread_item, canMarkUnplayed);
setItemVisibility(menu, R.id.reset_position, canResetPosition);
// Display proper strings when item has no media
if (selectedItems.size() == 1 && selectedItems.get(0).getMedia() == null) {
setItemTitle(menu, R.id.mark_read_item, R.string.mark_read_no_media_label);
setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label_no_media);
} else {
setItemTitle(menu, R.id.mark_read_item, R.string.mark_read_label);
setItemTitle(menu, R.id.mark_unread_item, R.string.mark_unread_label);
}
setItemVisibility(menu, R.id.add_to_favorites_item, canAddFavorite);
setItemVisibility(menu, R.id.remove_from_favorites_item, canRemoveFavorite);
setItemVisibility(menu, R.id.remove_item, canDelete);
setItemVisibility(menu, R.id.download_item, canDownload);
setItemVisibility(menu, R.id.transcript_item, canShowTranscript);
if (selectedItems.size() == 1 && selectedItems.get(0).getFeed().getState() != Feed.STATE_SUBSCRIBED) {
setItemVisibility(menu, R.id.mark_read_item, false);
}
if (excludeIds != null) {
for (int id : excludeIds) {
setItemVisibility(menu, id, false);
}
}
return true;
}
@ -125,26 +164,6 @@ public class FeedItemMenuHandler {
}
}
/**
* The same method as {@link #onPrepareMenu(Menu, FeedItem)}, 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(Menu menu, FeedItem selectedItem, int... excludeIds) {
if (menu == null || selectedItem == null) {
return false;
}
boolean rc = onPrepareMenu(menu, selectedItem);
if (rc && excludeIds != null) {
for (int id : excludeIds) {
setItemVisibility(menu, id, false);
}
}
return rc;
}
/**
* Default menu handling for the given FeedItem.
*

View File

@ -14,6 +14,7 @@ import de.danoeh.antennapod.model.feed.FeedItem;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class HorizontalItemListAdapter extends RecyclerView.Adapter<HorizontalItemViewHolder>
@ -125,7 +126,7 @@ public class HorizontalItemListAdapter extends RecyclerView.Adapter<HorizontalIt
menu.clear();
inflater.inflate(R.menu.feeditemlist_context, menu);
menu.setHeaderTitle(longPressedItem.getTitle());
FeedItemMenuHandler.onPrepareMenu(menu, longPressedItem, R.id.skip_episode_item);
FeedItemMenuHandler.onPrepareMenu(menu, Collections.singletonList(longPressedItem), R.id.skip_episode_item);
}

View File

@ -48,9 +48,6 @@ public class InboxFragment extends EpisodesListFragment {
emptyView.setIcon(R.drawable.ic_inbox);
emptyView.setTitle(R.string.no_inbox_head_label);
emptyView.setMessage(R.string.no_inbox_label);
floatingSelectMenu.getMenu().findItem(R.id.mark_unread_batch).setVisible(false);
floatingSelectMenu.getMenu().findItem(R.id.remove_from_queue_batch).setVisible(false);
floatingSelectMenu.getMenu().findItem(R.id.delete_batch).setVisible(false);
return root;
}

View File

@ -117,17 +117,13 @@ public class CompletedDownloadsFragment extends Fragment
floatingSelectMenu = root.findViewById(R.id.floatingSelectMenu);
floatingSelectMenu.inflate(R.menu.episodes_apply_action_speeddial);
floatingSelectMenu.getMenu().findItem(R.id.download_batch).setVisible(false);
floatingSelectMenu.getMenu().findItem(R.id.mark_read_batch).setVisible(false);
floatingSelectMenu.getMenu().findItem(R.id.mark_unread_batch).setVisible(false);
floatingSelectMenu.getMenu().findItem(R.id.remove_from_inbox_batch).setVisible(false);
floatingSelectMenu.setOnMenuItemClickListener(menuItem -> {
if (adapter.getSelectedCount() == 0) {
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.no_items_selected,
Snackbar.LENGTH_SHORT);
return false;
}
new EpisodeMultiSelectActionHandler(((MainActivity) getActivity()), menuItem.getItemId())
new EpisodeMultiSelectActionHandler(getActivity(), menuItem.getItemId())
.handleAction(adapter.getSelectedItems());
adapter.endSelectMode();
return true;
@ -370,6 +366,13 @@ public class CompletedDownloadsFragment extends Fragment
}
MenuItemUtils.setOnClickListeners(menu, CompletedDownloadsFragment.this::onContextItemSelected);
}
@Override
protected void onSelectedItemsUpdated() {
super.onSelectedItemsUpdated();
FeedItemMenuHandler.onPrepareMenu(floatingSelectMenu.getMenu(), getSelectedItems());
floatingSelectMenu.updateItemVisibility();
}
}
public static class DownloadsSortDialog extends ItemSortDialog {

View File

@ -32,6 +32,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import java.util.Collections;
import java.util.List;
/**
@ -144,10 +145,10 @@ public class ItemPagerFragment extends Fragment implements MaterialToolbar.OnMen
return;
}
if (item.hasMedia()) {
FeedItemMenuHandler.onPrepareMenu(toolbar.getMenu(), item);
FeedItemMenuHandler.onPrepareMenu(toolbar.getMenu(), Collections.singletonList(item));
} else {
// these are already available via button1 and button2
FeedItemMenuHandler.onPrepareMenu(toolbar.getMenu(), item,
FeedItemMenuHandler.onPrepareMenu(toolbar.getMenu(), Collections.singletonList(item),
R.id.mark_read_item, R.id.visit_website_item);
}
}

View File

@ -412,8 +412,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
@Override
public void onStartSelectMode() {
swipeActions.detach();
viewBinding.floatingSelectMenu.getMenu().findItem(R.id.download_batch).setVisible(!feed.isLocalFeed());
viewBinding.floatingSelectMenu.setVisibility(View.VISIBLE);
updateRecyclerPadding();
updateToolbar();
}
@ -695,5 +693,12 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
}
MenuItemUtils.setOnClickListeners(menu, FeedItemlistFragment.this::onContextItemSelected);
}
@Override
protected void onSelectedItemsUpdated() {
super.onSelectedItemsUpdated();
FeedItemMenuHandler.onPrepareMenu(viewBinding.floatingSelectMenu.getMenu(), getSelectedItems());
viewBinding.floatingSelectMenu.updateItemVisibility();
}
}
}

View File

@ -42,6 +42,7 @@ import org.greenrobot.eventbus.ThreadMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.List;
import de.danoeh.antennapod.R;
@ -467,7 +468,8 @@ public class AudioPlayerFragment extends Fragment implements
boolean isFeedMedia = media instanceof FeedMedia;
toolbar.getMenu().findItem(R.id.open_feed_item).setVisible(isFeedMedia);
if (isFeedMedia) {
FeedItemMenuHandler.onPrepareMenu(toolbar.getMenu(), ((FeedMedia) media).getItem());
FeedItemMenuHandler.onPrepareMenu(toolbar.getMenu(),
Collections.singletonList(((FeedMedia) media).getItem()));
}
toolbar.getMenu().findItem(R.id.set_sleeptimer_item).setVisible(!controller.sleepTimerActive());

View File

@ -74,6 +74,8 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.Collections;
/**
* Activity for playing video files.
*/
@ -549,7 +551,7 @@ public class VideoplayerActivity extends CastEnabledActivity implements SeekBar.
menu.findItem(R.id.open_feed_item).setVisible(isFeedMedia); // FeedMedia implies it belongs to a Feed
if (isFeedMedia) {
FeedItemMenuHandler.onPrepareMenu(menu, ((FeedMedia) media).getItem());
FeedItemMenuHandler.onPrepareMenu(menu, Collections.singletonList(((FeedMedia) media).getItem()));
}
menu.findItem(R.id.set_sleeptimer_item).setVisible(!controller.sleepTimerActive());

View File

@ -427,6 +427,14 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
super.onCreateContextMenu(menu, v, menuInfo);
MenuItemUtils.setOnClickListeners(menu, QueueFragment.this::onContextItemSelected);
}
@Override
protected void onSelectedItemsUpdated() {
super.onSelectedItemsUpdated();
FeedItemMenuHandler.onPrepareMenu(floatingSelectMenu.getMenu(), getSelectedItems(),
R.id.add_to_queue_item, R.id.remove_inbox_item);
floatingSelectMenu.updateItemVisibility();
}
};
recyclerAdapter.setOnSelectModeListener(this);
recyclerView.setAdapter(recyclerAdapter);
@ -444,15 +452,13 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte
floatingSelectMenu = root.findViewById(R.id.floatingSelectMenu);
floatingSelectMenu.inflate(R.menu.episodes_apply_action_speeddial);
floatingSelectMenu.getMenu().findItem(R.id.add_to_queue_batch).setVisible(false);
floatingSelectMenu.getMenu().findItem(R.id.remove_from_inbox_batch).setVisible(false);
floatingSelectMenu.setOnMenuItemClickListener(menuItem -> {
if (recyclerAdapter.getSelectedCount() == 0) {
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.no_items_selected,
Snackbar.LENGTH_SHORT);
return false;
}
new EpisodeMultiSelectActionHandler(((MainActivity) getActivity()), menuItem.getItemId())
new EpisodeMultiSelectActionHandler(getActivity(), menuItem.getItemId())
.handleAction(recyclerAdapter.getSelectedItems());
recyclerAdapter.endSelectMode();
return true;

View File

@ -30,7 +30,7 @@ public class DeleteSwipeAction implements SwipeAction {
@Override
public String getTitle(Context context) {
return context.getString(R.string.delete_episode_label);
return context.getString(R.string.delete_label);
}
@Override

View File

@ -23,7 +23,7 @@ public class LocalDeleteModal {
}
new MaterialAlertDialogBuilder(context)
.setTitle(R.string.delete_episode_label)
.setTitle(R.string.delete_label)
.setMessage(R.string.delete_local_feed_warning_body)
.setPositiveButton(R.string.delete_label, (dialog, which) -> deleteCommand.run())
.setNegativeButton(R.string.cancel_label, null)

View File

@ -11,7 +11,7 @@
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="16dp"
app:cardCornerRadius="16dp">
app:cardCornerRadius="8dp">
<HorizontalScrollView
android:id="@+id/scrollView"

View File

@ -21,8 +21,9 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="?android:attr/textColorPrimary"
android:lines="2"
android:maxLines="2"
android:textAlignment="center"
android:ellipsize="end" />
android:ellipsize="end"
style="@style/TextAppearance.Material3.BodySmall" />
</LinearLayout>

View File

@ -8,37 +8,37 @@
visually it will be shown at the bottom of the list of actions.
-->
<item
android:id="@+id/delete_batch"
android:id="@+id/remove_item"
android:icon="@drawable/ic_delete"
android:title="@string/delete_episode_label" />
android:title="@string/delete_label" />
<item
android:id="@+id/download_batch"
android:id="@+id/download_item"
android:icon="@drawable/ic_download"
android:title="@string/download_label" />
<item
android:id="@+id/mark_unread_batch"
android:id="@+id/mark_unread_item"
android:icon="@drawable/ic_mark_unplayed"
android:title="@string/mark_unread_label" />
<item
android:id="@+id/mark_read_batch"
android:id="@+id/mark_read_item"
android:icon="@drawable/ic_mark_played"
android:title="@string/mark_read_label" />
<item
android:id="@+id/remove_from_queue_batch"
android:id="@+id/remove_from_queue_item"
android:icon="@drawable/ic_playlist_remove"
android:title="@string/remove_from_queue_label" />
<item
android:id="@+id/add_to_queue_batch"
android:id="@+id/add_to_queue_item"
android:icon="@drawable/ic_playlist_play"
android:title="@string/add_to_queue_label" />
<item
android:id="@+id/remove_from_inbox_batch"
android:id="@+id/remove_inbox_item"
android:icon="@drawable/ic_check"
android:title="@string/remove_inbox_label" />

View File

@ -224,7 +224,6 @@
<string name="pause_label">Pause</string>
<string name="stream_label">Stream</string>
<string name="delete_label">Delete</string>
<string name="delete_episode_label">Delete episode</string>
<plurals name="deleted_multi_episode_batch_label">
<item quantity="one">%d downloaded episode deleted.</item>
<item quantity="other">%d downloaded episodes deleted.</item>