Feed multi select (#5261)
This commit is contained in:
parent
91967409cb
commit
eacc90af29
@ -76,21 +76,19 @@ public class EpisodeItemListAdapter extends SelectableAdapter<EpisodeItemViewHol
|
|||||||
int position = ArrayUtils.indexOf(ids, item.getId());
|
int position = ArrayUtils.indexOf(ids, item.getId());
|
||||||
activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
|
activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
|
||||||
} else {
|
} else {
|
||||||
toggleSelection(pos);
|
toggleSelection(holder.getBindingAdapterPosition());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
holder.itemView.setOnCreateContextMenuListener(this);
|
holder.itemView.setOnCreateContextMenuListener(this);
|
||||||
holder.itemView.setOnLongClickListener(v -> {
|
holder.itemView.setOnLongClickListener(v -> {
|
||||||
longPressedItem = item;
|
longPressedItem = getItem(holder.getBindingAdapterPosition());
|
||||||
longPressedPosition = pos;
|
longPressedPosition = holder.getBindingAdapterPosition();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (inActionMode()) {
|
if (inActionMode()) {
|
||||||
holder.secondaryActionButton.setVisibility(View.GONE);
|
holder.secondaryActionButton.setVisibility(View.GONE);
|
||||||
holder.selectCheckBox.setOnClickListener(v -> {
|
holder.selectCheckBox.setOnClickListener(v -> toggleSelection(holder.getBindingAdapterPosition()));
|
||||||
toggleSelection(pos);
|
|
||||||
});
|
|
||||||
holder.selectCheckBox.setChecked(isSelected(pos));
|
holder.selectCheckBox.setChecked(isSelected(pos));
|
||||||
holder.selectCheckBox.setVisibility(View.VISIBLE);
|
holder.selectCheckBox.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,152 +0,0 @@
|
|||||||
package de.danoeh.antennapod.adapter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.core.text.TextUtilsCompat;
|
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
|
||||||
import de.danoeh.antennapod.model.feed.Feed;
|
|
||||||
import de.danoeh.antennapod.core.feed.LocalFeedUpdater;
|
|
||||||
import de.danoeh.antennapod.core.storage.NavDrawerData;
|
|
||||||
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
|
|
||||||
import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
|
||||||
import jp.shts.android.library.TriangleLabelView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter for subscriptions
|
|
||||||
*/
|
|
||||||
public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
|
|
||||||
/** the position in the view that holds the add item; 0 is the first, -1 is the last position */
|
|
||||||
private static final String TAG = "SubscriptionsAdapter";
|
|
||||||
|
|
||||||
private final WeakReference<MainActivity> mainActivityRef;
|
|
||||||
private final ItemAccess itemAccess;
|
|
||||||
|
|
||||||
public SubscriptionsAdapter(MainActivity mainActivity, ItemAccess itemAccess) {
|
|
||||||
this.mainActivityRef = new WeakReference<>(mainActivity);
|
|
||||||
this.itemAccess = itemAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return itemAccess.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getItem(int position) {
|
|
||||||
return itemAccess.getItem(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasStableIds() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int position) {
|
|
||||||
return ((NavDrawerData.DrawerItem) getItem(position)).id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
Holder holder;
|
|
||||||
|
|
||||||
if (convertView == null) {
|
|
||||||
holder = new Holder();
|
|
||||||
|
|
||||||
LayoutInflater layoutInflater =
|
|
||||||
(LayoutInflater) mainActivityRef.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
convertView = layoutInflater.inflate(R.layout.subscription_item, parent, false);
|
|
||||||
holder.feedTitle = convertView.findViewById(R.id.txtvTitle);
|
|
||||||
holder.imageView = convertView.findViewById(R.id.imgvCover);
|
|
||||||
holder.count = convertView.findViewById(R.id.triangleCountView);
|
|
||||||
|
|
||||||
|
|
||||||
convertView.setTag(holder);
|
|
||||||
} else {
|
|
||||||
holder = (Holder) convertView.getTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
final NavDrawerData.DrawerItem drawerItem = (NavDrawerData.DrawerItem) getItem(position);
|
|
||||||
if (drawerItem == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.feedTitle.setText(drawerItem.getTitle());
|
|
||||||
holder.imageView.setContentDescription(drawerItem.getTitle());
|
|
||||||
holder.feedTitle.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
// Fix TriangleLabelView corner for RTL
|
|
||||||
if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())
|
|
||||||
== ViewCompat.LAYOUT_DIRECTION_RTL) {
|
|
||||||
holder.count.setCorner(TriangleLabelView.Corner.TOP_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drawerItem.getCounter() > 0) {
|
|
||||||
holder.count.setPrimaryText(NumberFormat.getInstance().format(drawerItem.getCounter()));
|
|
||||||
holder.count.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
holder.count.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
|
||||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
|
||||||
boolean textAndImageCombined = feed.isLocalFeed()
|
|
||||||
&& LocalFeedUpdater.getDefaultIconUrl(convertView.getContext()).equals(feed.getImageUrl());
|
|
||||||
new CoverLoader(mainActivityRef.get())
|
|
||||||
.withUri(feed.getImageUrl())
|
|
||||||
.withPlaceholderView(holder.feedTitle, textAndImageCombined)
|
|
||||||
.withCoverView(holder.imageView)
|
|
||||||
.load();
|
|
||||||
} else {
|
|
||||||
new CoverLoader(mainActivityRef.get())
|
|
||||||
.withResource(R.drawable.ic_folder)
|
|
||||||
.withPlaceholderView(holder.feedTitle, true)
|
|
||||||
.withCoverView(holder.imageView)
|
|
||||||
.load();
|
|
||||||
}
|
|
||||||
return convertView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
final NavDrawerData.DrawerItem drawerItem = (NavDrawerData.DrawerItem) getItem(position);
|
|
||||||
if (drawerItem == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
|
||||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
|
||||||
Fragment fragment = FeedItemlistFragment.newInstance(feed.getId());
|
|
||||||
mainActivityRef.get().loadChildFragment(fragment);
|
|
||||||
} else if (drawerItem.type == NavDrawerData.DrawerItem.Type.FOLDER) {
|
|
||||||
Fragment fragment = SubscriptionFragment.newInstance(drawerItem.getTitle());
|
|
||||||
mainActivityRef.get().loadChildFragment(fragment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Holder {
|
|
||||||
public TextView feedTitle;
|
|
||||||
public ImageView imageView;
|
|
||||||
public TriangleLabelView count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ItemAccess {
|
|
||||||
int getCount();
|
|
||||||
|
|
||||||
NavDrawerData.DrawerItem getItem(int position);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,245 @@
|
|||||||
|
package de.danoeh.antennapod.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.ContextMenu;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.text.TextUtilsCompat;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
|
import de.danoeh.antennapod.core.feed.LocalFeedUpdater;
|
||||||
|
import de.danoeh.antennapod.core.storage.NavDrawerData;
|
||||||
|
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
|
||||||
|
import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
||||||
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
|
import jp.shts.android.library.TriangleLabelView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for subscriptions
|
||||||
|
*/
|
||||||
|
public class SubscriptionsRecyclerAdapter extends SelectableAdapter<SubscriptionsRecyclerAdapter.SubscriptionViewHolder>
|
||||||
|
implements View.OnCreateContextMenuListener {
|
||||||
|
private final WeakReference<MainActivity> mainActivityRef;
|
||||||
|
private List<NavDrawerData.DrawerItem> listItems;
|
||||||
|
private Feed selectedFeed = null;
|
||||||
|
int longPressedPosition = 0; // used to init actionMode
|
||||||
|
|
||||||
|
public SubscriptionsRecyclerAdapter(MainActivity mainActivity) {
|
||||||
|
super(mainActivity);
|
||||||
|
this.mainActivityRef = new WeakReference<>(mainActivity);
|
||||||
|
this.listItems = new ArrayList<>();
|
||||||
|
setHasStableIds(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return listItems.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Feed getSelectedFeed() {
|
||||||
|
return selectedFeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public SubscriptionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View itemView = LayoutInflater.from(mainActivityRef.get()).inflate(R.layout.subscription_item, parent, false);
|
||||||
|
return new SubscriptionViewHolder(itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull SubscriptionViewHolder holder, int position) {
|
||||||
|
NavDrawerData.DrawerItem drawerItem = listItems.get(position);
|
||||||
|
boolean isFeed = drawerItem.type == NavDrawerData.DrawerItem.Type.FEED;
|
||||||
|
holder.bind(drawerItem);
|
||||||
|
holder.itemView.setOnCreateContextMenuListener(this);
|
||||||
|
if (inActionMode()) {
|
||||||
|
if (isFeed) {
|
||||||
|
holder.selectCheckbox.setVisibility(View.VISIBLE);
|
||||||
|
holder.selectView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
holder.selectCheckbox.setChecked((isSelected(position)));
|
||||||
|
holder.selectCheckbox.setOnCheckedChangeListener((buttonView, isChecked)
|
||||||
|
-> setSelected(holder.getBindingAdapterPosition(), isChecked));
|
||||||
|
holder.imageView.setAlpha(0.6f);
|
||||||
|
holder.count.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
holder.selectView.setVisibility(View.GONE);
|
||||||
|
holder.imageView.setAlpha(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.itemView.setOnLongClickListener(v -> {
|
||||||
|
if (!inActionMode()) {
|
||||||
|
if (isFeed) {
|
||||||
|
selectedFeed = ((NavDrawerData.FeedDrawerItem) getItem(holder.getBindingAdapterPosition())).feed;
|
||||||
|
longPressedPosition = holder.getBindingAdapterPosition();
|
||||||
|
} else {
|
||||||
|
selectedFeed = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (isFeed) {
|
||||||
|
if (inActionMode()) {
|
||||||
|
holder.selectCheckbox.setChecked(!isSelected(holder.getBindingAdapterPosition()));
|
||||||
|
} else {
|
||||||
|
Fragment fragment = FeedItemlistFragment
|
||||||
|
.newInstance(((NavDrawerData.FeedDrawerItem) drawerItem).feed.getId());
|
||||||
|
mainActivityRef.get().loadChildFragment(fragment);
|
||||||
|
}
|
||||||
|
} else if (!inActionMode()) {
|
||||||
|
Fragment fragment = SubscriptionFragment.newInstance(drawerItem.getTitle());
|
||||||
|
mainActivityRef.get().loadChildFragment(fragment);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return listItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return listItems.get(position).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
if (selectedFeed != null && !inActionMode()) {
|
||||||
|
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.nav_feed_context, menu);
|
||||||
|
menu.setHeaderTitle(selectedFeed.getTitle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
|
if (item.getItemId() == R.id.multi_select) {
|
||||||
|
startSelectMode(longPressedPosition);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Feed> getSelectedItems() {
|
||||||
|
List<Feed> items = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
|
if (isSelected(i)) {
|
||||||
|
NavDrawerData.DrawerItem drawerItem = listItems.get(i);
|
||||||
|
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||||
|
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||||
|
items.add(feed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<NavDrawerData.DrawerItem> listItems) {
|
||||||
|
this.listItems = listItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(int pos, boolean selected) {
|
||||||
|
NavDrawerData.DrawerItem drawerItem = listItems.get(pos);
|
||||||
|
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||||
|
super.setSelected(pos, selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SubscriptionViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final TextView feedTitle;
|
||||||
|
private final ImageView imageView;
|
||||||
|
private final TriangleLabelView count;
|
||||||
|
private final FrameLayout selectView;
|
||||||
|
private final CheckBox selectCheckbox;
|
||||||
|
|
||||||
|
public SubscriptionViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
feedTitle = itemView.findViewById(R.id.txtvTitle);
|
||||||
|
imageView = itemView.findViewById(R.id.imgvCover);
|
||||||
|
count = itemView.findViewById(R.id.triangleCountView);
|
||||||
|
selectView = itemView.findViewById(R.id.selectView);
|
||||||
|
selectCheckbox = itemView.findViewById(R.id.selectCheckBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(NavDrawerData.DrawerItem drawerItem) {
|
||||||
|
feedTitle.setText(drawerItem.getTitle());
|
||||||
|
imageView.setContentDescription(drawerItem.getTitle());
|
||||||
|
feedTitle.setVisibility(View.VISIBLE);
|
||||||
|
if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())
|
||||||
|
== ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||||
|
count.setCorner(TriangleLabelView.Corner.TOP_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawerItem.getCounter() > 0) {
|
||||||
|
count.setPrimaryText(NumberFormat.getInstance().format(drawerItem.getCounter()));
|
||||||
|
count.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
count.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||||
|
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||||
|
boolean textAndImageCombind = feed.isLocalFeed()
|
||||||
|
&& LocalFeedUpdater.getDefaultIconUrl(itemView.getContext()).equals(feed.getImageUrl());
|
||||||
|
new CoverLoader(mainActivityRef.get())
|
||||||
|
.withUri(feed.getImageUrl())
|
||||||
|
.withPlaceholderView(feedTitle, textAndImageCombind)
|
||||||
|
.withCoverView(imageView)
|
||||||
|
.load();
|
||||||
|
} else {
|
||||||
|
new CoverLoader(mainActivityRef.get())
|
||||||
|
.withResource(R.drawable.ic_folder)
|
||||||
|
.withPlaceholderView(feedTitle, true)
|
||||||
|
.withCoverView(imageView)
|
||||||
|
.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float convertDpToPixel(Context context, float dp) {
|
||||||
|
return dp * context.getResources().getDisplayMetrics().density;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GridDividerItemDecorator extends RecyclerView.ItemDecoration {
|
||||||
|
@Override
|
||||||
|
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||||
|
super.onDraw(c, parent, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(@NonNull Rect outRect,
|
||||||
|
@NonNull View view,
|
||||||
|
@NonNull RecyclerView parent,
|
||||||
|
@NonNull RecyclerView.State state) {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state);
|
||||||
|
Context context = parent.getContext();
|
||||||
|
int insetOffset = (int) convertDpToPixel(context, 1f);
|
||||||
|
outRect.set(insetOffset, insetOffset, insetOffset, insetOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,10 @@ import android.app.ProgressDialog;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||||
import de.danoeh.antennapod.model.feed.Feed;
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
@ -16,10 +20,17 @@ public class RemoveFeedDialog {
|
|||||||
private static final String TAG = "RemoveFeedDialog";
|
private static final String TAG = "RemoveFeedDialog";
|
||||||
|
|
||||||
public static void show(Context context, Feed feed, Runnable onSuccess) {
|
public static void show(Context context, Feed feed, Runnable onSuccess) {
|
||||||
int messageId = feed.isLocalFeed() ? R.string.feed_delete_confirmation_local_msg
|
List<Feed> feeds = Collections.singletonList(feed);
|
||||||
: R.string.feed_delete_confirmation_msg;
|
String message = getMessageId(context, feeds);
|
||||||
String message = context.getString(messageId, feed.getTitle());
|
showDialog(context, feeds, message, onSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void show(Context context, List<Feed> feeds, Runnable onSuccess) {
|
||||||
|
String message = getMessageId(context, feeds);
|
||||||
|
showDialog(context, feeds, message, onSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showDialog(Context context, List<Feed> feeds, String message, Runnable onSuccess) {
|
||||||
ConfirmationDialog dialog = new ConfirmationDialog(context, R.string.remove_feed_label, message) {
|
ConfirmationDialog dialog = new ConfirmationDialog(context, R.string.remove_feed_label, message) {
|
||||||
@Override
|
@Override
|
||||||
public void onConfirmButtonPressed(DialogInterface clickedDialog) {
|
public void onConfirmButtonPressed(DialogInterface clickedDialog) {
|
||||||
@ -31,12 +42,17 @@ public class RemoveFeedDialog {
|
|||||||
progressDialog.setCancelable(false);
|
progressDialog.setCancelable(false);
|
||||||
progressDialog.show();
|
progressDialog.show();
|
||||||
|
|
||||||
Completable.fromCallable(() -> DBWriter.deleteFeed(context, feed.getId()).get())
|
Completable.fromCallable(() -> {
|
||||||
|
for (Feed feed : feeds) {
|
||||||
|
DBWriter.deleteFeed(context, feed.getId()).get();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() -> {
|
() -> {
|
||||||
Log.d(TAG, "Feed was deleted");
|
Log.d(TAG, "Feed(s) deleted");
|
||||||
if (onSuccess != null) {
|
if (onSuccess != null) {
|
||||||
onSuccess.run();
|
onSuccess.run();
|
||||||
}
|
}
|
||||||
@ -49,4 +65,17 @@ public class RemoveFeedDialog {
|
|||||||
};
|
};
|
||||||
dialog.createNewDialog().show();
|
dialog.createNewDialog().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getMessageId(Context context, List<Feed> feeds) {
|
||||||
|
if (feeds.size() == 1) {
|
||||||
|
if (feeds.get(0).isLocalFeed()) {
|
||||||
|
return context.getString(R.string.feed_delete_confirmation_local_msg);
|
||||||
|
} else {
|
||||||
|
return context.getString(R.string.feed_delete_confirmation_msg, feeds.get(0).getTitle());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return context.getString(R.string.feed_delete_confirmation_msg_batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,41 +7,44 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.ContextMenu;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.GridView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.joanzapata.iconify.Iconify;
|
import com.joanzapata.iconify.Iconify;
|
||||||
|
import com.leinardi.android.speeddial.SpeedDialView;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.dialog.TagSettingsDialog;
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
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.SubscriptionsAdapter;
|
import de.danoeh.antennapod.adapter.SubscriptionsRecyclerAdapter;
|
||||||
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;
|
||||||
import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
|
import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
|
||||||
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
||||||
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
|
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
|
||||||
import de.danoeh.antennapod.dialog.TagSettingsDialog;
|
|
||||||
import de.danoeh.antennapod.model.feed.Feed;
|
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
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;
|
||||||
@ -49,24 +52,24 @@ import de.danoeh.antennapod.core.storage.DBWriter;
|
|||||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||||
import de.danoeh.antennapod.core.storage.NavDrawerData;
|
import de.danoeh.antennapod.core.storage.NavDrawerData;
|
||||||
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
|
||||||
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
|
|
||||||
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
|
|
||||||
import de.danoeh.antennapod.dialog.FeedSortDialog;
|
import de.danoeh.antennapod.dialog.FeedSortDialog;
|
||||||
|
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
|
||||||
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
||||||
|
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
|
||||||
|
import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler;
|
||||||
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import org.greenrobot.eventbus.EventBus;
|
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment for displaying feed subscriptions
|
* Fragment for displaying feed subscriptions
|
||||||
*/
|
*/
|
||||||
public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItemClickListener {
|
public class SubscriptionFragment extends Fragment
|
||||||
|
implements Toolbar.OnMenuItemClickListener,
|
||||||
|
SubscriptionsRecyclerAdapter.OnSelectModeListener {
|
||||||
public static final String TAG = "SubscriptionFragment";
|
public static final String TAG = "SubscriptionFragment";
|
||||||
private static final String PREFS = "SubscriptionFragment";
|
private static final String PREFS = "SubscriptionFragment";
|
||||||
private static final String PREF_NUM_COLUMNS = "columns";
|
private static final String PREF_NUM_COLUMNS = "columns";
|
||||||
@ -80,23 +83,24 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
R.id.subscription_num_columns_4,
|
R.id.subscription_num_columns_4,
|
||||||
R.id.subscription_num_columns_5};
|
R.id.subscription_num_columns_5};
|
||||||
|
|
||||||
private GridView subscriptionGridLayout;
|
private RecyclerView subscriptionRecycler;
|
||||||
private List<NavDrawerData.DrawerItem> listItems;
|
private SubscriptionsRecyclerAdapter subscriptionAdapter;
|
||||||
private SubscriptionsAdapter subscriptionAdapter;
|
|
||||||
private FloatingActionButton subscriptionAddButton;
|
private FloatingActionButton subscriptionAddButton;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private EmptyViewHandler emptyView;
|
private EmptyViewHandler emptyView;
|
||||||
private TextView feedsFilteredMsg;
|
private TextView feedsFilteredMsg;
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private String displayedFolder = null;
|
private String displayedFolder = null;
|
||||||
|
|
||||||
private Feed selectedFeed = null;
|
|
||||||
private boolean isUpdatingFeeds = false;
|
private boolean isUpdatingFeeds = false;
|
||||||
private boolean displayUpArrow;
|
private boolean displayUpArrow;
|
||||||
|
|
||||||
private Disposable disposable;
|
private Disposable disposable;
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
|
private SpeedDialView speedDialView;
|
||||||
|
|
||||||
|
private List<NavDrawerData.DrawerItem> listItems;
|
||||||
|
|
||||||
public static SubscriptionFragment newInstance(String folderTitle) {
|
public static SubscriptionFragment newInstance(String folderTitle) {
|
||||||
SubscriptionFragment fragment = new SubscriptionFragment();
|
SubscriptionFragment fragment = new SubscriptionFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
@ -139,9 +143,15 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subscriptionGridLayout = root.findViewById(R.id.subscriptions_grid);
|
subscriptionRecycler = root.findViewById(R.id.subscriptions_grid);
|
||||||
subscriptionGridLayout.setNumColumns(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
|
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),
|
||||||
registerForContextMenu(subscriptionGridLayout);
|
prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()),
|
||||||
|
RecyclerView.VERTICAL,
|
||||||
|
false);
|
||||||
|
subscriptionRecycler.setLayoutManager(gridLayoutManager);
|
||||||
|
subscriptionRecycler.addItemDecoration(new SubscriptionsRecyclerAdapter.GridDividerItemDecorator());
|
||||||
|
gridLayoutManager.setSpanCount(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
|
||||||
|
registerForContextMenu(subscriptionRecycler);
|
||||||
subscriptionAddButton = root.findViewById(R.id.subscriptions_add);
|
subscriptionAddButton = root.findViewById(R.id.subscriptions_add);
|
||||||
progressBar = root.findViewById(R.id.progLoading);
|
progressBar = root.findViewById(R.id.progLoading);
|
||||||
|
|
||||||
@ -155,6 +165,25 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false),
|
new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false),
|
||||||
getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
|
getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
speedDialView = root.findViewById(R.id.fabSD);
|
||||||
|
speedDialView.inflate(R.menu.nav_feed_action_speeddial);
|
||||||
|
speedDialView.setOnChangeListener(new SpeedDialView.OnChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMainActionSelected() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onToggleChanged(boolean isOpen) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
speedDialView.setOnActionSelectedListener(actionItem -> {
|
||||||
|
new FeedMultiSelectActionHandler((MainActivity) getActivity(), subscriptionAdapter.getSelectedItems())
|
||||||
|
.handleAction(actionItem.getId());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +233,9 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setColumnNumber(int columns) {
|
private void setColumnNumber(int columns) {
|
||||||
subscriptionGridLayout.setNumColumns(columns);
|
GridLayoutManager gridLayoutManager = (GridLayoutManager) subscriptionRecycler.getLayoutManager();
|
||||||
|
gridLayoutManager.setSpanCount(columns);
|
||||||
|
subscriptionAdapter.notifyDataSetChanged();
|
||||||
prefs.edit().putInt(PREF_NUM_COLUMNS, columns).apply();
|
prefs.edit().putInt(PREF_NUM_COLUMNS, columns).apply();
|
||||||
refreshToolbarState();
|
refreshToolbarState();
|
||||||
}
|
}
|
||||||
@ -214,18 +245,16 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
emptyView.setIcon(R.drawable.ic_folder);
|
emptyView.setIcon(R.drawable.ic_folder);
|
||||||
emptyView.setTitle(R.string.no_subscriptions_head_label);
|
emptyView.setTitle(R.string.no_subscriptions_head_label);
|
||||||
emptyView.setMessage(R.string.no_subscriptions_label);
|
emptyView.setMessage(R.string.no_subscriptions_label);
|
||||||
emptyView.attachToListView(subscriptionGridLayout);
|
emptyView.attachToRecyclerView(subscriptionRecycler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
subscriptionAdapter = new SubscriptionsRecyclerAdapter((MainActivity) getActivity());
|
||||||
subscriptionAdapter = new SubscriptionsAdapter((MainActivity) getActivity(), itemAccess);
|
subscriptionAdapter.setOnSelectModeListener(this);
|
||||||
subscriptionGridLayout.setAdapter(subscriptionAdapter);
|
subscriptionRecycler.setAdapter(subscriptionAdapter);
|
||||||
subscriptionGridLayout.setOnItemClickListener(subscriptionAdapter);
|
|
||||||
setupEmptyView();
|
setupEmptyView();
|
||||||
|
|
||||||
subscriptionAddButton.setOnClickListener(view -> {
|
subscriptionAddButton.setOnClickListener(view -> {
|
||||||
if (getActivity() instanceof MainActivity) {
|
if (getActivity() instanceof MainActivity) {
|
||||||
((MainActivity) getActivity()).loadChildFragment(new AddFeedFragment());
|
((MainActivity) getActivity()).loadChildFragment(new AddFeedFragment());
|
||||||
@ -247,6 +276,10 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
if (disposable != null) {
|
if (disposable != null) {
|
||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subscriptionAdapter != null) {
|
||||||
|
subscriptionAdapter.endSelectMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSubscriptions() {
|
private void loadSubscriptions() {
|
||||||
@ -271,6 +304,7 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
.subscribe(
|
.subscribe(
|
||||||
result -> {
|
result -> {
|
||||||
listItems = result;
|
listItems = result;
|
||||||
|
subscriptionAdapter.setItems(result);
|
||||||
subscriptionAdapter.notifyDataSetChanged();
|
subscriptionAdapter.notifyDataSetChanged();
|
||||||
emptyView.updateVisibility();
|
emptyView.updateVisibility();
|
||||||
progressBar.setVisibility(View.GONE); // Keep hidden to avoid flickering while refreshing
|
progressBar.setVisibility(View.GONE); // Keep hidden to avoid flickering while refreshing
|
||||||
@ -292,34 +326,13 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
return getResources().getInteger(R.integer.subscriptions_default_num_of_columns);
|
return getResources().getInteger(R.integer.subscriptions_default_num_of_columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
|
||||||
super.onCreateContextMenu(menu, v, menuInfo);
|
|
||||||
if (menuInfo == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
|
||||||
int position = adapterInfo.position;
|
|
||||||
|
|
||||||
NavDrawerData.DrawerItem selectedObject = (NavDrawerData.DrawerItem) subscriptionAdapter.getItem(position);
|
|
||||||
|
|
||||||
if (selectedObject.type == NavDrawerData.DrawerItem.Type.FEED) {
|
|
||||||
MenuInflater inflater = requireActivity().getMenuInflater();
|
|
||||||
inflater.inflate(R.menu.nav_feed_context, menu);
|
|
||||||
selectedFeed = ((NavDrawerData.FeedDrawerItem) selectedObject).feed;
|
|
||||||
}
|
|
||||||
menu.setHeaderTitle(selectedObject.getTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem item) {
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
if (selectedFeed == null) {
|
Feed feed = subscriptionAdapter.getSelectedFeed();
|
||||||
|
if (feed == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int itemId = item.getItemId();
|
||||||
Feed feed = selectedFeed;
|
|
||||||
selectedFeed = null;
|
|
||||||
final int itemId = item.getItemId();
|
|
||||||
if (itemId == R.id.remove_all_new_flags_item) {
|
if (itemId == R.id.remove_all_new_flags_item) {
|
||||||
displayConfirmationDialog(
|
displayConfirmationDialog(
|
||||||
R.string.remove_all_new_flags_label,
|
R.string.remove_all_new_flags_label,
|
||||||
@ -335,6 +348,9 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
} else if (itemId == R.id.remove_item) {
|
} else if (itemId == R.id.remove_item) {
|
||||||
RemoveFeedDialog.show(getContext(), feed, null);
|
RemoveFeedDialog.show(getContext(), feed, null);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (itemId == R.id.multi_select) {
|
||||||
|
speedDialView.setVisibility(View.VISIBLE);
|
||||||
|
return subscriptionAdapter.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
return super.onContextItemSelected(item);
|
return super.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
@ -376,23 +392,23 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
|
|||||||
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
|
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
|
||||||
() -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
|
() -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
|
||||||
|
|
||||||
private final SubscriptionsAdapter.ItemAccess itemAccess = new SubscriptionsAdapter.ItemAccess() {
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public void onEndSelectMode() {
|
||||||
if (listItems != null) {
|
speedDialView.close();
|
||||||
return listItems.size();
|
speedDialView.setVisibility(View.GONE);
|
||||||
} else {
|
subscriptionAdapter.setItems(listItems);
|
||||||
return 0;
|
subscriptionAdapter.notifyDataSetChanged();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NavDrawerData.DrawerItem getItem(int position) {
|
public void onStartSelectMode() {
|
||||||
if (listItems != null && 0 <= position && position < listItems.size()) {
|
List<NavDrawerData.DrawerItem> feedsOnly = new ArrayList<>();
|
||||||
return listItems.get(position);
|
for (NavDrawerData.DrawerItem item : listItems) {
|
||||||
} else {
|
if (item.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||||
return null;
|
feedsOnly.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
subscriptionAdapter.setItems(feedsOnly);
|
||||||
|
subscriptionAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
package de.danoeh.antennapod.fragment.actions;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.PluralsRes;
|
||||||
|
import androidx.core.util.Consumer;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
|
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
|
||||||
|
import de.danoeh.antennapod.fragment.preferences.dialog.PreferenceListDialog;
|
||||||
|
import de.danoeh.antennapod.fragment.preferences.dialog.PreferenceSwitchDialog;
|
||||||
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
|
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||||
|
|
||||||
|
public class FeedMultiSelectActionHandler {
|
||||||
|
private static final String TAG = "FeedSelectHandler";
|
||||||
|
private final MainActivity activity;
|
||||||
|
private final List<Feed> selectedItems;
|
||||||
|
|
||||||
|
public FeedMultiSelectActionHandler(MainActivity activity, List<Feed> selectedItems) {
|
||||||
|
this.activity = activity;
|
||||||
|
this.selectedItems = selectedItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleAction(int id) {
|
||||||
|
if (id == R.id.remove_item) {
|
||||||
|
RemoveFeedDialog.show(activity, selectedItems, null);
|
||||||
|
} else if (id == R.id.keep_updated) {
|
||||||
|
keepUpdatedPrefHandler();
|
||||||
|
} else if (id == R.id.autodownload) {
|
||||||
|
autoDownloadPrefHandler();
|
||||||
|
} else if (id == R.id.autoDeleteDownload) {
|
||||||
|
autoDeleteEpisodesPrefHandler();
|
||||||
|
} else if (id == R.id.playback_speed) {
|
||||||
|
playbackSpeedPrefHandler();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Unrecognized speed dial action item. Do nothing. id=" + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void autoDownloadPrefHandler() {
|
||||||
|
PreferenceSwitchDialog preferenceSwitchDialog = new PreferenceSwitchDialog(activity,
|
||||||
|
activity.getString(R.string.auto_download_settings_label),
|
||||||
|
activity.getString(R.string.auto_download_label));
|
||||||
|
preferenceSwitchDialog.setOnPreferenceChangedListener(new PreferenceSwitchDialog.OnPreferenceChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void preferenceChanged(boolean enabled) {
|
||||||
|
saveFeedPreferences(feedPreferences -> feedPreferences.setAutoDownload(enabled));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
preferenceSwitchDialog.openDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final DecimalFormat SPEED_FORMAT =
|
||||||
|
new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.US));
|
||||||
|
|
||||||
|
private void playbackSpeedPrefHandler() {
|
||||||
|
final String[] speeds = activity.getResources().getStringArray(R.array.playback_speed_values);
|
||||||
|
String[] values = new String[speeds.length + 1];
|
||||||
|
values[0] = SPEED_FORMAT.format(FeedPreferences.SPEED_USE_GLOBAL);
|
||||||
|
|
||||||
|
String[] entries = new String[speeds.length + 1];
|
||||||
|
entries[0] = activity.getString(R.string.feed_auto_download_global);
|
||||||
|
|
||||||
|
System.arraycopy(speeds, 0, values, 1, speeds.length);
|
||||||
|
System.arraycopy(speeds, 0, entries, 1, speeds.length);
|
||||||
|
|
||||||
|
PreferenceListDialog preferenceListDialog = new PreferenceListDialog(activity,
|
||||||
|
activity.getString(R.string.playback_speed));
|
||||||
|
preferenceListDialog.openDialog(entries);
|
||||||
|
preferenceListDialog.setOnPreferenceChangedListener(pos -> {
|
||||||
|
saveFeedPreferences(feedPreferences -> {
|
||||||
|
feedPreferences.setFeedPlaybackSpeed(Float.parseFloat((String) values[pos]));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void autoDeleteEpisodesPrefHandler() {
|
||||||
|
PreferenceListDialog preferenceListDialog = new PreferenceListDialog(activity,
|
||||||
|
"Auto delete episodes");
|
||||||
|
String[] items = activity.getResources().getStringArray(R.array.spnAutoDeleteItems);
|
||||||
|
String[] values = activity.getResources().getStringArray(R.array.spnAutoDeleteValues);
|
||||||
|
preferenceListDialog.openDialog(items);
|
||||||
|
preferenceListDialog.setOnPreferenceChangedListener(which -> {
|
||||||
|
FeedPreferences.AutoDeleteAction autoDeleteAction = null;
|
||||||
|
switch (values[which]) {
|
||||||
|
case "global":
|
||||||
|
autoDeleteAction = FeedPreferences.AutoDeleteAction.GLOBAL;
|
||||||
|
break;
|
||||||
|
case "always":
|
||||||
|
autoDeleteAction = FeedPreferences.AutoDeleteAction.YES;
|
||||||
|
break;
|
||||||
|
case "never":
|
||||||
|
autoDeleteAction = FeedPreferences.AutoDeleteAction.NO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
FeedPreferences.AutoDeleteAction finalAutoDeleteAction = autoDeleteAction;
|
||||||
|
saveFeedPreferences(feedPreferences -> {
|
||||||
|
feedPreferences.setAutoDeleteAction(finalAutoDeleteAction);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void keepUpdatedPrefHandler() {
|
||||||
|
PreferenceSwitchDialog preferenceSwitchDialog = new PreferenceSwitchDialog(activity,
|
||||||
|
activity.getString(R.string.kept_updated),
|
||||||
|
activity.getString(R.string.keep_updated_summary));
|
||||||
|
preferenceSwitchDialog.setOnPreferenceChangedListener(keepUpdated -> {
|
||||||
|
saveFeedPreferences(feedPreferences -> {
|
||||||
|
feedPreferences.setKeepUpdated(keepUpdated);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
preferenceSwitchDialog.openDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showMessage(@PluralsRes int msgId, int numItems) {
|
||||||
|
activity.showSnackbarAbovePlayer(activity.getResources()
|
||||||
|
.getQuantityString(msgId, numItems, numItems), Snackbar.LENGTH_LONG);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveFeedPreferences(Consumer<FeedPreferences> preferencesConsumer) {
|
||||||
|
for (Feed feed : selectedItems) {
|
||||||
|
preferencesConsumer.accept(feed.getPreferences());
|
||||||
|
DBWriter.setFeedPreferences(feed.getPreferences());
|
||||||
|
}
|
||||||
|
showMessage(R.plurals.updated_feeds_batch_label, selectedItems.size());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package de.danoeh.antennapod.fragment.preferences.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
|
||||||
|
public class PreferenceListDialog {
|
||||||
|
protected Context context;
|
||||||
|
private String title;
|
||||||
|
private OnPreferenceChangedListener onPreferenceChangedListener;
|
||||||
|
private int selectedPos = 0;
|
||||||
|
|
||||||
|
public PreferenceListDialog(Context context, String title) {
|
||||||
|
this.context = context;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnPreferenceChangedListener {
|
||||||
|
/**
|
||||||
|
* Notified when user confirms preference
|
||||||
|
*
|
||||||
|
* @param pos The index of the item that was selected
|
||||||
|
*/
|
||||||
|
|
||||||
|
void preferenceChanged(int pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openDialog(String[] items) {
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle(title);
|
||||||
|
builder.setSingleChoiceItems(items, selectedPos, (dialog, which) -> {
|
||||||
|
selectedPos = which;
|
||||||
|
});
|
||||||
|
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||||
|
if (onPreferenceChangedListener != null && selectedPos >= 0) {
|
||||||
|
onPreferenceChangedListener.preferenceChanged(selectedPos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(R.string.cancel_label, null);
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnPreferenceChangedListener(OnPreferenceChangedListener onPreferenceChangedListener) {
|
||||||
|
this.onPreferenceChangedListener = onPreferenceChangedListener;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package de.danoeh.antennapod.fragment.preferences.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
|
||||||
|
public class PreferenceSwitchDialog {
|
||||||
|
protected Context context;
|
||||||
|
private String title;
|
||||||
|
private String text;
|
||||||
|
private OnPreferenceChangedListener onPreferenceChangedListener;
|
||||||
|
|
||||||
|
public PreferenceSwitchDialog(Context context, String title, String text) {
|
||||||
|
this.context = context;
|
||||||
|
this.title = title;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnPreferenceChangedListener {
|
||||||
|
/**
|
||||||
|
* Notified when user confirms preference
|
||||||
|
*
|
||||||
|
* @param enabled The preference
|
||||||
|
*/
|
||||||
|
|
||||||
|
void preferenceChanged(boolean enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openDialog() {
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle(title);
|
||||||
|
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(this.context);
|
||||||
|
View layout = inflater.inflate(R.layout.dialog_switch_preference, null, false);
|
||||||
|
SwitchCompat switchButton = layout.findViewById(R.id.dialogSwitch);
|
||||||
|
switchButton.setText(text);
|
||||||
|
builder.setView(layout);
|
||||||
|
|
||||||
|
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||||
|
if (onPreferenceChangedListener != null) {
|
||||||
|
onPreferenceChangedListener.preferenceChanged(switchButton.isChecked());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(R.string.cancel_label, null);
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnPreferenceChangedListener(OnPreferenceChangedListener onPreferenceChangedListener) {
|
||||||
|
this.onPreferenceChangedListener = onPreferenceChangedListener;
|
||||||
|
}
|
||||||
|
}
|
15
app/src/main/res/layout/dialog_switch_preference.xml
Normal file
15
app/src/main/res/layout/dialog_switch_preference.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
|
android:id="@+id/dialogSwitch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="Switch" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -1,19 +1,20 @@
|
|||||||
<?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
|
||||||
|
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"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<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/subscriptions_label"
|
app:title="@string/subscriptions_label"
|
||||||
app:navigationIcon="?homeAsUpIndicator"
|
app:navigationIcon="?homeAsUpIndicator" />
|
||||||
android:id="@+id/toolbar"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/feeds_filtered_message"
|
android:id="@+id/feeds_filtered_message"
|
||||||
@ -35,16 +36,13 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@id/feeds_filtered_message">
|
android:layout_below="@id/feeds_filtered_message">
|
||||||
|
|
||||||
<GridView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/subscriptions_grid"
|
android:id="@+id/subscriptions_grid"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:numColumns="3"
|
|
||||||
android:horizontalSpacing="2dp"
|
|
||||||
android:verticalSpacing="2dp"
|
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:paddingBottom="88dp"
|
android:paddingBottom="88dp"
|
||||||
android:clipToPadding="false"/>
|
android:clipToPadding="false" />
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
@ -54,7 +52,7 @@
|
|||||||
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="visible"/>
|
android:visibility="visible" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/subscriptions_add"
|
android:id="@+id/subscriptions_add"
|
||||||
@ -65,5 +63,9 @@
|
|||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:contentDescription="@string/add_feed_label"
|
android:contentDescription="@string/add_feed_label"
|
||||||
app:srcCompat="@drawable/ic_add"/>
|
app:srcCompat="@drawable/ic_add" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/multi_select_speed_dial" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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"
|
||||||
xmlns:squareImageView="http://schemas.android.com/apk/de.danoeh.antennapod"
|
xmlns:squareImageView="http://schemas.android.com/apk/de.danoeh.antennapod"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:foreground="?attr/selectableItemBackground">
|
android:foreground="?attr/selectableItemBackground">
|
||||||
|
|
||||||
<de.danoeh.antennapod.ui.common.SquareImageView
|
<de.danoeh.antennapod.ui.common.SquareImageView
|
||||||
@ -15,7 +15,7 @@
|
|||||||
android:background="@color/non_square_icon_background"
|
android:background="@color/non_square_icon_background"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
squareImageView:direction="width"
|
squareImageView:direction="width"
|
||||||
tools:src="@mipmap/ic_launcher_round" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<com.joanzapata.iconify.widget.IconTextView
|
<com.joanzapata.iconify.widget.IconTextView
|
||||||
android:id="@+id/txtvTitle"
|
android:id="@+id/txtvTitle"
|
||||||
@ -46,4 +46,20 @@
|
|||||||
app:primaryTextColor="?attr/colorOnSecondary"
|
app:primaryTextColor="?attr/colorOnSecondary"
|
||||||
app:primaryTextSize="12sp" />
|
app:primaryTextSize="12sp" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/selectView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/ic_checkbox_background">
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/selectCheckBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="0dp"
|
||||||
|
android:minHeight="0dp"
|
||||||
|
android:layout_margin="8dp" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
28
app/src/main/res/menu/nav_feed_action_speeddial.xml
Normal file
28
app/src/main/res/menu/nav_feed_action_speeddial.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/remove_item"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/remove_feed_label"
|
||||||
|
android:icon="@drawable/ic_delete"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/keep_updated"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/keep_updated"
|
||||||
|
android:icon="@drawable/ic_refresh"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/autodownload"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/auto_download_label"
|
||||||
|
android:icon="@drawable/ic_download"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/autoDeleteDownload"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/auto_delete_label"
|
||||||
|
android:icon="@drawable/ic_delete_auto"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/playback_speed"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/playback_speed"
|
||||||
|
android:icon="@drawable/ic_playback_speed"/>
|
||||||
|
</menu>
|
@ -21,4 +21,8 @@
|
|||||||
android:menuCategory="container"
|
android:menuCategory="container"
|
||||||
android:title="@string/remove_feed_label" />
|
android:title="@string/remove_feed_label" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/multi_select"
|
||||||
|
android:menuCategory="container"
|
||||||
|
android:title="@string/multi_select" />
|
||||||
</menu>
|
</menu>
|
||||||
|
10
core/src/main/res/drawable/ic_checkbox_background.xml
Normal file
10
core/src/main/res/drawable/ic_checkbox_background.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="56dp"
|
||||||
|
android:height="56dp"
|
||||||
|
android:viewportWidth="15.1"
|
||||||
|
android:viewportHeight="15.1">
|
||||||
|
<path
|
||||||
|
android:pathData="M-7.4167,3.2465a11.2253,11.8267 0,1 0,22.4506 0a11.2253,11.8267 0,1 0,-22.4506 0z"
|
||||||
|
android:strokeWidth="0"
|
||||||
|
android:fillColor="#BBFFFFFF"/>
|
||||||
|
</vector>
|
15
core/src/main/res/drawable/ic_delete_auto.xml
Normal file
15
core/src/main/res/drawable/ic_delete_auto.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M15,2l-3.5,0l-1,-1l-5,0l-1,1l-3.5,0l0,2l14,0z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M16,9c-0.7,0 -1.37,0.1 -2,0.29V5H2v12c0,1.1 0.9,2 2,2h5.68c1.12,2.36 3.53,4 6.32,4c3.87,0 7,-3.13 7,-7C23,12.13 19.87,9 16,9zM9,16c0,0.34 0.03,0.67 0.08,1H4V7h8v3.26C10.19,11.53 9,13.62 9,16zM16,21c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5s5,2.24 5,5S18.76,21 16,21z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M16.5,12l-1.5,0l0,5l3.6,2.1l0.8,-1.2l-2.9,-1.7z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
@ -171,6 +171,7 @@
|
|||||||
<string name="share_website_url_label">Website address</string>
|
<string name="share_website_url_label">Website address</string>
|
||||||
<string name="share_feed_url_label">Podcast feed URL</string>
|
<string name="share_feed_url_label">Podcast feed URL</string>
|
||||||
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete the podcast \"%1$s\" and ALL its episodes (including downloaded episodes).</string>
|
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete the podcast \"%1$s\" and ALL its episodes (including downloaded episodes).</string>
|
||||||
|
<string name="feed_delete_confirmation_msg_batch">Please confirm that you want to remove the selected podcasts and ALL their episodes (including downloaded episodes).</string>
|
||||||
<string name="feed_delete_confirmation_local_msg">Please confirm that you want to remove the podcast \"%1$s\". The files in the local source folder will not be deleted.</string>
|
<string name="feed_delete_confirmation_local_msg">Please confirm that you want to remove the podcast \"%1$s\". The files in the local source folder will not be deleted.</string>
|
||||||
<string name="feed_remover_msg">Removing podcast</string>
|
<string name="feed_remover_msg">Removing podcast</string>
|
||||||
<string name="load_complete_feed">Refresh complete podcast</string>
|
<string name="load_complete_feed">Refresh complete podcast</string>
|
||||||
@ -182,6 +183,10 @@
|
|||||||
<string name="open_podcast">Open Podcast</string>
|
<string name="open_podcast">Open Podcast</string>
|
||||||
<string name="please_wait_for_data">Please wait until the data is loaded</string>
|
<string name="please_wait_for_data">Please wait until the data is loaded</string>
|
||||||
<string name="updates_disabled_label">Updates disabled</string>
|
<string name="updates_disabled_label">Updates disabled</string>
|
||||||
|
<plurals name="updated_feeds_batch_label">
|
||||||
|
<item quantity="one">%d subscription updated.</item>
|
||||||
|
<item quantity="other">%d subscriptions updated.</item>
|
||||||
|
</plurals>
|
||||||
<string name="add_to_folder">Add to folder</string>
|
<string name="add_to_folder">Add to folder</string>
|
||||||
|
|
||||||
<!-- actions on feeditems -->
|
<!-- actions on feeditems -->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user