Add long press menu to search results in subscriptions list (#6267)
This commit is contained in:
parent
e261514c5b
commit
f9e344e215
|
@ -16,10 +16,17 @@ import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFeedListAdapter.Holder> {
|
import android.view.ContextMenu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFeedListAdapter.Holder>
|
||||||
|
implements View.OnCreateContextMenuListener {
|
||||||
private final WeakReference<MainActivity> mainActivityRef;
|
private final WeakReference<MainActivity> mainActivityRef;
|
||||||
private final List<Feed> data = new ArrayList<>();
|
private final List<Feed> data = new ArrayList<>();
|
||||||
private int dummyViews = 0;
|
private int dummyViews = 0;
|
||||||
|
private Feed longPressedItem;
|
||||||
|
|
||||||
|
|
||||||
public HorizontalFeedListAdapter(MainActivity mainActivity) {
|
public HorizontalFeedListAdapter(MainActivity mainActivity) {
|
||||||
this.mainActivityRef = new WeakReference<>(mainActivity);
|
this.mainActivityRef = new WeakReference<>(mainActivity);
|
||||||
|
@ -57,6 +64,13 @@ public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFe
|
||||||
holder.imageView.setOnClickListener(v ->
|
holder.imageView.setOnClickListener(v ->
|
||||||
mainActivityRef.get().loadChildFragment(FeedItemlistFragment.newInstance(podcast.getId())));
|
mainActivityRef.get().loadChildFragment(FeedItemlistFragment.newInstance(podcast.getId())));
|
||||||
|
|
||||||
|
holder.imageView.setOnCreateContextMenuListener(this);
|
||||||
|
holder.imageView.setOnLongClickListener(v -> {
|
||||||
|
int currentItemPosition = holder.getBindingAdapterPosition();
|
||||||
|
longPressedItem = data.get(currentItemPosition);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
Glide.with(mainActivityRef.get())
|
Glide.with(mainActivityRef.get())
|
||||||
.load(podcast.getImageUrl())
|
.load(podcast.getImageUrl())
|
||||||
.apply(new RequestOptions()
|
.apply(new RequestOptions()
|
||||||
|
@ -66,6 +80,11 @@ public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFe
|
||||||
.into(holder.imageView);
|
.into(holder.imageView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Feed getLongPressedItem() {
|
||||||
|
return longPressedItem;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
if (position >= data.size()) {
|
if (position >= data.size()) {
|
||||||
|
@ -79,6 +98,16 @@ public class HorizontalFeedListAdapter extends RecyclerView.Adapter<HorizontalFe
|
||||||
return dummyViews + data.size();
|
return dummyViews + data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
|
||||||
|
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
|
||||||
|
if (longPressedItem == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inflater.inflate(R.menu.nav_feed_context, contextMenu);
|
||||||
|
contextMenu.setHeaderTitle(longPressedItem.getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
static class Holder extends RecyclerView.ViewHolder {
|
static class Holder extends RecyclerView.ViewHolder {
|
||||||
SquareImageView imageView;
|
SquareImageView imageView;
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,9 @@ import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||||
|
import de.danoeh.antennapod.event.FeedListUpdateEvent;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a search operation on all feeds or one specific feed and displays the search result.
|
* Performs a search operation on all feeds or one specific feed and displays the search result.
|
||||||
|
@ -132,6 +135,7 @@ public class SearchFragment extends Fragment {
|
||||||
|
|
||||||
recyclerView = layout.findViewById(R.id.recyclerView);
|
recyclerView = layout.findViewById(R.id.recyclerView);
|
||||||
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
|
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
|
||||||
|
registerForContextMenu(recyclerView);
|
||||||
adapter = new EpisodeItemListAdapter((MainActivity) getActivity()) {
|
adapter = new EpisodeItemListAdapter((MainActivity) getActivity()) {
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
@ -146,7 +150,14 @@ public class SearchFragment extends Fragment {
|
||||||
LinearLayoutManager layoutManagerFeeds = new LinearLayoutManager(getActivity());
|
LinearLayoutManager layoutManagerFeeds = new LinearLayoutManager(getActivity());
|
||||||
layoutManagerFeeds.setOrientation(RecyclerView.HORIZONTAL);
|
layoutManagerFeeds.setOrientation(RecyclerView.HORIZONTAL);
|
||||||
recyclerViewFeeds.setLayoutManager(layoutManagerFeeds);
|
recyclerViewFeeds.setLayoutManager(layoutManagerFeeds);
|
||||||
adapterFeeds = new HorizontalFeedListAdapter((MainActivity) getActivity());
|
adapterFeeds = new HorizontalFeedListAdapter((MainActivity) getActivity()) {
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu contextMenu, View view,
|
||||||
|
ContextMenu.ContextMenuInfo contextMenuInfo) {
|
||||||
|
super.onCreateContextMenu(contextMenu, view, contextMenuInfo);
|
||||||
|
MenuItemUtils.setOnClickListeners(contextMenu, SearchFragment.this::onContextItemSelected);
|
||||||
|
}
|
||||||
|
};
|
||||||
recyclerViewFeeds.setAdapter(adapterFeeds);
|
recyclerViewFeeds.setAdapter(adapterFeeds);
|
||||||
|
|
||||||
emptyViewHandler = new EmptyViewHandler(getContext());
|
emptyViewHandler = new EmptyViewHandler(getContext());
|
||||||
|
@ -241,12 +252,21 @@ public class SearchFragment extends Fragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||||
FeedItem selectedItem = adapter.getLongPressedItem();
|
Feed selectedFeedItem = adapterFeeds.getLongPressedItem();
|
||||||
if (selectedItem == null) {
|
if (selectedFeedItem != null
|
||||||
Log.i(TAG, "Selected item at current position was null, ignoring selection");
|
&& FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedFeedItem, () -> { })) {
|
||||||
return super.onContextItemSelected(item);
|
return true;
|
||||||
}
|
}
|
||||||
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
FeedItem selectedItem = adapter.getLongPressedItem();
|
||||||
|
if (selectedItem != null && FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onContextItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
public void onFeedListChanged(FeedListUpdateEvent event) {
|
||||||
|
search();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package de.danoeh.antennapod.fragment;
|
package de.danoeh.antennapod.fragment;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
@ -17,7 +15,6 @@ import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
@ -28,7 +25,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.joanzapata.iconify.Iconify;
|
import com.joanzapata.iconify.Iconify;
|
||||||
import com.leinardi.android.speeddial.SpeedDialView;
|
import com.leinardi.android.speeddial.SpeedDialView;
|
||||||
|
|
||||||
import de.danoeh.antennapod.dialog.TagSettingsDialog;
|
|
||||||
import de.danoeh.antennapod.ui.statistics.StatisticsFragment;
|
import de.danoeh.antennapod.ui.statistics.StatisticsFragment;
|
||||||
import de.danoeh.antennapod.view.LiftOnScrollListener;
|
import de.danoeh.antennapod.view.LiftOnScrollListener;
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
@ -36,15 +32,12 @@ import org.greenrobot.eventbus.Subscribe;
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
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.SubscriptionsRecyclerAdapter;
|
import de.danoeh.antennapod.adapter.SubscriptionsRecyclerAdapter;
|
||||||
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.event.FeedListUpdateEvent;
|
import de.danoeh.antennapod.event.FeedListUpdateEvent;
|
||||||
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
|
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
|
||||||
|
@ -52,16 +45,15 @@ import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
|
||||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
import de.danoeh.antennapod.storage.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;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
|
||||||
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.FeedSortDialog;
|
import de.danoeh.antennapod.dialog.FeedSortDialog;
|
||||||
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
|
|
||||||
import de.danoeh.antennapod.dialog.RenameItemDialog;
|
import de.danoeh.antennapod.dialog.RenameItemDialog;
|
||||||
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
|
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
|
||||||
import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler;
|
import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler;
|
||||||
import de.danoeh.antennapod.model.feed.Feed;
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
|
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||||
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;
|
||||||
|
@ -350,43 +342,11 @@ public class SubscriptionFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||||
if (itemId == R.id.remove_all_inbox_item) {
|
if (itemId == R.id.multi_select) {
|
||||||
displayConfirmationDialog(
|
|
||||||
R.string.remove_all_inbox_label,
|
|
||||||
R.string.remove_all_inbox_confirmation_msg,
|
|
||||||
() -> DBWriter.removeFeedNewFlag(feed.getId()));
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.edit_tags) {
|
|
||||||
TagSettingsDialog.newInstance(Collections.singletonList(feed.getPreferences()))
|
|
||||||
.show(getChildFragmentManager(), TagSettingsDialog.TAG);
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.rename_item) {
|
|
||||||
new RenameItemDialog(getActivity(), feed).show();
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.remove_feed) {
|
|
||||||
RemoveFeedDialog.show(getContext(), feed);
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.multi_select) {
|
|
||||||
speedDialView.setVisibility(View.VISIBLE);
|
speedDialView.setVisibility(View.VISIBLE);
|
||||||
return subscriptionAdapter.onContextItemSelected(item);
|
return subscriptionAdapter.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
return super.onContextItemSelected(item);
|
return FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), feed, this::loadSubscriptions);
|
||||||
}
|
|
||||||
|
|
||||||
private <T> void displayConfirmationDialog(@StringRes int title, @StringRes int message, Callable<? extends T> task) {
|
|
||||||
ConfirmationDialog dialog = new ConfirmationDialog(getActivity(), title, message) {
|
|
||||||
@Override
|
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
public void onConfirmButtonPressed(DialogInterface clickedDialog) {
|
|
||||||
clickedDialog.dismiss();
|
|
||||||
Observable.fromCallable(task)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(result -> loadSubscriptions(),
|
|
||||||
error -> Log.e(TAG, Log.getStackTraceString(error)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dialog.createNewDialog().show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
|
|
@ -14,6 +14,19 @@ import de.danoeh.antennapod.dialog.IntraFeedSortDialog;
|
||||||
import de.danoeh.antennapod.model.feed.Feed;
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
import de.danoeh.antennapod.model.feed.SortOrder;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||||
|
import de.danoeh.antennapod.dialog.RemoveFeedDialog;
|
||||||
|
import de.danoeh.antennapod.dialog.RenameItemDialog;
|
||||||
|
import de.danoeh.antennapod.dialog.TagSettingsDialog;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles interactions with the FeedItemMenu.
|
* Handles interactions with the FeedItemMenu.
|
||||||
|
@ -75,4 +88,38 @@ public class FeedMenuHandler {
|
||||||
sortDialog.openDialog();
|
sortDialog.openDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItemId,
|
||||||
|
@NonNull Feed selectedFeed, Runnable callback) {
|
||||||
|
@NonNull Context context = fragment.requireContext();
|
||||||
|
if (menuItemId == R.id.rename_folder_item) {
|
||||||
|
new RenameItemDialog(fragment.getActivity(), selectedFeed).show();
|
||||||
|
} else if (menuItemId == R.id.remove_all_inbox_item) {
|
||||||
|
ConfirmationDialog dialog = new ConfirmationDialog(fragment.getActivity(),
|
||||||
|
R.string.remove_all_inbox_label, R.string.remove_all_inbox_confirmation_msg) {
|
||||||
|
@Override
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
public void onConfirmButtonPressed(DialogInterface clickedDialog) {
|
||||||
|
clickedDialog.dismiss();
|
||||||
|
Observable.fromCallable((Callable<Future>) () -> DBWriter.removeFeedNewFlag(selectedFeed.getId()))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> callback.run(),
|
||||||
|
error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dialog.createNewDialog().show();
|
||||||
|
|
||||||
|
} else if (menuItemId == R.id.edit_tags) {
|
||||||
|
TagSettingsDialog.newInstance(Collections.singletonList(selectedFeed.getPreferences()))
|
||||||
|
.show(fragment.getChildFragmentManager(), TagSettingsDialog.TAG);
|
||||||
|
} else if (menuItemId == R.id.rename_item) {
|
||||||
|
new RenameItemDialog(fragment.getActivity(), selectedFeed).show();
|
||||||
|
} else if (menuItemId == R.id.remove_feed) {
|
||||||
|
RemoveFeedDialog.show(context, selectedFeed);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue