You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tasks/app/src/main/java/com/todoroo/astrid/core/SortHelper.java

239 lines
7.4 KiB
Java

/*
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.core;
import static org.tasks.db.QueryUtils.showCompleted;
import static org.tasks.db.QueryUtils.showHidden;
import android.annotation.SuppressLint;
import androidx.annotation.Nullable;
import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Order;
import com.todoroo.astrid.data.Task;
import org.tasks.preferences.QueryPreferences;
/**
* Helpers for sorting a list of tasks
*
* @author Tim Su <tim@todoroo.com>
*/
public class SortHelper {
public static final int SORT_AUTO = 0;
public static final int SORT_ALPHA = 1;
public static final int SORT_DUE = 2;
public static final int SORT_IMPORTANCE = 3;
public static final int SORT_MODIFIED = 4;
public static final int SORT_CREATED = 5;
public static final int SORT_GTASKS = 6;
public static final int SORT_CALDAV = 7;
public static final int SORT_START = 8;
public static final long APPLE_EPOCH = 978307200000L; // 1/1/2001 GMT
@SuppressLint("DefaultLocale")
public static final String CALDAV_ORDER_COLUMN =
String.format("IFNULL(tasks.`order`, (tasks.created - %d) / 1000)", APPLE_EPOCH);
private static final String ADJUSTED_DUE_DATE =
"(CASE WHEN (dueDate / 1000) % 60 > 0 THEN dueDate ELSE (dueDate + 43140000) END)";
private static final String ADJUSTED_START_DATE =
"(CASE WHEN (hideUntil / 1000) % 60 > 0 THEN hideUntil ELSE (hideUntil + 86399000) END)";
private static final Order ORDER_TITLE = Order.asc(Functions.upper(Task.TITLE));
/** Takes a SQL query, and if there isn't already an order, creates an order. */
public static String adjustQueryForFlagsAndSort(
QueryPreferences preferences, String originalSql, int sort) {
// sort
if (originalSql == null) {
originalSql = "";
}
if (!originalSql.toUpperCase().contains("ORDER BY")) {
Order order = orderForSortType(sort);
if (preferences.isReverseSort()) {
order = order.reverse();
}
originalSql += " ORDER BY " + order;
}
return adjustQueryForFlags(preferences, originalSql);
}
public static String adjustQueryForFlags(QueryPreferences preferences, String originalSql) {
String adjustedSql = originalSql;
// flags
if (preferences.getShowCompleted()) {
adjustedSql = showCompleted(adjustedSql);
}
if (preferences.getShowHidden()) {
adjustedSql = showHidden(adjustedSql);
}
return adjustedSql;
}
private static Order orderForSortType(int sortType) {
Order order;
switch (sortType) {
case SORT_ALPHA:
order = ORDER_TITLE;
break;
case SORT_DUE:
order =
Order.asc(
"(CASE WHEN (dueDate=0) THEN (strftime('%s','now')*1000)*2 ELSE "
+ ADJUSTED_DUE_DATE
+ " END)+importance");
break;
case SORT_START:
order =
Order.asc(
"(CASE WHEN (hideUntil=0) THEN (strftime('%s','now')*1000)*2 ELSE "
+ ADJUSTED_START_DATE
+ " END)+importance");
break;
case SORT_IMPORTANCE:
order =
Order.asc(
"importance*(strftime('%s','now')*1000)+(CASE WHEN (dueDate=0) THEN (strftime('%s','now')*1000) ELSE dueDate END)");
break;
case SORT_MODIFIED:
order = Order.desc(Task.MODIFICATION_DATE);
break;
case SORT_CREATED:
order = Order.desc(Task.CREATION_DATE);
break;
default:
order =
Order.asc(
"(CASE WHEN (dueDate=0) "
+ // if no due date
"THEN (strftime('%s','now')*1000)*2 "
+ // then now * 2
"ELSE ("
+ ADJUSTED_DUE_DATE
+ ") END) "
+ // else due time
// add slightly less than 2 days * importance to give due date priority over importance in case of tie
"+ 172799999 * importance");
}
if (sortType != SORT_ALPHA) {
order.addSecondaryExpression(ORDER_TITLE);
}
return order;
}
public static @Nullable String getSortGroup(int sortType) {
switch (sortType) {
case SORT_DUE:
return "tasks.dueDate";
case SORT_START:
return "tasks.hideUntil";
case SORT_IMPORTANCE:
return "tasks.importance";
case SORT_MODIFIED:
return "tasks.modified";
case SORT_CREATED:
return "tasks.created";
default:
return null;
}
}
public static String orderSelectForSortTypeRecursive(int sortType) {
String select;
switch (sortType) {
case SORT_ALPHA:
// Return an empty string, providing a value to fill the WITH clause template
select = "''";
break;
case SORT_DUE:
select = "(CASE WHEN (tasks.dueDate=0) THEN (strftime('%s','now')*1000)*2 ELSE "
+ ADJUSTED_DUE_DATE.replace("dueDate", "tasks.dueDate")
+ " END)+tasks.importance AS sort_duedate";
break;
case SORT_START:
select = "(CASE WHEN (tasks.hideUntil=0) THEN (strftime('%s','now')*1000)*2 ELSE "
+ ADJUSTED_START_DATE.replace("hideUntil", "tasks.hideUntil")
+ " END)+tasks.importance AS sort_startdate";
break;
case SORT_IMPORTANCE:
select = "tasks.importance*(strftime('%s','now')*1000)+(CASE WHEN (tasks.dueDate=0) THEN (strftime('%s','now')*1000) ELSE tasks.dueDate END) AS sort_importance";
break;
case SORT_MODIFIED:
select = "tasks.modified AS sort_modified";
break;
case SORT_CREATED:
select = "tasks.created AS sort_created";
break;
case SORT_GTASKS:
select = "tasks.`order` AS sort_manual";
break;
case SORT_CALDAV:
select = CALDAV_ORDER_COLUMN + " AS sort_manual";
break;
default:
select ="(CASE WHEN (tasks.dueDate=0) "
+ // if no due date
"THEN (strftime('%s','now')*1000)*2 "
+ // then now * 2
"ELSE ("
+ ADJUSTED_DUE_DATE.replace("dueDate", "tasks.dueDate")
+ ") END) "
+ // else due time
// add slightly less than 2 days * importance to give due date priority over importance in case of tie
"+ 172799999 * tasks.importance AS sort_smart";
}
return select;
}
public static Order orderForSortTypeRecursive(int sortMode, boolean reverse) {
Order order;
switch (sortMode) {
case SORT_ALPHA:
order = Order.asc("sort_title");
break;
case SORT_DUE:
order = Order.asc("sort_duedate");
break;
case SORT_START:
order = Order.asc("sort_startdate");
break;
case SORT_IMPORTANCE:
order = Order.asc("sort_importance");
break;
case SORT_MODIFIED:
order = Order.desc("sort_modified");
break;
case SORT_CREATED:
order = Order.desc("sort_created");
break;
case SORT_GTASKS:
case SORT_CALDAV:
order = Order.asc("sort_manual");
break;
default:
order = Order.asc("sort_smart");
}
if (sortMode != SORT_ALPHA) {
order.addSecondaryExpression(Order.asc("sort_title"));
}
if (reverse) {
order = order.reverse();
}
return order;
}
}