summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java51
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java18
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java26
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java20
-rw-r--r--app/src/main/res/menu/feedlist.xml19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java32
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java28
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java (renamed from core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java)90
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/SortOrder.java63
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java2
-rw-r--r--core/src/main/res/drawable-hdpi/ic_filter_grey600_24dp.pngbin111 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_filter_white_24dp.pngbin110 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_filter_grey600_24dp.pngbin91 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-mdpi/ic_filter_white_24dp.pngbin90 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_filter_grey600_24dp.pngbin106 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_filter_white_24dp.pngbin103 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_filter_grey600_24dp.pngbin114 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_filter_white_24dp.pngbin107 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_filter_grey600_24dp.pngbin123 -> 0 bytes
-rw-r--r--core/src/main/res/drawable-xxxhdpi/ic_filter_white_24dp.pngbin106 -> 0 bytes
-rw-r--r--core/src/main/res/drawable/ic_filter_grey600_24dp.xml7
-rw-r--r--core/src/main/res/drawable/ic_filter_white_24dp.xml7
-rw-r--r--core/src/main/res/values/arrays.xml19
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java24
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/util/FeedItemPermutorsTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/util/QueueSorterTest.java)78
29 files changed, 403 insertions, 111 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
index 09a8466e6..ebf59fea7 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
@@ -44,8 +44,8 @@ class DBTestUtils {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
for (int i = 0; i < numFeeds; i++) {
- Feed f = new Feed(0, null, "feed " + i, null, "link" + i, "descr", null, null,
- null, null, "id" + i, null, null, "url" + i, false, false, null, null, false);
+ Feed f = new Feed(0, null, "feed " + i, "link" + i, "descr", null, null,
+ null, null, "id" + i, null, null, "url" + i, false);
f.setItems(new ArrayList<>());
for (int j = 0; j < numItems; j++) {
FeedItem item = new FeedItem(0, "item " + j, "id" + j, "link" + j, new Date(),
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java
new file mode 100644
index 000000000..2ee716c7c
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/IntraFeedSortDialog.java
@@ -0,0 +1,51 @@
+package de.danoeh.antennapod.dialog;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.util.SortOrder;
+
+public abstract class IntraFeedSortDialog {
+
+ @Nullable
+ protected SortOrder currentSortOrder;
+ @NonNull
+ protected Context context;
+
+ public IntraFeedSortDialog(@NonNull Context context, @Nullable SortOrder sortOrder) {
+ this.context = context;
+ this.currentSortOrder = sortOrder;
+ }
+
+ public void openDialog() {
+ final String[] items = context.getResources().getStringArray(R.array.feed_episodes_sort_options);
+ final String[] valueStrs = context.getResources().getStringArray(R.array.feed_episodes_sort_values);
+ final SortOrder[] values = new SortOrder[valueStrs.length];
+ for (int i = 0; i < valueStrs.length; i++) {
+ values[i] = SortOrder.valueOf(valueStrs[i]);
+ }
+
+ int idxCurrentSort = -1;
+ for (int i = 0; i < values.length; i++) {
+ if (currentSortOrder == values[i]) {
+ idxCurrentSort = i;
+ break;
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.sort);
+ builder.setSingleChoiceItems(items, idxCurrentSort, (dialog, idxNewSort) -> {
+ updateSort(values[idxNewSort]);
+ dialog.dismiss();
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.create().show();
+ }
+
+ protected abstract void updateSort(@NonNull SortOrder sortOrder);
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
index 0c33dce5a..076320754 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java
@@ -5,10 +5,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.ListFragment;
-import androidx.core.view.MenuItemCompat;
-import androidx.appcompat.widget.SearchView;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -23,12 +19,16 @@ import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.SearchView;
+import androidx.core.view.MenuItemCompat;
+import androidx.fragment.app.ListFragment;
+
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView;
-import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -45,6 +45,7 @@ import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
@@ -59,6 +60,7 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.FeedItemPermutors;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.Optional;
@@ -192,6 +194,7 @@ public class FeedItemlistFragment extends ListFragment {
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
+ menu.findItem(R.id.sort_items).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.findItem(R.id.filter_items).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.findItem(R.id.episode_actions).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.findItem(R.id.refresh_item).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
@@ -629,6 +632,11 @@ public class FeedItemlistFragment extends ListFragment {
FeedItemFilter filter = feed.getItemFilter();
feed.setItems(filter.filter(feed.getItems()));
}
+ if (feed != null && feed.getSortOrder() != null) {
+ List<FeedItem> feedItems = feed.getItems();
+ FeedItemPermutors.getPermutor(feed.getSortOrder()).reorder(feedItems);
+ feed.setItems(feedItems);
+ }
return Optional.ofNullable(feed);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
index 37277a7c4..c0552775f 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -4,15 +4,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
-import com.google.android.material.snackbar.Snackbar;
-import androidx.fragment.app.Fragment;
-import androidx.core.view.MenuItemCompat;
-import androidx.appcompat.app.AlertDialog;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.appcompat.widget.SearchView;
-import androidx.recyclerview.widget.SimpleItemAnimator;
-import androidx.recyclerview.widget.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -24,9 +15,18 @@ import android.widget.CheckBox;
import android.widget.ProgressBar;
import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.widget.SearchView;
+import androidx.core.view.MenuItemCompat;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.SimpleItemAnimator;
+
+import com.google.android.material.snackbar.Snackbar;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
-import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -40,6 +40,7 @@ import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
+import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -54,7 +55,6 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.core.util.QueueSorter;
import de.danoeh.antennapod.core.util.SortOrder;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
@@ -372,7 +372,7 @@ public class QueueFragment extends Fragment {
UserPreferences.setQueueKeepSorted(keepSortedNew);
if (keepSortedNew) {
SortOrder sortOrder = UserPreferences.getQueueKeepSortedOrder();
- QueueSorter.sort(sortOrder, true);
+ DBWriter.reorderQueue(sortOrder, true);
if (recyclerAdapter != null) {
recyclerAdapter.setLocked(true);
}
@@ -438,7 +438,7 @@ public class QueueFragment extends Fragment {
*/
private void setSortOrder(SortOrder sortOrder) {
UserPreferences.setQueueKeepSortedOrder(sortOrder);
- QueueSorter.sort(sortOrder, true);
+ DBWriter.reorderQueue(sortOrder, true);
}
@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 f7aae8cde..e32deba27 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
@@ -7,6 +7,8 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import androidx.annotation.NonNull;
+
import org.apache.commons.lang3.StringUtils;
import java.util.Set;
@@ -19,7 +21,9 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
+import de.danoeh.antennapod.core.util.SortOrder;
import de.danoeh.antennapod.dialog.FilterDialog;
+import de.danoeh.antennapod.dialog.IntraFeedSortDialog;
/**
* Handles interactions with the FeedItemMenu.
@@ -65,6 +69,9 @@ public class FeedMenuHandler {
case R.id.refresh_complete_item:
DBTasks.forceRefreshCompleteFeed(context, selectedFeed);
break;
+ case R.id.sort_items:
+ showSortDialog(context, selectedFeed);
+ break;
case R.id.filter_items:
showFilterDialog(context, selectedFeed);
break;
@@ -108,4 +115,17 @@ public class FeedMenuHandler {
filterDialog.openDialog();
}
+
+
+ private static void showSortDialog(Context context, Feed selectedFeed) {
+ IntraFeedSortDialog sortDialog = new IntraFeedSortDialog(context, selectedFeed.getSortOrder()) {
+ @Override
+ protected void updateSort(@NonNull SortOrder sortOrder) {
+ selectedFeed.setSortOrder(sortOrder);
+ DBWriter.setFeedItemSortOrder(selectedFeed.getId(), sortOrder);
+ }
+ };
+ sortDialog.openDialog();
+ }
+
}
diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml
index fdd0e01bc..13c019b65 100644
--- a/app/src/main/res/menu/feedlist.xml
+++ b/app/src/main/res/menu/feedlist.xml
@@ -3,17 +3,17 @@
xmlns:custom="http://schemas.android.com/apk/res-auto">
<item
- android:id="@+id/filter_items"
- android:icon="?attr/ic_filter"
+ android:id="@+id/sort_items"
+ android:icon="?attr/ic_sort"
android:menuCategory="container"
- android:title="@string/filter"
+ android:title="@string/sort"
custom:showAsAction="always">
</item>
<item
- android:id="@+id/episode_actions"
+ android:id="@+id/filter_items"
+ android:icon="?attr/ic_filter"
android:menuCategory="container"
- android:icon="?attr/checkbox_multiple"
- android:title="@string/batch_edit"
+ android:title="@string/filter"
custom:showAsAction="always">
</item>
<item
@@ -38,6 +38,13 @@
android:title="@string/search_label"/>
<item
+ android:id="@+id/episode_actions"
+ android:menuCategory="container"
+ android:icon="?attr/checkbox_multiple"
+ android:title="@string/batch_edit"
+ custom:showAsAction="collapseActionView">
+ </item>
+ <item
android:id="@+id/visit_website_item"
android:icon="?attr/location_web_site"
android:menuCategory="container"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
index 6a7c97b7b..0d17e3faa 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
@@ -1,9 +1,10 @@
package de.danoeh.antennapod.core.feed;
import android.database.Cursor;
-import androidx.annotation.Nullable;
import android.text.TextUtils;
+import androidx.annotation.Nullable;
+
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -11,6 +12,8 @@ import java.util.List;
import de.danoeh.antennapod.core.asynctask.ImageResource;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import de.danoeh.antennapod.core.util.SortOrder;
+
/**
* Data Object for a whole feed
*
@@ -89,12 +92,19 @@ public class Feed extends FeedFile implements ImageResource {
private FeedItemFilter itemfilter;
/**
+ * User-preferred sortOrder for display.
+ * Only those of scope {@link SortOrder.Scope#INTRA_FEED} is allowed.
+ */
+ @Nullable
+ private SortOrder sortOrder;
+
+ /**
* This constructor is used for restoring a feed from the database.
*/
public Feed(long id, String lastUpdate, String title, String customTitle, String link, String description, String paymentLink,
String author, String language, String type, String feedIdentifier, String imageUrl, String fileUrl,
String downloadUrl, boolean downloaded, boolean paged, String nextPageLink,
- String filter, boolean lastUpdateFailed) {
+ String filter, @Nullable SortOrder sortOrder, boolean lastUpdateFailed) {
super(fileUrl, downloadUrl, downloaded);
this.id = id;
this.feedTitle = title;
@@ -116,6 +126,7 @@ public class Feed extends FeedFile implements ImageResource {
} else {
this.itemfilter = new FeedItemFilter(new String[0]);
}
+ setSortOrder(sortOrder);
this.lastUpdateFailed = lastUpdateFailed;
}
@@ -126,7 +137,7 @@ public class Feed extends FeedFile implements ImageResource {
String author, String language, String type, String feedIdentifier, String imageUrl, String fileUrl,
String downloadUrl, boolean downloaded) {
this(id, lastUpdate, title, null, link, description, paymentLink, author, language, type, feedIdentifier, imageUrl,
- fileUrl, downloadUrl, downloaded, false, null, null, false);
+ fileUrl, downloadUrl, downloaded, false, null, null, null, false);
}
/**
@@ -181,6 +192,7 @@ public class Feed extends FeedFile implements ImageResource {
int indexIsPaged = cursor.getColumnIndex(PodDBAdapter.KEY_IS_PAGED);
int indexNextPageLink = cursor.getColumnIndex(PodDBAdapter.KEY_NEXT_PAGE_LINK);
int indexHide = cursor.getColumnIndex(PodDBAdapter.KEY_HIDE);
+ int indexSortOrder = cursor.getColumnIndex(PodDBAdapter.KEY_SORT_ORDER);
int indexLastUpdateFailed = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_UPDATE_FAILED);
int indexImageUrl = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL);
@@ -203,6 +215,7 @@ public class Feed extends FeedFile implements ImageResource {
cursor.getInt(indexIsPaged) > 0,
cursor.getString(indexNextPageLink),
cursor.getString(indexHide),
+ SortOrder.fromCodeString(cursor.getString(indexSortOrder)),
cursor.getInt(indexLastUpdateFailed) > 0
);
@@ -523,6 +536,19 @@ public class Feed extends FeedFile implements ImageResource {
}
}
+ @Nullable
+ public SortOrder getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setSortOrder(@Nullable SortOrder sortOrder) {
+ if (sortOrder != null && sortOrder.scope != SortOrder.Scope.INTRA_FEED) {
+ throw new IllegalArgumentException("The specified sortOrder " + sortOrder
+ + " is invalid. Only those with INTRA_FEED scope are allowed.");
+ }
+ this.sortOrder = sortOrder;
+ }
+
public boolean hasLastUpdateFailed() {
return this.lastUpdateFailed;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
index b790faadf..15cdf92dc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedEvent.java
@@ -6,7 +6,8 @@ import org.apache.commons.lang3.builder.ToStringStyle;
public class FeedEvent {
public enum Action {
- FILTER_CHANGED
+ FILTER_CHANGED,
+ SORT_ORDER_CHANGED
}
private final Action action;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
index 575b8d2ac..0c8f89348 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
@@ -294,6 +294,11 @@ class DBUpgrader {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ " ADD COLUMN " + PodDBAdapter.KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL);
}
+
+ if (oldVersion < 1070401) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + PodDBAdapter.KEY_SORT_ORDER + " TEXT");
+ }
}
}
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 9225155cf..32b04deea 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
@@ -5,6 +5,7 @@ import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.core.event.PlaybackHistoryEvent;
@@ -38,10 +39,10 @@ import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
+import de.danoeh.antennapod.core.util.FeedItemPermutors;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.Permutor;
-import de.danoeh.antennapod.core.util.QueueSorter;
import de.danoeh.antennapod.core.util.SortOrder;
/**
@@ -387,7 +388,7 @@ public class DBWriter {
// do not shuffle the list on every change
return;
}
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(sortOrder);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(sortOrder);
permutor.reorder(queue);
// Replace ADDED events by a single SORTED event
@@ -847,14 +848,18 @@ public class DBWriter {
}
/**
- * Sort the FeedItems in the queue with the given Permutor.
+ * Sort the FeedItems in the queue with the given the named sort order.
*
- * @param permutor Encapsulates whole-Queue reordering logic.
* @param broadcastUpdate <code>true</code> if this operation should trigger a
* QueueUpdateBroadcast. This option should be set to <code>false</code>
* if the caller wants to avoid unexpected updates of the GUI.
*/
- public static Future<?> reorderQueue(final Permutor<FeedItem> permutor, final boolean broadcastUpdate) {
+ public static Future<?> reorderQueue(@Nullable SortOrder sortOrder, final boolean broadcastUpdate) {
+ if (sortOrder == null) {
+ Log.w(TAG, "reorderQueue() - sortOrder is null. Do nothing.");
+ return dbExec.submit(() -> { });
+ }
+ final Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(sortOrder);
return dbExec.submit(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -946,6 +951,19 @@ public class DBWriter {
});
}
+ /**
+ * Set item sort order of the feed
+ *
+ */
+ public static Future<?> setFeedItemSortOrder(long feedId, @Nullable SortOrder sortOrder) {
+ return dbExec.submit(() -> {
+ PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
+ adapter.setFeedItemSortOrder(feedId, sortOrder);
+ adapter.close();
+ EventBus.getDefault().post(new FeedEvent(FeedEvent.Action.SORT_ORDER_CHANGED, feedId));
+ });
+ }
/**
* Reset the statistics in DB
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
index 66f6d223d..a37f357ae 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -13,11 +13,11 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import org.apache.commons.io.FileUtils;
import java.io.File;
@@ -35,8 +35,10 @@ import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
+import de.danoeh.antennapod.core.util.SortOrder;
import static de.danoeh.antennapod.core.feed.FeedPreferences.SPEED_USE_GLOBAL;
+import static de.danoeh.antennapod.core.util.SortOrder.toCodeString;
// TODO Remove media column from feeditem table
@@ -101,6 +103,7 @@ public class PodDBAdapter {
public static final String KEY_IS_PAGED = "is_paged";
public static final String KEY_NEXT_PAGE_LINK = "next_page_link";
public static final String KEY_HIDE = "hide";
+ public static final String KEY_SORT_ORDER = "sort_order";
public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed";
public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture";
public static final String KEY_LAST_PLAYED_TIME = "last_played_time";
@@ -138,6 +141,7 @@ public class PodDBAdapter {
+ KEY_IS_PAGED + " INTEGER DEFAULT 0,"
+ KEY_NEXT_PAGE_LINK + " TEXT,"
+ KEY_HIDE + " TEXT,"
+ + KEY_SORT_ORDER + " TEXT,"
+ KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0,"
+ KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0,"
+ KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + ")";
@@ -234,6 +238,7 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_USERNAME,
TABLE_NAME_FEEDS + "." + KEY_PASSWORD,
TABLE_NAME_FEEDS + "." + KEY_HIDE,
+ TABLE_NAME_FEEDS + "." + KEY_SORT_ORDER,
TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED,
TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION,
TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER,
@@ -378,6 +383,7 @@ public class PodDBAdapter {
} else {
values.put(KEY_HIDE, "");
}
+ values.put(KEY_SORT_ORDER, toCodeString(feed.getSortOrder()));
values.put(KEY_LAST_UPDATE_FAILED, feed.hasLastUpdateFailed());
if (feed.getId() == 0) {
// Create new entry
@@ -416,6 +422,12 @@ public class PodDBAdapter {
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
}
+ public void setFeedItemSortOrder(long feedId, @Nullable SortOrder sortOrder) {
+ ContentValues values = new ContentValues();
+ values.put(KEY_SORT_ORDER, toCodeString(sortOrder));
+ db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
+ }
+
/**
* Inserts or updates a media entry
*
@@ -1455,7 +1467,7 @@ public class PodDBAdapter {
*/
private static class PodDBHelper extends SQLiteOpenHelper {
- private static final int VERSION = 1070400;
+ private static final int VERSION = 1070401;
private final Context context;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java
index 0c21ca393..9bf9b9db0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java
@@ -1,89 +1,58 @@
package de.danoeh.antennapod.core.util;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.storage.DBWriter;
/**
- * Provides method for sorting the queue according to rules.
+ * Provides method for sorting the a list of {@link FeedItem} according to rules.
*/
-public class QueueSorter {
-
- /**
- * Sorts the queue by the given sort order and sends a broadcast update.
- *
- * @param sortOrder Sort order.
- * @param broadcastUpdate Send broadcast update?
- */
- public static void sort(SortOrder sortOrder, boolean broadcastUpdate) {
- Permutor<FeedItem> permutor = getPermutor(sortOrder);
- if (permutor != null) {
- DBWriter.reorderQueue(permutor, broadcastUpdate);
- }
- }
+public class FeedItemPermutors {
/**
* Returns a Permutor that sorts a list appropriate to the given sort order.
*
- * @param sortOrder Sort order.
- * @return Permutor that sorts a list appropriate to the given sort order. <code>null</code> if the order is unknown or <code>null</code>.
+ * @return Permutor that sorts a list appropriate to the given sort order.
*/
- public static Permutor<FeedItem> getPermutor(SortOrder sortOrder) {
- if (sortOrder == null) {
- return null;
- }
+ @NonNull
+ public static Permutor<FeedItem> getPermutor(@NonNull SortOrder sortOrder) {
Comparator<FeedItem> comparator = null;
Permutor<FeedItem> permutor = null;
switch (sortOrder) {
case EPISODE_TITLE_A_Z:
- comparator = (f1, f2) -> f1.getTitle().compareTo(f2.getTitle());
+ comparator = (f1, f2) -> itemTitle(f1).compareTo(itemTitle(f2));
break;
case EPISODE_TITLE_Z_A:
- comparator = (f1, f2) -> f2.getTitle().compareTo(f1.getTitle());
+ comparator = (f1, f2) -> itemTitle(f2).compareTo(itemTitle(f1));
break;
case DATE_OLD_NEW:
- comparator = (f1, f2) -> f1.getPubDate().compareTo(f2.getPubDate());
+ comparator = (f1, f2) -> pubDate(f1).compareTo(pubDate(f2));
break;
case DATE_NEW_OLD:
- comparator = (f1, f2) -> f2.getPubDate().compareTo(f1.getPubDate());
+ comparator = (f1, f2) -> pubDate(f2).compareTo(pubDate(f1));
break;
case DURATION_SHORT_LONG:
- comparator = (f1, f2) -> {
- FeedMedia f1Media = f1.getMedia();
- FeedMedia f2Media = f2.getMedia();
- int duration1 = f1Media != null ? f1Media.getDuration() : -1;
- int duration2 = f2Media != null ? f2Media.getDuration() : -1;
-
- if (duration1 == -1 || duration2 == -1)
- return duration2 - duration1;
- else
- return duration1 - duration2;
- };
+ comparator = (f1, f2) -> Integer.compare(duration(f1), duration(f2));
break;
case DURATION_LONG_SHORT:
- comparator = (f1, f2) -> {
- FeedMedia f1Media = f1.getMedia();
- FeedMedia f2Media = f2.getMedia();
- int duration1 = f1Media != null ? f1Media.getDuration() : -1;
- int duration2 = f2Media != null ? f2Media.getDuration() : -1;
-
- return -1 * (duration1 - duration2);
- };
+ comparator = (f1, f2) -> Integer.compare(duration(f2), duration(f1));
break;
case FEED_TITLE_A_Z:
- comparator = (f1, f2) -> f1.getFeed().getTitle().compareTo(f2.getFeed().getTitle());
+ comparator = (f1, f2) -> feedTitle(f1).compareTo(feedTitle(f2));
break;
case FEED_TITLE_Z_A:
- comparator = (f1, f2) -> f2.getFeed().getTitle().compareTo(f1.getFeed().getTitle());
+ comparator = (f1, f2) -> feedTitle(f2).compareTo(feedTitle(f1));
break;
case RANDOM:
permutor = Collections::shuffle;
@@ -103,6 +72,31 @@ public class QueueSorter {
return permutor;
}
+ // Null-safe accessors
+
+ @NonNull
+ private static Date pubDate(@Nullable FeedItem item) {
+ return (item != null && item.getPubDate() != null) ?
+ item.getPubDate() : new Date(0);
+ }
+
+ @NonNull
+ private static String itemTitle(@Nullable FeedItem item) {
+ return (item != null && item.getTitle() != null) ?
+ item.getTitle() : "";
+ }
+
+ private static int duration(@Nullable FeedItem item) {
+ return (item != null && item.getMedia() != null) ?
+ item.getMedia().getDuration() : 0;
+ }
+
+ @NonNull
+ private static String feedTitle(@Nullable FeedItem item) {
+ return (item != null && item.getFeed() != null && item.getFeed().getTitle() != null) ?
+ item.getFeed().getTitle() : "";
+ }
+
/**
* Implements a reordering by pubdate that avoids consecutive episodes from the same feed in
* the queue.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/SortOrder.java b/core/src/main/java/de/danoeh/antennapod/core/util/SortOrder.java
index ae6fceb47..96a18506d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/SortOrder.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/SortOrder.java
@@ -1,20 +1,42 @@
package de.danoeh.antennapod.core.util;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import static de.danoeh.antennapod.core.util.SortOrder.Scope.INTER_FEED;
+import static de.danoeh.antennapod.core.util.SortOrder.Scope.INTRA_FEED;
+
/**
* Provides sort orders to sort a list of episodes.
*/
public enum SortOrder {
- EPISODE_TITLE_A_Z,
- EPISODE_TITLE_Z_A,
- DATE_OLD_NEW,
- DATE_NEW_OLD,
- DURATION_SHORT_LONG,
- DURATION_LONG_SHORT,
- FEED_TITLE_A_Z,
- FEED_TITLE_Z_A,
- RANDOM,
- SMART_SHUFFLE_OLD_NEW,
- SMART_SHUFFLE_NEW_OLD;
+ DATE_OLD_NEW(1, INTRA_FEED),
+ DATE_NEW_OLD(2, INTRA_FEED),
+ EPISODE_TITLE_A_Z(3, INTRA_FEED),
+ EPISODE_TITLE_Z_A(4, INTRA_FEED),
+ DURATION_SHORT_LONG(5, INTRA_FEED),
+ DURATION_LONG_SHORT(6, INTRA_FEED),
+ FEED_TITLE_A_Z(101, INTER_FEED),
+ FEED_TITLE_Z_A(102, INTER_FEED),
+ RANDOM(103, INTER_FEED),
+ SMART_SHUFFLE_OLD_NEW(104, INTER_FEED),
+ SMART_SHUFFLE_NEW_OLD(105, INTER_FEED);
+
+ public enum Scope {
+ INTRA_FEED, INTER_FEED;
+ }
+
+ public final int code;
+
+ @NonNull
+ public final Scope scope;
+
+ SortOrder(int code, @NonNull Scope scope) {
+ this.code = code;
+ this.scope = scope;
+ }
/**
* Converts the string representation to its enum value. If the string value is unknown,
@@ -27,4 +49,23 @@ public enum SortOrder {
return defaultValue;
}
}
+
+ @Nullable
+ public static SortOrder fromCodeString(@Nullable String codeStr) {
+ if (TextUtils.isEmpty(codeStr)) {
+ return null;
+ }
+ int code = Integer.parseInt(codeStr);
+ for (SortOrder sortOrder : values()) {
+ if (sortOrder.code == code) {
+ return sortOrder;
+ }
+ }
+ throw new IllegalArgumentException("Unsupported code: " + code);
+ }
+
+ @Nullable
+ public static String toCodeString(@Nullable SortOrder sortOrder) {
+ return sortOrder != null ? Integer.toString(sortOrder.code) : null;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java
index a96eda3c5..51fe2da78 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/FeedItemPubdateComparator.java
@@ -7,7 +7,7 @@ import de.danoeh.antennapod.core.feed.FeedItem;
/** Compares the pubDate of two FeedItems for sorting*/
public class FeedItemPubdateComparator implements Comparator<FeedItem> {
- /** Returns a new instance of this comparator in reverse order.
+ /** Returns a new instance of this comparator in reverse order.
public static FeedItemPubdateComparator newInstance() {
FeedItemPubdateComparator
}*/
diff --git a/core/src/main/res/drawable-hdpi/ic_filter_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_filter_grey600_24dp.png
deleted file mode 100644
index 0d2f6ccb4..000000000
--- a/core/src/main/res/drawable-hdpi/ic_filter_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_filter_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_filter_white_24dp.png
deleted file mode 100644
index ea6f9078e..000000000
--- a/core/src/main/res/drawable-hdpi/ic_filter_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_filter_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_filter_grey600_24dp.png
deleted file mode 100644
index b78e7d4d2..000000000
--- a/core/src/main/res/drawable-mdpi/ic_filter_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-mdpi/ic_filter_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_filter_white_24dp.png
deleted file mode 100644
index 59a2ec755..000000000
--- a/core/src/main/res/drawable-mdpi/ic_filter_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_filter_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_filter_grey600_24dp.png
deleted file mode 100644
index 4c6a96eba..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_filter_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_filter_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_filter_white_24dp.png
deleted file mode 100644
index 9416c70ec..000000000
--- a/core/src/main/res/drawable-xhdpi/ic_filter_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_filter_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_filter_grey600_24dp.png
deleted file mode 100644
index 5846ad140..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_filter_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_filter_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_filter_white_24dp.png
deleted file mode 100644
index 1263ae82e..000000000
--- a/core/src/main/res/drawable-xxhdpi/ic_filter_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_filter_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_filter_grey600_24dp.png
deleted file mode 100644
index 3fe8eb4dd..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_filter_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable-xxxhdpi/ic_filter_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_filter_white_24dp.png
deleted file mode 100644
index cb2207f11..000000000
--- a/core/src/main/res/drawable-xxxhdpi/ic_filter_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/core/src/main/res/drawable/ic_filter_grey600_24dp.xml b/core/src/main/res/drawable/ic_filter_grey600_24dp.xml
new file mode 100644
index 000000000..dc164504c
--- /dev/null
+++ b/core/src/main/res/drawable/ic_filter_grey600_24dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#FF757575" android:pathData="M15,19.88C15.04,20.18 14.94,20.5 14.71,20.71C14.32,21.1 13.69,21.1 13.3,20.71L9.29,16.7C9.06,16.47 8.96,16.16 9,15.87V10.75L4.21,4.62C3.87,4.19 3.95,3.56 4.38,3.22C4.57,3.08 4.78,3 5,3V3H19V3C19.22,3 19.43,3.08 19.62,3.22C20.05,3.56 20.13,4.19 19.79,4.62L15,10.75V19.88M7.04,5L11,10.06V15.58L13,17.58V10.05L16.96,5H7.04Z" />
+</vector>
diff --git a/core/src/main/res/drawable/ic_filter_white_24dp.xml b/core/src/main/res/drawable/ic_filter_white_24dp.xml
new file mode 100644
index 000000000..4b1b88581
--- /dev/null
+++ b/core/src/main/res/drawable/ic_filter_white_24dp.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#FFFFFFFF" android:pathData="M15,19.88C15.04,20.18 14.94,20.5 14.71,20.71C14.32,21.1 13.69,21.1 13.3,20.71L9.29,16.7C9.06,16.47 8.96,16.16 9,15.87V10.75L4.21,4.62C3.87,4.19 3.95,3.56 4.38,3.22C4.57,3.08 4.78,3 5,3V3H19V3C19.22,3 19.43,3.08 19.62,3.22C20.05,3.56 20.13,4.19 19.79,4.62L15,10.75V19.88M7.04,5L11,10.06V15.58L13,17.58V10.05L16.96,5H7.04Z" />
+</vector>
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 5e7eab1ea..2dd985d6a 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -254,6 +254,25 @@
<item>is_favorite</item>
</string-array>
+ <!-- sort for podcast screen, not for queue -->
+ <string-array name="feed_episodes_sort_options">
+ <item>@string/sort_date_new_old</item>
+ <item>@string/sort_date_old_new</item>
+ <item>@string/sort_title_a_z</item>
+ <item>@string/sort_title_z_a</item>
+ <item>@string/sort_duration_short_long</item>
+ <item>@string/sort_duration_long_short</item>
+ </string-array>
+
+ <string-array name="feed_episodes_sort_values">
+ <item>DATE_NEW_OLD</item>
+ <item>DATE_OLD_NEW</item>
+ <item>EPISODE_TITLE_A_Z</item>
+ <item>EPISODE_TITLE_Z_A</item>
+ <item>DURATION_SHORT_LONG</item>
+ <item>DURATION_LONG_SHORT</item>
+ </string-array>
+
<string-array name="image_cache_size_options">
<item>20 MiB</item>
<item>50 MiB</item>
diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java
index 4717041f4..88b342850 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java
@@ -3,10 +3,13 @@ package de.danoeh.antennapod.core.feed;
import org.junit.Before;
import org.junit.Test;
+import de.danoeh.antennapod.core.util.SortOrder;
+
import static de.danoeh.antennapod.core.feed.FeedMother.anyFeed;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
public class FeedTest {
@@ -59,6 +62,27 @@ public class FeedTest {
feedImageWasUpdated();
}
+ @Test
+ public void testSetSortOrder_OnlyIntraFeedSortAllowed() throws Exception {
+ for (SortOrder sortOrder : SortOrder.values()) {
+ if (sortOrder.scope == SortOrder.Scope.INTRA_FEED) {
+ original.setSortOrder(sortOrder); // should be okay
+ } else {
+ try {
+ original.setSortOrder(sortOrder);
+ fail("SortOrder " + sortOrder + " should not be allowed on a feed");
+ } catch (IllegalArgumentException iae) {
+ // expected exception
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testSetSortOrder_NullAllowed() throws Exception {
+ original.setSortOrder(null); // should be okay
+ }
+
private void feedHasNotChanged() {
assertFalse(original.compareWithOther(changedFeed));
}
diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/QueueSorterTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/FeedItemPermutorsTest.java
index 791b6a75b..ccaa77ae8 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/util/QueueSorterTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/util/FeedItemPermutorsTest.java
@@ -10,22 +10,25 @@ import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNull;
/**
- * Test class for QueueSorter.
+ * Test class for FeedItemPermutors.
*/
-public class QueueSorterTest {
+public class FeedItemPermutorsTest {
@Test
- public void testPermutorForRule_null() {
- assertNull(QueueSorter.getPermutor(null));
+ public void testEnsureNonNullPermutors() {
+ for (SortOrder sortOrder : SortOrder.values()) {
+ assertNotNull("The permutor for SortOrder " + sortOrder + " is unexpectedly null",
+ FeedItemPermutors.getPermutor(sortOrder));
+ }
}
@Test
public void testPermutorForRule_EPISODE_TITLE_ASC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.EPISODE_TITLE_A_Z);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.EPISODE_TITLE_A_Z);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -34,8 +37,21 @@ public class QueueSorterTest {
}
@Test
+ public void testPermutorForRule_EPISODE_TITLE_ASC_NullTitle() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.EPISODE_TITLE_A_Z);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(2) // itemId 2
+ .setTitle(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+
+ @Test
public void testPermutorForRule_EPISODE_TITLE_DESC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.EPISODE_TITLE_Z_A);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.EPISODE_TITLE_Z_A);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -45,7 +61,7 @@ public class QueueSorterTest {
@Test
public void testPermutorForRule_DATE_ASC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.DATE_OLD_NEW);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DATE_OLD_NEW);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -54,8 +70,20 @@ public class QueueSorterTest {
}
@Test
+ public void testPermutorForRule_DATE_ASC_NulPubDatel() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DATE_OLD_NEW);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(2) // itemId 2
+ .setPubDate(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+ @Test
public void testPermutorForRule_DATE_DESC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.DATE_NEW_OLD);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DATE_NEW_OLD);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -65,7 +93,7 @@ public class QueueSorterTest {
@Test
public void testPermutorForRule_DURATION_ASC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.DURATION_SHORT_LONG);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DURATION_SHORT_LONG);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -75,7 +103,7 @@ public class QueueSorterTest {
@Test
public void testPermutorForRule_DURATION_DESC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.DURATION_LONG_SHORT);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DURATION_LONG_SHORT);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -84,8 +112,20 @@ public class QueueSorterTest {
}
@Test
+ public void testPermutorForRule_DURATION_DESC_NullMedia() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.DURATION_LONG_SHORT);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(1) // itemId 3
+ .setMedia(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
+ @Test
public void testPermutorForRule_FEED_TITLE_ASC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.FEED_TITLE_A_Z);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.FEED_TITLE_A_Z);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -95,7 +135,7 @@ public class QueueSorterTest {
@Test
public void testPermutorForRule_FEED_TITLE_DESC() {
- Permutor<FeedItem> permutor = QueueSorter.getPermutor(SortOrder.FEED_TITLE_Z_A);
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.FEED_TITLE_Z_A);
List<FeedItem> itemList = getTestList();
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
@@ -103,6 +143,18 @@ public class QueueSorterTest {
assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
}
+ @Test
+ public void testPermutorForRule_FEED_TITLE_DESC_NullTitle() {
+ Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(SortOrder.FEED_TITLE_Z_A);
+
+ List<FeedItem> itemList = getTestList();
+ itemList.get(1) // itemId 3
+ .getFeed().setTitle(null);
+ assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
+ permutor.reorder(itemList);
+ assertTrue(checkIdOrder(itemList, 2, 1, 3)); // after sorting
+ }
+
/**
* Generates a list with test data.
*/