Add sort 'By start date'

pull/1294/head
Alex Baker 3 years ago
parent 7f5cbf372a
commit dbf4d6fdf7

@ -5,15 +5,16 @@
*/
package com.todoroo.astrid.adapter
import com.todoroo.astrid.core.SortHelper.SORT_DUE
import com.todoroo.astrid.core.SortHelper.SORT_IMPORTANCE
import com.todoroo.astrid.core.SortHelper.*
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.HIDE_UNTIL_SPECIFIC_DAY
import org.tasks.BuildConfig
import org.tasks.LocalBroadcastManager
import org.tasks.data.*
import org.tasks.date.DateTimeUtils.toAppleEpoch
import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.time.DateTimeUtils.millisOfDay
import java.util.*
import kotlin.collections.HashSet
@ -207,15 +208,16 @@ open class TaskAdapter(
taskDao.save(t)
}
}
SORT_DUE -> applyDate(task.task, dataSource.nearestHeader(if (pos == 0) 1 else pos))
SORT_DUE -> applyDueDate(task.task, dataSource.nearestHeader(if (pos == 0) 1 else pos))
SORT_START -> applyStartDate(task.task, dataSource.nearestHeader(if (pos == 0) 1 else pos))
}
}
private suspend fun applyDate(task: Task, date: Long) {
private suspend fun applyDueDate(task: Task, date: Long) {
val original = task.dueDate
task.setDueDateAdjustingHideUntil(when {
date == 0L -> 0L
task.hasDueTime() -> date.toDateTime().withMillisOfDay(task.dueDate.toDateTime().millisOfDay).millis
task.hasDueTime() -> date.toDateTime().withMillisOfDay(original.millisOfDay()).millis
else -> Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, date)
})
if (original != task.dueDate) {
@ -223,6 +225,18 @@ open class TaskAdapter(
}
}
private suspend fun applyStartDate(task: Task, date: Long) {
val original = task.hideUntil
task.hideUntil = when {
date == 0L -> 0L
task.hasHideUntilDate() -> date.toDateTime().withMillisOfDay(original.millisOfDay()).millis
else -> task.createHideUntil(HIDE_UNTIL_SPECIFIC_DAY, date)
}
if (original != task.hideUntil) {
taskDao.save(task)
}
}
private suspend fun moveToTopLevel(task: TaskContainer) {
when {
task.isGoogleTask -> changeGoogleTaskParent(task, null)

@ -32,6 +32,7 @@ public class SortHelper {
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")
@ -40,6 +41,8 @@ public class SortHelper {
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. */
@ -90,6 +93,13 @@ public class SortHelper {
+ 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(
@ -126,6 +136,8 @@ public class SortHelper {
switch (sortType) {
case SORT_DUE:
return "tasks.dueDate";
case SORT_START:
return "tasks.hideUntil";
case SORT_IMPORTANCE:
return "tasks.importance";
case SORT_MODIFIED:
@ -149,6 +161,11 @@ public class SortHelper {
+ 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;
@ -189,6 +206,9 @@ public class SortHelper {
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;

@ -86,6 +86,7 @@ public class SortDialog extends DialogFragment {
}
items.add(getString(R.string.SSD_sort_auto));
items.add(getString(R.string.SSD_sort_start));
items.add(getString(R.string.SSD_sort_due));
items.add(getString(R.string.SSD_sort_importance));
items.add(getString(R.string.SSD_sort_alpha));
@ -173,16 +174,18 @@ public class SortDialog extends DialogFragment {
switch (sortMode) {
case SortHelper.SORT_AUTO:
return 1;
case SortHelper.SORT_DUE:
case SortHelper.SORT_START:
return 2;
case SortHelper.SORT_IMPORTANCE:
case SortHelper.SORT_DUE:
return 3;
case SortHelper.SORT_ALPHA:
case SortHelper.SORT_IMPORTANCE:
return 4;
case SortHelper.SORT_MODIFIED:
case SortHelper.SORT_ALPHA:
return 5;
case SortHelper.SORT_CREATED:
case SortHelper.SORT_MODIFIED:
return 6;
case SortHelper.SORT_CREATED:
return 7;
}
Timber.e("Invalid sort mode: %s", sortMode);
@ -194,14 +197,16 @@ public class SortDialog extends DialogFragment {
case 1:
return SortHelper.SORT_AUTO;
case 2:
return SortHelper.SORT_DUE;
return SortHelper.SORT_START;
case 3:
return SortHelper.SORT_IMPORTANCE;
return SortHelper.SORT_DUE;
case 4:
return SortHelper.SORT_ALPHA;
return SortHelper.SORT_IMPORTANCE;
case 5:
return SortHelper.SORT_MODIFIED;
return SortHelper.SORT_ALPHA;
case 6:
return SortHelper.SORT_MODIFIED;
case 7:
return SortHelper.SORT_CREATED;
}

@ -203,6 +203,7 @@ class ScrollableWidget : InjectingPreferenceFragment() {
} else {
when (widgetPreferences.sortMode) {
SORT_DUE -> R.string.SSD_sort_due
SORT_START -> R.string.SSD_sort_start
SORT_IMPORTANCE -> R.string.SSD_sort_importance
SORT_ALPHA -> R.string.SSD_sort_alpha
SORT_MODIFIED -> R.string.SSD_sort_modified

@ -34,17 +34,24 @@ class HeaderViewHolder(
this.header.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, if (section.collapsed) R.drawable.ic_keyboard_arrow_down_black_18dp else R.drawable.ic_keyboard_arrow_up_black_18dp, 0)
this.header.setTextColor(
context.getColor(
if (sortMode == SortHelper.SORT_DUE && sortGroup > 0 && newDateTime(sortGroup).plusDays(1).startOfDay().isBeforeNow) R.color.overdue else R.color.text_secondary))
if ((sortMode == SortHelper.SORT_DUE || sortMode == SortHelper.SORT_START)
&& sortGroup > 0
&& newDateTime(sortGroup).plusDays(1).startOfDay().isBeforeNow) {
R.color.overdue
} else {
R.color.text_secondary
}))
}
}
private fun getHeader(sortMode: Int, alwaysDisplayFullDate: Boolean, group: Long): String =
when {
sortMode == SortHelper.SORT_IMPORTANCE -> context.getString(priorityToString(group.toInt()))
group == 0L -> context.getString(if (sortMode == SortHelper.SORT_DUE) {
R.string.no_due_date
} else {
R.string.no_date
sortMode == SortHelper.SORT_IMPORTANCE ->
context.getString(priorityToString(group.toInt()))
group == 0L -> context.getString(when (sortMode) {
SortHelper.SORT_DUE -> R.string.no_due_date
SortHelper.SORT_START -> R.string.no_start_date
else -> R.string.no_date
})
sortMode == SortHelper.SORT_CREATED ->
context.getString(R.string.sort_created_group, getDateString(group, alwaysDisplayFullDate))

@ -6,7 +6,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.adapter.TaskAdapter
import com.todoroo.astrid.adapter.TaskAdapterDataSource
import com.todoroo.astrid.core.SortHelper.SORT_DUE
import org.tasks.data.TaskContainer
import org.tasks.preferences.Preferences
@ -22,13 +21,13 @@ abstract class TaskListRecyclerAdapter internal constructor(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val filter = taskList.getFilter()
val sortByDueDate = filter.supportsSorting()
&& preferences.sortMode == SORT_DUE
val groupsEnabled = filter.supportsSorting()
&& !(filter.supportsManualSort() && preferences.isManualSort)
&& !(filter.supportsAstridSorting() && preferences.isAstridSort)
val task = getItem(position)
if (task != null) {
(holder as TaskViewHolder).bindView(task, filter, sortByDueDate)
(holder as TaskViewHolder)
.bindView(task, filter, if (groupsEnabled) preferences.sortMode else -1)
holder.moving = false
val indent = adapter.getIndent(task)
task.setIndent(indent)

@ -15,6 +15,8 @@ import butterknife.OnLongClick
import com.google.android.material.chip.ChipGroup
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.core.SortHelper.SORT_DUE
import com.todoroo.astrid.core.SortHelper.SORT_START
import com.todoroo.astrid.ui.CheckableImageView
import org.tasks.R
import org.tasks.data.TaskContainer
@ -132,13 +134,13 @@ class TaskViewHolder internal constructor(
private fun getIndentSize(indent: Int) = (indent * shiftSize).roundToInt()
fun bindView(task: TaskContainer, filter: Filter, sortByDueDate: Boolean) {
fun bindView(task: TaskContainer, filter: Filter, sortMode: Int) {
this.task = task
indent = task.indent
nameView.text = task.title
setupTitleAndCheckbox()
setupDueDate(sortByDueDate)
setupChips(filter)
setupDueDate(sortMode == SORT_DUE)
setupChips(filter, sortMode == SORT_START)
if (preferences.getBoolean(R.string.p_show_description, true)) {
description.text = task.notes
description.visibility = if (task.hasNotes()) View.VISIBLE else View.GONE
@ -201,8 +203,8 @@ class TaskViewHolder internal constructor(
}
}
private fun setupChips(filter: Filter) {
val chips = chipProvider.getChips(filter, indent > 0, task)
private fun setupChips(filter: Filter, sortByStartDate: Boolean) {
val chips = chipProvider.getChips(filter, indent > 0, task, sortByStartDate)
if (chips.isEmpty()) {
chipGroup.visibility = View.GONE
} else {

@ -11,11 +11,13 @@ import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.TagFilter
import com.todoroo.astrid.data.Task
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.billing.Inventory
import org.tasks.data.TagData
import org.tasks.data.TaskContainer
import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.filters.PlaceFilter
import org.tasks.locale.Locale
import org.tasks.preferences.Preferences
@ -48,23 +50,24 @@ class ChipProvider @Inject constructor(
showIcon = appearance != 1
}
private fun newStartDateChip(task: TaskContainer, compact: Boolean): Chip {
private fun newStartDateChip(task: TaskContainer, compact: Boolean, timeOnly: Boolean): Chip? {
val chip = newChip(task)
apply(
chip,
R.drawable.ic_pending_actions_24px,
DateUtilities.getRelativeDateTime(
activity,
task.startDate,
locale.locale,
if (compact) FormatStyle.SHORT else FormatStyle.MEDIUM,
false,
false
),
0,
showText = true,
showIcon = true
)
val text = if (timeOnly) {
task.startDate
.takeIf { Task.hasDueTime(it) }
?.let { DateUtilities.getTimeString(activity, task.startDate.toDateTime()) }
?: return null
} else {
DateUtilities.getRelativeDateTime(
activity,
task.startDate,
locale.locale,
if (compact) FormatStyle.SHORT else FormatStyle.MEDIUM,
false,
false
)
}
apply(chip, R.drawable.ic_pending_actions_24px, text, 0, showText = true, showIcon = true)
return chip
}
@ -82,14 +85,14 @@ class ChipProvider @Inject constructor(
return chip
}
fun getChips(filter: Filter?, isSubtask: Boolean, task: TaskContainer): List<Chip> {
fun getChips(filter: Filter?, isSubtask: Boolean, task: TaskContainer, sortByStartDate: Boolean): List<Chip> {
AndroidUtilities.assertMainThread()
val chips = ArrayList<Chip>()
if (task.hasChildren() && preferences.showSubtaskChip) {
chips.add(newSubtaskChip(task, !showText))
}
if (task.isHidden && preferences.showStartDateChip) {
chips.add(newStartDateChip(task, !showText))
newStartDateChip(task, !showText, sortByStartDate)?.let(chips::add)
}
if (task.hasLocation() && filter !is PlaceFilter && preferences.showPlaceChip) {
val location = task.getLocation()

@ -150,6 +150,10 @@ internal class ScrollableViewsFactory(
&& sortGroup > 0
&& DateTimeUtils.newDateTime(sortGroup).plusDays(1).startOfDay().isBeforeNow) {
context.getColor(R.color.overdue)
} else if (sortMode == SortHelper.SORT_START
&& sortGroup > 0
&& DateTimeUtils.newDateTime(sortGroup).plusDays(1).startOfDay().isBeforeNow) {
context.getColor(R.color.overdue)
} else {
textColorSecondary
}
@ -169,10 +173,10 @@ internal class ScrollableViewsFactory(
private fun getHeader(sortMode: Int, group: Long): String = when {
sortMode == SortHelper.SORT_IMPORTANCE -> context.getString(priorityToString(group.toInt()))
group == 0L -> context.getString(if (sortMode == SortHelper.SORT_DUE) {
R.string.no_due_date
} else {
R.string.no_date
group == 0L -> context.getString(when (sortMode) {
SortHelper.SORT_DUE -> R.string.no_due_date
SortHelper.SORT_START -> R.string.no_start_date
else -> R.string.no_date
})
sortMode == SortHelper.SORT_CREATED ->
context.getString(R.string.sort_created_group, getDateString(group))

@ -38,6 +38,7 @@ File %1$s contained %2$s.\n\n
<string name="astrid_sort_order_summary">Enable Astrid\'s manual sort mode for \'My Tasks\', \'Today\', and tags. This sort mode will be replaced by \'My order\' in a future update</string>
<string name="SSD_sort_auto">Smart sort</string>
<string name="SSD_sort_alpha">By title</string>
<string name="SSD_sort_start">By start date</string>
<string name="SSD_sort_due">By due date</string>
<string name="SSD_sort_importance">By priority</string>
<string name="SSD_sort_modified">By last modified</string>

Loading…
Cancel
Save