Merge pull request #3437 from orionlee/easier_remove_new_flag_3302
Support remove new flag in Podcast screen and Podcast Episode Screen
This commit is contained in:
commit
c4f92881b1
@ -262,7 +262,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
FeedItem item = itemAccess.getItem(getAdapterPosition());
|
||||
|
||||
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
|
||||
inflater.inflate(R.menu.allepisodes_context, menu);
|
||||
inflater.inflate(R.menu.feeditemlist_context, menu);
|
||||
|
||||
if (item != null) {
|
||||
menu.setHeaderTitle(item.getTitle());
|
||||
@ -278,8 +278,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
}
|
||||
};
|
||||
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
|
||||
|
||||
contextMenuInterface.setItemVisibility(R.id.remove_new_flag_item, item.isNew());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,9 +4,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@ -23,8 +21,16 @@ import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
|
||||
@ -35,19 +41,15 @@ import de.danoeh.antennapod.core.event.FeedItemEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedItemFilter;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
import de.danoeh.antennapod.dialog.FilterDialog;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||
@ -55,13 +57,6 @@ import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
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.Set;
|
||||
|
||||
/**
|
||||
* Shows unread or recently published episodes
|
||||
@ -262,17 +257,7 @@ public abstract class EpisodesListFragment extends Fragment {
|
||||
}
|
||||
FeedItem selectedItem = listAdapter.getSelectedItem();
|
||||
|
||||
// Remove new flag contains UI logic specific to All/New/FavoriteSegments,
|
||||
// e.g., Undo with Snackbar,
|
||||
// and is handled by this class rather than the generic FeedItemMenuHandler
|
||||
// Undo is useful for Remove new flag, given there is no UI to undo it otherwise,
|
||||
// i.e., there is context menu item for Mark as new
|
||||
if (R.id.remove_new_flag_item == item.getItemId()) {
|
||||
removeNewFlagWithUndo(selectedItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
|
||||
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -453,36 +438,4 @@ public abstract class EpisodesListFragment extends Fragment {
|
||||
|
||||
@NonNull
|
||||
protected abstract List<FeedItem> loadData();
|
||||
|
||||
void removeNewFlagWithUndo(FeedItem item) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "removeNewFlagWithUndo(" + item.getId() + ")");
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
// we're marking it as unplayed since the user didn't actually play it
|
||||
// but they don't want it considered 'NEW' anymore
|
||||
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
|
||||
|
||||
final Handler h = new Handler(getActivity().getMainLooper());
|
||||
final Runnable r = () -> {
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
|
||||
DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
|
||||
}
|
||||
};
|
||||
|
||||
Snackbar snackbar = Snackbar.make(getView(), getString(R.string.removed_new_flag_label),
|
||||
Snackbar.LENGTH_LONG);
|
||||
snackbar.setAction(getString(R.string.undo), v -> {
|
||||
DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
|
||||
// don't forget to cancel the thing that's going to remove the media
|
||||
h.removeCallbacks(r);
|
||||
});
|
||||
snackbar.show();
|
||||
h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
|
||||
}
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ public class FeedItemlistFragment extends ListFragment {
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
|
||||
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,7 +55,6 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
@ -351,7 +350,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
|
||||
openPodcast();
|
||||
return true;
|
||||
default:
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
|
||||
return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.getItemId(), item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@ -16,6 +15,7 @@ import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
|
||||
/**
|
||||
* Like 'EpisodesFragment' except that it only shows new episodes and
|
||||
@ -63,7 +63,7 @@ public class NewEpisodesFragment extends EpisodesListFragment {
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
|
||||
AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
|
||||
removeNewFlagWithUndo(holder.getFeedItem());
|
||||
FeedItemMenuHandler.removeNewFlagWithUndo(NewEpisodesFragment.this, holder.getFeedItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,12 +21,15 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
@ -56,15 +59,11 @@ import de.danoeh.antennapod.core.util.SortOrder;
|
||||
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
|
||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
|
||||
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_REMOVE_FROM_QUEUE;
|
||||
@ -464,7 +463,7 @@ public class QueueFragment extends Fragment {
|
||||
DBWriter.moveQueueItemToBottom(selectedItem.getId(), true);
|
||||
return true;
|
||||
default:
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
|
||||
return FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,11 @@ package de.danoeh.antennapod.menuhandler;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -104,6 +108,7 @@ public class FeedItemMenuHandler {
|
||||
boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists();
|
||||
mi.setItemVisibility(R.id.share_file, fileDownloaded);
|
||||
|
||||
mi.setItemVisibility(R.id.remove_new_flag_item, selectedItem.isNew());
|
||||
if (selectedItem.isPlayed()) {
|
||||
mi.setItemVisibility(R.id.mark_read_item, false);
|
||||
} else {
|
||||
@ -153,8 +158,16 @@ public class FeedItemMenuHandler {
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static boolean onMenuItemClicked(Context context, int menuItemId,
|
||||
FeedItem selectedItem) {
|
||||
/**
|
||||
* Default menu handling for the given FeedItem.
|
||||
*
|
||||
* A Fragment instance, (rather than the more generic Context), is needed as a parameter
|
||||
* to support some UI operations, e.g., creating a Snackbar.
|
||||
*/
|
||||
public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItemId,
|
||||
@NonNull FeedItem selectedItem) {
|
||||
|
||||
@NonNull Context context = fragment.requireContext();
|
||||
switch (menuItemId) {
|
||||
case R.id.skip_episode_item:
|
||||
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
|
||||
@ -162,6 +175,9 @@ public class FeedItemMenuHandler {
|
||||
case R.id.remove_item:
|
||||
DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId());
|
||||
break;
|
||||
case R.id.remove_new_flag_item:
|
||||
removeNewFlagWithUndo(fragment, selectedItem);
|
||||
break;
|
||||
case R.id.mark_read_item:
|
||||
selectedItem.setPlayed(true);
|
||||
DBWriter.markItemPlayed(selectedItem, FeedItem.PLAYED, false);
|
||||
@ -249,4 +265,39 @@ public class FeedItemMenuHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove new flag with additional UI logic to allow undo with Snackbar.
|
||||
*
|
||||
* Undo is useful for Remove new flag, given there is no UI to undo it otherwise
|
||||
* ,i.e., there is (context) menu item for add new flag
|
||||
*/
|
||||
public static void removeNewFlagWithUndo(@NonNull Fragment fragment, FeedItem item) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "removeNewFlagWithUndo(" + item.getId() + ")");
|
||||
// we're marking it as unplayed since the user didn't actually play it
|
||||
// but they don't want it considered 'NEW' anymore
|
||||
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
|
||||
|
||||
final Handler h = new Handler(fragment.requireContext().getMainLooper());
|
||||
final Runnable r = () -> {
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
|
||||
DBWriter.deleteFeedMediaOfItem(fragment.requireContext(), media.getId());
|
||||
}
|
||||
};
|
||||
|
||||
Snackbar snackbar = Snackbar.make(fragment.getView(), fragment.getString(R.string.removed_new_flag_label),
|
||||
Snackbar.LENGTH_LONG);
|
||||
snackbar.setAction(fragment.getString(R.string.undo), v -> {
|
||||
DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
|
||||
// don't forget to cancel the thing that's going to remove the media
|
||||
h.removeCallbacks(r);
|
||||
});
|
||||
snackbar.show();
|
||||
h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@id/skip_episode_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/skip_episode_label" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/remove_new_flag_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/remove_new_flag_label" />
|
||||
|
||||
<item
|
||||
android:id="@+id/mark_read_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/mark_read_label" />
|
||||
<item
|
||||
android:id="@+id/mark_unread_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/mark_unread_label" />
|
||||
|
||||
<item
|
||||
android:id="@+id/add_to_queue_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/add_to_queue_label" />
|
||||
<item
|
||||
android:id="@+id/remove_from_queue_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/remove_from_queue_label" />
|
||||
<item
|
||||
android:id="@+id/add_to_favorites_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/add_to_favorite_label" />
|
||||
<item
|
||||
android:id="@+id/remove_from_favorites_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/remove_from_favorite_label" />
|
||||
<item
|
||||
android:id="@+id/reset_position"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/reset_position" />
|
||||
|
||||
<item
|
||||
android:id="@+id/activate_auto_download"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/activate_auto_download" />
|
||||
<item
|
||||
android:id="@+id/deactivate_auto_download"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/deactivate_auto_download" />
|
||||
|
||||
<item
|
||||
android:id="@+id/visit_website_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/visit_website_label" />
|
||||
<item
|
||||
android:id="@+id/share_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/share_label">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/share_link_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/share_link_label" />
|
||||
<item
|
||||
android:id="@+id/share_link_with_position_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/share_link_with_position_label" />
|
||||
<item
|
||||
android:id="@+id/share_download_url_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/share_item_url_label" />
|
||||
<item
|
||||
android:id="@+id/share_download_url_with_position_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/share_item_url_with_position_label" />
|
||||
<item
|
||||
android:id="@+id/share_file"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/share_file_label" />
|
||||
</menu>
|
||||
</item>
|
||||
</menu>
|
@ -8,6 +8,11 @@
|
||||
custom:showAsAction="collapseActionView">
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/remove_new_flag_item"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/remove_new_flag_label" />
|
||||
|
||||
<item
|
||||
android:id="@+id/mark_read_item"
|
||||
custom:showAsAction="collapseActionView"
|
||||
|
@ -7,6 +7,11 @@
|
||||
android:menuCategory="container"
|
||||
android:title="@string/skip_episode_label" />
|
||||
|
||||
<item
|
||||
android:id="@+id/remove_new_flag_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/remove_new_flag_label" />
|
||||
|
||||
<item
|
||||
android:id="@+id/mark_read_item"
|
||||
android:menuCategory="container"
|
||||
|
Loading…
x
Reference in New Issue
Block a user