Use natural ordering for lists and filters

gtask_related_email
Alex Baker 6 years ago
parent 2f37c76d93
commit 1b35cd5dd4

@ -11,9 +11,11 @@ import static com.google.common.collect.Lists.transform;
import com.todoroo.astrid.api.CustomFilter; import com.todoroo.astrid.api.CustomFilter;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.data.FilterDao; import org.tasks.data.FilterDao;
import org.tasks.filters.AlphanumComparator;
public final class CustomFilterExposer { public final class CustomFilterExposer {
@ -25,7 +27,9 @@ public final class CustomFilterExposer {
} }
public List<Filter> getFilters() { public List<Filter> getFilters() {
return newArrayList(transform(filterDao.getFilters(), this::load)); List<Filter> filters = newArrayList(transform(filterDao.getFilters(), this::load));
Collections.sort(filters, new AlphanumComparator());
return filters;
} }
public Filter getFilter(long id) { public Filter getFilter(long id) {

@ -11,6 +11,7 @@ import static com.todoroo.andlib.utility.DateUtilities.now;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.GtasksFilter; import com.todoroo.astrid.api.GtasksFilter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -18,6 +19,7 @@ import javax.inject.Inject;
import org.tasks.data.GoogleTaskAccount; import org.tasks.data.GoogleTaskAccount;
import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao; import org.tasks.data.GoogleTaskListDao;
import org.tasks.filters.AlphanumComparator;
import org.tasks.filters.GoogleTaskFilters; import org.tasks.filters.GoogleTaskFilters;
import org.tasks.sync.SyncAdapters; import org.tasks.sync.SyncAdapters;
@ -53,6 +55,9 @@ public class GtasksFilterExposer {
filters.get(filter.googleTaskAccount).add(filter.toGtasksFilter()); filters.get(filter.googleTaskAccount).add(filter.toGtasksFilter());
} }
} }
for (Map.Entry<GoogleTaskAccount, List<Filter>> entry : filters.entrySet()) {
Collections.sort(entry.getValue(), new AlphanumComparator());
}
return filters; return filters;
} }

@ -6,16 +6,19 @@
package com.todoroo.astrid.tags; package com.todoroo.astrid.tags;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform; import static com.google.common.collect.Lists.transform;
import static com.todoroo.andlib.utility.DateUtilities.now; import static com.todoroo.andlib.utility.DateUtilities.now;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.TagFilter; import com.todoroo.astrid.api.TagFilter;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.data.TagData; import org.tasks.data.TagData;
import org.tasks.data.TagDataDao; import org.tasks.data.TagDataDao;
import org.tasks.filters.AlphanumComparator;
import org.tasks.filters.TagFilters; import org.tasks.filters.TagFilters;
/** /**
@ -41,7 +44,10 @@ public class TagFilterExposer {
} }
public List<Filter> getFilters() { public List<Filter> getFilters() {
return transform(tagDataDao.getTagFilters(now()), TagFilters::toTagFilter); List<Filter> tags =
newArrayList(transform(tagDataDao.getTagFilters(now()), TagFilters::toTagFilter));
Collections.sort(tags, new AlphanumComparator());
return tags;
} }
public Filter getFilterByUuid(String uuid) { public Filter getFilterByUuid(String uuid) {

@ -5,6 +5,7 @@ import static com.todoroo.andlib.utility.DateUtilities.now;
import com.todoroo.astrid.api.CaldavFilter; import com.todoroo.astrid.api.CaldavFilter;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -12,6 +13,7 @@ import javax.inject.Inject;
import org.tasks.data.CaldavAccount; import org.tasks.data.CaldavAccount;
import org.tasks.data.CaldavCalendar; import org.tasks.data.CaldavCalendar;
import org.tasks.data.CaldavDao; import org.tasks.data.CaldavDao;
import org.tasks.filters.AlphanumComparator;
import org.tasks.filters.CaldavFilters; import org.tasks.filters.CaldavFilters;
import org.tasks.sync.SyncAdapters; import org.tasks.sync.SyncAdapters;
@ -37,6 +39,9 @@ public class CaldavFilterExposer {
filters.get(filter.caldavAccount).add(filter.toCaldavFilter()); filters.get(filter.caldavAccount).add(filter.toCaldavFilter());
} }
} }
for (Map.Entry<CaldavAccount, List<Filter>> entry : filters.entrySet()) {
Collections.sort(entry.getValue(), new AlphanumComparator());
}
return filters; return filters;
} }

@ -132,7 +132,7 @@ public abstract class CaldavDao {
+ " LEFT JOIN caldav_tasks ON caldav_tasks.cd_calendar = caldav_lists.cdl_uuid" + " LEFT JOIN caldav_tasks ON caldav_tasks.cd_calendar = caldav_lists.cdl_uuid"
+ " LEFT JOIN tasks ON caldav_tasks.cd_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now AND cd_deleted = 0" + " LEFT JOIN tasks ON caldav_tasks.cd_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now AND cd_deleted = 0"
+ " GROUP BY caldav_lists.cdl_uuid" + " GROUP BY caldav_lists.cdl_uuid"
+ " ORDER BY caldav_accounts.cda_name COLLATE NOCASE, caldav_lists.cdl_name COLLATE NOCASE") + " ORDER BY caldav_accounts.cda_name COLLATE NOCASE")
public abstract List<CaldavFilters> getCaldavFilters(long now); public abstract List<CaldavFilters> getCaldavFilters(long now);
@Query( @Query(

@ -25,7 +25,7 @@ public interface FilterDao {
@Insert @Insert
void insert(Filter filter); void insert(Filter filter);
@Query("SELECT * FROM filters ORDER BY title ASC") @Query("SELECT * FROM filters")
List<Filter> getFilters(); List<Filter> getFilters();
@Query("SELECT * FROM filters WHERE _id = :id LIMIT 1") @Query("SELECT * FROM filters WHERE _id = :id LIMIT 1")

@ -66,6 +66,6 @@ public abstract class GoogleTaskListDao {
+ " LEFT JOIN google_tasks ON google_tasks.gt_list_id = google_task_lists.gtl_remote_id" + " LEFT JOIN google_tasks ON google_tasks.gt_list_id = google_task_lists.gtl_remote_id"
+ " LEFT JOIN tasks ON google_tasks.gt_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now AND gt_deleted = 0" + " LEFT JOIN tasks ON google_tasks.gt_task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now AND gt_deleted = 0"
+ " GROUP BY google_task_lists.gtl_remote_id" + " GROUP BY google_task_lists.gtl_remote_id"
+ " ORDER BY google_task_lists.gtl_account COLLATE NOCASE, google_task_lists.gtl_title COLLATE NOCASE") + " ORDER BY google_task_lists.gtl_account COLLATE NOCASE")
public abstract List<GoogleTaskFilters> getGoogleTaskFilters(long now); public abstract List<GoogleTaskFilters> getGoogleTaskFilters(long now);
} }

@ -82,7 +82,6 @@ public abstract class TagDataDao {
+ " LEFT JOIN tags ON tags.tag_uid = tagdata.remoteId" + " LEFT JOIN tags ON tags.tag_uid = tagdata.remoteId"
+ " LEFT JOIN tasks ON tags.task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now" + " LEFT JOIN tasks ON tags.task = tasks._id AND tasks.deleted = 0 AND tasks.completed = 0 AND tasks.hideUntil < :now"
+ " WHERE tagdata.name IS NOT NULL AND tagdata.name != ''" + " WHERE tagdata.name IS NOT NULL AND tagdata.name != ''"
+ " GROUP BY tagdata.remoteId" + " GROUP BY tagdata.remoteId")
+ " ORDER BY tagdata.name COLLATE NOCASE")
public abstract List<TagFilters> getTagFilters(long now); public abstract List<TagFilters> getTagFilters(long now);
} }

@ -0,0 +1,114 @@
package org.tasks.filters;
/*
* The Alphanum Algorithm is an improved sorting algorithm for strings
* containing numbers. Instead of sorting numbers in ASCII order like
* a standard sort, this algorithm sorts numbers in numeric order.
*
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
*
* Released under the MIT License - https://opensource.org/licenses/MIT
*
* Copyright 2007-2017 David Koelle
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import com.todoroo.astrid.api.Filter;
import java.util.Comparator;
/**
* This is an updated version with enhancements made by Daniel Migowski, Andre Bogus, and David
* Koelle. Updated by David Koelle in 2017.
*
* <p>To use this class: Use the static "sort" method from the java.util.Collections class:
* Collections.sort(your list, new AlphanumComparator());
*/
public class AlphanumComparator implements Comparator<Filter> {
private boolean isDigit(char ch) {
return ((ch >= 48) && (ch <= 57));
}
/** Length of string is passed in for improved efficiency (only need to calculate it once) * */
private String getChunk(String s, int slength, int marker) {
StringBuilder chunk = new StringBuilder();
char c = s.charAt(marker);
chunk.append(c);
marker++;
if (isDigit(c)) {
while (marker < slength) {
c = s.charAt(marker);
if (!isDigit(c)) break;
chunk.append(c);
marker++;
}
} else {
while (marker < slength) {
c = s.charAt(marker);
if (isDigit(c)) break;
chunk.append(c);
marker++;
}
}
return chunk.toString();
}
public int compare(Filter f1, Filter f2) {
String s1 = f1.listingTitle;
String s2 = f2.listingTitle;
if ((s1 == null) || (s2 == null)) {
return 0;
}
int thisMarker = 0;
int thatMarker = 0;
int s1Length = s1.length();
int s2Length = s2.length();
while (thisMarker < s1Length && thatMarker < s2Length) {
String thisChunk = getChunk(s1, s1Length, thisMarker);
thisMarker += thisChunk.length();
String thatChunk = getChunk(s2, s2Length, thatMarker);
thatMarker += thatChunk.length();
// If both chunks contain numeric characters, sort them numerically
int result;
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
// Simple chunk comparison by length.
int thisChunkLength = thisChunk.length();
result = thisChunkLength - thatChunk.length();
// If equal, the first different number counts
if (result == 0) {
for (int i = 0; i < thisChunkLength; i++) {
result = thisChunk.charAt(i) - thatChunk.charAt(i);
if (result != 0) {
return result;
}
}
}
} else {
result = thisChunk.compareTo(thatChunk);
}
if (result != 0) return result;
}
return s1Length - s2Length;
}
}
Loading…
Cancel
Save