diff --git a/app/src/main/java/org/tasks/compose/StartDateChip.kt b/app/src/main/java/org/tasks/compose/StartDateChip.kt new file mode 100644 index 000000000..c7c74c9be --- /dev/null +++ b/app/src/main/java/org/tasks/compose/StartDateChip.kt @@ -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, + ) + } +} diff --git a/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt b/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt index 9bac2004e..463a30941 100644 --- a/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt +++ b/app/src/main/java/org/tasks/tasklist/TaskViewHolder.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import android.view.ViewGroup.MarginLayoutParams import android.widget.TextView import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.unit.dp @@ -15,17 +16,24 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.composethemeadapter.MdcTheme import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities.now +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.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 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.databinding.TaskAdapterRowBinding import org.tasks.date.DateTimeUtils.newDateTime import org.tasks.dialogs.Linkify +import org.tasks.filters.PlaceFilter import org.tasks.markdown.Markdown import org.tasks.preferences.Preferences import org.tasks.time.DateTimeUtils.startOfDay @@ -221,6 +229,22 @@ class TaskViewHolder internal constructor( } 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 { MdcTheme { ChipGroup( @@ -229,24 +253,76 @@ class TaskViewHolder internal constructor( bottom = rowPaddingDp.dp ) ) { - chipProvider.Chips( - filter = filter, - id = task.id, - children = task.children, - collapsed = task.isCollapsed, - isHidden = task.isHidden, - sortGroup = task.sortGroup, - startDate = task.task.hideUntil, - place = task.location?.place, - list = task.caldav, - tagsString = task.tagsString, - 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) }, - ) + if (children > 0 && remember { preferences.showSubtaskChip }) { + SubtaskChip( + collapsed = collapsed, + children = children, + compact = !showText, + onClick = { toggleSubtasks(id, !collapsed) } + ) + } + if (isHidden && remember { preferences.showStartDateChip }) { + StartDateChip( + sortGroup = sortGroup, + startDate = startDate, + compact = !showText, + timeOnly = sortByStartDate, + colorProvider = { chipProvider.getColor(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) }, + ) + } + } } } } diff --git a/app/src/main/java/org/tasks/ui/ChipProvider.kt b/app/src/main/java/org/tasks/ui/ChipProvider.kt index b61302a02..33f623606 100644 --- a/app/src/main/java/org/tasks/ui/ChipProvider.kt +++ b/app/src/main/java/org/tasks/ui/ChipProvider.kt @@ -1,173 +1,18 @@ 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 -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.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.time.DateTimeUtils.startOfDay -import java.time.format.FormatStyle -import java.util.Locale import javax.inject.Inject +@Deprecated("remove me") class ChipProvider @Inject constructor( private val activity: Activity, private val inventory: Inventory, - private val lists: ChipListCache, - private val preferences: Preferences, + val lists: ChipListCache, 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 { if (theme != 0) { diff --git a/compose-metrics/app_googleplayDebug-classes.txt b/compose-metrics/app_googleplayDebug-classes.txt index 8d9fa7715..7e783ac31 100644 --- a/compose-metrics/app_googleplayDebug-classes.txt +++ b/compose-metrics/app_googleplayDebug-classes.txt @@ -3037,11 +3037,7 @@ unstable class ChipProvider { unstable val activity: Activity unstable val inventory: Inventory unstable val lists: ChipListCache - unstable val preferences: Preferences unstable val colorProvider: ColorProvider - unstable val locale: Locale - stable val showIcon: Boolean - stable val showText: Boolean = Unstable } unstable class CompletableViewModel { diff --git a/compose-metrics/app_googleplayDebug-composables.txt b/compose-metrics/app_googleplayDebug-composables.txt index f18abcbec..e29e6df42 100644 --- a/compose-metrics/app_googleplayDebug-composables.txt +++ b/compose-metrics/app_googleplayDebug-composables.txt @@ -289,6 +289,13 @@ restartable fun Spinner( stable onSelected: Function1 stable setExpanded: Function1 ) +restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun StartDateChip( + stable sortGroup: Long? + stable startDate: Long + stable compact: Boolean + stable timeOnly: Boolean + stable colorProvider: Function1 +) restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun PurchaseText( stable nameYourPrice: MutableState? = @dynamic mutableStateOf( value = false @@ -766,29 +773,3 @@ restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun OrderingB stable onClick: Function0 ) 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 : 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 - stable onClick: Function1 - unstable : ChipProvider -) diff --git a/compose-metrics/app_googleplayDebug-module.json b/compose-metrics/app_googleplayDebug-module.json index 92e354e48..e44329ed1 100644 --- a/compose-metrics/app_googleplayDebug-module.json +++ b/compose-metrics/app_googleplayDebug-module.json @@ -1,16 +1,16 @@ { - "skippableComposables": 364, - "restartableComposables": 490, + "skippableComposables": 365, + "restartableComposables": 489, "readonlyComposables": 0, - "totalComposables": 496, - "restartGroups": 490, - "totalGroups": 599, + "totalComposables": 495, + "restartGroups": 489, + "totalGroups": 598, "staticArguments": 762, - "certainArguments": 328, - "knownStableArguments": 4878, + "certainArguments": 314, + "knownStableArguments": 4864, "knownUnstableArguments": 139, - "unknownStableArguments": 10, - "totalArguments": 5027, + "unknownStableArguments": 9, + "totalArguments": 5012, "markedStableClasses": 0, "inferredStableClasses": 100, "inferredUnstableClasses": 345, @@ -21,5 +21,5 @@ "singletonLambdas": 182, "singletonComposableLambdas": 90, "composableLambdas": 223, - "totalLambdas": 631 + "totalLambdas": 633 } \ No newline at end of file