summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java398
1 files changed, 398 insertions, 0 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
new file mode 100644
index 000000000..4101ee46d
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java
@@ -0,0 +1,398 @@
+package de.danoeh.antennapod.fragment;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+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.ListView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.activity.PreferenceActivity;
+import de.danoeh.antennapod.adapter.NavListAdapter;
+import de.danoeh.antennapod.core.asynctask.FeedRemover;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
+import de.danoeh.antennapod.core.event.QueueEvent;
+import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.playback.PlaybackService;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.dialog.RenameFeedDialog;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+import org.apache.commons.lang3.StringUtils;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+
+import java.util.List;
+
+public class NavDrawerFragment extends Fragment implements AdapterView.OnItemClickListener,
+ AdapterView.OnItemLongClickListener {
+ private static final String PREF_LAST_FRAGMENT_TAG = "prefLastFragmentTag";
+ private static final String PREF_NAME = "NavDrawerPrefs";
+ public static final String TAG = "NavDrawerFragment";
+
+ public static final String[] NAV_DRAWER_TAGS = {
+ QueueFragment.TAG,
+ EpisodesFragment.TAG,
+ SubscriptionFragment.TAG,
+ DownloadsFragment.TAG,
+ PlaybackHistoryFragment.TAG,
+ AddFeedFragment.TAG,
+ NavListAdapter.SUBSCRIPTION_LIST_TAG
+ };
+
+ private DBReader.NavDrawerData navDrawerData;
+ private int selectedNavListIndex = -1;
+ private int position = -1;
+ private NavListAdapter navAdapter;
+ private Disposable disposable;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ View root = inflater.inflate(R.layout.nav_list, container, false);
+
+ ListView navList = root.findViewById(R.id.nav_list);
+ navAdapter = new NavListAdapter(itemAccess, getActivity());
+ navList.setAdapter(navAdapter);
+ navList.setOnItemClickListener(this);
+ navList.setOnItemLongClickListener(this);
+ registerForContextMenu(navList);
+ updateSelection();
+
+ root.findViewById(R.id.nav_settings).setOnClickListener(v -> {
+ startActivity(new Intent(getActivity(), PreferenceActivity.class));
+ });
+ return root;
+ }
+
+ private void updateSelection() {
+ String lastNavFragment = getLastNavFragment(getContext());
+ int tagIndex = navAdapter.getTags().indexOf(lastNavFragment);
+ if (tagIndex >= 0) {
+ selectedNavListIndex = tagIndex;
+ } else if (StringUtils.isNumeric(lastNavFragment)) { // last fragment was not a list, but a feed
+ long feedId = Long.parseLong(lastNavFragment);
+ if (navDrawerData != null) {
+ List<Feed> feeds = navDrawerData.feeds;
+ for (int i = 0; i < feeds.size(); i++) {
+ if (feeds.get(i).getId() == feedId) {
+ selectedNavListIndex = navAdapter.getSubscriptionOffset() + i;
+ break;
+ }
+ }
+ }
+ }
+ navAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ EventBus.getDefault().register(this);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ EventBus.getDefault().unregister(this);
+ if (disposable != null) {
+ disposable.dispose();
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(@NonNull ContextMenu menu, @NonNull View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ if (v.getId() != R.id.nav_list) {
+ return;
+ }
+ AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ int position = adapterInfo.position;
+ if (position < navAdapter.getSubscriptionOffset()) {
+ return;
+ }
+ MenuInflater inflater = getActivity().getMenuInflater();
+ inflater.inflate(R.menu.nav_feed_context, menu);
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ menu.setHeaderTitle(feed.getTitle());
+ // episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
+ }
+
+ @Override
+ public boolean onContextItemSelected(@NonNull MenuItem item) {
+ final int position = this.position;
+ this.position = -1; // reset
+ if (position < 0) {
+ return false;
+ }
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ switch (item.getItemId()) {
+ case R.id.remove_all_new_flags_item:
+ ConfirmationDialog removeAllNewFlagsConfirmationDialog = new ConfirmationDialog(getContext(),
+ R.string.remove_all_new_flags_label,
+ R.string.remove_all_new_flags_confirmation_msg) {
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.removeFeedNewFlag(feed.getId());
+ }
+ };
+ removeAllNewFlagsConfirmationDialog.createNewDialog().show();
+ return true;
+ case R.id.mark_all_read_item:
+ ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getContext(),
+ R.string.mark_all_read_label,
+ R.string.mark_all_read_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.markFeedRead(feed.getId());
+ }
+ };
+ markAllReadConfirmationDialog.createNewDialog().show();
+ return true;
+ case R.id.rename_item:
+ new RenameFeedDialog(getActivity(), feed).show();
+ return true;
+ case R.id.remove_item:
+ final FeedRemover remover = new FeedRemover(getContext(), feed) {
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ if (selectedNavListIndex == position) {
+ ((MainActivity) getActivity()).loadFragment(EpisodesFragment.TAG, null);
+ saveLastNavFragment(EpisodesFragment.TAG);
+ }
+ }
+ };
+ ConfirmationDialog conDialog = new ConfirmationDialog(getContext(),
+ R.string.remove_feed_label,
+ getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ long mediaId = PlaybackPreferences.getCurrentlyPlayingFeedMediaId();
+ if (mediaId > 0 && FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId) >= 0) {
+ Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
+ remover.skipOnCompletion = true;
+ int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
+ if (playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
+ IntentUtils.sendLocalBroadcast(getContext(),
+ PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
+ }
+ }
+ remover.executeAsync();
+ }
+ };
+ conDialog.createNewDialog().show();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ @Subscribe
+ public void onUnreadItemsChanged(UnreadItemsUpdateEvent event) {
+ loadData();
+ }
+
+
+ @Subscribe
+ public void onFeedListChanged(FeedListUpdateEvent event) {
+ loadData();
+ }
+
+ @Subscribe
+ public void onQueueChanged(QueueEvent event) {
+ Log.d(TAG, "onQueueChanged(" + event + ")");
+ // we are only interested in the number of queue items, not download status or position
+ if (event.action == QueueEvent.Action.DELETED_MEDIA
+ || event.action == QueueEvent.Action.SORTED
+ || event.action == QueueEvent.Action.MOVED) {
+ return;
+ }
+ loadData();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ loadData();
+ }
+
+ private void showDrawerPreferencesDialog() {
+ final List<String> hiddenDrawerItems = UserPreferences.getHiddenDrawerItems();
+ String[] navLabels = new String[NAV_DRAWER_TAGS.length];
+ final boolean[] checked = new boolean[NAV_DRAWER_TAGS.length];
+ for (int i = 0; i < NAV_DRAWER_TAGS.length; i++) {
+ String tag = NAV_DRAWER_TAGS[i];
+ navLabels[i] = navAdapter.getLabel(tag);
+ if (!hiddenDrawerItems.contains(tag)) {
+ checked[i] = true;
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle(R.string.drawer_preferences);
+ builder.setMultiChoiceItems(navLabels, checked, (dialog, which, isChecked) -> {
+ if (isChecked) {
+ hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]);
+ } else {
+ hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
+ }
+ });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
+ updateSelection();
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.create().show();
+ }
+
+ private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
+ @Override
+ public int getCount() {
+ if (navDrawerData != null) {
+ return navDrawerData.feeds.size();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public Feed getItem(int position) {
+ if (navDrawerData != null && 0 <= position && position < navDrawerData.feeds.size()) {
+ return navDrawerData.feeds.get(position);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public int getSelectedItemIndex() {
+ return selectedNavListIndex;
+ }
+
+ @Override
+ public int getQueueSize() {
+ return (navDrawerData != null) ? navDrawerData.queueSize : 0;
+ }
+
+ @Override
+ public int getNumberOfNewItems() {
+ return (navDrawerData != null) ? navDrawerData.numNewItems : 0;
+ }
+
+ @Override
+ public int getNumberOfDownloadedItems() {
+ return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0;
+ }
+
+ @Override
+ public int getReclaimableItems() {
+ return (navDrawerData != null) ? navDrawerData.reclaimableSpace : 0;
+ }
+
+ @Override
+ public int getFeedCounter(long feedId) {
+ return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
+ }
+
+ @Override
+ public int getFeedCounterSum() {
+ if (navDrawerData == null) {
+ return 0;
+ }
+ int sum = 0;
+ for (int counter : navDrawerData.feedCounters.values()) {
+ sum += counter;
+ }
+ return sum;
+ }
+
+ };
+
+ private void loadData() {
+ disposable = Observable.fromCallable(DBReader::getNavDrawerData)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ navDrawerData = result;
+ updateSelection(); // Selected item might be a feed
+ navAdapter.notifyDataSetChanged();
+ }, error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ int viewType = parent.getAdapter().getItemViewType(position);
+ if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER) {
+ if (position < navAdapter.getSubscriptionOffset()) {
+ String tag = navAdapter.getTags().get(position);
+ ((MainActivity) getActivity()).loadFragment(tag, null);
+ saveLastNavFragment(tag);
+ } else {
+ int pos = position - navAdapter.getSubscriptionOffset();
+ long feedId = navDrawerData.feeds.get(pos).getId();
+ ((MainActivity) getActivity()).loadFeedFragmentById(feedId, null);
+ saveLastNavFragment(String.valueOf(feedId));
+ }
+ selectedNavListIndex = position;
+ navAdapter.notifyDataSetChanged();
+ }
+ }
+
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+ if (position < navAdapter.getTags().size()) {
+ showDrawerPreferencesDialog();
+ return true;
+ } else {
+ this.position = position;
+ return false;
+ }
+ }
+
+ private void saveLastNavFragment(String tag) {
+ Log.d(TAG, "saveLastNavFragment(tag: " + tag + ")");
+ SharedPreferences prefs = getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = prefs.edit();
+ if (tag != null) {
+ edit.putString(PREF_LAST_FRAGMENT_TAG, tag);
+ } else {
+ edit.remove(PREF_LAST_FRAGMENT_TAG);
+ }
+ edit.apply();
+ }
+
+ public static String getLastNavFragment(Context context) {
+ SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+ String lastFragment = prefs.getString(PREF_LAST_FRAGMENT_TAG, QueueFragment.TAG);
+ Log.d(TAG, "getLastNavFragment() -> " + lastFragment);
+ return lastFragment;
+ }
+}