diff options
author | Tom Hennen <TomHennen@users.noreply.github.com> | 2015-06-28 16:27:41 -0400 |
---|---|---|
committer | Tom Hennen <TomHennen@users.noreply.github.com> | 2015-06-28 16:27:41 -0400 |
commit | cff363e474d5527a18a05cec0ce81fcb05be2d3c (patch) | |
tree | 2f7b8dc044e0022caf9214238d60552964c92b8e | |
parent | acd62a799df0965df666d839e707a5b2ca81e6e7 (diff) | |
parent | c7256d8152cf062c8e608b87e62f645ef2c72642 (diff) | |
download | AntennaPod-cff363e474d5527a18a05cec0ce81fcb05be2d3c.zip |
Merge pull request #974 from mfietz/feature/episodes-actions
Perform action on episodes
9 files changed, 669 insertions, 22 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java new file mode 100644 index 000000000..1ca5b831c --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -0,0 +1,416 @@ +package de.danoeh.antennapod.dialog; + +import android.content.res.TypedArray; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.Toast; + +import com.joanzapata.android.iconify.IconDrawable; +import com.joanzapata.android.iconify.Iconify; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.storage.DBTasks; +import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.DownloadRequestException; +import de.danoeh.antennapod.core.util.LongList; + +public class EpisodesApplyActionFragment extends Fragment { + + public String TAG = "EpisodeActionFragment"; + + private ListView mListView; + private ArrayAdapter<String> mAdapter; + + private Button btnAddToQueue; + private Button btnMarkAsPlayed; + private Button btnMarkAsUnplayed; + private Button btnDownload; + private Button btnDelete; + + private final Map<Long,FeedItem> idMap; + private final List<FeedItem> episodes; + private final List<String> titles = new ArrayList(); + private final LongList checkedIds = new LongList(); + + private MenuItem mSelectToggle; + + private int textColor; + + public EpisodesApplyActionFragment(List<FeedItem> episodes) { + this.episodes = episodes; + this.idMap = new HashMap<>(episodes.size()); + for(FeedItem episode : episodes) { + this.idMap.put(episode.getId(), episode); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.episodes_apply_action_fragment, container, false); + + mListView = (ListView) view.findViewById(android.R.id.list); + mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView<?> ListView, View view, int position, long rowId) { + long id = episodes.get(position).getId(); + if (checkedIds.contains(id)) { + checkedIds.remove(id); + } else { + checkedIds.add(id); + } + refreshCheckboxes(); + } + }); + + for(FeedItem episode : episodes) { + titles.add(episode.getTitle()); + } + + mAdapter = new ArrayAdapter<>(getActivity(), + android.R.layout.simple_list_item_multiple_choice, titles); + mListView.setAdapter(mAdapter); + checkAll(); + + btnAddToQueue = (Button) view.findViewById(R.id.btnAddToQueue); + btnAddToQueue.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + queueChecked(); + } + }); + btnMarkAsPlayed = (Button) view.findViewById(R.id.btnMarkAsPlayed); + btnMarkAsPlayed.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + markedCheckedPlayed(); + } + }); + btnMarkAsUnplayed = (Button) view.findViewById(R.id.btnMarkAsUnplayed); + btnMarkAsUnplayed.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + markedCheckedUnplayed(); + } + }); + btnDownload = (Button) view.findViewById(R.id.btnDownload); + btnDownload.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + downloadChecked(); + } + }); + btnDelete = (Button) view.findViewById(R.id.btnDelete); + btnDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + deleteChecked(); + } + }); + + return view; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.episodes_apply_action_options, menu); + + int[] attrs = { android.R.attr.textColor }; + TypedArray ta = getActivity().obtainStyledAttributes(attrs); + textColor = ta.getColor(0, Color.GRAY); + ta.recycle(); + + menu.findItem(R.id.sort).setIcon(new IconDrawable(getActivity(), + Iconify.IconValue.fa_sort).color(textColor).actionBarSize()); + + mSelectToggle = menu.findItem(R.id.select_toggle); + mSelectToggle.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + if (checkedIds.size() == episodes.size()) { + checkNone(); + } else { + checkAll(); + } + return true; + } + }); + + menu.findItem(R.id.select_options).setIcon(new IconDrawable(getActivity(), + Iconify.IconValue.fa_caret_down).color(textColor).actionBarSize()); + } + + @Override + public void onPrepareOptionsMenu (Menu menu) { + Iconify.IconValue iVal; + if(checkedIds.size() == episodes.size()) { + iVal = Iconify.IconValue.fa_check_square_o; + } else if(checkedIds.size() == 0) { + iVal = Iconify.IconValue.fa_square_o; + } else { + iVal = Iconify.IconValue.fa_minus_square_o; + } + mSelectToggle.setIcon(new IconDrawable(getActivity(), iVal).color(textColor).actionBarSize()); + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int resId = 0; + switch(item.getItemId()) { + case R.id.select_options: + return true; + case R.id.check_all: + checkAll(); + resId = R.string.selected_all_label; + break; + case R.id.check_none: + checkNone(); + resId = R.string.deselected_all_label; + break; + case R.id.check_played: + checkPlayed(true); + resId = R.string.selected_played_label; + break; + case R.id.check_unplayed: + checkPlayed(false); + resId = R.string.selected_unplayed_label; + break; + case R.id.check_downloaded: + checkDownloaded(true); + resId = R.string.selected_downloaded_label; + break; + case R.id.check_not_downloaded: + checkDownloaded(false); + resId = R.string.selected_not_downloaded_label; + break; + case R.id.sort_title_a_z: + sortByTitle(false); + return true; + case R.id.sort_title_z_a: + sortByTitle(true); + return true; + case R.id.sort_date_new_old: + sortByDate(true); + return true; + case R.id.sort_date_old_new: + sortByDate(false); + return true; + case R.id.sort_duration_long_short: + sortByDuration(true); + return true; + case R.id.sort_duration_short_long: + sortByDuration(false); + return true; + } + if(resId != 0) { + Toast.makeText(getActivity(), resId, Toast.LENGTH_SHORT).show(); + return true; + } else { + return false; + } + } + + private void sortByTitle(final boolean reverse) { + Collections.sort(episodes, new Comparator<FeedItem>() { + @Override + public int compare(FeedItem lhs, FeedItem rhs) { + if (reverse) { + return -1 * lhs.getTitle().compareTo(rhs.getTitle()); + } else { + return lhs.getTitle().compareTo(rhs.getTitle()); + } + } + }); + refreshTitles(); + refreshCheckboxes(); + } + + private void sortByDate(final boolean reverse) { + Collections.sort(episodes, new Comparator<FeedItem>() { + @Override + public int compare(FeedItem lhs, FeedItem rhs) { + if (lhs.getPubDate() == null) { + return -1; + } else if (rhs.getPubDate() == null) { + return 1; + } + int code = lhs.getPubDate().compareTo(rhs.getPubDate()); + if (reverse) { + return -1 * code; + } else { + return code; + } + } + }); + refreshTitles(); + refreshCheckboxes(); + } + + private void sortByDuration(final boolean reverse) { + Collections.sort(episodes, new Comparator<FeedItem>() { + @Override + public int compare(FeedItem lhs, FeedItem rhs) { + int ordering; + if (false == lhs.hasMedia()) { + ordering = 1; + } else if (false == rhs.hasMedia()) { + ordering = -1; + } else { + ordering = lhs.getMedia().getDuration() - rhs.getMedia().getDuration(); + } + if(reverse) { + return -1 * ordering; + } else { + return ordering; + } + } + }); + refreshTitles(); + refreshCheckboxes(); + } + + private void checkAll() { + for (FeedItem episode : episodes) { + if(false == checkedIds.contains(episode.getId())) { + checkedIds.add(episode.getId()); + } + } + refreshCheckboxes(); + } + + private void checkNone() { + checkedIds.clear(); + refreshCheckboxes(); + } + + private void checkPlayed(boolean isPlayed) { + for (FeedItem episode : episodes) { + if(episode.isRead() == isPlayed) { + if(!checkedIds.contains(episode.getId())) { + checkedIds.add(episode.getId()); + } + } else { + if(checkedIds.contains(episode.getId())) { + checkedIds.remove(episode.getId()); + } + } + } + refreshCheckboxes(); + } + + private void checkDownloaded(boolean isDownloaded) { + for (FeedItem episode : episodes) { + if(episode.hasMedia() && episode.getMedia().isDownloaded() == isDownloaded) { + if(!checkedIds.contains(episode.getId())) { + checkedIds.add(episode.getId()); + } + } else { + if(checkedIds.contains(episode.getId())) { + checkedIds.remove(episode.getId()); + } + } + } + refreshCheckboxes(); + } + + private void refreshTitles() { + titles.clear(); + for(FeedItem episode : episodes) { + titles.add(episode.getTitle()); + } + mAdapter.notifyDataSetChanged(); + } + + private void refreshCheckboxes() { + for (int i = 0; i < episodes.size(); i++) { + FeedItem episode = episodes.get(i); + boolean checked = checkedIds.contains(episode.getId()); + mListView.setItemChecked(i, checked); + } + ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity()); + } + + private void queueChecked() { + LongList orderedIds = new LongList(); + for(FeedItem episode : episodes) { + if(checkedIds.contains(episode.getId())) { + orderedIds.add((episode.getId())); + } + } + DBWriter.addQueueItem(getActivity(), false, orderedIds.toArray()); + close(); + } + + private void markedCheckedPlayed() { + DBWriter.markItemRead(getActivity(), true, checkedIds.toArray()); + close(); + } + + private void markedCheckedUnplayed() { + DBWriter.markItemRead(getActivity(), false, checkedIds.toArray()); + close(); + } + + private void downloadChecked() { + // download the check episodes in the same order as they are currently displayed + List<FeedItem> toDownload = new ArrayList<FeedItem>(checkedIds.size()); + for(FeedItem episode : episodes) { + if(checkedIds.contains(episode.getId())) { + toDownload.add(episode); + } + } + try { + DBTasks.downloadFeedItems(getActivity(), toDownload.toArray(new FeedItem[0])); + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage()); + } + close(); + } + + private void deleteChecked() { + for(long id : checkedIds.toArray()) { + FeedItem episode = idMap.get(id); + if(episode.hasMedia()) { + DBWriter.deleteFeedMediaOfItem(getActivity(), episode.getMedia().getId()); + } + } + close(); + } + + private void close() { + getActivity().getSupportFragmentManager().popBackStack(); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index 726e99621..797e5fb82 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -4,13 +4,15 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.res.TypedArray; +import android.graphics.Color; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.support.v4.app.Fragment; import android.support.v4.app.ListFragment; import android.support.v4.view.MenuItemCompat; - import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.SearchView; import android.util.Log; @@ -29,6 +31,7 @@ import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; +import com.joanzapata.android.iconify.IconDrawable; import com.joanzapata.android.iconify.Iconify; import com.squareup.picasso.Picasso; @@ -61,6 +64,7 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil; +import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; @@ -156,6 +160,7 @@ public class ItemlistFragment extends ListFragment { @Override public void onResume() { super.onResume(); + Log.d(TAG, "onResume()"); updateProgressBarVisibility(); startItemLoader(); } @@ -222,6 +227,13 @@ public class ItemlistFragment extends ListFragment { menu.findItem(R.id.share_link_item).setVisible(false); menu.findItem(R.id.visit_website_item).setVisible(false); } + int[] attrs = { android.R.attr.textColor }; + TypedArray ta = getActivity().obtainStyledAttributes(attrs); + int textColor = ta.getColor(0, Color.GRAY); + ta.recycle(); + + menu.findItem(R.id.episode_actions).setIcon(new IconDrawable(getActivity(), + Iconify.IconValue.fa_gears).color(textColor).actionBarSize()); isUpdatingFeed = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); } @@ -240,6 +252,10 @@ public class ItemlistFragment extends ListFragment { try { if (!FeedMenuHandler.onOptionsItemClicked(getActivity(), item, feed)) { switch (item.getItemId()) { + case R.id.episode_actions: + Fragment fragment = new EpisodesApplyActionFragment(feed.getItems()); + ((MainActivity)getActivity()).loadChildFragment(fragment); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover( getActivity(), feed) { @@ -406,6 +422,9 @@ public class ItemlistFragment extends ListFragment { private boolean insideOnFragmentLoaded = false; private void onFragmentLoaded() { + if(!isVisible()) { + return; + } insideOnFragmentLoaded = true; if (adapter == null) { setListAdapter(null); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index 4bce3c7ba..cbf3ffdd7 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -72,7 +72,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { Log.d(TAG, "remove(" + which + ")"); stopItemLoader(); FeedItem item = (FeedItem) listView.getAdapter().getItem(which); - DBWriter.markItemRead(getActivity(), item.getId(), true); + DBWriter.markItemRead(getActivity(), true, item.getId()); undoBarController.showUndoBar(false, getString(R.string.marked_as_read_label), new FeedItemUndoToken(item, which) @@ -88,7 +88,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { public void onUndo(FeedItemUndoToken token) { if (token != null) { long itemId = token.getFeedItemId(); - DBWriter.markItemRead(context, itemId, false); + DBWriter.markItemRead(context, false, itemId); } } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java index 30cc2c640..3df59724d 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java @@ -41,7 +41,6 @@ public class FeedMenuHandler { } Log.d(TAG, "Preparing options menu"); - menu.findItem(R.id.mark_all_read_item).setVisible(selectedFeed.hasNewItems()); if (selectedFeed.getPaymentLink() != null && selectedFeed.getFlattrStatus().flattrable()) { menu.findItem(R.id.support_item).setVisible(true); } else { diff --git a/app/src/main/res/layout/episodes_apply_action_fragment.xml b/app/src/main/res/layout/episodes_apply_action_fragment.xml new file mode 100644 index 000000000..d63088662 --- /dev/null +++ b/app/src/main/res/layout/episodes_apply_action_fragment.xml @@ -0,0 +1,120 @@ +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + <LinearLayout + android:id="@+id/bottomBar" + android:layout_width="wrap_content" + android:layout_height="68dp" + android:layout_alignParentBottom="true" + android:orientation="horizontal" + android:gravity="center_vertical" + android:padding="4dp"> + + <Button + android:id="@+id/btnAddToQueue" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableTop="?attr/content_new" + android:text="@string/add_to_queue_label" + android:textSize="10sp" + android:background="@android:color/transparent"/> + + <View xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="1dp" + android:layout_height="match_parent" + android:layout_margin="4dp" + android:background="?android:attr/listDivider" + tools:background="@android:color/holo_red_dark" /> + + <Button + android:id="@+id/btnMarkAsPlayed" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableTop="?attr/navigation_accept" + android:text="@string/mark_read_label" + android:textSize="10sp" + android:background="@android:color/transparent"/> + + <View xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="1dp" + android:layout_height="match_parent" + android:layout_margin="4dp" + android:background="?android:attr/listDivider" + tools:background="@android:color/holo_red_dark" /> + + <Button + android:id="@+id/btnMarkAsUnplayed" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableTop="?attr/navigation_cancel" + android:text="@string/mark_unread_label" + android:textSize="10sp" + android:background="@android:color/transparent"/> + + <View xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="1dp" + android:layout_height="match_parent" + android:layout_margin="4dp" + android:background="?android:attr/listDivider" + tools:background="@android:color/holo_red_dark" /> + + <Button + android:id="@+id/btnDownload" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableTop="?attr/av_download" + android:text="@string/download_label" + android:textSize="10sp" + android:background="@android:color/transparent"/> + + <View xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="1dp" + android:layout_height="match_parent" + android:layout_margin="4dp" + android:background="?android:attr/listDivider" + tools:background="@android:color/holo_red_dark" /> + + <Button + android:id="@+id/btnDelete" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableTop="?attr/content_discard" + android:text="@string/remove_episode_lable" + android:textSize="10sp" + android:background="@android:color/transparent"/> + + </LinearLayout> + + <View + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/divider" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?android:attr/listDivider" + android:paddingBottom="4dp" + android:layout_above="@id/bottomBar" + tools:background="@android:color/holo_red_dark" /> + + <ListView + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_above="@id/divider"> + + </ListView> + + +</RelativeLayout> diff --git a/app/src/main/res/menu/episodes_apply_action_options.xml b/app/src/main/res/menu/episodes_apply_action_options.xml new file mode 100644 index 000000000..88bef8d1f --- /dev/null +++ b/app/src/main/res/menu/episodes_apply_action_options.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <item + android:id="@+id/sort" + android:title="@string/sort" + app:showAsAction="always"> + <menu> + <item android:id="@+id/sort_title" + android:title="@string/sort_title"/> + <item android:id="@+id/sort_title_a_z" + android:title="@string/sort_title_a_z"/> + <item android:id="@+id/sort_title_z_a" + android:title="@string/sort_title_z_a"/> + <item android:id="@+id/sort_date_new_old" + android:title="@string/sort_date_new_old"/> + <item android:id="@+id/sort_date_old_new" + android:title="@string/sort_date_old_new"/> + <item android:id="@+id/sort_duration_short_long" + android:title="@string/sort_duration_short_long"/> + <item android:id="@+id/sort_duration_long_short" + android:title="@string/sort_duration_long_short"/> + </menu> + </item> + + <item + android:id="@+id/select_toggle" + android:title="@string/select_all_label" + app:showAsAction="always"/> + + <item + android:id="@+id/select_options" + android:title="@string/all_label" + app:showAsAction="always"> + + <menu> + <item android:id="@+id/select_label" + android:title="@string/select_label"/> + <item android:id="@+id/check_all" + android:title="@string/all_label"/> + <item android:id="@+id/check_none" + android:title="@string/none_label"/> + <item android:id="@+id/check_played" + android:title="@string/played_label"/> + <item android:id="@+id/check_unplayed" + android:title="@string/unplayed_label"/> + <item android:id="@+id/check_downloaded" + android:title="@string/downloaded_label"/> + <item android:id="@+id/check_not_downloaded" + android:title="@string/not_downloaded_label"/> + </menu> + </item> + +</menu> diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml index e6e85093b..54b90f5c6 100644 --- a/app/src/main/res/menu/feedlist.xml +++ b/app/src/main/res/menu/feedlist.xml @@ -10,6 +10,12 @@ custom:showAsAction="always"> </item> <item + android:id="@+id/episode_actions" + android:menuCategory="container" + android:title="@string/episode_actions" + custom:showAsAction="always"> + </item> + <item android:id="@+id/refresh_item" android:icon="?attr/navigation_refresh" android:menuCategory="container" @@ -31,13 +37,6 @@ android:title="@string/search_label"/> <item - android:id="@+id/mark_all_read_item" - android:menuCategory="container" - android:title="@string/mark_all_read_label" - custom:showAsAction="collapseActionView"> - </item> - - <item android:id="@+id/support_item" android:menuCategory="container" android:title="@string/support_label" diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index feeee48c5..e103007e3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -375,14 +375,21 @@ public class DBWriter { } + public static Future<?> addQueueItem(final Context context, + final long... itemIds) { + return addQueueItem(context, false, itemIds); + } + + /** * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true. * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue. * * @param context A context that is used for opening a database connection. + * @param performAutoDownload true if an auto-download process should be started after the operation. * @param itemIds IDs of the FeedItem objects that should be added to the queue. */ - public static Future<?> addQueueItem(final Context context, + public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload, final long... itemIds) { return dbExec.submit(new Runnable() { @@ -408,7 +415,7 @@ public class DBWriter { boolean addToFront = UserPreferences.enqueueAtFront(); if(addToFront){ - queue.add(0, item); + queue.add(0+i, item); } else { queue.add(item); } @@ -423,11 +430,12 @@ public class DBWriter { } } adapter.close(); - DBTasks.autodownloadUndownloadedItems(context); + if (performAutoDownload) { + DBTasks.autodownloadUndownloadedItems(context); + } } } }); - } /** @@ -595,16 +603,24 @@ public class DBWriter { adapter.close(); } - /** - * Sets the 'read'-attribute of a FeedItem to the specified value. + /* + * Sets the 'read'-attribute of all specified FeedItems * * @param context A context that is used for opening a database connection. - * @param itemId ID of the FeedItem * @param read New value of the 'read'-attribute + * @param itemIds IDs of the FeedItems. */ - public static Future<?> markItemRead(final Context context, final long itemId, - final boolean read) { - return markItemRead(context, itemId, read, 0, false); + public static Future<?> markItemRead(final Context context, final boolean read, final long... itemIds) { + return dbExec.submit(new Runnable() { + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedItemRead(read, itemIds); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0f1830202..00d7ed1bd 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -96,6 +96,7 @@ <string name="feed_remover_msg">Removing Feed</string> <string name="load_complete_feed">Refresh complete Feed</string> <string name="hide_episodes_title">Hide Episodes</string> + <string name="episode_actions">Apply actions</string> <string name="hide_unplayed_episodes_label">Unplayed</string> <string name="hide_paused_episodes_label">Paused</string> <string name="hide_played_episodes_label">Played</string> @@ -115,8 +116,8 @@ <string name="remove_label">Remove</string> <string name="remove_episode_lable">Remove Episode</string> <string name="mark_read_label">Mark as played</string> - <string name="mark_unread_label">Mark as unplayed</string> <string name="marked_as_read_label">Marked as played</string> + <string name="mark_unread_label">Mark as unplayed</string> <string name="add_to_queue_label">Add to Queue</string> <string name="added_to_queue_label">Added to Queue</string> <string name="remove_from_queue_label">Remove from Queue</string> @@ -346,6 +347,7 @@ <string name="opml_import_error_dir_empty">The import directory is empty.</string> <string name="select_all_label">Select all</string> <string name="deselect_all_label">Deselect all</string> + <string name="select_options_label">Select ...</string> <string name="choose_file_from_filesystem">From local filesystem</string> <string name="choose_file_from_external_application">Use external application</string> <string name="opml_export_label">OPML export</string> @@ -450,4 +452,25 @@ <string name="sp_apps_importing_feeds_msg">Importing subscriptions from single-purpose apps…</string> <string name="search_itunes_label">Search iTunes</string> + + <string name="select_label"><b>Select ...</b></string> + <string name="all_label">All</string> + <string name="selected_all_label">Selected all Episodes</string> + <string name="none_label">None</string> + <string name="deselected_all_label">Deselected all Episodes</string> + <string name="played_label">Played</string> + <string name="selected_played_label">Selected played Episodes</string> + <string name="unplayed_label">Unplayed</string> + <string name="selected_unplayed_label">Selected unplayed Episodes</string> + <string name="downloaded_label">Downloaded</string> + <string name="selected_downloaded_label">Selected downloaded Episodes</string> + <string name="not_downloaded_label">Not downloaded</string> + <string name="selected_not_downloaded_label">Selected not downloaded Episodes</string> + <string name="sort_title"><b>Sort by ...</b></string> + <string name="sort_title_a_z">Title (A \u2192 Z)</string> + <string name="sort_title_z_a">Title (Z \u2192 A)</string> + <string name="sort_date_new_old">Date (New \u2192 Old)</string> + <string name="sort_date_old_new">Date (Old \u2192 New)</string> + <string name="sort_duration_short_long">Duration (Short \u2192 Long)</string> + <string name="sort_duration_long_short">Duration (Long \u2192 Short)</string> </resources> |