Replace old episode multi-select with new multi-select. (#5253)
This commit is contained in:
parent
323f1f6142
commit
00bf2db0a4
@ -106,5 +106,5 @@ workflows:
|
|||||||
branchBaseCommit=`git merge-base origin/develop HEAD`
|
branchBaseCommit=`git merge-base origin/develop HEAD`
|
||||||
echo "Comparing to $branchBaseCommit"
|
echo "Comparing to $branchBaseCommit"
|
||||||
curl -s -L https://github.com/ByteHamster/android-xml-formatter/releases/download/1.1.0/android-xml-formatter.jar > android-xml-formatter.jar
|
curl -s -L https://github.com/ByteHamster/android-xml-formatter/releases/download/1.1.0/android-xml-formatter.jar > android-xml-formatter.jar
|
||||||
git diff --name-only $branchBaseCommit | { grep "res/layout/" || true; } | xargs java -jar android-xml-formatter.jar
|
git diff --name-only $branchBaseCommit --diff-filter=AM | { grep "res/layout/" || true; } | xargs java -jar android-xml-formatter.jar
|
||||||
test $(git diff | wc -l) -eq 0 || (echo -e "\n\n===== Found XML code style violations! See output below how to fix them. =====\n\n" && git --no-pager diff --color=always && false)
|
test $(git diff | wc -l) -eq 0 || (echo -e "\n\n===== Found XML code style violations! See output below how to fix them. =====\n\n" && git --no-pager diff --color=always && false)
|
||||||
|
@ -44,7 +44,7 @@ public class QueueRecyclerAdapter extends EpisodeItemListAdapter {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!dragDropEnabled) {
|
if (!dragDropEnabled || inActionMode()) {
|
||||||
holder.dragHandle.setVisibility(View.GONE);
|
holder.dragHandle.setVisibility(View.GONE);
|
||||||
holder.dragHandle.setOnTouchListener(null);
|
holder.dragHandle.setOnTouchListener(null);
|
||||||
holder.coverHolder.setOnTouchListener(null);
|
holder.coverHolder.setOnTouchListener(null);
|
||||||
@ -63,11 +63,17 @@ public class QueueRecyclerAdapter extends EpisodeItemListAdapter {
|
|||||||
inflater.inflate(R.menu.queue_context, menu);
|
inflater.inflate(R.menu.queue_context, menu);
|
||||||
super.onCreateContextMenu(menu, v, menuInfo);
|
super.onCreateContextMenu(menu, v, menuInfo);
|
||||||
|
|
||||||
final boolean keepSorted = UserPreferences.isQueueKeepSorted();
|
if (!inActionMode()) {
|
||||||
if (getItem(0).getId() == getLongPressedItem().getId() || keepSorted) {
|
menu.findItem(R.id.multi_select).setVisible(true);
|
||||||
|
final boolean keepSorted = UserPreferences.isQueueKeepSorted();
|
||||||
|
if (getItem(0).getId() == getLongPressedItem().getId() || keepSorted) {
|
||||||
|
menu.findItem(R.id.move_to_top_item).setVisible(false);
|
||||||
|
}
|
||||||
|
if (getItem(getItemCount() - 1).getId() == getLongPressedItem().getId() || keepSorted) {
|
||||||
|
menu.findItem(R.id.move_to_bottom_item).setVisible(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
menu.findItem(R.id.move_to_top_item).setVisible(false);
|
menu.findItem(R.id.move_to_top_item).setVisible(false);
|
||||||
}
|
|
||||||
if (getItem(getItemCount() - 1).getId() == getLongPressedItem().getId() || keepSorted) {
|
|
||||||
menu.findItem(R.id.move_to_bottom_item).setVisible(false);
|
menu.findItem(R.id.move_to_bottom_item).setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,466 +0,0 @@
|
|||||||
package de.danoeh.antennapod.dialog;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import androidx.annotation.IdRes;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.PluralsRes;
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.collection.ArrayMap;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
import com.leinardi.android.speeddial.SpeedDialView;
|
|
||||||
import de.danoeh.antennapod.R;
|
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
|
||||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
|
||||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
|
||||||
import de.danoeh.antennapod.core.util.FeedItemPermutors;
|
|
||||||
import de.danoeh.antennapod.core.util.LongList;
|
|
||||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class EpisodesApplyActionFragment extends Fragment implements Toolbar.OnMenuItemClickListener {
|
|
||||||
|
|
||||||
public static final String TAG = "EpisodeActionFragment";
|
|
||||||
|
|
||||||
public static final int ACTION_ADD_TO_QUEUE = 1;
|
|
||||||
public static final int ACTION_REMOVE_FROM_QUEUE = 2;
|
|
||||||
private static final int ACTION_MARK_PLAYED = 4;
|
|
||||||
private static final int ACTION_MARK_UNPLAYED = 8;
|
|
||||||
public static final int ACTION_DOWNLOAD = 16;
|
|
||||||
public static final int ACTION_DELETE = 32;
|
|
||||||
public static final int ACTION_ALL = ACTION_ADD_TO_QUEUE | ACTION_REMOVE_FROM_QUEUE
|
|
||||||
| ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED | ACTION_DOWNLOAD | ACTION_DELETE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify an action (defined by #flag) 's UI bindings.
|
|
||||||
*
|
|
||||||
* Includes: the menu / action item and the actual logic
|
|
||||||
*/
|
|
||||||
private static class ActionBinding {
|
|
||||||
int flag;
|
|
||||||
@IdRes
|
|
||||||
final int actionItemId;
|
|
||||||
@NonNull
|
|
||||||
final Runnable action;
|
|
||||||
|
|
||||||
ActionBinding(int flag, @IdRes int actionItemId, @NonNull Runnable action) {
|
|
||||||
this.flag = flag;
|
|
||||||
this.actionItemId = actionItemId;
|
|
||||||
this.action = action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<? extends ActionBinding> actionBindings;
|
|
||||||
private final Map<Long, FeedItem> idMap = new ArrayMap<>();
|
|
||||||
private final List<FeedItem> episodes = new ArrayList<>();
|
|
||||||
private int actions;
|
|
||||||
private final List<String> titles = new ArrayList<>();
|
|
||||||
private final LongList checkedIds = new LongList();
|
|
||||||
|
|
||||||
private ListView mListView;
|
|
||||||
private ArrayAdapter<String> mAdapter;
|
|
||||||
private SpeedDialView mSpeedDialView;
|
|
||||||
private Toolbar toolbar;
|
|
||||||
|
|
||||||
public EpisodesApplyActionFragment() {
|
|
||||||
actionBindings = Arrays.asList(
|
|
||||||
new ActionBinding(ACTION_ADD_TO_QUEUE,
|
|
||||||
R.id.add_to_queue_batch, this::queueChecked),
|
|
||||||
new ActionBinding(ACTION_REMOVE_FROM_QUEUE,
|
|
||||||
R.id.remove_from_queue_batch, this::removeFromQueueChecked),
|
|
||||||
new ActionBinding(ACTION_MARK_PLAYED,
|
|
||||||
R.id.mark_read_batch, this::markedCheckedPlayed),
|
|
||||||
new ActionBinding(ACTION_MARK_UNPLAYED,
|
|
||||||
R.id.mark_unread_batch, this::markedCheckedUnplayed),
|
|
||||||
new ActionBinding(ACTION_DOWNLOAD,
|
|
||||||
R.id.download_batch, this::downloadChecked),
|
|
||||||
new ActionBinding(ACTION_DELETE,
|
|
||||||
R.id.delete_batch, this::deleteChecked)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EpisodesApplyActionFragment newInstance(List<FeedItem> items, int actions) {
|
|
||||||
EpisodesApplyActionFragment f = new EpisodesApplyActionFragment();
|
|
||||||
f.episodes.addAll(items);
|
|
||||||
for (FeedItem episode : items) {
|
|
||||||
f.idMap.put(episode.getId(), episode);
|
|
||||||
}
|
|
||||||
f.actions = actions;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setRetainInstance(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
View view = inflater.inflate(R.layout.episodes_apply_action_fragment, container, false);
|
|
||||||
|
|
||||||
toolbar = view.findViewById(R.id.toolbar);
|
|
||||||
toolbar.inflateMenu(R.menu.episodes_apply_action_options);
|
|
||||||
toolbar.setNavigationOnClickListener(v -> getParentFragmentManager().popBackStack());
|
|
||||||
toolbar.setOnMenuItemClickListener(this);
|
|
||||||
refreshToolbarState();
|
|
||||||
|
|
||||||
mListView = view.findViewById(android.R.id.list);
|
|
||||||
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
|
||||||
mListView.setOnItemClickListener((listView, view1, position, rowId) -> {
|
|
||||||
long id = episodes.get(position).getId();
|
|
||||||
if (checkedIds.contains(id)) {
|
|
||||||
checkedIds.remove(id);
|
|
||||||
} else {
|
|
||||||
checkedIds.add(id);
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
});
|
|
||||||
mListView.setOnItemLongClickListener((adapterView, view12, position, id) -> {
|
|
||||||
new AlertDialog.Builder(getActivity())
|
|
||||||
.setItems(R.array.batch_long_press_options, (dialogInterface, item) -> {
|
|
||||||
int direction;
|
|
||||||
if (item == 0) {
|
|
||||||
direction = -1;
|
|
||||||
} else {
|
|
||||||
direction = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentPosition = position + direction;
|
|
||||||
while (currentPosition >= 0 && currentPosition < episodes.size()) {
|
|
||||||
long id1 = episodes.get(currentPosition).getId();
|
|
||||||
if (!checkedIds.contains(id1)) {
|
|
||||||
checkedIds.add(id1);
|
|
||||||
}
|
|
||||||
currentPosition += direction;
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
}).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
titles.clear();
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
titles.add(episode.getTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
mAdapter = new ArrayAdapter<>(getActivity(),
|
|
||||||
R.layout.simple_list_item_multiple_choice_on_start, titles);
|
|
||||||
mListView.setAdapter(mAdapter);
|
|
||||||
|
|
||||||
// Init action UI (via a FAB Speed Dial)
|
|
||||||
mSpeedDialView = view.findViewById(R.id.fabSD);
|
|
||||||
mSpeedDialView.inflate(R.menu.episodes_apply_action_speeddial);
|
|
||||||
|
|
||||||
// show only specified actions, and bind speed dial UIs to the actual logic
|
|
||||||
for (ActionBinding binding : actionBindings) {
|
|
||||||
if ((actions & binding.flag) == 0) {
|
|
||||||
mSpeedDialView.removeActionItemById(binding.actionItemId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mSpeedDialView.setOnChangeListener(new SpeedDialView.OnChangeListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMainActionSelected() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onToggleChanged(boolean open) {
|
|
||||||
if (open && checkedIds.size() == 0) {
|
|
||||||
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.no_items_selected,
|
|
||||||
Snackbar.LENGTH_SHORT);
|
|
||||||
mSpeedDialView.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mSpeedDialView.setOnActionSelectedListener(actionItem -> {
|
|
||||||
ActionBinding selectedBinding = null;
|
|
||||||
for (ActionBinding binding : actionBindings) {
|
|
||||||
if (actionItem.getId() == binding.actionItemId) {
|
|
||||||
selectedBinding = binding;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedBinding != null) {
|
|
||||||
selectedBinding.action.run();
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Unrecognized speed dial action item. Do nothing. id=" + actionItem.getId());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
refreshCheckboxes();
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshToolbarState() {
|
|
||||||
MenuItem selectAllItem = toolbar.getMenu().findItem(R.id.select_toggle);
|
|
||||||
if (checkedIds.size() == episodes.size()) {
|
|
||||||
selectAllItem.setIcon(R.drawable.ic_select_none);
|
|
||||||
selectAllItem.setTitle(R.string.deselect_all_label);
|
|
||||||
} else {
|
|
||||||
selectAllItem.setIcon(R.drawable.ic_select_all);
|
|
||||||
selectAllItem.setTitle(R.string.select_all_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Integer, SortOrder> menuItemIdToSortOrder;
|
|
||||||
static {
|
|
||||||
Map<Integer, SortOrder> map = new ArrayMap<>();
|
|
||||||
map.put(R.id.sort_title_a_z, SortOrder.EPISODE_TITLE_A_Z);
|
|
||||||
map.put(R.id.sort_title_z_a, SortOrder.EPISODE_TITLE_Z_A);
|
|
||||||
map.put(R.id.sort_date_new_old, SortOrder.DATE_NEW_OLD);
|
|
||||||
map.put(R.id.sort_date_old_new, SortOrder.DATE_OLD_NEW);
|
|
||||||
map.put(R.id.sort_duration_long_short, SortOrder.DURATION_LONG_SHORT);
|
|
||||||
map.put(R.id.sort_duration_short_long, SortOrder.DURATION_SHORT_LONG);
|
|
||||||
menuItemIdToSortOrder = Collections.unmodifiableMap(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
|
||||||
@StringRes int resId = 0;
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.select_options:
|
|
||||||
return true;
|
|
||||||
case R.id.select_toggle:
|
|
||||||
if (checkedIds.size() == episodes.size()) {
|
|
||||||
checkNone();
|
|
||||||
} else {
|
|
||||||
checkAll();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case R.id.check_all:
|
|
||||||
checkAll();
|
|
||||||
resId = R.string.selected_all_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_none:
|
|
||||||
checkNone();
|
|
||||||
resId = R.string.deselected_all_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_played:
|
|
||||||
checkPlayed(true);
|
|
||||||
resId = R.string.selected_played_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_unplayed:
|
|
||||||
checkPlayed(false);
|
|
||||||
resId = R.string.selected_unplayed_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_downloaded:
|
|
||||||
checkDownloaded(true);
|
|
||||||
resId = R.string.selected_downloaded_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_not_downloaded:
|
|
||||||
checkDownloaded(false);
|
|
||||||
resId = R.string.selected_not_downloaded_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_queued:
|
|
||||||
checkQueued(true);
|
|
||||||
resId = R.string.selected_queued_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_not_queued:
|
|
||||||
checkQueued(false);
|
|
||||||
resId = R.string.selected_not_queued_label;
|
|
||||||
break;
|
|
||||||
case R.id.check_has_media:
|
|
||||||
checkWithMedia();
|
|
||||||
resId = R.string.selected_has_media_label;
|
|
||||||
break;
|
|
||||||
default: // handle various sort options
|
|
||||||
SortOrder sortOrder = menuItemIdToSortOrder.get(item.getItemId());
|
|
||||||
if (sortOrder != null) {
|
|
||||||
sort(sortOrder);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resId != 0) {
|
|
||||||
((MainActivity) getActivity()).showSnackbarAbovePlayer(resId, Snackbar.LENGTH_SHORT);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sort(@NonNull SortOrder sortOrder) {
|
|
||||||
FeedItemPermutors.getPermutor(sortOrder)
|
|
||||||
.reorder(episodes);
|
|
||||||
refreshTitles();
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkAll() {
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
if (!checkedIds.contains(episode.getId())) {
|
|
||||||
checkedIds.add(episode.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkNone() {
|
|
||||||
checkedIds.clear();
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkPlayed(boolean isPlayed) {
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
if (episode.isPlayed() == isPlayed) {
|
|
||||||
if (!checkedIds.contains(episode.getId())) {
|
|
||||||
checkedIds.add(episode.getId());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (checkedIds.contains(episode.getId())) {
|
|
||||||
checkedIds.remove(episode.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDownloaded(boolean isDownloaded) {
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
if (episode.hasMedia() && episode.getMedia().isDownloaded() == isDownloaded) {
|
|
||||||
if (!checkedIds.contains(episode.getId())) {
|
|
||||||
checkedIds.add(episode.getId());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (checkedIds.contains(episode.getId())) {
|
|
||||||
checkedIds.remove(episode.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkQueued(boolean isQueued) {
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
if (episode.isTagged(FeedItem.TAG_QUEUE) == isQueued) {
|
|
||||||
checkedIds.add(episode.getId());
|
|
||||||
} else {
|
|
||||||
checkedIds.remove(episode.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkWithMedia() {
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
if (episode.hasMedia()) {
|
|
||||||
checkedIds.add(episode.getId());
|
|
||||||
} else {
|
|
||||||
checkedIds.remove(episode.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshCheckboxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshTitles() {
|
|
||||||
titles.clear();
|
|
||||||
for (FeedItem episode : episodes) {
|
|
||||||
titles.add(episode.getTitle());
|
|
||||||
}
|
|
||||||
mAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshCheckboxes() {
|
|
||||||
for (int i = 0; i < episodes.size(); i++) {
|
|
||||||
FeedItem episode = episodes.get(i);
|
|
||||||
boolean checked = checkedIds.contains(episode.getId());
|
|
||||||
mListView.setItemChecked(i, checked);
|
|
||||||
}
|
|
||||||
refreshToolbarState();
|
|
||||||
toolbar.setTitle(getResources().getQuantityString(R.plurals.num_selected_label,
|
|
||||||
checkedIds.size(), checkedIds.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void queueChecked() {
|
|
||||||
// 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() {
|
|
||||||
DBWriter.removeQueueItem(getActivity(), true, checkedIds.toArray());
|
|
||||||
close(R.plurals.removed_from_queue_batch_label, checkedIds.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void markedCheckedPlayed() {
|
|
||||||
DBWriter.markItemPlayed(FeedItem.PLAYED, checkedIds.toArray());
|
|
||||||
close(R.plurals.marked_read_batch_label, checkedIds.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void markedCheckedUnplayed() {
|
|
||||||
DBWriter.markItemPlayed(FeedItem.UNPLAYED, checkedIds.toArray());
|
|
||||||
close(R.plurals.marked_unread_batch_label, checkedIds.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
if (checkedIds.contains(episode.getId()) && episode.hasMedia() && !episode.getFeed().isLocalFeed()) {
|
|
||||||
toDownload.add(episode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
DownloadRequester.getInstance().downloadMedia(getActivity(), true, toDownload.toArray(new FeedItem[0]));
|
|
||||||
} catch (DownloadRequestException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage());
|
|
||||||
}
|
|
||||||
close(R.plurals.downloading_batch_label, toDownload.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteChecked() {
|
|
||||||
int countHasMedia = 0;
|
|
||||||
int countNoMedia = 0;
|
|
||||||
for (long id : checkedIds.toArray()) {
|
|
||||||
FeedItem episode = idMap.get(id);
|
|
||||||
if (episode.hasMedia() && episode.getMedia().isDownloaded()) {
|
|
||||||
countHasMedia++;
|
|
||||||
DBWriter.deleteFeedMediaOfItem(getActivity(), episode.getMedia().getId());
|
|
||||||
} else {
|
|
||||||
countNoMedia++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closeMore(R.plurals.deleted_multi_episode_batch_label, countNoMedia, countHasMedia);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void close(@PluralsRes int msgId, int numItems) {
|
|
||||||
((MainActivity) getActivity()).showSnackbarAbovePlayer(
|
|
||||||
getResources().getQuantityString(msgId, numItems, numItems), Snackbar.LENGTH_LONG);
|
|
||||||
getActivity().getSupportFragmentManager().popBackStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void closeMore(@PluralsRes int msgId, int countNoMedia, int countHasMedia) {
|
|
||||||
((MainActivity) getActivity()).showSnackbarAbovePlayer(
|
|
||||||
getResources().getQuantityString(msgId,
|
|
||||||
(countHasMedia + countNoMedia),
|
|
||||||
(countHasMedia + countNoMedia), countHasMedia),
|
|
||||||
Snackbar.LENGTH_LONG);
|
|
||||||
getActivity().getSupportFragmentManager().popBackStack();
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package de.danoeh.antennapod.fragment;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -12,6 +13,10 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.leinardi.android.speeddial.SpeedDialView;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
|
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
|
||||||
@ -22,13 +27,13 @@ import de.danoeh.antennapod.core.event.FeedItemEvent;
|
|||||||
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
|
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
|
||||||
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
|
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
|
||||||
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
||||||
|
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
|
||||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||||
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
||||||
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
|
|
||||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
@ -45,13 +50,11 @@ import org.greenrobot.eventbus.ThreadMode;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_ADD_TO_QUEUE;
|
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays all completed downloads and provides a button to delete them.
|
* Displays all completed downloads and provides a button to delete them.
|
||||||
*/
|
*/
|
||||||
public class CompletedDownloadsFragment extends Fragment {
|
public class CompletedDownloadsFragment extends Fragment implements
|
||||||
|
EpisodeItemListAdapter.OnEndSelectModeListener {
|
||||||
|
|
||||||
private static final String TAG = CompletedDownloadsFragment.class.getSimpleName();
|
private static final String TAG = CompletedDownloadsFragment.class.getSimpleName();
|
||||||
|
|
||||||
@ -64,6 +67,8 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
|
|
||||||
private boolean isUpdatingFeeds = false;
|
private boolean isUpdatingFeeds = false;
|
||||||
|
|
||||||
|
private SpeedDialView speedDialView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
@ -74,9 +79,39 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
recyclerView = root.findViewById(R.id.recyclerView);
|
recyclerView = root.findViewById(R.id.recyclerView);
|
||||||
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
|
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
|
||||||
adapter = new CompletedDownloadsListAdapter((MainActivity) getActivity());
|
adapter = new CompletedDownloadsListAdapter((MainActivity) getActivity());
|
||||||
|
adapter.setOnEndSelectModeListener(this);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
progressBar = root.findViewById(R.id.progLoading);
|
progressBar = root.findViewById(R.id.progLoading);
|
||||||
|
|
||||||
|
speedDialView = root.findViewById(R.id.fabSD);
|
||||||
|
speedDialView.inflate(R.menu.episodes_apply_action_speeddial);
|
||||||
|
speedDialView.removeActionItemById(R.id.download_batch);
|
||||||
|
speedDialView.removeActionItemById(R.id.mark_read_batch);
|
||||||
|
speedDialView.removeActionItemById(R.id.mark_unread_batch);
|
||||||
|
speedDialView.removeActionItemById(R.id.remove_from_queue_batch);
|
||||||
|
speedDialView.setOnChangeListener(new SpeedDialView.OnChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMainActionSelected() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onToggleChanged(boolean open) {
|
||||||
|
if (open && adapter.getSelectedCount() == 0) {
|
||||||
|
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.no_items_selected,
|
||||||
|
Snackbar.LENGTH_SHORT);
|
||||||
|
speedDialView.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
speedDialView.setOnActionSelectedListener(actionItem -> {
|
||||||
|
new EpisodeMultiSelectActionHandler(((MainActivity) getActivity()), adapter.getSelectedItems())
|
||||||
|
.handleAction(actionItem.getId());
|
||||||
|
onEndSelectMode();
|
||||||
|
adapter.endSelectMode();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
addEmptyView();
|
addEmptyView();
|
||||||
EventBus.getDefault().register(this);
|
EventBus.getDefault().register(this);
|
||||||
return root;
|
return root;
|
||||||
@ -105,17 +140,12 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(@NonNull Menu menu) {
|
public void onPrepareOptionsMenu(@NonNull Menu menu) {
|
||||||
menu.findItem(R.id.clear_logs_item).setVisible(false);
|
menu.findItem(R.id.clear_logs_item).setVisible(false);
|
||||||
menu.findItem(R.id.episode_actions).setVisible(items.size() > 0);
|
|
||||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if (item.getItemId() == R.id.episode_actions) {
|
if (item.getItemId() == R.id.refresh_item) {
|
||||||
((MainActivity) requireActivity())
|
|
||||||
.loadChildFragment(EpisodesApplyActionFragment.newInstance(items, ACTION_DELETE | ACTION_ADD_TO_QUEUE));
|
|
||||||
return true;
|
|
||||||
} else if (item.getItemId() == R.id.refresh_item) {
|
|
||||||
AutoUpdateManager.runImmediate(requireContext());
|
AutoUpdateManager.runImmediate(requireContext());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -140,6 +170,13 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
Log.i(TAG, "Selected item at current position was null, ignoring selection");
|
Log.i(TAG, "Selected item at current position was null, ignoring selection");
|
||||||
return super.onContextItemSelected(item);
|
return super.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
|
if (item.getItemId() == R.id.multi_select) {
|
||||||
|
speedDialView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
if (adapter.onContextItemSelected(item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +188,6 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
emptyView.attachToRecyclerView(recyclerView);
|
emptyView.attachToRecyclerView(recyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(FeedItemEvent event) {
|
public void onEventMainThread(FeedItemEvent event) {
|
||||||
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||||
@ -221,6 +257,12 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEndSelectMode() {
|
||||||
|
speedDialView.close();
|
||||||
|
speedDialView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
private static class CompletedDownloadsListAdapter extends EpisodeItemListAdapter {
|
private static class CompletedDownloadsListAdapter extends EpisodeItemListAdapter {
|
||||||
|
|
||||||
public CompletedDownloadsListAdapter(MainActivity mainActivity) {
|
public CompletedDownloadsListAdapter(MainActivity mainActivity) {
|
||||||
@ -232,5 +274,13 @@ public class CompletedDownloadsFragment extends Fragment {
|
|||||||
DeleteActionButton actionButton = new DeleteActionButton(getItem(pos));
|
DeleteActionButton actionButton = new DeleteActionButton(getItem(pos));
|
||||||
actionButton.configure(holder.secondaryActionButton, holder.secondaryActionIcon, getActivity());
|
actionButton.configure(holder.secondaryActionButton, holder.secondaryActionIcon, getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
super.onCreateContextMenu(menu, v, menuInfo);
|
||||||
|
if (!inActionMode()) {
|
||||||
|
menu.findItem(R.id.multi_select).setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,6 @@ public class DownloadLogFragment extends ListFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(@NonNull Menu menu) {
|
public void onPrepareOptionsMenu(@NonNull Menu menu) {
|
||||||
menu.findItem(R.id.episode_actions).setVisible(false);
|
|
||||||
menu.findItem(R.id.clear_logs_item).setVisible(!downloadLog.isEmpty());
|
menu.findItem(R.id.clear_logs_item).setVisible(!downloadLog.isEmpty());
|
||||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,11 @@ import androidx.recyclerview.widget.SimpleItemAnimator;
|
|||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.leinardi.android.speeddial.SpeedDialView;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
|
import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
|
||||||
import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
|
import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
|
||||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||||
import de.danoeh.antennapod.core.event.DownloadEvent;
|
import de.danoeh.antennapod.core.event.DownloadEvent;
|
||||||
@ -35,6 +38,7 @@ import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
|
|||||||
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
|
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
|
||||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||||
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
||||||
|
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
|
||||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
|
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
@ -46,7 +50,6 @@ import de.danoeh.antennapod.core.util.Converter;
|
|||||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
import de.danoeh.antennapod.model.feed.SortOrder;
|
||||||
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
||||||
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
|
|
||||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
@ -63,14 +66,11 @@ import org.greenrobot.eventbus.ThreadMode;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
|
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DOWNLOAD;
|
|
||||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_REMOVE_FROM_QUEUE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows all items in the queue.
|
* Shows all items in the queue.
|
||||||
*/
|
*/
|
||||||
public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickListener {
|
public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickListener,
|
||||||
|
EpisodeItemListAdapter.OnEndSelectModeListener {
|
||||||
public static final String TAG = "QueueFragment";
|
public static final String TAG = "QueueFragment";
|
||||||
private static final String KEY_UP_ARROW = "up_arrow";
|
private static final String KEY_UP_ARROW = "up_arrow";
|
||||||
|
|
||||||
@ -93,6 +93,8 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
private ItemTouchHelper itemTouchHelper;
|
private ItemTouchHelper itemTouchHelper;
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
|
private SpeedDialView speedDialView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -277,11 +279,6 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
};
|
};
|
||||||
conDialog.createNewDialog().show();
|
conDialog.createNewDialog().show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.episode_actions:
|
|
||||||
((MainActivity) requireActivity()).loadChildFragment(
|
|
||||||
EpisodesApplyActionFragment.newInstance(queue,
|
|
||||||
ACTION_DELETE | ACTION_REMOVE_FROM_QUEUE | ACTION_DOWNLOAD));
|
|
||||||
return true;
|
|
||||||
case R.id.queue_sort_episode_title_asc:
|
case R.id.queue_sort_episode_title_asc:
|
||||||
setSortOrder(SortOrder.EPISODE_TITLE_A_Z);
|
setSortOrder(SortOrder.EPISODE_TITLE_A_Z);
|
||||||
return true;
|
return true;
|
||||||
@ -402,6 +399,15 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
Log.i(TAG, "Selected item no longer exist, ignoring selection");
|
Log.i(TAG, "Selected item no longer exist, ignoring selection");
|
||||||
return super.onContextItemSelected(item);
|
return super.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
|
if (item.getItemId() == R.id.multi_select) {
|
||||||
|
speedDialView.setVisibility(View.VISIBLE);
|
||||||
|
refreshToolbarState();
|
||||||
|
infoBar.setVisibility(View.GONE);
|
||||||
|
// Do not return: Let adapter handle its actions, too.
|
||||||
|
}
|
||||||
|
if (recyclerAdapter.onContextItemSelected(item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
switch(item.getItemId()) {
|
switch(item.getItemId()) {
|
||||||
case R.id.move_to_top_item:
|
case R.id.move_to_top_item:
|
||||||
@ -419,7 +425,6 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
super.onCreateView(inflater, container, savedInstanceState);
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
@ -538,6 +543,33 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
progLoading = root.findViewById(R.id.progLoading);
|
progLoading = root.findViewById(R.id.progLoading);
|
||||||
progLoading.setVisibility(View.VISIBLE);
|
progLoading.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
speedDialView = root.findViewById(R.id.fabSD);
|
||||||
|
speedDialView.inflate(R.menu.episodes_apply_action_speeddial);
|
||||||
|
speedDialView.removeActionItemById(R.id.mark_read_batch);
|
||||||
|
speedDialView.removeActionItemById(R.id.mark_unread_batch);
|
||||||
|
speedDialView.removeActionItemById(R.id.add_to_queue_batch);
|
||||||
|
speedDialView.setOnChangeListener(new SpeedDialView.OnChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMainActionSelected() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onToggleChanged(boolean open) {
|
||||||
|
if (open && recyclerAdapter.getSelectedCount() == 0) {
|
||||||
|
((MainActivity) getActivity()).showSnackbarAbovePlayer(R.string.no_items_selected,
|
||||||
|
Snackbar.LENGTH_SHORT);
|
||||||
|
speedDialView.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
speedDialView.setOnActionSelectedListener(actionItem -> {
|
||||||
|
new EpisodeMultiSelectActionHandler(((MainActivity) getActivity()), recyclerAdapter.getSelectedItems())
|
||||||
|
.handleAction(actionItem.getId());
|
||||||
|
onEndSelectMode();
|
||||||
|
recyclerAdapter.endSelectMode();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,6 +584,7 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
if (recyclerAdapter == null) {
|
if (recyclerAdapter == null) {
|
||||||
MainActivity activity = (MainActivity) getActivity();
|
MainActivity activity = (MainActivity) getActivity();
|
||||||
recyclerAdapter = new QueueRecyclerAdapter(activity, itemTouchHelper);
|
recyclerAdapter = new QueueRecyclerAdapter(activity, itemTouchHelper);
|
||||||
|
recyclerAdapter.setOnEndSelectModeListener(this);
|
||||||
recyclerView.setAdapter(recyclerAdapter);
|
recyclerView.setAdapter(recyclerAdapter);
|
||||||
emptyView.updateAdapter(recyclerAdapter);
|
emptyView.updateAdapter(recyclerAdapter);
|
||||||
}
|
}
|
||||||
@ -615,4 +648,11 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
|
|||||||
}
|
}
|
||||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEndSelectMode() {
|
||||||
|
speedDialView.close();
|
||||||
|
speedDialView.setVisibility(View.GONE);
|
||||||
|
infoBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="?attr/actionBarSize"
|
|
||||||
android:theme="?attr/actionBarTheme"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
app:navigationIcon="?homeAsUpIndicator"
|
|
||||||
android:id="@+id/toolbar"/>
|
|
||||||
|
|
||||||
<ListView
|
|
||||||
android:id="@android:id/list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/toolbar"
|
|
||||||
android:layout_marginTop="0dp" />
|
|
||||||
|
|
||||||
<com.leinardi.android.speeddial.SpeedDialOverlayLayout
|
|
||||||
android:id="@+id/fabSDOverlay"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:layout_below="@id/toolbar" />
|
|
||||||
<!-- The FAB SpeedDial
|
|
||||||
1. MUST be placed at the bottom of the layout xml to ensure it is at the front,
|
|
||||||
clickable on Pre-Lollipop devices (that do not support elevation).
|
|
||||||
See: https://stackoverflow.com/a/2614402
|
|
||||||
2. ScrollView is needed to ensure the vertical list of speed dials are
|
|
||||||
accessible when screen height is small, eg., landscape mode on most phones.
|
|
||||||
-->
|
|
||||||
<ScrollView
|
|
||||||
android:id="@+id/fabSDScrollCtr"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:elevation="@dimen/sd_open_elevation"
|
|
||||||
tools:ignore="UnusedAttribute" >
|
|
||||||
|
|
||||||
<com.leinardi.android.speeddial.SpeedDialView
|
|
||||||
android:id="@+id/fabSD"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:sdMainFabClosedSrc="@drawable/ic_fab_edit"
|
|
||||||
app:sdOverlayLayout="@id/fabSDOverlay"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:accessibilityTraversalBefore="@android:id/list"
|
|
||||||
android:contentDescription="@string/apply_action" />
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -21,6 +21,9 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|right"
|
android:layout_gravity="bottom|right"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
android:elevation="@dimen/sd_open_elevation">
|
android:elevation="@dimen/sd_open_elevation">
|
||||||
|
|
||||||
<com.leinardi.android.speeddial.SpeedDialView
|
<com.leinardi.android.speeddial.SpeedDialView
|
||||||
|
@ -1,42 +1,44 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?attr/actionBarSize"
|
android:minHeight="?attr/actionBarSize"
|
||||||
android:theme="?attr/actionBarTheme"
|
android:theme="?attr/actionBarTheme"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
app:title="@string/queue_label"
|
app:title="@string/queue_label" />
|
||||||
android:id="@+id/toolbar"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_below="@id/toolbar"
|
|
||||||
android:id="@+id/info_bar"
|
android:id="@+id/info_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:layout_marginTop="-8dp"
|
android:layout_marginTop="-8dp"
|
||||||
android:layout_marginLeft="72dp"
|
android:layout_marginLeft="72dp"
|
||||||
android:layout_marginStart="72dp"
|
android:layout_marginStart="72dp"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
tools:text="12 Episodes - Time remaining: 12 hours"/>
|
tools:text="12 Episodes - Time remaining: 12 hours" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:layout_below="@id/info_bar"
|
android:layout_below="@id/info_bar"
|
||||||
android:background="?android:attr/listDivider"/>
|
android:background="?android:attr/listDivider" />
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swipeRefresh"
|
android:id="@+id/swipeRefresh"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@id/divider">
|
android:layout_below="@id/divider">
|
||||||
|
|
||||||
<de.danoeh.antennapod.view.EpisodeItemListRecyclerView
|
<de.danoeh.antennapod.view.EpisodeItemListRecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
@ -54,4 +56,7 @@
|
|||||||
android:indeterminateOnly="true"
|
android:indeterminateOnly="true"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/multi_select_speed_dial" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_height="match_parent">
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/toolbar"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:minHeight="?attr/actionBarSize"
|
android:layout_height="wrap_content"
|
||||||
android:theme="?attr/actionBarTheme"
|
android:minHeight="?attr/actionBarSize"
|
||||||
android:layout_alignParentTop="true"
|
android:theme="?attr/actionBarTheme"
|
||||||
android:id="@+id/toolbar"/>
|
android:layout_alignParentTop="true" />
|
||||||
|
|
||||||
<de.danoeh.antennapod.view.EpisodeItemListRecyclerView
|
<de.danoeh.antennapod.view.EpisodeItemListRecyclerView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_height="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:paddingHorizontal="@dimen/additional_horizontal_spacing"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@id/toolbar"
|
android:paddingHorizontal="@dimen/additional_horizontal_spacing"
|
||||||
android:id="@+id/recyclerView"/>
|
android:layout_below="@id/toolbar" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progLoading"
|
android:id="@+id/progLoading"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:indeterminateOnly="true"
|
android:indeterminateOnly="true"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/multi_select_speed_dial" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<item
|
|
||||||
android:id="@+id/episode_actions"
|
|
||||||
android:menuCategory="container"
|
|
||||||
android:title="@string/multi_select"
|
|
||||||
android:icon="@drawable/ic_check_multiple"
|
|
||||||
android:visible="false"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/clear_logs_item"
|
android:id="@+id/clear_logs_item"
|
||||||
android:menuCategory="container"
|
android:menuCategory="container"
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/sort"
|
|
||||||
android:icon="@drawable/ic_sort"
|
|
||||||
android:title="@string/sort"
|
|
||||||
app:showAsAction="always">
|
|
||||||
<menu>
|
|
||||||
<item android:id="@+id/sort_title_a_z"
|
|
||||||
android:title="@string/sort_title_a_z"/>
|
|
||||||
<item android:id="@+id/sort_title_z_a"
|
|
||||||
android:title="@string/sort_title_z_a"/>
|
|
||||||
<item android:id="@+id/sort_date_new_old"
|
|
||||||
android:title="@string/sort_date_new_old"/>
|
|
||||||
<item android:id="@+id/sort_date_old_new"
|
|
||||||
android:title="@string/sort_date_old_new"/>
|
|
||||||
<item android:id="@+id/sort_duration_short_long"
|
|
||||||
android:title="@string/sort_duration_short_long"/>
|
|
||||||
<item android:id="@+id/sort_duration_long_short"
|
|
||||||
android:title="@string/sort_duration_long_short"/>
|
|
||||||
</menu>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/select_options"
|
|
||||||
android:icon="@drawable/ic_filter"
|
|
||||||
android:title="@string/filter"
|
|
||||||
app:showAsAction="always">
|
|
||||||
|
|
||||||
<menu>
|
|
||||||
<item android:id="@+id/check_all"
|
|
||||||
android:title="@string/all_label"/>
|
|
||||||
<item android:id="@+id/check_none"
|
|
||||||
android:title="@string/select_none_label"/>
|
|
||||||
<item android:id="@+id/check_played"
|
|
||||||
android:title="@string/played_label"/>
|
|
||||||
<item android:id="@+id/check_unplayed"
|
|
||||||
android:title="@string/unplayed_label"/>
|
|
||||||
<item android:id="@+id/check_downloaded"
|
|
||||||
android:title="@string/downloaded_label"/>
|
|
||||||
<item android:id="@+id/check_not_downloaded"
|
|
||||||
android:title="@string/not_downloaded_label"/>
|
|
||||||
<item android:id="@+id/check_queued"
|
|
||||||
android:title="@string/queued_label"/>
|
|
||||||
<item android:id="@+id/check_not_queued"
|
|
||||||
android:title="@string/not_queued_label"/>
|
|
||||||
<item android:id="@+id/check_has_media"
|
|
||||||
android:title="@string/has_media"/>
|
|
||||||
</menu>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/select_toggle"
|
|
||||||
android:title="@string/select_all_label"
|
|
||||||
app:showAsAction="always"/>
|
|
||||||
</menu>
|
|
@ -1,11 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item
|
|
||||||
android:id="@+id/multi_select"
|
|
||||||
android:menuCategory="container"
|
|
||||||
android:title="@string/multi_select"
|
|
||||||
android:visible="false"/>
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@id/skip_episode_item"
|
android:id="@id/skip_episode_item"
|
||||||
android:menuCategory="container"
|
android:menuCategory="container"
|
||||||
@ -75,4 +69,10 @@
|
|||||||
android:id="@+id/share_item"
|
android:id="@+id/share_item"
|
||||||
android:menuCategory="container"
|
android:menuCategory="container"
|
||||||
android:title="@string/share_label" />
|
android:title="@string/share_label" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/multi_select"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/multi_select"
|
||||||
|
android:visible="false" />
|
||||||
</menu>
|
</menu>
|
@ -115,10 +115,4 @@
|
|||||||
android:title="@string/clear_queue_label"
|
android:title="@string/clear_queue_label"
|
||||||
custom:showAsAction="collapseActionView"
|
custom:showAsAction="collapseActionView"
|
||||||
android:icon="@drawable/ic_check"/>
|
android:icon="@drawable/ic_check"/>
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/episode_actions"
|
|
||||||
custom:showAsAction="collapseActionView"
|
|
||||||
android:title="@string/multi_select" />
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<vector android:height="24dp"
|
|
||||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<path android:fillColor="?attr/action_icon_color" android:pathData="M20,16V10H22V16A2,2 0 0,1 20,18H8C6.89,18 6,17.1 6,16V4C6,2.89 6.89,2 8,2H16V4H8V16H20M10.91,7.08L14,10.17L20.59,3.58L22,5L14,13L9.5,8.5L10.91,7.08M16,20V22H4A2,2 0 0,1 2,20V7H4V20H16Z"/>
|
|
||||||
</vector>
|
|
@ -314,11 +314,6 @@
|
|||||||
<item>continue</item>
|
<item>continue</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="batch_long_press_options">
|
|
||||||
<item>@string/select_all_above</item>
|
|
||||||
<item>@string/select_all_below</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="back_button_behavior_options">
|
<string-array name="back_button_behavior_options">
|
||||||
<item>@string/back_button_default</item>
|
<item>@string/back_button_default</item>
|
||||||
<item>@string/back_button_go_to_page</item>
|
<item>@string/back_button_go_to_page</item>
|
||||||
|
@ -727,24 +727,6 @@
|
|||||||
<string name="unable_to_start_system_file_manager">Unable to start system file manager</string>
|
<string name="unable_to_start_system_file_manager">Unable to start system file manager</string>
|
||||||
|
|
||||||
<string name="filter">Filter</string>
|
<string name="filter">Filter</string>
|
||||||
|
|
||||||
<!-- Episodes apply actions -->
|
|
||||||
<string name="all_label">All</string>
|
|
||||||
<string name="selected_all_label">Selected all Episodes</string>
|
|
||||||
<string name="select_none_label">None</string>
|
|
||||||
<string name="deselected_all_label">Deselected all Episodes</string>
|
|
||||||
<string name="played_label">Played</string>
|
|
||||||
<string name="selected_played_label">Selected played Episodes</string>
|
|
||||||
<string name="unplayed_label">Unplayed</string>
|
|
||||||
<string name="selected_unplayed_label">Selected unplayed Episodes</string>
|
|
||||||
<string name="downloaded_label">Downloaded</string>
|
|
||||||
<string name="selected_downloaded_label">Selected downloaded Episodes</string>
|
|
||||||
<string name="not_downloaded_label">Not downloaded</string>
|
|
||||||
<string name="selected_not_downloaded_label">Selected not downloaded Episodes</string>
|
|
||||||
<string name="selected_queued_label">Selected queued Episodes</string>
|
|
||||||
<string name="selected_not_queued_label">Selected not queued Episodes</string>
|
|
||||||
<string name="selected_has_media_label">Selected episodes with media</string>
|
|
||||||
|
|
||||||
<string name="hide_is_favorite_label">Is favorite</string>
|
<string name="hide_is_favorite_label">Is favorite</string>
|
||||||
<string name="not_favorite">Not favorite</string>
|
<string name="not_favorite">Not favorite</string>
|
||||||
<string name="hide_downloaded_episodes_label">Downloaded</string>
|
<string name="hide_downloaded_episodes_label">Downloaded</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user