Add sort by list

pull/2282/head
Alex Baker 3 years ago
parent 13b4f80c70
commit 18242e5284

@ -17,6 +17,7 @@ import com.todoroo.andlib.sql.Functions;
import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Order;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import org.tasks.data.CaldavCalendar;
import org.tasks.preferences.QueryPreferences; import org.tasks.preferences.QueryPreferences;
import java.util.Locale; import java.util.Locale;
@ -37,6 +38,7 @@ public class SortHelper {
public static final int SORT_GTASKS = 6; public static final int SORT_GTASKS = 6;
public static final int SORT_CALDAV = 7; public static final int SORT_CALDAV = 7;
public static final int SORT_START = 8; public static final int SORT_START = 8;
public static final int SORT_LIST = 9;
public static final long APPLE_EPOCH = 978307200000L; // 1/1/2001 GMT public static final long APPLE_EPOCH = 978307200000L; // 1/1/2001 GMT
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
@ -48,6 +50,7 @@ public class SortHelper {
private static final String ADJUSTED_START_DATE = private static final String ADJUSTED_START_DATE =
"(CASE WHEN (hideUntil / 1000) % 60 > 0 THEN hideUntil ELSE (hideUntil + 86399000) END)"; "(CASE WHEN (hideUntil / 1000) % 60 > 0 THEN hideUntil ELSE (hideUntil + 86399000) END)";
private static final Order ORDER_TITLE = Order.asc(Functions.upper(Task.TITLE)); private static final Order ORDER_TITLE = Order.asc(Functions.upper(Task.TITLE));
private static final Order ORDER_LIST = Order.asc(Functions.upper(CaldavCalendar.NAME));
/** Takes a SQL query, and if there isn't already an order, creates an order. */ /** Takes a SQL query, and if there isn't already an order, creates an order. */
public static String adjustQueryForFlagsAndSort( public static String adjustQueryForFlagsAndSort(
@ -113,6 +116,9 @@ public class SortHelper {
case SORT_CREATED: case SORT_CREATED:
order = Order.desc(Task.CREATION_DATE); order = Order.desc(Task.CREATION_DATE);
break; break;
case SORT_LIST:
order = ORDER_LIST;
break;
default: default:
order = order =
Order.asc( Order.asc(
@ -146,6 +152,8 @@ public class SortHelper {
return "tasks.modified"; return "tasks.modified";
case SORT_CREATED: case SORT_CREATED:
return "tasks.created"; return "tasks.created";
case SORT_LIST:
return "cdl_id";
default: default:
return null; return null;
} }
@ -168,6 +176,7 @@ public class SortHelper {
case SORT_CREATED -> "tasks.created"; case SORT_CREATED -> "tasks.created";
case SORT_GTASKS -> "tasks.`order`"; case SORT_GTASKS -> "tasks.`order`";
case SORT_CALDAV -> CALDAV_ORDER_COLUMN; case SORT_CALDAV -> CALDAV_ORDER_COLUMN;
case SORT_LIST -> "cdl_name";
default -> "(CASE WHEN (tasks.dueDate=0) " default -> "(CASE WHEN (tasks.dueDate=0) "
+ // if no due date + // if no due date
"THEN (strftime('%s','now')*1000)*2 " "THEN (strftime('%s','now')*1000)*2 "

@ -51,6 +51,6 @@ data class CaldavCalendar(
val TABLE = Table("caldav_lists") val TABLE = Table("caldav_lists")
val ACCOUNT = TABLE.column("cdl_account") val ACCOUNT = TABLE.column("cdl_account")
val UUID = TABLE.column("cdl_uuid") val UUID = TABLE.column("cdl_uuid")
val NAME = TABLE.column("cdl_name") @JvmField val NAME = TABLE.column("cdl_name")
} }
} }

@ -33,6 +33,9 @@ abstract class CaldavDao {
@Query("SELECT * FROM caldav_lists WHERE cdl_uuid = :uuid LIMIT 1") @Query("SELECT * FROM caldav_lists WHERE cdl_uuid = :uuid LIMIT 1")
abstract suspend fun getCalendarByUuid(uuid: String): CaldavCalendar? abstract suspend fun getCalendarByUuid(uuid: String): CaldavCalendar?
@Query("SELECT * FROM caldav_lists WHERE cdl_id = :id LIMIT 1")
abstract suspend fun getCalendarById(id: Long): CaldavCalendar?
@Query("SELECT * FROM caldav_lists WHERE cdl_account = :uuid") @Query("SELECT * FROM caldav_lists WHERE cdl_account = :uuid")
abstract suspend fun getCalendarsByAccount(uuid: String): List<CaldavCalendar> abstract suspend fun getCalendarsByAccount(uuid: String): List<CaldavCalendar>

@ -48,14 +48,22 @@ internal object TaskListQueryRecursive {
else -> PermaSql.replacePlaceholdersForQuery(filter.getSqlQuery()) else -> PermaSql.replacePlaceholdersForQuery(filter.getSqlQuery())
} }
val manualSort = preferences.isManualSort val manualSort = preferences.isManualSort
val sortPreference = preferences.sortMode
val sortMode = when { val sortMode = when {
manualSort && filter is GtasksFilter -> SortHelper.SORT_GTASKS manualSort && filter is GtasksFilter -> SortHelper.SORT_GTASKS
manualSort && filter is CaldavFilter -> SortHelper.SORT_CALDAV manualSort && filter is CaldavFilter -> SortHelper.SORT_CALDAV
else -> preferences.sortMode sortPreference == SortHelper.SORT_LIST && (filter is GtasksFilter || filter is CaldavFilter) ->
SortHelper.SORT_AUTO
else -> sortPreference
} }
val reverseSort = val reverseSort =
preferences.isReverseSort && sortMode != SortHelper.SORT_GTASKS && sortMode != SortHelper.SORT_CALDAV preferences.isReverseSort && sortMode != SortHelper.SORT_GTASKS && sortMode != SortHelper.SORT_CALDAV
val sortSelect = SortHelper.orderSelectForSortTypeRecursive(sortMode) val primarySortSelect = SortHelper.orderSelectForSortTypeRecursive(sortMode)
val secondarySortSelect = if (sortMode == SortHelper.SORT_LIST) {
"NULL"
} else {
primarySortSelect
}
val parentCompleted = if (preferences.completedTasksAtBottom) "tasks.completed > 0" else "0" val parentCompleted = if (preferences.completedTasksAtBottom) "tasks.completed > 0" else "0"
val completionSort = val completionSort =
if (preferences.completedTasksAtBottom && preferences.sortCompletedByCompletionDate) { if (preferences.completedTasksAtBottom && preferences.sortCompletedByCompletionDate) {
@ -66,10 +74,20 @@ internal object TaskListQueryRecursive {
val withClause = """ val withClause = """
CREATE TEMPORARY TABLE `recursive_tasks` AS CREATE TEMPORARY TABLE `recursive_tasks` AS
WITH RECURSIVE recursive_tasks (task, parent_complete, subtask_complete, completion_sort, parent, collapsed, hidden, indent, title, primary_sort, secondary_sort, sort_group) AS ( WITH RECURSIVE recursive_tasks (task, parent_complete, subtask_complete, completion_sort, parent, collapsed, hidden, indent, title, primary_sort, secondary_sort, sort_group) AS (
SELECT tasks._id, $parentCompleted as parent_complete, 0 as subtask_complete, $completionSort as completion_sort, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, $sortSelect as primary_sort, NULL as secondarySort, ${SortHelper.getSortGroup(sortMode)} SELECT tasks._id, $parentCompleted as parent_complete, 0 as subtask_complete, $completionSort as completion_sort, 0 as parent, tasks.collapsed as collapsed, 0 as hidden, 0 AS sort_indent, UPPER(tasks.title) AS sort_title, $primarySortSelect as primary_sort, NULL as secondarySort, ${SortHelper.getSortGroup(sortMode)}
FROM tasks FROM tasks
${
if (sortMode == SortHelper.SORT_LIST) {
"""
LEFT JOIN caldav_tasks on cd_task = tasks._id AND cd_deleted = 0
LEFT JOIN caldav_lists on cd_calendar = cdl_uuid
""".trimIndent()
} else {
""
}
}
$parentQuery $parentQuery
UNION ALL SELECT tasks._id, recursive_tasks.parent_complete, $parentCompleted as subtask_complete, $completionSort as completion_sort, recursive_tasks.task as parent, tasks.collapsed as collapsed, CASE WHEN recursive_tasks.collapsed > 0 OR recursive_tasks.hidden > 0 THEN 1 ELSE 0 END as hidden, recursive_tasks.indent+1 AS sort_indent, UPPER(tasks.title) AS sort_title, recursive_tasks.primary_sort as primary_sort, $sortSelect as secondary_sort, recursive_tasks.sort_group FROM tasks UNION ALL SELECT tasks._id, recursive_tasks.parent_complete, $parentCompleted as subtask_complete, $completionSort as completion_sort, recursive_tasks.task as parent, tasks.collapsed as collapsed, CASE WHEN recursive_tasks.collapsed > 0 OR recursive_tasks.hidden > 0 THEN 1 ELSE 0 END as hidden, recursive_tasks.indent+1 AS sort_indent, UPPER(tasks.title) AS sort_title, recursive_tasks.primary_sort as primary_sort, $secondarySortSelect as secondary_sort, recursive_tasks.sort_group FROM tasks
$SUBTASK_QUERY $SUBTASK_QUERY
ORDER BY parent_complete ASC, sort_indent DESC, subtask_complete ASC, completion_sort DESC, ${SortHelper.orderForSortTypeRecursive(sortMode, reverseSort)} ORDER BY parent_complete ASC, sort_indent DESC, subtask_complete ASC, completion_sort DESC, ${SortHelper.orderForSortTypeRecursive(sortMode, reverseSort)}
) SELECT * FROM recursive_tasks ) SELECT * FROM recursive_tasks

@ -7,20 +7,26 @@ import android.app.Dialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Button; import android.widget.Button;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.SortHelper; import com.todoroo.astrid.core.SortHelper;
import dagger.hilt.android.AndroidEntryPoint;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.preferences.QueryPreferences; import org.tasks.preferences.QueryPreferences;
import org.tasks.widget.WidgetPreferences; import org.tasks.widget.WidgetPreferences;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import timber.log.Timber; import timber.log.Timber;
@AndroidEntryPoint @AndroidEntryPoint
@ -92,6 +98,7 @@ public class SortDialog extends DialogFragment {
items.add(getString(R.string.SSD_sort_alpha)); items.add(getString(R.string.SSD_sort_alpha));
items.add(getString(R.string.SSD_sort_modified)); items.add(getString(R.string.SSD_sort_modified));
items.add(getString(R.string.sort_created)); items.add(getString(R.string.sort_created));
items.add(getString(R.string.sort_list));
if (manualEnabled) { if (manualEnabled) {
if (preferences.isManualSort()) { if (preferences.isManualSort()) {
@ -186,6 +193,8 @@ public class SortDialog extends DialogFragment {
return 6; return 6;
case SortHelper.SORT_CREATED: case SortHelper.SORT_CREATED:
return 7; return 7;
case SortHelper.SORT_LIST:
return 8;
} }
Timber.e("Invalid sort mode: %s", sortMode); Timber.e("Invalid sort mode: %s", sortMode);
@ -208,6 +217,8 @@ public class SortDialog extends DialogFragment {
return SortHelper.SORT_MODIFIED; return SortHelper.SORT_MODIFIED;
case 7: case 7:
return SortHelper.SORT_CREATED; return SortHelper.SORT_CREATED;
case 8:
return SortHelper.SORT_LIST;
} }
Timber.e("Invalid sort mode: %s", index); Timber.e("Invalid sort mode: %s", index);

@ -1,16 +1,10 @@
package org.tasks.tasklist package org.tasks.tasklist
import android.content.Context import android.content.Context
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.astrid.core.SortHelper.SORT_START
import com.todoroo.astrid.core.SortHelper.*
import org.tasks.R import org.tasks.R
import org.tasks.date.DateTimeUtils.toDateTime import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED
import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_OVERDUE
import java.time.format.FormatStyle
import java.util.*
data class AdapterSection( data class AdapterSection(
var firstPosition: Int, var firstPosition: Int,
@ -26,48 +20,4 @@ data class AdapterSection(
} else { } else {
textColor textColor
}) })
fun headerString(
context: Context,
locale: Locale,
sortMode: Int,
alwaysDisplayFullDate: Boolean,
style: FormatStyle = FormatStyle.FULL,
compact: Boolean = false
): String =
when {
value == HEADER_COMPLETED -> context.getString(R.string.completed)
sortMode == SORT_IMPORTANCE -> context.getString(priorityToString())
value == HEADER_OVERDUE -> context.getString(R.string.filter_overdue)
value == 0L -> context.getString(when (sortMode) {
SORT_DUE -> R.string.no_due_date
SORT_START -> R.string.no_start_date
else -> R.string.no_date
})
else -> {
val dateString = DateUtilities.getRelativeDay(
context, value, locale, style, alwaysDisplayFullDate, !compact
)
when {
compact -> dateString
sortMode == SORT_DUE ->
context.getString(R.string.sort_due_group, dateString)
sortMode == SORT_START ->
context.getString(R.string.sort_start_group, dateString)
sortMode == SORT_CREATED ->
context.getString(R.string.sort_created_group, dateString)
sortMode == SORT_MODIFIED ->
context.getString(R.string.sort_modified_group, dateString)
else -> throw IllegalArgumentException()
}
}
}
@StringRes
private fun priorityToString() = when (value) {
0L -> R.string.filter_high_priority
1L -> R.string.filter_medium_priority
2L -> R.string.filter_low_priority
else -> R.string.filter_no_priority
}
} }

@ -4,8 +4,13 @@ import android.graphics.Canvas
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.* import androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG
import androidx.recyclerview.widget.ItemTouchHelper.Callback
import androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags import androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags
import androidx.recyclerview.widget.ItemTouchHelper.DOWN
import androidx.recyclerview.widget.ItemTouchHelper.LEFT
import androidx.recyclerview.widget.ItemTouchHelper.RIGHT
import androidx.recyclerview.widget.ItemTouchHelper.UP
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.adapter.TaskAdapter import com.todoroo.astrid.adapter.TaskAdapter
@ -18,7 +23,8 @@ import kotlinx.coroutines.runBlocking
import org.tasks.activities.DragAndDropDiffer import org.tasks.activities.DragAndDropDiffer
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import java.util.* import java.util.LinkedList
import java.util.Queue
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -50,7 +56,7 @@ class DragAndDropRecyclerAdapter(
val viewType = getItemViewType(position) val viewType = getItemViewType(position)
if (viewType == 1) { if (viewType == 1) {
val headerSection = items.getSection(position) val headerSection = items.getSection(position)
(holder as HeaderViewHolder).bind(taskList.getFilter(), preferences.sortMode, preferences.alwaysDisplayFullDate, headerSection) (holder as HeaderViewHolder).bind(taskList.getFilter(), preferences.sortMode, headerSection)
} else { } else {
super.onBindViewHolder(holder, position) super.onBindViewHolder(holder, position)
} }

@ -0,0 +1,77 @@
package org.tasks.tasklist
import android.content.Context
import androidx.annotation.StringRes
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.core.SortHelper
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.runBlocking
import org.tasks.R
import org.tasks.data.CaldavDao
import org.tasks.preferences.Preferences
import java.time.format.FormatStyle
import java.util.Locale
import javax.inject.Inject
class HeaderFormatter @Inject constructor(
@ApplicationContext private val context: Context,
private val preferences: Preferences,
private val locale: Locale,
private val caldavDao: CaldavDao,
) {
private val listCache = HashMap<Long, String?>()
fun headerStringBlocking(
value: Long,
sortMode: Int = preferences.sortMode,
alwaysDisplayFullDate: Boolean = preferences.alwaysDisplayFullDate,
style: FormatStyle = FormatStyle.FULL,
compact: Boolean = false,
) = runBlocking {
headerString(value, sortMode, alwaysDisplayFullDate, style, compact)
}
suspend fun headerString(
value: Long,
sortMode: Int = preferences.sortMode,
alwaysDisplayFullDate: Boolean = preferences.alwaysDisplayFullDate,
style: FormatStyle = FormatStyle.FULL,
compact: Boolean = false
): String =
when {
value == SectionedDataSource.HEADER_COMPLETED -> context.getString(R.string.completed)
sortMode == SortHelper.SORT_IMPORTANCE -> context.getString(priorityToString(value))
sortMode == SortHelper.SORT_LIST ->
listCache.getOrPut(value) { caldavDao.getCalendarById(value)?.name }?: "list: $value"
value == SectionedDataSource.HEADER_OVERDUE -> context.getString(R.string.filter_overdue)
value == 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
})
else -> {
val dateString = DateUtilities.getRelativeDay(
context, value, locale, style, alwaysDisplayFullDate, !compact
)
when {
compact -> dateString
sortMode == SortHelper.SORT_DUE ->
context.getString(R.string.sort_due_group, dateString)
sortMode == SortHelper.SORT_START ->
context.getString(R.string.sort_start_group, dateString)
sortMode == SortHelper.SORT_CREATED ->
context.getString(R.string.sort_created_group, dateString)
sortMode == SortHelper.SORT_MODIFIED ->
context.getString(R.string.sort_modified_group, dateString)
else -> throw IllegalArgumentException()
}
}
}
@StringRes
private fun priorityToString(value: Long) = when (value) {
0L -> R.string.filter_high_priority
1L -> R.string.filter_medium_priority
2L -> R.string.filter_low_priority
else -> R.string.filter_no_priority
}
}

@ -7,11 +7,10 @@ import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import org.tasks.R import org.tasks.R
import java.util.*
class HeaderViewHolder( class HeaderViewHolder(
private val context: Context, private val context: Context,
private val locale: Locale, private val headerFormatter: HeaderFormatter,
view: View, view: View,
callback: (Long) -> Unit callback: (Long) -> Unit
) : RecyclerView.ViewHolder(view) { ) : RecyclerView.ViewHolder(view) {
@ -21,10 +20,10 @@ class HeaderViewHolder(
private var sortGroup = -1L private var sortGroup = -1L
private var rotation = 0f private var rotation = 0f
fun bind(filter: Filter, sortMode: Int, alwaysDisplayFullDate: Boolean, section: AdapterSection) { fun bind(filter: Filter, sortMode: Int, section: AdapterSection) {
sortGroup = section.value sortGroup = section.value
val header = if (filter.supportsSorting()) { val header = if (filter.supportsSorting()) {
section.headerString(context, locale, sortMode, alwaysDisplayFullDate) headerFormatter.headerStringBlocking(section.value)
} else { } else {
null null
} }

@ -66,7 +66,11 @@ class SectionedDataSource constructor(
HEADER_COMPLETED HEADER_COMPLETED
} else if (sortGroup == null) { } else if (sortGroup == null) {
continue continue
} else if (sortMode == SortHelper.SORT_IMPORTANCE || sortGroup == 0L) { } else if (
sortMode == SortHelper.SORT_LIST ||
sortMode == SortHelper.SORT_IMPORTANCE ||
sortGroup == 0L
) {
sortGroup sortGroup
} else if (sortMode == SortHelper.SORT_DUE) { } else if (sortMode == SortHelper.SORT_DUE) {
when { when {
@ -89,6 +93,7 @@ class SectionedDataSource constructor(
sections.add(AdapterSection(i, header, 0, isCollapsed)) sections.add(AdapterSection(i, header, 0, isCollapsed))
} }
} }
sortMode == SortHelper.SORT_LIST ||
sortMode == SortHelper.SORT_IMPORTANCE -> sortMode == SortHelper.SORT_IMPORTANCE ->
if (header != previous) { if (header != previous) {
sections.add(AdapterSection(i, header, 0, isCollapsed)) sections.add(AdapterSection(i, header, 0, isCollapsed))

@ -17,6 +17,7 @@ import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.core.SortHelper.SORT_DUE import com.todoroo.astrid.core.SortHelper.SORT_DUE
import com.todoroo.astrid.core.SortHelper.SORT_LIST
import com.todoroo.astrid.core.SortHelper.SORT_START import com.todoroo.astrid.core.SortHelper.SORT_START
import com.todoroo.astrid.ui.CheckableImageView import com.todoroo.astrid.ui.CheckableImageView
import org.tasks.R import org.tasks.R
@ -140,7 +141,7 @@ class TaskViewHolder internal constructor(
markdown.setMarkdown(nameView, task.title) markdown.setMarkdown(nameView, task.title)
setupTitleAndCheckbox() setupTitleAndCheckbox()
setupDueDate(sortMode == SORT_DUE) setupDueDate(sortMode == SORT_DUE)
setupChips(filter, sortMode == SORT_START) setupChips(filter, sortMode == SORT_START, sortMode == SORT_LIST)
if (preferences.getBoolean(R.string.p_show_description, true)) { if (preferences.getBoolean(R.string.p_show_description, true)) {
markdown.setMarkdown(description, task.notes) markdown.setMarkdown(description, task.notes)
description.visibility = if (task.hasNotes()) View.VISIBLE else View.GONE description.visibility = if (task.hasNotes()) View.VISIBLE else View.GONE
@ -215,7 +216,7 @@ class TaskViewHolder internal constructor(
} }
} }
private fun setupChips(filter: Filter, sortByStartDate: Boolean) { private fun setupChips(filter: Filter, sortByStartDate: Boolean, sortByList: Boolean) {
chipGroup.setContent { chipGroup.setContent {
AppCompatTheme { AppCompatTheme {
ChipGroup( ChipGroup(
@ -238,6 +239,7 @@ class TaskViewHolder internal constructor(
isSubtask = task.hasParent(), isSubtask = task.hasParent(),
isGoogleTask = task.isGoogleTask, isGoogleTask = task.isGoogleTask,
sortByStartDate = sortByStartDate, sortByStartDate = sortByStartDate,
sortByList = sortByList,
toggleSubtasks = { task: Long, collapsed: Boolean -> callback.toggleSubtasks(task, collapsed) }, toggleSubtasks = { task: Long, collapsed: Boolean -> callback.toggleSubtasks(task, collapsed) },
onClick = { it: Filter -> callback.onClick(it) }, onClick = { it: Filter -> callback.onClick(it) },
) )

@ -16,7 +16,7 @@ import org.tasks.preferences.ResourceResolver
import org.tasks.tasklist.TaskViewHolder.ViewHolderCallbacks import org.tasks.tasklist.TaskViewHolder.ViewHolderCallbacks
import org.tasks.ui.CheckBoxProvider import org.tasks.ui.CheckBoxProvider
import org.tasks.ui.ChipProvider import org.tasks.ui.ChipProvider
import java.util.* import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
class ViewHolderFactory @Inject constructor( class ViewHolderFactory @Inject constructor(
@ -25,7 +25,9 @@ class ViewHolderFactory @Inject constructor(
private val chipProvider: ChipProvider, private val chipProvider: ChipProvider,
private val checkBoxProvider: CheckBoxProvider, private val checkBoxProvider: CheckBoxProvider,
private val linkify: Linkify, private val linkify: Linkify,
private val locale: Locale) { private val locale: Locale,
private val headerFormatter: HeaderFormatter,
) {
private val textColorSecondary: Int = ResourceResolver.getData(context, android.R.attr.textColorSecondary) private val textColorSecondary: Int = ResourceResolver.getData(context, android.R.attr.textColorSecondary)
private val textColorOverdue: Int = context.getColor(R.color.overdue) private val textColorOverdue: Int = context.getColor(R.color.overdue)
private val fontSize: Int = preferences.fontSize private val fontSize: Int = preferences.fontSize
@ -40,9 +42,10 @@ class ViewHolderFactory @Inject constructor(
fun newHeaderViewHolder(parent: ViewGroup?, callback: (Long) -> Unit) = fun newHeaderViewHolder(parent: ViewGroup?, callback: (Long) -> Unit) =
HeaderViewHolder( HeaderViewHolder(
context, context,
locale, headerFormatter,
LayoutInflater.from(context).inflate(R.layout.task_adapter_header, parent, false), LayoutInflater.from(context).inflate(R.layout.task_adapter_header, parent, false),
callback) callback,
)
fun newViewHolder(parent: ViewGroup?, callbacks: ViewHolderCallbacks) = fun newViewHolder(parent: ViewGroup?, callbacks: ViewHolderCallbacks) =
TaskViewHolder( TaskViewHolder(

@ -97,6 +97,7 @@ class ChipProvider @Inject constructor(
place: Place?, place: Place?,
tagsString: String?, tagsString: String?,
sortByStartDate: Boolean, sortByStartDate: Boolean,
sortByList: Boolean,
list: String?, list: String?,
isSubtask: Boolean, isSubtask: Boolean,
isGoogleTask: Boolean, isGoogleTask: Boolean,
@ -125,7 +126,7 @@ class ChipProvider @Inject constructor(
) )
} }
if (!isSubtask && preferences.showListChip && filter !is CaldavFilter) { if (!isSubtask && !sortByList && preferences.showListChip && filter !is CaldavFilter) {
remember(list, isGoogleTask) { remember(list, isGoogleTask) {
lists lists
.getCaldavList(list) .getCaldavList(list)

@ -26,13 +26,14 @@ import org.tasks.date.DateTimeUtils
import org.tasks.markdown.Markdown import org.tasks.markdown.Markdown
import org.tasks.preferences.DefaultFilterProvider import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.tasklist.HeaderFormatter
import org.tasks.tasklist.SectionedDataSource import org.tasks.tasklist.SectionedDataSource
import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED
import org.tasks.time.DateTimeUtils.startOfDay import org.tasks.time.DateTimeUtils.startOfDay
import org.tasks.ui.CheckBoxProvider import org.tasks.ui.CheckBoxProvider
import timber.log.Timber import timber.log.Timber
import java.time.format.FormatStyle import java.time.format.FormatStyle
import java.util.* import java.util.Locale
import kotlin.math.max import kotlin.math.max
internal class ScrollableViewsFactory( internal class ScrollableViewsFactory(
@ -46,7 +47,8 @@ internal class ScrollableViewsFactory(
private val locale: Locale, private val locale: Locale,
private val chipProvider: ChipProvider, private val chipProvider: ChipProvider,
private val localBroadcastManager: LocalBroadcastManager, private val localBroadcastManager: LocalBroadcastManager,
private val markdown: Markdown private val markdown: Markdown,
private val headerFormatter: HeaderFormatter,
) : RemoteViewsFactory { ) : RemoteViewsFactory {
private val indentPadding: Int private val indentPadding: Int
private var showDueDates = false private var showDueDates = false
@ -145,13 +147,12 @@ internal class ScrollableViewsFactory(
val section = tasks.getSection(position) val section = tasks.getSection(position)
val sortGroup = section.value val sortGroup = section.value
val header: String? = if (filter?.supportsSorting() == true) { val header: String? = if (filter?.supportsSorting() == true) {
section.headerString( headerFormatter.headerStringBlocking(
context, value = section.value,
locale, sortMode = sortMode,
sortMode, alwaysDisplayFullDate = showFullDate,
showFullDate, style = FormatStyle.MEDIUM,
FormatStyle.MEDIUM, compact = compact,
compact
) )
} else { } else {
null null

@ -13,6 +13,7 @@ import org.tasks.data.TaskDao;
import org.tasks.markdown.MarkdownProvider; import org.tasks.markdown.MarkdownProvider;
import org.tasks.preferences.DefaultFilterProvider; import org.tasks.preferences.DefaultFilterProvider;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.tasklist.HeaderFormatter;
import org.tasks.themes.ColorProvider; import org.tasks.themes.ColorProvider;
import org.tasks.ui.CheckBoxProvider; import org.tasks.ui.CheckBoxProvider;
@ -33,6 +34,7 @@ public class ScrollableWidgetUpdateService extends RemoteViewsService {
@Inject ChipProvider chipProvider; @Inject ChipProvider chipProvider;
@Inject LocalBroadcastManager localBroadcastManager; @Inject LocalBroadcastManager localBroadcastManager;
@Inject MarkdownProvider markdownProvider; @Inject MarkdownProvider markdownProvider;
@Inject HeaderFormatter headerFormatter;
@Override @Override
public void onStart(Intent intent, int startId) { public void onStart(Intent intent, int startId) {
@ -65,6 +67,8 @@ public class ScrollableWidgetUpdateService extends RemoteViewsService {
locale, locale,
chipProvider, chipProvider,
localBroadcastManager, localBroadcastManager,
markdownProvider.markdown(false)); markdownProvider.markdown(false),
headerFormatter
);
} }
} }

@ -42,6 +42,7 @@ File %1$s contained %2$s.\n\n
<string name="SSD_sort_importance">By priority</string> <string name="SSD_sort_importance">By priority</string>
<string name="SSD_sort_modified">By last modified</string> <string name="SSD_sort_modified">By last modified</string>
<string name="sort_created">By creation time</string> <string name="sort_created">By creation time</string>
<string name="sort_list">By list</string>
<string name="FLA_search_filter">Matching \'%s\'</string> <string name="FLA_search_filter">Matching \'%s\'</string>
<string name="FLA_new_filter">Create new filter</string> <string name="FLA_new_filter">Create new filter</string>
<string name="TEA_title_hint">Task name</string> <string name="TEA_title_hint">Task name</string>

Loading…
Cancel
Save