Make chips skippable

pull/2586/head
Alex Baker 8 months ago
parent 11fa9a2bbd
commit 82103eb477

@ -0,0 +1,56 @@
package org.tasks.compose
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.data.Task
import org.tasks.R
import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.time.DateTimeUtils.startOfDay
import java.time.format.FormatStyle
@Composable
fun StartDateChip(
sortGroup: Long?,
startDate: Long,
compact: Boolean,
timeOnly: Boolean,
colorProvider: (Int) -> Int,
) {
val context = LocalContext.current
val text by remember(sortGroup, startDate, timeOnly, compact) {
derivedStateOf {
if (
timeOnly &&
sortGroup?.startOfDay() == startDate.startOfDay()
) {
startDate
.takeIf { Task.hasDueTime(it) }
?.let { DateUtilities.getTimeString(context, it.toDateTime()) }
} else {
DateUtilities.getRelativeDateTime(
context,
startDate,
context.resources.configuration.locales[0],
if (compact) FormatStyle.SHORT else FormatStyle.MEDIUM,
false,
false
)
}
}
}
if (text != null) {
Chip(
icon = R.drawable.ic_pending_actions_24px,
name = text,
theme = 0,
showText = true,
showIcon = true,
onClick = {},
colorProvider = colorProvider,
)
}
}

@ -8,6 +8,7 @@ import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams import android.view.ViewGroup.MarginLayoutParams
import android.widget.TextView import android.widget.TextView
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -15,17 +16,24 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.composethemeadapter.MdcTheme import com.google.android.material.composethemeadapter.MdcTheme
import com.todoroo.andlib.utility.DateUtilities 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.CaldavFilter
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.TagFilter
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_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
import org.tasks.compose.ChipGroup import org.tasks.compose.ChipGroup
import org.tasks.compose.FilterChip
import org.tasks.compose.StartDateChip
import org.tasks.compose.SubtaskChip
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.databinding.TaskAdapterRowBinding import org.tasks.databinding.TaskAdapterRowBinding
import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.dialogs.Linkify import org.tasks.dialogs.Linkify
import org.tasks.filters.PlaceFilter
import org.tasks.markdown.Markdown import org.tasks.markdown.Markdown
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils.startOfDay import org.tasks.time.DateTimeUtils.startOfDay
@ -221,6 +229,22 @@ class TaskViewHolder internal constructor(
} }
private fun setupChips(filter: Filter, sortByStartDate: Boolean, sortByList: Boolean) { private fun setupChips(filter: Filter, sortByStartDate: Boolean, sortByList: Boolean) {
val id = task.id
val children = task.children
val collapsed = task.isCollapsed
val isHidden = task.isHidden
val sortGroup = task.sortGroup
val startDate = task.task.hideUntil
val place = task.location?.place
val list = task.caldav
val tagsString = task.tagsString
val isSubtask = task.hasParent()
val isGoogleTask = task.isGoogleTask
val appearance = preferences.getIntegerFromString(R.string.p_chip_appearance, 0)
val showText = appearance != 2
val showIcon = appearance != 1
val toggleSubtasks = { task: Long, collapsed: Boolean -> callback.toggleSubtasks(task, collapsed) }
val onClick = { it: Filter -> callback.onClick(it) }
chipGroup.setContent { chipGroup.setContent {
MdcTheme { MdcTheme {
ChipGroup( ChipGroup(
@ -229,24 +253,76 @@ class TaskViewHolder internal constructor(
bottom = rowPaddingDp.dp bottom = rowPaddingDp.dp
) )
) { ) {
chipProvider.Chips( if (children > 0 && remember { preferences.showSubtaskChip }) {
filter = filter, SubtaskChip(
id = task.id, collapsed = collapsed,
children = task.children, children = children,
collapsed = task.isCollapsed, compact = !showText,
isHidden = task.isHidden, onClick = { toggleSubtasks(id, !collapsed) }
sortGroup = task.sortGroup, )
startDate = task.task.hideUntil, }
place = task.location?.place, if (isHidden && remember { preferences.showStartDateChip }) {
list = task.caldav, StartDateChip(
tagsString = task.tagsString, sortGroup = sortGroup,
isSubtask = task.hasParent(), startDate = startDate,
isGoogleTask = task.isGoogleTask, compact = !showText,
sortByStartDate = sortByStartDate, timeOnly = sortByStartDate,
sortByList = sortByList, colorProvider = { chipProvider.getColor(it) },
toggleSubtasks = { task: Long, collapsed: Boolean -> callback.toggleSubtasks(task, collapsed) }, )
onClick = { it: Filter -> callback.onClick(it) }, }
) 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 = { chipProvider.getColor(it) },
)
}
if (
!isSubtask &&
!sortByList &&
preferences.showListChip &&
filter !is CaldavFilter &&
filter !is GtasksFilter
) {
remember(list, isGoogleTask) {
chipProvider.lists
.getCaldavList(list)
?.let { if (isGoogleTask) GtasksFilter(it) else CaldavFilter(it) }
}?.let {
FilterChip(
filter = it,
defaultIcon = R.drawable.ic_list_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = { chipProvider.getColor(it) },
)
}
}
if (!tagsString.isNullOrBlank() && remember { preferences.showTagChip }) {
remember(tagsString, filter) {
val tags = tagsString.split(",").toHashSet()
if (filter is TagFilter) {
tags.remove(filter.uuid)
}
tags.mapNotNull { chipProvider.lists.getTag(it) }
.sortedBy(TagFilter::title)
}
.forEach {
FilterChip(
filter = it,
defaultIcon = R.drawable.ic_outline_label_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = { chipProvider.getColor(it) },
)
}
}
} }
} }
} }

@ -1,173 +1,18 @@
package org.tasks.ui package org.tasks.ui
import android.app.Activity 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
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.R
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.compose.Chip
import org.tasks.compose.FilterChip
import org.tasks.compose.SubtaskChip
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.themes.ColorProvider
import org.tasks.time.DateTimeUtils.startOfDay
import java.time.format.FormatStyle
import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
@Deprecated("remove me")
class ChipProvider @Inject constructor( class ChipProvider @Inject constructor(
private val activity: Activity, private val activity: Activity,
private val inventory: Inventory, private val inventory: Inventory,
private val lists: ChipListCache, val lists: ChipListCache,
private val preferences: Preferences,
private val colorProvider: ColorProvider, private val colorProvider: ColorProvider,
private val locale: Locale
) { ) {
private val showIcon: Boolean
private val showText: Boolean
init {
val appearance = preferences.getIntegerFromString(R.string.p_chip_appearance, 0)
showText = appearance != 2
showIcon = appearance != 1
}
@Composable
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()
) {
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,
)
}
}
@Composable
fun Chips(
filter: Filter?,
id: Long,
children: Int,
collapsed: Boolean,
isHidden: Boolean,
sortGroup: Long?,
startDate: Long,
place: Place?,
tagsString: String?,
sortByStartDate: Boolean,
sortByList: Boolean,
list: String?,
isSubtask: Boolean,
isGoogleTask: Boolean,
toggleSubtasks: (Long, Boolean) -> Unit,
onClick: (Filter) -> Unit,
) {
if (children > 0 && remember { preferences.showSubtaskChip }) {
SubtaskChip(
collapsed = collapsed,
children = children,
compact = !showText,
onClick = { toggleSubtasks(id, !collapsed) }
)
}
if (isHidden && remember { preferences.showStartDateChip }) {
StartDateChip(sortGroup, startDate, !showText, sortByStartDate)
}
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 &&
!sortByList &&
preferences.showListChip &&
filter !is CaldavFilter &&
filter !is GtasksFilter
) {
remember(list, isGoogleTask) {
lists
.getCaldavList(list)
?.let { if (isGoogleTask) GtasksFilter(it) else CaldavFilter(it) }
}?.let {
FilterChip(
filter = it,
defaultIcon = R.drawable.ic_list_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
}
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::title)
}
.forEach {
FilterChip(
filter = it,
defaultIcon = R.drawable.ic_outline_label_24px,
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
}
}
fun getColor(theme: Int): Int { fun getColor(theme: Int): Int {
if (theme != 0) { if (theme != 0) {

@ -3037,11 +3037,7 @@ unstable class ChipProvider {
unstable val activity: Activity unstable val activity: Activity
unstable val inventory: Inventory unstable val inventory: Inventory
unstable val lists: ChipListCache unstable val lists: ChipListCache
unstable val preferences: Preferences
unstable val colorProvider: ColorProvider unstable val colorProvider: ColorProvider
unstable val locale: Locale
stable val showIcon: Boolean
stable val showText: Boolean
<runtime stability> = Unstable <runtime stability> = Unstable
} }
unstable class CompletableViewModel { unstable class CompletableViewModel {

@ -289,6 +289,13 @@ restartable fun Spinner(
stable onSelected: Function1<T, Unit> stable onSelected: Function1<T, Unit>
stable setExpanded: Function1<Boolean, Unit> stable setExpanded: Function1<Boolean, Unit>
) )
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun StartDateChip(
stable sortGroup: Long?
stable startDate: Long
stable compact: Boolean
stable timeOnly: Boolean
stable colorProvider: Function1<Int, Int>
)
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun PurchaseText( restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun PurchaseText(
stable nameYourPrice: MutableState<Boolean>? = @dynamic mutableStateOf( stable nameYourPrice: MutableState<Boolean>? = @dynamic mutableStateOf(
value = false value = false
@ -766,29 +773,3 @@ restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun OrderingB
stable onClick: Function0<Unit> stable onClick: Function0<Unit>
) )
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun PreviewSortBottomSheet() restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun PreviewSortBottomSheet()
restartable scheme("[androidx.compose.ui.UiComposable]") fun StartDateChip(
stable sortGroup: Long?
stable startDate: Long
stable compact: Boolean
stable timeOnly: Boolean
unstable <this>: ChipProvider
)
restartable scheme("[androidx.compose.ui.UiComposable]") fun Chips(
filter: Filter?
stable id: Long
stable children: Int
stable collapsed: Boolean
stable isHidden: Boolean
stable sortGroup: Long?
stable startDate: Long
stable place: Place?
stable tagsString: String?
stable sortByStartDate: Boolean
stable sortByList: Boolean
stable list: String?
stable isSubtask: Boolean
stable isGoogleTask: Boolean
stable toggleSubtasks: Function2<Long, Boolean, Unit>
stable onClick: Function1<Filter, Unit>
unstable <this>: ChipProvider
)

@ -1,16 +1,16 @@
{ {
"skippableComposables": 364, "skippableComposables": 365,
"restartableComposables": 490, "restartableComposables": 489,
"readonlyComposables": 0, "readonlyComposables": 0,
"totalComposables": 496, "totalComposables": 495,
"restartGroups": 490, "restartGroups": 489,
"totalGroups": 599, "totalGroups": 598,
"staticArguments": 762, "staticArguments": 762,
"certainArguments": 328, "certainArguments": 314,
"knownStableArguments": 4878, "knownStableArguments": 4864,
"knownUnstableArguments": 139, "knownUnstableArguments": 139,
"unknownStableArguments": 10, "unknownStableArguments": 9,
"totalArguments": 5027, "totalArguments": 5012,
"markedStableClasses": 0, "markedStableClasses": 0,
"inferredStableClasses": 100, "inferredStableClasses": 100,
"inferredUnstableClasses": 345, "inferredUnstableClasses": 345,
@ -21,5 +21,5 @@
"singletonLambdas": 182, "singletonLambdas": 182,
"singletonComposableLambdas": 90, "singletonComposableLambdas": 90,
"composableLambdas": 223, "composableLambdas": 223,
"totalLambdas": 631 "totalLambdas": 633
} }
Loading…
Cancel
Save