Queue: Keep sorted #1556
This commit is contained in:
parent
63eb766dff
commit
9b7a61471d
|
@ -272,6 +272,13 @@ public class QueueFragment extends Fragment {
|
||||||
|
|
||||||
MenuItemUtils.refreshLockItem(getActivity(), menu);
|
MenuItemUtils.refreshLockItem(getActivity(), menu);
|
||||||
|
|
||||||
|
// Show Lock Item and Sort Item only if queue is sorted manually
|
||||||
|
boolean sortedManually = UserPreferences.isQueueSortedManually();
|
||||||
|
MenuItem lockItem = menu.findItem(R.id.queue_lock);
|
||||||
|
lockItem.setVisible(sortedManually);
|
||||||
|
MenuItem sortItem = menu.findItem(R.id.queue_sort);
|
||||||
|
sortItem.setVisible(sortedManually);
|
||||||
|
|
||||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,37 +324,37 @@ public class QueueFragment extends Fragment {
|
||||||
conDialog.createNewDialog().show();
|
conDialog.createNewDialog().show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_episode_title_asc:
|
case R.id.queue_sort_episode_title_asc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_ASC, true);
|
QueueSorter.sort(QueueSorter.Rule.EPISODE_TITLE_ASC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_episode_title_desc:
|
case R.id.queue_sort_episode_title_desc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_DESC, true);
|
QueueSorter.sort(QueueSorter.Rule.EPISODE_TITLE_DESC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_date_asc:
|
case R.id.queue_sort_date_asc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_ASC, true);
|
QueueSorter.sort(QueueSorter.Rule.DATE_ASC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_date_desc:
|
case R.id.queue_sort_date_desc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_DESC, true);
|
QueueSorter.sort(QueueSorter.Rule.DATE_DESC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_duration_asc:
|
case R.id.queue_sort_duration_asc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_ASC, true);
|
QueueSorter.sort(QueueSorter.Rule.DURATION_ASC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_duration_desc:
|
case R.id.queue_sort_duration_desc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_DESC, true);
|
QueueSorter.sort(QueueSorter.Rule.DURATION_DESC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_feed_title_asc:
|
case R.id.queue_sort_feed_title_asc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_ASC, true);
|
QueueSorter.sort(QueueSorter.Rule.FEED_TITLE_ASC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_feed_title_desc:
|
case R.id.queue_sort_feed_title_desc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_DESC, true);
|
QueueSorter.sort(QueueSorter.Rule.FEED_TITLE_DESC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_random:
|
case R.id.queue_sort_random:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.RANDOM, true);
|
QueueSorter.sort(QueueSorter.Rule.RANDOM, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_smart_shuffle_asc:
|
case R.id.queue_sort_smart_shuffle_asc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.SMART_SHUFFLE_ASC, true);
|
QueueSorter.sort(QueueSorter.Rule.SMART_SHUFFLE_ASC, true);
|
||||||
return true;
|
return true;
|
||||||
case R.id.queue_sort_smart_shuffle_desc:
|
case R.id.queue_sort_smart_shuffle_desc:
|
||||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.SMART_SHUFFLE_DESC, true);
|
QueueSorter.sort(QueueSorter.Rule.SMART_SHUFFLE_DESC, true);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -661,5 +668,4 @@ public class QueueFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,12 @@ import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
|
import de.danoeh.antennapod.core.util.Permutor;
|
||||||
|
import de.danoeh.antennapod.core.util.QueueSorter;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -89,6 +94,17 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
|
||||||
if (Build.VERSION.SDK_INT >= 26) {
|
if (Build.VERSION.SDK_INT >= 26) {
|
||||||
findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false);
|
findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findPreference(UserPreferences.PREF_QUEUE_SORT_ORDER)
|
||||||
|
.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
|
UserPreferences.QueueSortOrder newSortOrder = UserPreferences.parseQueueSortOrder((String) newValue);
|
||||||
|
if (newSortOrder != UserPreferences.QueueSortOrder.MANUALLY) {
|
||||||
|
QueueSorter.Rule sortRule = QueueSorter.queueSortOrder2Rule(newSortOrder);
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(sortRule);
|
||||||
|
DBWriter.reorderQueue(permutor, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDrawerPreferencesDialog() {
|
private void showDrawerPreferencesDialog() {
|
||||||
|
|
|
@ -68,16 +68,17 @@ public class FeedItemMenuHandler {
|
||||||
}
|
}
|
||||||
boolean hasMedia = selectedItem.getMedia() != null;
|
boolean hasMedia = selectedItem.getMedia() != null;
|
||||||
boolean isPlaying = hasMedia && selectedItem.getState() == FeedItem.State.PLAYING;
|
boolean isPlaying = hasMedia && selectedItem.getState() == FeedItem.State.PLAYING;
|
||||||
|
boolean sortedManually = UserPreferences.isQueueSortedManually();
|
||||||
|
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
mi.setItemVisibility(R.id.skip_episode_item, false);
|
mi.setItemVisibility(R.id.skip_episode_item, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
|
boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
|
||||||
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) {
|
if (queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId() || !sortedManually) {
|
||||||
mi.setItemVisibility(R.id.move_to_top_item, false);
|
mi.setItemVisibility(R.id.move_to_top_item, false);
|
||||||
}
|
}
|
||||||
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId()) {
|
if (queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId() || !sortedManually) {
|
||||||
mi.setItemVisibility(R.id.move_to_bottom_item, false);
|
mi.setItemVisibility(R.id.move_to_bottom_item, false);
|
||||||
}
|
}
|
||||||
if (!isInQueue) {
|
if (!isInQueue) {
|
||||||
|
|
|
@ -32,6 +32,14 @@
|
||||||
android:summary="@string/pref_nav_drawer_feed_counter_sum"
|
android:summary="@string/pref_nav_drawer_feed_counter_sum"
|
||||||
android:defaultValue="0"
|
android:defaultValue="0"
|
||||||
app:useStockLayout="true"/>
|
app:useStockLayout="true"/>
|
||||||
|
<ListPreference
|
||||||
|
android:entryValues="@array/nav_queue_sort_values"
|
||||||
|
android:entries="@array/nav_queue_sort_options"
|
||||||
|
android:title="@string/pref_queue_sort_title"
|
||||||
|
android:key="prefQueueSortOrder"
|
||||||
|
android:summary="@string/pref_queue_sort_sum"
|
||||||
|
android:defaultValue="MANUALLY"
|
||||||
|
app:useStockLayout="true"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/external_elements">
|
<PreferenceCategory android:title="@string/external_elements">
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class UserPreferences {
|
||||||
private static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
|
private static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
|
||||||
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
|
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
|
||||||
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
|
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
|
||||||
|
public static final String PREF_QUEUE_SORT_ORDER = "prefQueueSortOrder";
|
||||||
|
|
||||||
// Queue
|
// Queue
|
||||||
private static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront";
|
private static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront";
|
||||||
|
@ -506,7 +507,8 @@ public class UserPreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isQueueLocked() {
|
public static boolean isQueueLocked() {
|
||||||
return prefs.getBoolean(PREF_QUEUE_LOCKED, false);
|
return prefs.getBoolean(PREF_QUEUE_LOCKED, false)
|
||||||
|
|| !isQueueSortedManually();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setFastForwardSecs(int secs) {
|
public static void setFastForwardSecs(int secs) {
|
||||||
|
@ -894,4 +896,32 @@ public class UserPreferences {
|
||||||
public static boolean timeRespectsSpeed() {
|
public static boolean timeRespectsSpeed() {
|
||||||
return prefs.getBoolean(PREF_TIME_RESPECTS_SPEED, false);
|
return prefs.getBoolean(PREF_TIME_RESPECTS_SPEED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported episode queue sort orders.
|
||||||
|
* Use enum instead of integer to avoid mistakes at later maintenance changes.
|
||||||
|
*/
|
||||||
|
public enum QueueSortOrder {
|
||||||
|
MANUALLY, DATE_NEW_OLD, DATE_OLD_NEW, DURATION_SHORT_LONG, DURATION_LONG_SHORT,
|
||||||
|
EPISODE_TITLE_A_Z, EPISODE_TITLE_Z_A, FEED_TITLE_A_Z, FEED_TITLE_Z_A
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueueSortOrder getQueueSortOrder() {
|
||||||
|
String sortOrderStr = prefs.getString(PREF_QUEUE_SORT_ORDER, "default");
|
||||||
|
return parseQueueSortOrder(sortOrderStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueueSortOrder parseQueueSortOrder(String value) {
|
||||||
|
try {
|
||||||
|
return QueueSortOrder.valueOf(value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// default value
|
||||||
|
return QueueSortOrder.MANUALLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isQueueSortedManually() {
|
||||||
|
QueueSortOrder sortedOrder = getQueueSortOrder();
|
||||||
|
return sortedOrder == QueueSortOrder.MANUALLY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||||
import de.danoeh.antennapod.core.util.LongList;
|
import de.danoeh.antennapod.core.util.LongList;
|
||||||
import de.danoeh.antennapod.core.util.Permutor;
|
import de.danoeh.antennapod.core.util.Permutor;
|
||||||
|
import de.danoeh.antennapod.core.util.QueueSorter;
|
||||||
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
|
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
|
||||||
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
|
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
|
||||||
import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing;
|
import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing;
|
||||||
|
@ -388,6 +389,7 @@ public class DBWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (queueModified) {
|
if (queueModified) {
|
||||||
|
applySortOrder(queue, events);
|
||||||
adapter.setQueue(queue);
|
adapter.setQueue(queue);
|
||||||
for (QueueEvent event : events) {
|
for (QueueEvent event : events) {
|
||||||
EventBus.getDefault().post(event);
|
EventBus.getDefault().post(event);
|
||||||
|
@ -406,6 +408,29 @@ public class DBWriter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the queue depending on the configured sort order. If manual order is configured, the queue is not modified.
|
||||||
|
*
|
||||||
|
* @param queue The queue to be sorted.
|
||||||
|
* @param events Replaces the events by a single SORT event if the list has to be sorted automatically.
|
||||||
|
*/
|
||||||
|
private static void applySortOrder(List<FeedItem> queue, List<QueueEvent> events) {
|
||||||
|
if (UserPreferences.isQueueSortedManually()) {
|
||||||
|
// automatic sort order is disabled, don't change anything
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort queue by configured sort order
|
||||||
|
UserPreferences.QueueSortOrder sortOrder = UserPreferences.getQueueSortOrder();
|
||||||
|
QueueSorter.Rule sortRule = QueueSorter.queueSortOrder2Rule(sortOrder);
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(sortRule);
|
||||||
|
permutor.reorder(queue);
|
||||||
|
|
||||||
|
// Replace ADDED events by a single SORTED event
|
||||||
|
events.clear();
|
||||||
|
events.add(QueueEvent.sorted(queue));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all FeedItem objects from the queue.
|
* Removes all FeedItem objects from the queue.
|
||||||
*
|
*
|
||||||
|
@ -964,31 +989,8 @@ public class DBWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the FeedItems in the queue with the given Comparator.
|
* Sort the FeedItems in the queue with the given Permutor.
|
||||||
* @param comparator FeedItem comparator
|
*
|
||||||
* @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
|
|
||||||
*/
|
|
||||||
public static Future<?> sortQueue(final Comparator<FeedItem> comparator, final boolean broadcastUpdate) {
|
|
||||||
return dbExec.submit(() -> {
|
|
||||||
final PodDBAdapter adapter = PodDBAdapter.getInstance();
|
|
||||||
adapter.open();
|
|
||||||
final List<FeedItem> queue = DBReader.getQueue(adapter);
|
|
||||||
|
|
||||||
if (queue != null) {
|
|
||||||
Collections.sort(queue, comparator);
|
|
||||||
adapter.setQueue(queue);
|
|
||||||
if (broadcastUpdate) {
|
|
||||||
EventBus.getDefault().post(QueueEvent.sorted(queue));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "sortQueue: Could not load queue");
|
|
||||||
}
|
|
||||||
adapter.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to sortQueue, but allows more complex reordering by providing whole-queue context.
|
|
||||||
* @param permutor Encapsulates whole-Queue reordering logic.
|
* @param permutor Encapsulates whole-Queue reordering logic.
|
||||||
* @param broadcastUpdate <code>true</code> if this operation should trigger a
|
* @param broadcastUpdate <code>true</code> if this operation should trigger a
|
||||||
* QueueUpdateBroadcast. This option should be set to <code>false</code>
|
* QueueUpdateBroadcast. This option should be set to <code>false</code>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package de.danoeh.antennapod.core.util;
|
package de.danoeh.antennapod.core.util;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -11,6 +9,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +30,30 @@ public class QueueSorter {
|
||||||
SMART_SHUFFLE_DESC
|
SMART_SHUFFLE_DESC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(final Context context, final Rule rule, final boolean broadcastUpdate) {
|
/**
|
||||||
|
* Sorts the queue by the given rule and sends a broadcast update.
|
||||||
|
*
|
||||||
|
* @param rule Sort rule.
|
||||||
|
* @param broadcastUpdate Send broadcast update?
|
||||||
|
*/
|
||||||
|
public static void sort(Rule rule, boolean broadcastUpdate) {
|
||||||
|
Permutor<FeedItem> permutor = getPermutor(rule);
|
||||||
|
if (permutor != null) {
|
||||||
|
DBWriter.reorderQueue(permutor, broadcastUpdate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Permutor that sorts a list appropriate to the given sort rule.
|
||||||
|
*
|
||||||
|
* @param rule Sort rule.
|
||||||
|
* @return Permutor that sorts a list appropriate to the given sort rule. <code>null</code> if the rule is unknown or <code>null</code>.
|
||||||
|
*/
|
||||||
|
public static Permutor<FeedItem> getPermutor(Rule rule) {
|
||||||
|
if (rule == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Comparator<FeedItem> comparator = null;
|
Comparator<FeedItem> comparator = null;
|
||||||
Permutor<FeedItem> permutor = null;
|
Permutor<FeedItem> permutor = null;
|
||||||
|
|
||||||
|
@ -86,13 +108,44 @@ public class QueueSorter {
|
||||||
case SMART_SHUFFLE_DESC:
|
case SMART_SHUFFLE_DESC:
|
||||||
permutor = (queue) -> smartShuffle(queue, false);
|
permutor = (queue) -> smartShuffle(queue, false);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comparator != null) {
|
if (comparator != null) {
|
||||||
DBWriter.sortQueue(comparator, broadcastUpdate);
|
final Comparator<FeedItem> comparator2 = comparator;
|
||||||
} else if (permutor != null) {
|
permutor = (queue) -> Collections.sort(queue, comparator2);
|
||||||
DBWriter.reorderQueue(permutor, broadcastUpdate);
|
}
|
||||||
|
return permutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a QueueSortOrder value to its corresponding Rule value.
|
||||||
|
*
|
||||||
|
* @param sortOrder Sort order.
|
||||||
|
* @return Rule value corresponding to the given sort order. <code>null</code> if the sort order is unknown or <code>null</code>.
|
||||||
|
*/
|
||||||
|
public static Rule queueSortOrder2Rule(UserPreferences.QueueSortOrder sortOrder) {
|
||||||
|
if (sortOrder == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (sortOrder) {
|
||||||
|
case DATE_NEW_OLD:
|
||||||
|
return QueueSorter.Rule.DATE_DESC;
|
||||||
|
case DATE_OLD_NEW:
|
||||||
|
return QueueSorter.Rule.DATE_ASC;
|
||||||
|
case DURATION_SHORT_LONG:
|
||||||
|
return QueueSorter.Rule.DURATION_ASC;
|
||||||
|
case DURATION_LONG_SHORT:
|
||||||
|
return QueueSorter.Rule.DURATION_DESC;
|
||||||
|
case EPISODE_TITLE_A_Z:
|
||||||
|
return QueueSorter.Rule.EPISODE_TITLE_ASC;
|
||||||
|
case EPISODE_TITLE_Z_A:
|
||||||
|
return QueueSorter.Rule.EPISODE_TITLE_DESC;
|
||||||
|
case FEED_TITLE_A_Z:
|
||||||
|
return QueueSorter.Rule.FEED_TITLE_ASC;
|
||||||
|
case FEED_TITLE_Z_A:
|
||||||
|
return QueueSorter.Rule.FEED_TITLE_DESC;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,8 @@
|
||||||
<string name="ascending">Aufsteigend</string>
|
<string name="ascending">Aufsteigend</string>
|
||||||
<string name="descending">Absteigend</string>
|
<string name="descending">Absteigend</string>
|
||||||
<string name="clear_queue_confirmation_msg">Bitte bestätige, dass ALLE Episoden aus der Abspielliste entfernt werden sollen</string>
|
<string name="clear_queue_confirmation_msg">Bitte bestätige, dass ALLE Episoden aus der Abspielliste entfernt werden sollen</string>
|
||||||
|
<string name="sort_new_to_old">Neu bis alt</string>
|
||||||
|
<string name="sort_old_to_new">Alt bis neu</string>
|
||||||
<!--Flattr-->
|
<!--Flattr-->
|
||||||
<string name="flattr_auth_label">Flattr Anmeldung</string>
|
<string name="flattr_auth_label">Flattr Anmeldung</string>
|
||||||
<string name="flattr_auth_explanation">Drücke den Button unten, um den Authentifizierungsprozess zu starten. Du wirst zur Flattr-Anmeldeseite weitergeleitet. Hier wirst du gefragt, AntennaPod die Erlaubnis zu geben, Dinge zu flattrn. Nachdem du die Erlaubnis erteilt hast, kehrst du automatisch zu diesem Bildschirm zurück.</string>
|
<string name="flattr_auth_explanation">Drücke den Button unten, um den Authentifizierungsprozess zu starten. Du wirst zur Flattr-Anmeldeseite weitergeleitet. Hier wirst du gefragt, AntennaPod die Erlaubnis zu geben, Dinge zu flattrn. Nachdem du die Erlaubnis erteilt hast, kehrst du automatisch zu diesem Bildschirm zurück.</string>
|
||||||
|
@ -414,6 +416,8 @@
|
||||||
<string name="pref_nav_drawer_feed_order_sum">Ändere die Reihenfolge deiner Abonnements</string>
|
<string name="pref_nav_drawer_feed_order_sum">Ändere die Reihenfolge deiner Abonnements</string>
|
||||||
<string name="pref_nav_drawer_feed_counter_title">Abonnement-Zähler einstellen</string>
|
<string name="pref_nav_drawer_feed_counter_title">Abonnement-Zähler einstellen</string>
|
||||||
<string name="pref_nav_drawer_feed_counter_sum">Ändere die durch den Abonnementszähler angezeigten Informationen. Betrifft auch die Sortierung der Abonnements wenn \"Reihenfolge der Abonnements\" auf \"Zähler\" gesetzt ist.</string>
|
<string name="pref_nav_drawer_feed_counter_sum">Ändere die durch den Abonnementszähler angezeigten Informationen. Betrifft auch die Sortierung der Abonnements wenn \"Reihenfolge der Abonnements\" auf \"Zähler\" gesetzt ist.</string>
|
||||||
|
<string name="pref_queue_sort_title">Sortierung der Abspielliste einstellen</string>
|
||||||
|
<string name="pref_queue_sort_sum">Ändere die Sortierreihenfolge der Episoden in der Abspielliste.</string>
|
||||||
<string name="pref_set_theme_sum">Ändere das Aussehen von AntennaPod.</string>
|
<string name="pref_set_theme_sum">Ändere das Aussehen von AntennaPod.</string>
|
||||||
<string name="pref_automatic_download_title">Automatisches Herunterladen</string>
|
<string name="pref_automatic_download_title">Automatisches Herunterladen</string>
|
||||||
<string name="pref_automatic_download_sum">Konfiguriere das automatische Herunterladen von Episoden.</string>
|
<string name="pref_automatic_download_sum">Konfiguriere das automatische Herunterladen von Episoden.</string>
|
||||||
|
@ -686,6 +690,11 @@
|
||||||
<string name="sort_date_old_new">Datum (alt \u2192 neu)</string>
|
<string name="sort_date_old_new">Datum (alt \u2192 neu)</string>
|
||||||
<string name="sort_duration_short_long">Dauer (kurz \u2192 lang)</string>
|
<string name="sort_duration_short_long">Dauer (kurz \u2192 lang)</string>
|
||||||
<string name="sort_duration_long_short">Dauer (lang \u2192 kurz)</string>
|
<string name="sort_duration_long_short">Dauer (lang \u2192 kurz)</string>
|
||||||
|
<string name="sort_episode_title_a_z">Episodentitel (A \u2192 Z)</string>
|
||||||
|
<string name="sort_episode_title_z_a">Episodentitel (Z \u2192 A)</string>
|
||||||
|
<string name="sort_feed_title_a_z">Podcasttitel (A \u2192 Z)</string>
|
||||||
|
<string name="sort_feed_title_z_a">Podcasttitel (Z \u2192 A)</string>
|
||||||
|
<string name="sort_manually">Manuell</string>
|
||||||
<!--Rating dialog-->
|
<!--Rating dialog-->
|
||||||
<string name="rating_title">Gefällt dir AntennaPod?</string>
|
<string name="rating_title">Gefällt dir AntennaPod?</string>
|
||||||
<string name="rating_message">Wir würden uns freuen, wenn du dir kurz die Zeit nimmst, AntennaPod zu bewerten.</string>
|
<string name="rating_message">Wir würden uns freuen, wenn du dir kurz die Zeit nimmst, AntennaPod zu bewerten.</string>
|
||||||
|
|
|
@ -187,6 +187,29 @@
|
||||||
<item>3</item>
|
<item>3</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="nav_queue_sort_options">
|
||||||
|
<item>@string/sort_manually</item>
|
||||||
|
<item>@string/sort_date_new_old</item>
|
||||||
|
<item>@string/sort_date_old_new</item>
|
||||||
|
<item>@string/sort_duration_short_long</item>
|
||||||
|
<item>@string/sort_duration_long_short</item>
|
||||||
|
<item>@string/sort_episode_title_a_z</item>
|
||||||
|
<item>@string/sort_episode_title_z_a</item>
|
||||||
|
<item>@string/sort_feed_title_a_z</item>
|
||||||
|
<item>@string/sort_feed_title_z_a</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="nav_queue_sort_values">
|
||||||
|
<item>MANUALLY</item>
|
||||||
|
<item>DATE_NEW_OLD</item>
|
||||||
|
<item>DATE_OLD_NEW</item>
|
||||||
|
<item>DURATION_SHORT_LONG</item>
|
||||||
|
<item>DURATION_LONG_SHORT</item>
|
||||||
|
<item>EPISODE_TITLE_A_Z</item>
|
||||||
|
<item>EPISODE_TITLE_Z_A</item>
|
||||||
|
<item>FEED_TITLE_A_Z</item>
|
||||||
|
<item>FEED_TITLE_Z_A</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="nav_drawer_feed_counter_options">
|
<string-array name="nav_drawer_feed_counter_options">
|
||||||
<item>@string/drawer_feed_counter_new_unplayed</item>
|
<item>@string/drawer_feed_counter_new_unplayed</item>
|
||||||
<item>@string/drawer_feed_counter_new</item>
|
<item>@string/drawer_feed_counter_new</item>
|
||||||
|
|
|
@ -438,6 +438,8 @@
|
||||||
<string name="pref_nav_drawer_feed_order_sum">Change the order of your subscriptions</string>
|
<string name="pref_nav_drawer_feed_order_sum">Change the order of your subscriptions</string>
|
||||||
<string name="pref_nav_drawer_feed_counter_title">Set Subscription Counter</string>
|
<string name="pref_nav_drawer_feed_counter_title">Set Subscription Counter</string>
|
||||||
<string name="pref_nav_drawer_feed_counter_sum">Change the information displayed by the subscription counter. Also affects the sorting of subscriptions if \'Subscription Order\' is set to \'Counter\'.</string>
|
<string name="pref_nav_drawer_feed_counter_sum">Change the information displayed by the subscription counter. Also affects the sorting of subscriptions if \'Subscription Order\' is set to \'Counter\'.</string>
|
||||||
|
<string name="pref_queue_sort_title">Set Queue Sort Order</string>
|
||||||
|
<string name="pref_queue_sort_sum">Change the sort order of the episodes in the queue.</string>
|
||||||
<string name="pref_set_theme_sum">Change the appearance of AntennaPod.</string>
|
<string name="pref_set_theme_sum">Change the appearance of AntennaPod.</string>
|
||||||
<string name="pref_automatic_download_title">Automatic Download</string>
|
<string name="pref_automatic_download_title">Automatic Download</string>
|
||||||
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
|
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
|
||||||
|
@ -735,6 +737,11 @@
|
||||||
<string name="sort_date_old_new">Date (Old \u2192 New)</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_short_long">Duration (Short \u2192 Long)</string>
|
||||||
<string name="sort_duration_long_short">Duration (Long \u2192 Short)</string>
|
<string name="sort_duration_long_short">Duration (Long \u2192 Short)</string>
|
||||||
|
<string name="sort_episode_title_a_z">Episode title (A \u2192 Z)</string>
|
||||||
|
<string name="sort_episode_title_z_a">Episode title (Z \u2192 A)</string>
|
||||||
|
<string name="sort_feed_title_a_z">Podcast title (A \u2192 Z)</string>
|
||||||
|
<string name="sort_feed_title_z_a">Podcast title (Z \u2192 A)</string>
|
||||||
|
<string name="sort_manually">Manually</string>
|
||||||
|
|
||||||
<!-- Rating dialog -->
|
<!-- Rating dialog -->
|
||||||
<string name="rating_title">Like AntennaPod?</string>
|
<string name="rating_title">Like AntennaPod?</string>
|
||||||
|
|
|
@ -29,4 +29,13 @@ public class TextUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the string is <code>null</code> or has zero length.
|
||||||
|
*
|
||||||
|
* @param str The string to be examined, can be <code>null</code>.
|
||||||
|
* @return <code>true</code> if the string is <code>null</code> or has zero length.
|
||||||
|
*/
|
||||||
|
public static boolean isEmpty(CharSequence str) {
|
||||||
|
return str == null || str.length() == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package de.danoeh.antennapod.core.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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.assertTrue;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for QueueSorter.
|
||||||
|
*/
|
||||||
|
public class QueueSorterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_null() {
|
||||||
|
assertNull(QueueSorter.getPermutor(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_EPISODE_TITLE_ASC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.EPISODE_TITLE_ASC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_EPISODE_TITLE_DESC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.EPISODE_TITLE_DESC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_DATE_ASC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.DATE_ASC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_DATE_DESC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.DATE_DESC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_DURATION_ASC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.DURATION_ASC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_DURATION_DESC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.DURATION_DESC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_FEED_TITLE_ASC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.FEED_TITLE_ASC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 2, 3)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermutorForRule_FEED_TITLE_DESC() {
|
||||||
|
Permutor<FeedItem> permutor = QueueSorter.getPermutor(QueueSorter.Rule.FEED_TITLE_DESC);
|
||||||
|
|
||||||
|
List<FeedItem> itemList = getTestList();
|
||||||
|
assertTrue(checkIdOrder(itemList, 1, 3, 2)); // before sorting
|
||||||
|
permutor.reorder(itemList);
|
||||||
|
assertTrue(checkIdOrder(itemList, 3, 2, 1)); // after sorting
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a list with test data.
|
||||||
|
*/
|
||||||
|
private List<FeedItem> getTestList() {
|
||||||
|
List<FeedItem> itemList = new ArrayList<>();
|
||||||
|
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.set(2019, 0, 1); // January 1st
|
||||||
|
Feed feed1 = new Feed(null, null, "Feed title 1");
|
||||||
|
FeedItem feedItem1 = new FeedItem(1, "Title 1", null, null, calendar.getTime(), 0, feed1);
|
||||||
|
FeedMedia feedMedia1 = new FeedMedia(0, feedItem1, 1000, 0, 0, null, null, null, true, null, 0, 0);
|
||||||
|
feedItem1.setMedia(feedMedia1);
|
||||||
|
itemList.add(feedItem1);
|
||||||
|
|
||||||
|
calendar.set(2019, 2, 1); // March 1st
|
||||||
|
Feed feed2 = new Feed(null, null, "Feed title 3");
|
||||||
|
FeedItem feedItem2 = new FeedItem(3, "Title 3", null, null, calendar.getTime(), 0, feed2);
|
||||||
|
FeedMedia feedMedia2 = new FeedMedia(0, feedItem2, 3000, 0, 0, null, null, null, true, null, 0, 0);
|
||||||
|
feedItem2.setMedia(feedMedia2);
|
||||||
|
itemList.add(feedItem2);
|
||||||
|
|
||||||
|
calendar.set(2019, 1, 1); // February 1st
|
||||||
|
Feed feed3 = new Feed(null, null, "Feed title 2");
|
||||||
|
FeedItem feedItem3 = new FeedItem(2, "Title 2", null, null, calendar.getTime(), 0, feed3);
|
||||||
|
FeedMedia feedMedia3 = new FeedMedia(0, feedItem3, 2000, 0, 0, null, null, null, true, null, 0, 0);
|
||||||
|
feedItem3.setMedia(feedMedia3);
|
||||||
|
itemList.add(feedItem3);
|
||||||
|
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if both lists have the same size and the same ID order.
|
||||||
|
*
|
||||||
|
* @param itemList Item list.
|
||||||
|
* @param ids List of IDs.
|
||||||
|
* @return <code>true</code> if both lists have the same size and the same ID order.
|
||||||
|
*/
|
||||||
|
private boolean checkIdOrder(List<FeedItem> itemList, long... ids) {
|
||||||
|
if (itemList.size() != ids.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
if (itemList.get(i).getId() != ids[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue