Fix some recomposition issues on chips

pull/2260/head
Alex Baker 1 year ago
parent 4018277645
commit e37497b77f

@ -918,9 +918,9 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
showDateTimePicker(task)
}
override fun toggleSubtasks(task: TaskContainer, collapsed: Boolean) {
override fun toggleSubtasks(task: Long, collapsed: Boolean) {
lifecycleScope.launch {
taskDao.setCollapsed(task.id, collapsed)
taskDao.setCollapsed(task, collapsed)
}
}

@ -11,6 +11,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Cancel
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
@ -36,7 +37,7 @@ fun Chip(
clear: (() -> Unit)? = null,
) {
Chip(
color = Color(colorProvider(theme)),
color = remember(theme) { Color(colorProvider(theme)) },
text = if (showText) name else null,
icon = if (showIcon && icon != null) icon else null,
onClick = onClick,

@ -1,27 +1,30 @@
package org.tasks.compose
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import org.tasks.R
import org.tasks.data.TaskContainer
import java.text.NumberFormat
@Composable
fun SubtaskChip(
task: TaskContainer,
collapsed: Boolean,
children: Int,
compact: Boolean,
onClick: () -> Unit,
) {
val context = LocalContext.current
Chip(
icon = if (task.isCollapsed)
icon = if (collapsed)
R.drawable.ic_keyboard_arrow_down_black_24dp
else
R.drawable.ic_keyboard_arrow_up_black_24dp,
name = if (compact)
NumberFormat.getInstance().format(task.children)
NumberFormat.getInstance().format(children)
else
context.resources.getQuantityString(R.plurals.subtask_count, task.children, task.children),
remember(children) {
context.resources.getQuantityString(R.plurals.subtask_count, children, children)
},
theme = 0,
showText = true,
showIcon = true,

@ -210,7 +210,8 @@ fun ExistingSubtaskRow(
)
if (task.hasChildren()) {
SubtaskChip(
task = task,
collapsed = task.isCollapsed,
children = task.children,
compact = true,
onClick = onToggleSubtaskClick,
)

@ -226,24 +226,26 @@ class TaskViewHolder internal constructor(
) {
chipProvider.Chips(
filter = filter,
isSubtask = indent > 0,
task = task,
id = task.id,
children = task.children,
collapsed = task.isCollapsed,
isHidden = task.isHidden,
sortGroup = task.sortGroup,
startDate = task.startDate,
place = task.location?.place,
list = task.caldav,
tagsString = task.tagsString,
isSubtask = task.hasParent(),
isGoogleTask = task.isGoogleTask,
sortByStartDate = sortByStartDate,
onClick = this::onChipClick
toggleSubtasks = { task: Long, collapsed: Boolean -> callback.toggleSubtasks(task, collapsed) },
onClick = { it: Filter -> callback.onClick(it) },
)
}
}
}
}
private fun onChipClick(tag: Any) {
if (tag is Filter) {
callback.onClick(tag)
} else if (tag is TaskContainer) {
callback.toggleSubtasks(tag, !tag.isCollapsed)
}
}
private fun onCompleteBoxClick() {
val newState = completeBox.isChecked
if (newState != task.isCompleted) {
@ -263,7 +265,7 @@ class TaskViewHolder internal constructor(
fun onLinkClicked(vh: TaskViewHolder, url: String): Boolean
fun onClick(taskViewHolder: TaskViewHolder)
fun onClick(filter: Filter)
fun toggleSubtasks(task: TaskContainer, collapsed: Boolean)
fun toggleSubtasks(task: Long, collapsed: Boolean)
fun onLongPress(taskViewHolder: TaskViewHolder): Boolean
fun onChangeDueDate(task: TaskContainer)
}

@ -2,6 +2,9 @@ package org.tasks.ui
import android.app.Activity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
@ -9,19 +12,18 @@ 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.compose.Chip
import org.tasks.compose.FilterChip
import org.tasks.compose.SubtaskChip
import org.tasks.data.TaskContainer
import org.tasks.data.Place
import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.filters.PlaceFilter
import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider
import org.tasks.time.DateTimeUtils.startOfDay
import java.time.format.FormatStyle
import java.util.*
import java.util.Locale
import javax.inject.Inject
class ChipProvider @Inject constructor(
@ -42,67 +44,95 @@ class ChipProvider @Inject constructor(
}
@Composable
private fun StartDateChip(task: TaskContainer, compact: Boolean, timeOnly: Boolean) {
val text = if (timeOnly
&& task.sortGroup?.startOfDay() == task.startDate.startOfDay()
&& preferences.showGroupHeaders()
) {
task.startDate
.takeIf { Task.hasDueTime(it) }
?.let { DateUtilities.getTimeString(activity, it.toDateTime()) }
?: return
} else {
DateUtilities.getRelativeDateTime(
activity,
task.startDate,
locale,
if (compact) FormatStyle.SHORT else FormatStyle.MEDIUM,
false,
false
private fun StartDateChip(
sortGroup: Long?,
startDate: Long,
compact: Boolean,
timeOnly: Boolean
) {
val text by remember(sortGroup, startDate, timeOnly, compact) {
derivedStateOf {
if (
timeOnly &&
sortGroup?.startOfDay() == startDate.startOfDay() &&
preferences.showGroupHeaders()
) {
startDate
.takeIf { Task.hasDueTime(it) }
?.let { DateUtilities.getTimeString(activity, it.toDateTime()) }
} else {
DateUtilities.getRelativeDateTime(
activity,
startDate,
locale,
if (compact) FormatStyle.SHORT else FormatStyle.MEDIUM,
false,
false
)
}
}
}
if (text != null) {
Chip(
R.drawable.ic_pending_actions_24px,
text,
0,
showText = true,
showIcon = true,
onClick = {},
colorProvider = this::getColor,
)
}
Chip(
R.drawable.ic_pending_actions_24px,
text,
0,
showText = true,
showIcon = true,
onClick = {},
colorProvider = this::getColor,
)
}
@Composable
fun Chips(
filter: Filter?,
isSubtask: Boolean,
task: TaskContainer,
id: Long,
children: Int,
collapsed: Boolean,
isHidden: Boolean,
sortGroup: Long?,
startDate: Long,
place: Place?,
tagsString: String?,
sortByStartDate: Boolean,
onClick: (Any) -> Unit,
list: String?,
isSubtask: Boolean,
isGoogleTask: Boolean,
toggleSubtasks: (Long, Boolean) -> Unit,
onClick: (Filter) -> Unit,
) {
if (task.hasChildren() && preferences.showSubtaskChip) {
SubtaskChip(task, !showText, onClick = { onClick(task) })
if (children > 0 && remember { preferences.showSubtaskChip }) {
SubtaskChip(
collapsed = collapsed,
children = children,
compact = !showText,
onClick = { toggleSubtasks(id, !collapsed) }
)
}
if (task.isHidden && preferences.showStartDateChip) {
StartDateChip(task, !showText, sortByStartDate)
if (isHidden && remember { preferences.showStartDateChip }) {
StartDateChip(sortGroup, startDate, !showText, sortByStartDate)
}
if (task.hasLocation() && filter !is PlaceFilter && preferences.showPlaceChip) {
val location = task.getLocation()
if (location != null) {
FilterChip(
filter = PlaceFilter(location.place),
defaultIcon = R.drawable.ic_outline_place_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
if (place != null && filter !is PlaceFilter && remember { preferences.showPlaceChip }) {
FilterChip(
filter = PlaceFilter(place),
defaultIcon = R.drawable.ic_outline_place_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
if (!isSubtask && preferences.showListChip && filter !is CaldavFilter) {
lists.getCaldavList(task.caldav)?.let { list ->
remember(list, isGoogleTask) {
lists
.getCaldavList(list)
?.let { if (isGoogleTask) GtasksFilter(it) else CaldavFilter(it) }
}?.let {
FilterChip(
filter = if (task.isGoogleTask) GtasksFilter(list) else CaldavFilter(list),
filter = it,
defaultIcon = R.drawable.ic_list_24px,
onClick = onClick,
showText = showText,
@ -111,14 +141,15 @@ class ChipProvider @Inject constructor(
)
}
}
val tagString = task.tagsString
if (!isNullOrEmpty(tagString) && preferences.showTagChip) {
val tags = tagString.split(",").toHashSet()
if (filter is TagFilter) {
tags.remove(filter.uuid)
if (!tagsString.isNullOrBlank() && remember { preferences.showTagChip }) {
remember(tagsString, filter) {
val tags = tagsString.split(",").toHashSet()
if (filter is TagFilter) {
tags.remove(filter.uuid)
}
tags.mapNotNull(lists::getTag)
.sortedBy(TagFilter::listingTitle)
}
tags.mapNotNull(lists::getTag)
.sortedBy(TagFilter::listingTitle)
.forEach {
FilterChip(
filter = it,

Loading…
Cancel
Save