From 18242e528460c31dd4e24ef45adc6441f90a2799 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Wed, 19 Apr 2023 23:57:18 -0500 Subject: [PATCH] Add sort by list --- .../com/todoroo/astrid/core/SortHelper.java | 9 +++ .../java/org/tasks/data/CaldavCalendar.kt | 2 +- app/src/main/java/org/tasks/data/CaldavDao.kt | 3 + .../org/tasks/data/TaskListQueryRecursive.kt | 26 ++++++- .../java/org/tasks/dialogs/SortDialog.java | 19 ++++- .../java/org/tasks/tasklist/AdapterSection.kt | 52 +------------ .../tasklist/DragAndDropRecyclerAdapter.kt | 12 ++- .../org/tasks/tasklist/HeaderFormatter.kt | 77 +++++++++++++++++++ .../org/tasks/tasklist/HeaderViewHolder.kt | 7 +- .../org/tasks/tasklist/SectionedDataSource.kt | 7 +- .../java/org/tasks/tasklist/TaskViewHolder.kt | 6 +- .../org/tasks/tasklist/ViewHolderFactory.kt | 11 ++- .../main/java/org/tasks/ui/ChipProvider.kt | 3 +- .../tasks/widget/ScrollableViewsFactory.kt | 19 ++--- .../widget/ScrollableWidgetUpdateService.java | 6 +- app/src/main/res/values/strings.xml | 1 + 16 files changed, 175 insertions(+), 85 deletions(-) create mode 100644 app/src/main/java/org/tasks/tasklist/HeaderFormatter.kt diff --git a/app/src/main/java/com/todoroo/astrid/core/SortHelper.java b/app/src/main/java/com/todoroo/astrid/core/SortHelper.java index 64d5561c6..369aa90fc 100644 --- a/app/src/main/java/com/todoroo/astrid/core/SortHelper.java +++ b/app/src/main/java/com/todoroo/astrid/core/SortHelper.java @@ -17,6 +17,7 @@ import com.todoroo.andlib.sql.Functions; import com.todoroo.andlib.sql.Order; import com.todoroo.astrid.data.Task; +import org.tasks.data.CaldavCalendar; import org.tasks.preferences.QueryPreferences; import java.util.Locale; @@ -37,6 +38,7 @@ public class SortHelper { public static final int SORT_GTASKS = 6; public static final int SORT_CALDAV = 7; 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 @SuppressLint("DefaultLocale") @@ -48,6 +50,7 @@ public class SortHelper { 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)); + 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. */ public static String adjustQueryForFlagsAndSort( @@ -113,6 +116,9 @@ public class SortHelper { case SORT_CREATED: order = Order.desc(Task.CREATION_DATE); break; + case SORT_LIST: + order = ORDER_LIST; + break; default: order = Order.asc( @@ -146,6 +152,8 @@ public class SortHelper { return "tasks.modified"; case SORT_CREATED: return "tasks.created"; + case SORT_LIST: + return "cdl_id"; default: return null; } @@ -168,6 +176,7 @@ public class SortHelper { case SORT_CREATED -> "tasks.created"; case SORT_GTASKS -> "tasks.`order`"; case SORT_CALDAV -> CALDAV_ORDER_COLUMN; + case SORT_LIST -> "cdl_name"; default -> "(CASE WHEN (tasks.dueDate=0) " + // if no due date "THEN (strftime('%s','now')*1000)*2 " diff --git a/app/src/main/java/org/tasks/data/CaldavCalendar.kt b/app/src/main/java/org/tasks/data/CaldavCalendar.kt index d6d56b306..918937f9d 100644 --- a/app/src/main/java/org/tasks/data/CaldavCalendar.kt +++ b/app/src/main/java/org/tasks/data/CaldavCalendar.kt @@ -51,6 +51,6 @@ data class CaldavCalendar( val TABLE = Table("caldav_lists") val ACCOUNT = TABLE.column("cdl_account") val UUID = TABLE.column("cdl_uuid") - val NAME = TABLE.column("cdl_name") + @JvmField val NAME = TABLE.column("cdl_name") } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/CaldavDao.kt b/app/src/main/java/org/tasks/data/CaldavDao.kt index efb75d5bc..069c75a59 100644 --- a/app/src/main/java/org/tasks/data/CaldavDao.kt +++ b/app/src/main/java/org/tasks/data/CaldavDao.kt @@ -33,6 +33,9 @@ abstract class CaldavDao { @Query("SELECT * FROM caldav_lists WHERE cdl_uuid = :uuid LIMIT 1") 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") abstract suspend fun getCalendarsByAccount(uuid: String): List diff --git a/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt b/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt index 849625600..6f689d185 100644 --- a/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt +++ b/app/src/main/java/org/tasks/data/TaskListQueryRecursive.kt @@ -48,14 +48,22 @@ internal object TaskListQueryRecursive { else -> PermaSql.replacePlaceholdersForQuery(filter.getSqlQuery()) } val manualSort = preferences.isManualSort + val sortPreference = preferences.sortMode val sortMode = when { manualSort && filter is GtasksFilter -> SortHelper.SORT_GTASKS 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 = 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 completionSort = if (preferences.completedTasksAtBottom && preferences.sortCompletedByCompletionDate) { @@ -66,10 +74,20 @@ internal object TaskListQueryRecursive { val withClause = """ 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 ( - 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 + ${ + 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 - 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 ORDER BY parent_complete ASC, sort_indent DESC, subtask_complete ASC, completion_sort DESC, ${SortHelper.orderForSortTypeRecursive(sortMode, reverseSort)} ) SELECT * FROM recursive_tasks diff --git a/app/src/main/java/org/tasks/dialogs/SortDialog.java b/app/src/main/java/org/tasks/dialogs/SortDialog.java index 8cf452cb1..5e266a6d3 100644 --- a/app/src/main/java/org/tasks/dialogs/SortDialog.java +++ b/app/src/main/java/org/tasks/dialogs/SortDialog.java @@ -7,20 +7,26 @@ import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.widget.Button; + import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; + import com.todoroo.astrid.api.Filter; 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.preferences.Preferences; import org.tasks.preferences.QueryPreferences; 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; @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_modified)); items.add(getString(R.string.sort_created)); + items.add(getString(R.string.sort_list)); if (manualEnabled) { if (preferences.isManualSort()) { @@ -186,6 +193,8 @@ public class SortDialog extends DialogFragment { return 6; case SortHelper.SORT_CREATED: return 7; + case SortHelper.SORT_LIST: + return 8; } Timber.e("Invalid sort mode: %s", sortMode); @@ -208,6 +217,8 @@ public class SortDialog extends DialogFragment { return SortHelper.SORT_MODIFIED; case 7: return SortHelper.SORT_CREATED; + case 8: + return SortHelper.SORT_LIST; } Timber.e("Invalid sort mode: %s", index); diff --git a/app/src/main/java/org/tasks/tasklist/AdapterSection.kt b/app/src/main/java/org/tasks/tasklist/AdapterSection.kt index 7d5d0aad1..a731ad5b0 100644 --- a/app/src/main/java/org/tasks/tasklist/AdapterSection.kt +++ b/app/src/main/java/org/tasks/tasklist/AdapterSection.kt @@ -1,16 +1,10 @@ package org.tasks.tasklist import android.content.Context -import androidx.annotation.StringRes import androidx.core.content.ContextCompat -import com.todoroo.andlib.utility.DateUtilities -import com.todoroo.astrid.core.SortHelper.* +import com.todoroo.astrid.core.SortHelper.SORT_START import org.tasks.R 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( var firstPosition: Int, @@ -26,48 +20,4 @@ data class AdapterSection( } else { 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 - } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt b/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt index b684f01a2..4f07fea7c 100644 --- a/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt +++ b/app/src/main/java/org/tasks/tasklist/DragAndDropRecyclerAdapter.kt @@ -4,8 +4,13 @@ import android.graphics.Canvas import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil 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.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 com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.adapter.TaskAdapter @@ -18,7 +23,8 @@ import kotlinx.coroutines.runBlocking import org.tasks.activities.DragAndDropDiffer import org.tasks.data.TaskContainer import org.tasks.preferences.Preferences -import java.util.* +import java.util.LinkedList +import java.util.Queue import java.util.concurrent.Executors import kotlin.math.max import kotlin.math.min @@ -50,7 +56,7 @@ class DragAndDropRecyclerAdapter( val viewType = getItemViewType(position) if (viewType == 1) { 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 { super.onBindViewHolder(holder, position) } diff --git a/app/src/main/java/org/tasks/tasklist/HeaderFormatter.kt b/app/src/main/java/org/tasks/tasklist/HeaderFormatter.kt new file mode 100644 index 000000000..b330b978d --- /dev/null +++ b/app/src/main/java/org/tasks/tasklist/HeaderFormatter.kt @@ -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() + + 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 + } +} diff --git a/app/src/main/java/org/tasks/tasklist/HeaderViewHolder.kt b/app/src/main/java/org/tasks/tasklist/HeaderViewHolder.kt index 880c0f075..cc95bb714 100644 --- a/app/src/main/java/org/tasks/tasklist/HeaderViewHolder.kt +++ b/app/src/main/java/org/tasks/tasklist/HeaderViewHolder.kt @@ -7,11 +7,10 @@ import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.todoroo.astrid.api.Filter import org.tasks.R -import java.util.* class HeaderViewHolder( private val context: Context, - private val locale: Locale, + private val headerFormatter: HeaderFormatter, view: View, callback: (Long) -> Unit ) : RecyclerView.ViewHolder(view) { @@ -21,10 +20,10 @@ class HeaderViewHolder( private var sortGroup = -1L 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 val header = if (filter.supportsSorting()) { - section.headerString(context, locale, sortMode, alwaysDisplayFullDate) + headerFormatter.headerStringBlocking(section.value) } else { null } diff --git a/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt b/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt index 15165f93b..300be50e1 100644 --- a/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt +++ b/app/src/main/java/org/tasks/tasklist/SectionedDataSource.kt @@ -66,7 +66,11 @@ class SectionedDataSource constructor( HEADER_COMPLETED } else if (sortGroup == null) { continue - } else if (sortMode == SortHelper.SORT_IMPORTANCE || sortGroup == 0L) { + } else if ( + sortMode == SortHelper.SORT_LIST || + sortMode == SortHelper.SORT_IMPORTANCE || + sortGroup == 0L + ) { sortGroup } else if (sortMode == SortHelper.SORT_DUE) { when { @@ -89,6 +93,7 @@ class SectionedDataSource constructor( sections.add(AdapterSection(i, header, 0, isCollapsed)) } } + sortMode == SortHelper.SORT_LIST || sortMode == SortHelper.SORT_IMPORTANCE -> if (header != previous) { sections.add(AdapterSection(i, header, 0, isCollapsed)) diff --git a/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt b/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt index 595893b65..5c076469b 100644 --- a/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt +++ b/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt @@ -17,6 +17,7 @@ import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities.now import com.todoroo.astrid.api.Filter 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.ui.CheckableImageView import org.tasks.R @@ -140,7 +141,7 @@ class TaskViewHolder internal constructor( markdown.setMarkdown(nameView, task.title) setupTitleAndCheckbox() 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)) { markdown.setMarkdown(description, task.notes) 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 { AppCompatTheme { ChipGroup( @@ -238,6 +239,7 @@ class TaskViewHolder internal constructor( isSubtask = task.hasParent(), isGoogleTask = task.isGoogleTask, sortByStartDate = sortByStartDate, + sortByList = sortByList, toggleSubtasks = { task: Long, collapsed: Boolean -> callback.toggleSubtasks(task, collapsed) }, onClick = { it: Filter -> callback.onClick(it) }, ) diff --git a/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.kt b/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.kt index c1ae8eb77..9d8be1015 100644 --- a/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.kt +++ b/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.kt @@ -16,7 +16,7 @@ import org.tasks.preferences.ResourceResolver import org.tasks.tasklist.TaskViewHolder.ViewHolderCallbacks import org.tasks.ui.CheckBoxProvider import org.tasks.ui.ChipProvider -import java.util.* +import java.util.Locale import javax.inject.Inject class ViewHolderFactory @Inject constructor( @@ -25,7 +25,9 @@ class ViewHolderFactory @Inject constructor( private val chipProvider: ChipProvider, private val checkBoxProvider: CheckBoxProvider, 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 textColorOverdue: Int = context.getColor(R.color.overdue) private val fontSize: Int = preferences.fontSize @@ -40,9 +42,10 @@ class ViewHolderFactory @Inject constructor( fun newHeaderViewHolder(parent: ViewGroup?, callback: (Long) -> Unit) = HeaderViewHolder( context, - locale, + headerFormatter, LayoutInflater.from(context).inflate(R.layout.task_adapter_header, parent, false), - callback) + callback, + ) fun newViewHolder(parent: ViewGroup?, callbacks: ViewHolderCallbacks) = TaskViewHolder( diff --git a/app/src/main/java/org/tasks/ui/ChipProvider.kt b/app/src/main/java/org/tasks/ui/ChipProvider.kt index fb7452634..678f2357b 100644 --- a/app/src/main/java/org/tasks/ui/ChipProvider.kt +++ b/app/src/main/java/org/tasks/ui/ChipProvider.kt @@ -97,6 +97,7 @@ class ChipProvider @Inject constructor( place: Place?, tagsString: String?, sortByStartDate: Boolean, + sortByList: Boolean, list: String?, isSubtask: 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) { lists .getCaldavList(list) diff --git a/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.kt b/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.kt index f65c27613..83aebc801 100644 --- a/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.kt +++ b/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.kt @@ -26,13 +26,14 @@ import org.tasks.date.DateTimeUtils import org.tasks.markdown.Markdown import org.tasks.preferences.DefaultFilterProvider import org.tasks.preferences.Preferences +import org.tasks.tasklist.HeaderFormatter import org.tasks.tasklist.SectionedDataSource import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED import org.tasks.time.DateTimeUtils.startOfDay import org.tasks.ui.CheckBoxProvider import timber.log.Timber import java.time.format.FormatStyle -import java.util.* +import java.util.Locale import kotlin.math.max internal class ScrollableViewsFactory( @@ -46,7 +47,8 @@ internal class ScrollableViewsFactory( private val locale: Locale, private val chipProvider: ChipProvider, private val localBroadcastManager: LocalBroadcastManager, - private val markdown: Markdown + private val markdown: Markdown, + private val headerFormatter: HeaderFormatter, ) : RemoteViewsFactory { private val indentPadding: Int private var showDueDates = false @@ -145,13 +147,12 @@ internal class ScrollableViewsFactory( val section = tasks.getSection(position) val sortGroup = section.value val header: String? = if (filter?.supportsSorting() == true) { - section.headerString( - context, - locale, - sortMode, - showFullDate, - FormatStyle.MEDIUM, - compact + headerFormatter.headerStringBlocking( + value = section.value, + sortMode = sortMode, + alwaysDisplayFullDate = showFullDate, + style = FormatStyle.MEDIUM, + compact = compact, ) } else { null diff --git a/app/src/main/java/org/tasks/widget/ScrollableWidgetUpdateService.java b/app/src/main/java/org/tasks/widget/ScrollableWidgetUpdateService.java index 4a6d9c87b..cb9ebeace 100644 --- a/app/src/main/java/org/tasks/widget/ScrollableWidgetUpdateService.java +++ b/app/src/main/java/org/tasks/widget/ScrollableWidgetUpdateService.java @@ -13,6 +13,7 @@ import org.tasks.data.TaskDao; import org.tasks.markdown.MarkdownProvider; import org.tasks.preferences.DefaultFilterProvider; import org.tasks.preferences.Preferences; +import org.tasks.tasklist.HeaderFormatter; import org.tasks.themes.ColorProvider; import org.tasks.ui.CheckBoxProvider; @@ -33,6 +34,7 @@ public class ScrollableWidgetUpdateService extends RemoteViewsService { @Inject ChipProvider chipProvider; @Inject LocalBroadcastManager localBroadcastManager; @Inject MarkdownProvider markdownProvider; + @Inject HeaderFormatter headerFormatter; @Override public void onStart(Intent intent, int startId) { @@ -65,6 +67,8 @@ public class ScrollableWidgetUpdateService extends RemoteViewsService { locale, chipProvider, localBroadcastManager, - markdownProvider.markdown(false)); + markdownProvider.markdown(false), + headerFormatter + ); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6b8c1ec16..a355594c9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -42,6 +42,7 @@ File %1$s contained %2$s.\n\n By priority By last modified By creation time + By list Matching \'%s\' Create new filter Task name