Emit SectionedDataSource from TaskListViewModel

pull/2803/head
Alex Baker 1 month ago
parent d686b8c7e0
commit 1067de4183

@ -118,6 +118,7 @@ import org.tasks.preferences.Preferences
import org.tasks.sync.SyncAdapters
import org.tasks.tags.TagPickerActivity
import org.tasks.tasklist.DragAndDropRecyclerAdapter
import org.tasks.tasklist.SectionedDataSource
import org.tasks.tasklist.TaskViewHolder
import org.tasks.tasklist.ViewHolderFactory
import org.tasks.themes.ColorProvider
@ -188,7 +189,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
activity?.recreate()
}
if (data.getBooleanExtra(SortSettingsActivity.EXTRA_CHANGED_GROUP, false)) {
taskAdapter.clearCollapsed()
listViewModel.clearCollapsed()
}
listViewModel.invalidate()
}
@ -237,7 +238,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
super.onSaveInstanceState(outState)
val selectedTaskIds: List<Long> = taskAdapter.getSelected()
outState.putLongArray(EXTRA_SELECTED_TASK_IDS, selectedTaskIds.toLongArray())
outState.putLongArray(EXTRA_COLLAPSED, taskAdapter.getCollapsed().toLongArray())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -274,7 +274,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
// set up list adapters
taskAdapter = taskAdapterProvider.createTaskAdapter(filter)
taskAdapter.setCollapsed(savedInstanceState?.getLongArray(EXTRA_COLLAPSED))
listViewModel.setFilter(filter)
(recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
recyclerView.layoutManager = LinearLayoutManager(context)
@ -362,11 +361,19 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
return binding.root
}
private fun submitList(tasks: List<TaskContainer>) {
private fun submitList(tasks: SectionedDataSource) {
if (recyclerAdapter !is DragAndDropRecyclerAdapter) {
setAdapter(
DragAndDropRecyclerAdapter(
taskAdapter, binding.bodyStandard.recyclerView, viewHolderFactory, this, tasks, preferences))
adapter = taskAdapter,
recyclerView = binding.bodyStandard.recyclerView,
viewHolderFactory = viewHolderFactory,
taskList = this,
tasks = tasks,
preferences = preferences,
toggleCollapsed = { listViewModel.toggleCollapsed(it) },
)
)
} else {
recyclerAdapter?.submitList(tasks)
}
@ -894,8 +901,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
makeSnackbar(R.string.copy_multiple_tasks_confirmation, duplicates.size.toString())?.show()
}
fun clearCollapsed() = taskAdapter.clearCollapsed()
override fun onCompletedTask(task: TaskContainer, newState: Boolean) {
if (task.isReadOnly) {
return
@ -1010,7 +1015,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
const val ACTION_RELOAD = "action_reload"
const val ACTION_DELETED = "action_deleted"
private const val EXTRA_SELECTED_TASK_IDS = "extra_selected_task_ids"
private const val EXTRA_COLLAPSED = "extra_collapsed"
private const val VOICE_RECOGNITION_REQUEST_CODE = 1234
private const val EXTRA_FILTER = "extra_filter"
private const val FRAG_TAG_REMOTE_LIST_PICKER = "frag_tag_remote_list_picker"

@ -34,11 +34,11 @@ class NavigationDrawerAdapter @Inject constructor(
private val colorProvider: ColorProvider,
private val subheaderClickHandler: SubheaderClickHandler,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(),
DragAndDropDiffer<FilterListItem, MutableList<FilterListItem>> {
DragAndDropDiffer<FilterListItem, ArrayList<FilterListItem>> {
private lateinit var onClick: (FilterListItem?) -> Unit
override val channel = Channel<List<FilterListItem>>(Channel.UNLIMITED)
override val updates: Queue<Pair<MutableList<FilterListItem>, DiffUtil.DiffResult?>> = LinkedList()
override val channel = Channel<ArrayList<FilterListItem>>(Channel.UNLIMITED)
override val updates: Queue<Pair<ArrayList<FilterListItem>, DiffUtil.DiffResult?>> = LinkedList()
override val scope: CoroutineScope =
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job())
override var items = initializeDiffer(ArrayList())
@ -84,9 +84,7 @@ class NavigationDrawerAdapter @Inject constructor(
private fun getItem(position: Int) = items[position]
override fun transform(list: List<FilterListItem>) = list.toMutableList()
override fun diff(last: MutableList<FilterListItem>, next: MutableList<FilterListItem>) =
override fun diff(last: ArrayList<FilterListItem>, next: ArrayList<FilterListItem>) =
DiffUtil.calculateDiff(DiffCallback(last, next))
private class DiffCallback(val old: List<FilterListItem>, val new: List<FilterListItem>) : DiffUtil.Callback() {

@ -22,7 +22,6 @@ import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskContainer
import org.tasks.date.DateTimeUtils.toAppleEpoch
import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED
import org.tasks.time.DateTimeUtils.millisOfDay
open class TaskAdapter(
@ -34,7 +33,6 @@ open class TaskAdapter(
private val taskMover: TaskMover,
) {
private val selected = HashSet<Long>()
private val collapsed = mutableSetOf(HEADER_COMPLETED)
private lateinit var dataSource: TaskAdapterDataSource
val count: Int
@ -56,15 +54,6 @@ open class TaskAdapter(
fun clearSelections() = selected.clear()
fun getCollapsed() = HashSet(collapsed)
fun setCollapsed(groups: LongArray?) {
clearCollapsed()
groups?.toList()?.let(collapsed::addAll)
}
fun clearCollapsed() = collapsed.retainAll(listOf(HEADER_COMPLETED))
open fun getIndent(task: TaskContainer): Int = task.indent
open fun canMove(source: TaskContainer, from: Int, target: TaskContainer, to: Int): Boolean {
@ -125,14 +114,6 @@ open class TaskAdapter(
}
}
fun toggleCollapsed(group: Long) {
if (collapsed.contains(group)) {
collapsed.remove(group)
} else {
collapsed.add(group)
}
}
open fun supportsAstridSorting(): Boolean = false
open suspend fun moved(from: Int, to: Int, indent: Int) {

@ -13,25 +13,24 @@ import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.scan
import java.util.Queue
interface DragAndDropDiffer<T, R> : ListUpdateCallback {
val channel: Channel<List<T>>
interface DragAndDropDiffer<T, R : List<T>> : ListUpdateCallback {
val channel: Channel<R>
val updates: Queue<Pair<R, DiffUtil.DiffResult?>>
var items: R
var dragging: Boolean
val scope: CoroutineScope
fun submitList(list: List<T>) {
fun submitList(list: R) {
channel.trySend(list)
}
fun calculateDiff(last: Pair<R, DiffUtil.DiffResult?>, next: R): Pair<R, DiffUtil.DiffResult?> {
AndroidUtilities.assertNotMainThread()
return Pair(next, diff(last.first!!, next))
return Pair(next, diff(last.first, next))
}
fun applyDiff(update: Pair<R, DiffUtil.DiffResult?>) {
@ -53,11 +52,9 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
}
@ExperimentalCoroutinesApi
fun initializeDiffer(list: List<T>): R {
val initial = transform(list)
fun initializeDiffer(initial: R): R {
channel
.consumeAsFlow()
.map { transform(it) }
.scan(Pair(initial, null)) { last: Pair<R, DiffUtil.DiffResult?>, next: R ->
calculateDiff(last, next)
}
@ -68,8 +65,6 @@ interface DragAndDropDiffer<T, R> : ListUpdateCallback {
return initial
}
fun transform(list: List<T>): R
fun diff(last: R, next: R): DiffUtil.DiffResult
fun dispose() {

@ -100,7 +100,7 @@ class NavigationDrawerCustomization : ThemedInjectingAppCompatActivity(), Toolba
private fun updateFilters() = lifecycleScope.launch {
filterProvider
.drawerCustomizationItems()
.let { adapter.submitList(it) }
.let { adapter.submitList(ArrayList(it)) }
}
private fun onClick(item: FilterListItem?) {

@ -44,6 +44,7 @@ import org.tasks.compose.SubtaskChip
import org.tasks.compose.TaskEditIcon
import org.tasks.compose.TaskEditRow
import org.tasks.data.TaskContainer
import org.tasks.tasklist.SectionedDataSource
import org.tasks.ui.TaskListViewModel
@Composable
@ -90,7 +91,11 @@ fun SubtaskRow(
} else {
Spacer(modifier = Modifier.height(height = 8.dp))
if (existingSubtasks is TaskListViewModel.TasksResults.Results) {
existingSubtasks.tasks.forEach { task ->
existingSubtasks
.tasks
.filterIsInstance<TaskListViewModel.UiItem.Task>()
.map { it.task }
.forEach { task ->
ExistingSubtaskRow(
task = task,
desaturate = desaturate,
@ -237,7 +242,7 @@ fun NoSubtasks() {
filter = null,
hasParent = false,
desaturate = true,
existingSubtasks = TaskListViewModel.TasksResults.Results(emptyList()),
existingSubtasks = TaskListViewModel.TasksResults.Results(SectionedDataSource()),
newSubtasks = emptyList(),
openSubtask = {},
completeExistingSubtask = { _, _ -> },
@ -260,20 +265,22 @@ fun SubtasksPreview() {
hasParent = false,
desaturate = true,
existingSubtasks = TaskListViewModel.TasksResults.Results(
listOf(
TaskContainer(
task = Task(
title = "Existing subtask 1",
priority = Task.Priority.HIGH,
SectionedDataSource(
tasks = listOf(
TaskContainer(
task = Task(
title = "Existing subtask 1",
priority = Task.Priority.HIGH,
),
indent = 0
),
indent = 0
),
TaskContainer(
task = Task(
title = "Existing subtask 2 with a really long title",
priority = Task.Priority.LOW,
),
indent = 1
TaskContainer(
task = Task(
title = "Existing subtask 2 with a really long title",
priority = Task.Priority.LOW,
),
indent = 1
)
)
)
),

@ -30,7 +30,7 @@ internal class DiffCallback(
return if (isHeader) {
old.groupMode == new.groupMode && old.getHeaderValue(oldPosition) == new.getHeaderValue(newPosition)
} else {
old.getItem(oldPosition)!!.id == new.getItem(newPosition)!!.id
old.getItem(oldPosition).id == new.getItem(newPosition).id
}
}
@ -38,8 +38,8 @@ internal class DiffCallback(
if (new.isHeader(newPosition)) {
return old.getSection(oldPosition).collapsed == new.getSection(newPosition).collapsed
}
val oldItem = old.getItem(oldPosition)!!
val newItem = new.getItem(newPosition)!!
val oldItem = old.getItem(oldPosition)
val newItem = new.getItem(newPosition)
return !refreshDates && oldItem == newItem && oldItem.indent == adapter.getIndent(newItem)
}
}

@ -14,7 +14,6 @@ import androidx.recyclerview.widget.ItemTouchHelper.UP
import androidx.recyclerview.widget.RecyclerView
import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.adapter.TaskAdapter
import com.todoroo.astrid.api.AstridOrderingFilter
import com.todoroo.astrid.utility.Flags
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@ -24,6 +23,7 @@ import kotlinx.coroutines.runBlocking
import org.tasks.activities.DragAndDropDiffer
import org.tasks.data.TaskContainer
import org.tasks.preferences.Preferences
import org.tasks.ui.TaskListViewModel.UiItem
import java.util.LinkedList
import java.util.Queue
import java.util.concurrent.Executors
@ -31,21 +31,18 @@ import kotlin.math.max
import kotlin.math.min
class DragAndDropRecyclerAdapter(
private val adapter: TaskAdapter,
private val recyclerView: RecyclerView,
viewHolderFactory: ViewHolderFactory,
private val taskList: TaskListFragment,
tasks: List<TaskContainer>,
preferences: Preferences) : TaskListRecyclerAdapter(adapter, viewHolderFactory, taskList, preferences), DragAndDropDiffer<TaskContainer, SectionedDataSource> {
private val disableHeaders = taskList.getFilter().let {
!it.supportsSorting()
|| (it.supportsManualSort() && preferences.isManualSort)
|| (it is AstridOrderingFilter && preferences.isAstridSort)
}
private val adapter: TaskAdapter,
private val recyclerView: RecyclerView,
viewHolderFactory: ViewHolderFactory,
private val taskList: TaskListFragment,
tasks: SectionedDataSource,
preferences: Preferences,
private val toggleCollapsed: (Long) -> Unit,
) : TaskListRecyclerAdapter(adapter, viewHolderFactory, taskList, preferences), DragAndDropDiffer<UiItem, SectionedDataSource> {
private val itemTouchHelper = ItemTouchHelper(ItemTouchHelperCallback()).apply {
attachToRecyclerView(recyclerView)
}
override val channel = Channel<List<TaskContainer>>(Channel.UNLIMITED)
override val channel = Channel<SectionedDataSource>(Channel.UNLIMITED)
override val updates: Queue<Pair<SectionedDataSource, DiffUtil.DiffResult?>> = LinkedList()
override var dragging = false
override val scope: CoroutineScope =
@ -70,7 +67,7 @@ class DragAndDropRecyclerAdapter(
override fun getItemViewType(position: Int) = if (items.isHeader(position)) 1 else 0
override fun submitList(list: List<TaskContainer>) {
override fun submitList(list: SectionedDataSource) {
super.submitList(list)
}
@ -81,8 +78,7 @@ class DragAndDropRecyclerAdapter(
}
private fun toggleGroup(group: Long) {
adapter.toggleCollapsed(group)
taskList.loadTaskListContent()
toggleCollapsed(group)
}
override fun dragAndDropEnabled() = taskList.getFilter().supportsSubtasks()
@ -93,18 +89,8 @@ class DragAndDropRecyclerAdapter(
override fun getItem(position: Int) = items.getItem(position)
override fun transform(list: List<TaskContainer>): SectionedDataSource =
SectionedDataSource(
tasks = list,
disableHeaders = disableHeaders,
groupMode = preferences.groupMode,
subtaskMode = preferences.subtaskMode,
collapsed = adapter.getCollapsed(),
completedAtBottom = preferences.completedTasksAtBottom,
)
override fun diff(last: SectionedDataSource, next: SectionedDataSource) =
DiffUtil.calculateDiff(DiffCallback(last, next, adapter), next.size < LONG_LIST_SIZE)
DiffUtil.calculateDiff(DiffCallback(last, next, adapter), next.size < LONG_LIST_SIZE)
override fun drainQueue() {
val recyclerViewState = recyclerView.layoutManager!!.onSaveInstanceState()

@ -6,6 +6,7 @@ import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.core.SortHelper
import org.tasks.data.TaskContainer
import org.tasks.time.DateTimeUtils.startOfDay
import org.tasks.ui.TaskListViewModel.UiItem
class SectionedDataSource(
tasks: List<TaskContainer> = emptyList(),
@ -14,7 +15,7 @@ class SectionedDataSource(
val subtaskMode: Int = SortHelper.SORT_MANUAL,
private val collapsed: Set<Long> = emptySet(),
private val completedAtBottom: Boolean = true,
) {
): List<UiItem> {
private val tasks = tasks.toMutableList()
private val sections = if (disableHeaders || groupMode == SortHelper.GROUP_NONE) {
@ -23,7 +24,7 @@ class SectionedDataSource(
getSections()
}
fun getItem(position: Int): TaskContainer? = tasks.getOrNull(sectionedPositionToPosition(position))
fun getItem(position: Int): TaskContainer = tasks[sectionedPositionToPosition(position)]
fun getHeaderValue(position: Int): Long = getSection(position).value
@ -48,9 +49,52 @@ class SectionedDataSource(
val taskCount: Int
get() = tasks.size
val size: Int
override val size: Int
get() = tasks.size + sections.size()
override fun get(index: Int) =
sections[index]
?.let { UiItem.Header(it.value) }
?: UiItem.Task(getItem(index))
override fun isEmpty() = size == 0
override fun iterator(): Iterator<UiItem> {
return object : Iterator<UiItem> {
private var index = 0
override fun hasNext() = index < size
override fun next(): UiItem = get(index++)
}
}
override fun listIterator(): ListIterator<UiItem> {
TODO("Not yet implemented")
}
override fun listIterator(index: Int): ListIterator<UiItem> {
TODO("Not yet implemented")
}
override fun subList(fromIndex: Int, toIndex: Int): List<UiItem> {
TODO("Not yet implemented")
}
override fun lastIndexOf(element: UiItem): Int {
TODO("Not yet implemented")
}
override fun indexOf(element: UiItem): Int {
TODO("Not yet implemented")
}
override fun containsAll(elements: Collection<UiItem>): Boolean {
TODO("Not yet implemented")
}
override fun contains(element: UiItem): Boolean {
TODO("Not yet implemented")
}
fun getSection(position: Int): AdapterSection = sections[position]
fun add(position: Int, task: TaskContainer) = tasks.add(sectionedPositionToPosition(position), task)

@ -8,15 +8,14 @@ import com.todoroo.astrid.adapter.TaskAdapter
import com.todoroo.astrid.adapter.TaskAdapterDataSource
import com.todoroo.astrid.api.AstridOrderingFilter
import com.todoroo.astrid.core.SortHelper
import org.tasks.data.TaskContainer
import org.tasks.preferences.Preferences
abstract class TaskListRecyclerAdapter internal constructor(
private val adapter: TaskAdapter,
internal val viewHolderFactory: ViewHolderFactory,
private val taskList: TaskListFragment,
internal val preferences: Preferences)
: RecyclerView.Adapter<RecyclerView.ViewHolder>(), ListUpdateCallback, TaskAdapterDataSource {
internal val preferences: Preferences
): RecyclerView.Adapter<RecyclerView.ViewHolder>(), ListUpdateCallback, TaskAdapterDataSource {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
= viewHolderFactory.newViewHolder(parent, taskList)
@ -51,7 +50,7 @@ abstract class TaskListRecyclerAdapter internal constructor(
abstract fun dragAndDropEnabled(): Boolean
abstract fun submitList(list: List<TaskContainer>)
abstract fun submitList(list: SectionedDataSource)
override fun onInserted(position: Int, count: Int) {
notifyItemRangeInserted(position, count)

@ -7,6 +7,7 @@ import android.content.Intent
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.AstridOrderingFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.FilterImpl
import com.todoroo.astrid.api.SearchFilter
@ -19,7 +20,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@ -36,8 +36,10 @@ import org.tasks.data.TaskContainer
import org.tasks.data.TaskDao
import org.tasks.data.TaskListQuery.getQuery
import org.tasks.db.QueryUtils
import org.tasks.filters.MyTasksFilter
import org.tasks.preferences.Preferences
import org.tasks.preferences.QueryPreferences
import org.tasks.tasklist.SectionedDataSource
import javax.inject.Inject
@HiltViewModel
@ -53,18 +55,24 @@ class TaskListViewModel @Inject constructor(
private val firebase: Firebase,
) : ViewModel() {
sealed class UiItem {
data class Header(val value: Long): UiItem()
data class Task(val task: TaskContainer): UiItem()
}
sealed interface TasksResults {
data object Loading : TasksResults
data class Results(val tasks: List<TaskContainer>) : TasksResults
data class Results(val tasks: SectionedDataSource) : TasksResults
}
data class State(
val filter: Filter? = null,
val filter: Filter = MyTasksFilter(""),
val now: Long = DateUtilities.now(),
val searchQuery: String? = null,
val tasks: TasksResults = TasksResults.Loading,
val begForSubscription: Boolean = false,
val syncOngoing: Boolean = false,
val collapsed: Set<Long> = setOf(SectionedDataSource.HEADER_COMPLETED),
)
private val _state = MutableStateFlow(State())
@ -104,7 +112,7 @@ class TaskListViewModel @Inject constructor(
}
suspend fun getTasksToClear(): List<Long> {
val filter = _state.value.filter ?: return emptyList()
val filter = _state.value.filter
val deleteFilter = FilterImpl(
sql = QueryUtils.removeOrder(QueryUtils.showHiddenAndCompleted(filter.sql!!)),
)
@ -130,13 +138,12 @@ class TaskListViewModel @Inject constructor(
localBroadcastManager.registerRefreshReceiver(refreshReceiver)
_state
.filter { it.filter != null }
.map { it.copy(tasks = TasksResults.Loading) }
.distinctUntilChanged()
.throttleLatest(333)
.map {
val filter = when {
it.searchQuery == null -> it.filter!!
it.searchQuery == null -> it.filter
it.searchQuery.isBlank() -> BuiltInFilterExposer.getMyTasksFilter(context.resources)
else -> context.createSearchQuery(it.searchQuery)
}
@ -144,7 +151,20 @@ class TaskListViewModel @Inject constructor(
}
.onEach { tasks ->
_state.update {
it.copy(tasks = TasksResults.Results(tasks))
it.copy(
tasks = TasksResults.Results(
SectionedDataSource(
tasks = tasks,
disableHeaders = !it.filter.supportsSorting()
|| (it.filter.supportsManualSort() && preferences.isManualSort)
|| (it.filter is AstridOrderingFilter && preferences.isAstridSort),
groupMode = preferences.groupMode,
subtaskMode = preferences.subtaskMode,
collapsed = it.collapsed,
completedAtBottom = preferences.completedTasksAtBottom,
)
)
)
}
}
.flowOn(Dispatchers.Default)
@ -163,6 +183,24 @@ class TaskListViewModel @Inject constructor(
localBroadcastManager.unregisterReceiver(refreshReceiver)
}
fun clearCollapsed() {
_state.update {
it.copy(collapsed = setOf(SectionedDataSource.HEADER_COMPLETED))
}
}
fun toggleCollapsed(group: Long) {
_state.update {
it.copy(
collapsed = if (it.collapsed.contains(group)) {
it.collapsed.minus(group)
} else {
it.collapsed.plus(group)
}
)
}
}
companion object {
fun Context.createSearchQuery(query: String): Filter =
SearchFilter(getString(R.string.FLA_search_filter, query), query)

@ -92,7 +92,7 @@ internal class TasksWidgetViewFactory(
override fun getViewTypeCount(): Int = 2
override fun getItemId(position: Int) = getTask(position)?.id ?: 0
override fun getItemId(position: Int) = getTask(position).id
override fun hasStableIds(): Boolean = true
@ -145,7 +145,7 @@ internal class TasksWidgetViewFactory(
private fun buildUpdate(position: Int): RemoteViews? {
return try {
val taskContainer = getTask(position) ?: return null
val taskContainer = getTask(position)
val task = taskContainer.task
val textColorTitle = when {
task.isHidden -> onSurfaceVariant
@ -258,7 +258,7 @@ internal class TasksWidgetViewFactory(
}
}
private fun getTask(position: Int): TaskContainer? = tasks.getItem(position)
private fun getTask(position: Int): TaskContainer = tasks.getItem(position)
private suspend fun getQuery(filter: Filter): List<String> {
subtasksHelper.applySubtasksToWidgetFilter(filter, widgetPreferences)

Loading…
Cancel
Save