Move more composable logic

pull/1952/head
Alex Baker 2 years ago
parent 3e3de3c1d6
commit 85b8092982

@ -2,18 +2,15 @@ package com.todoroo.astrid.tags
import android.app.Activity
import android.content.Intent
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import com.google.android.material.composethemeadapter.MdcTheme
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.compose.DisabledText
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.data.TagData
import org.tasks.compose.edit.TagsRow
import org.tasks.tags.TagPickerActivity
import org.tasks.ui.ChipGroup
import org.tasks.ui.ChipProvider
import org.tasks.ui.TaskEditControlComposeFragment
import javax.inject.Inject
@ -28,23 +25,18 @@ class TagsControlSet : TaskEditControlComposeFragment() {
startActivityForResult(intent, REQUEST_TAG_PICKER_ACTIVITY)
}
@Composable
override fun Body() {
val tags = viewModel.selectedTags.collectAsStateLifecycleAware()
ChipGroup(modifier = Modifier.padding(top = 20.dp, bottom = 20.dp, end = 16.dp)) {
if (tags.value.isEmpty()) {
DisabledText(text = stringResource(id = R.string.add_tags))
} else {
tags.value.sortedBy(TagData::name).forEach { tag ->
chipProvider.TagChip(tag, this@TagsControlSet::onRowClick)
override fun bind(parent: ViewGroup?): View =
(parent as ComposeView).apply {
setContent {
MdcTheme {
TagsRow(
tags = viewModel.selectedTags.collectAsStateLifecycleAware().value,
colorProvider = { chipProvider.getColor(it) },
onClick = this@TagsControlSet::onRowClick
)
}
}
}
}
override val isClickable = true
override val icon = R.drawable.ic_outline_label_24px
override fun controlId() = TAG
@ -64,4 +56,4 @@ class TagsControlSet : TaskEditControlComposeFragment() {
const val TAG = R.string.TEA_ctrl_lists_pref
private const val REQUEST_TAG_PICKER_ACTIVITY = 10582
}
}
}

@ -0,0 +1,130 @@
package org.tasks.compose
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.android.material.composethemeadapter.MdcTheme
import org.tasks.themes.CustomIcons
@Composable
fun Chip(
@DrawableRes icon: Int?,
name: String?,
theme: Int,
showText: Boolean,
showIcon: Boolean,
onClick: () -> Unit,
colorProvider: (Int) -> Int,
) {
Chip(
color = Color(colorProvider(theme)),
text = if (showText) name else null,
icon = if (showIcon && icon != null) icon else null,
onClick = onClick,
)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun Chip(
text: String? = null,
icon: Int? = null,
color: Color,
onClick: () -> Unit = {},
) {
CompositionLocalProvider(
LocalMinimumTouchTargetEnforcement provides false
) {
Chip(
onClick = onClick,
border = BorderStroke(1.dp, color = color),
leadingIcon = {
if (text != null) {
ChipIcon(iconRes = icon)
}
},
modifier = Modifier.defaultMinSize(minHeight = 26.dp),
colors = ChipDefaults.chipColors(
backgroundColor = color.copy(alpha = .1f),
contentColor = MaterialTheme.colors.onSurface
),
) {
if (text == null) {
ChipIcon(iconRes = icon)
}
text?.let {
Text(
text = it,
style = MaterialTheme.typography.caption,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}
@Composable
private fun ChipIcon(iconRes: Int?) {
iconRes?.let {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
modifier = Modifier.size(18.dp)
)
}
}
@ExperimentalComposeUiApi
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun TasksChipIconAndTextPreview() {
MdcTheme {
Chip(
text = "Home",
icon = CustomIcons.getIconResId(CustomIcons.LABEL),
color = Color.Red,
)
}
}
@ExperimentalComposeUiApi
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun TasksChipIconPreview() {
MdcTheme {
Chip(
text = null,
icon = CustomIcons.getIconResId(CustomIcons.LABEL),
color = Color.Red,
)
}
}
@ExperimentalComposeUiApi
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun TasksChipTextPreview() {
MdcTheme {
Chip(
text = "Home",
icon = null,
color = Color.Red,
)
}
}

@ -0,0 +1,17 @@
package org.tasks.compose
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.google.accompanist.flowlayout.FlowRow
@Composable
fun ChipGroup(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
FlowRow(
mainAxisSpacing = 4.dp,
crossAxisSpacing = 4.dp,
modifier = modifier,
) {
content()
}
}

@ -0,0 +1,25 @@
package org.tasks.compose
import androidx.compose.runtime.Composable
import com.todoroo.astrid.api.Filter
import org.tasks.themes.CustomIcons
@Composable
fun FilterChip(
filter: Filter,
defaultIcon: Int,
showText: Boolean,
showIcon: Boolean,
onClick: (Filter) -> Unit,
colorProvider: (Int) -> Int,
) {
Chip(
CustomIcons.getIcon(filter.icon, defaultIcon),
filter.listingTitle,
filter.tint,
showText,
showIcon,
onClick = { onClick(filter) },
colorProvider = colorProvider,
)
}

@ -0,0 +1,37 @@
package org.tasks.compose.edit
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.todoroo.astrid.api.Filter
import org.tasks.R
import org.tasks.compose.ChipGroup
import org.tasks.compose.FilterChip
import org.tasks.compose.TaskEditRow
@Composable
fun ListRow(
list: Filter?,
colorProvider: (Int) -> Int,
onClick: () -> Unit,
) {
TaskEditRow(
iconRes = R.drawable.ic_list_24px,
content = {
ChipGroup(modifier = Modifier.padding(vertical = 20.dp)) {
if (list != null) {
FilterChip(
filter = list,
defaultIcon = R.drawable.ic_list_24px,
showText = true,
showIcon = true,
onClick = { onClick() },
colorProvider = colorProvider
)
}
}
},
onClick = onClick
)
}

@ -0,0 +1,48 @@
package org.tasks.compose.edit
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import org.tasks.R
import org.tasks.compose.Chip
import org.tasks.compose.ChipGroup
import org.tasks.compose.DisabledText
import org.tasks.compose.TaskEditRow
import org.tasks.data.TagData
import org.tasks.themes.CustomIcons
@Composable
fun TagsRow(
tags: List<TagData>,
colorProvider: (Int) -> Int,
onClick: () -> Unit,
) {
TaskEditRow(
iconRes = R.drawable.ic_outline_label_24px,
content = {
ChipGroup(modifier = Modifier.padding(top = 20.dp, bottom = 20.dp, end = 16.dp)) {
if (tags.isEmpty()) {
DisabledText(text = stringResource(id = R.string.add_tags))
} else {
tags.sortedBy(TagData::name).forEach { tag ->
Chip(
icon = CustomIcons.getIcon(
tag.getIcon()!!,
R.drawable.ic_outline_label_24px
),
name = tag.name,
theme = tag.getColor()!!,
showText = true,
showIcon = true,
onClick = onClick,
colorProvider = colorProvider,
)
}
}
}
},
onClick = onClick
)
}

@ -20,6 +20,7 @@ import com.todoroo.astrid.core.SortHelper.SORT_DUE
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.data.TaskContainer
import org.tasks.databinding.TaskAdapterRowBinding
import org.tasks.date.DateTimeUtils.newDateTime
@ -28,7 +29,6 @@ import org.tasks.markdown.Markdown
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils.startOfDay
import org.tasks.ui.CheckBoxProvider
import org.tasks.ui.ChipGroup
import org.tasks.ui.ChipProvider
import java.time.format.FormatStyle
import java.util.*

@ -1,5 +1,6 @@
package org.tasks.themes
import androidx.annotation.DrawableRes
import org.tasks.R
object CustomIcons {
@ -218,4 +219,7 @@ object CustomIcons {
@JvmStatic
fun getIndex(position: Int) = getIconList()[position]
@DrawableRes
fun getIcon(index: Int, def: Int) = getIconResId(index) ?: def
}

@ -1,23 +1,7 @@
package org.tasks.ui
import android.app.Activity
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.accompanist.flowlayout.FlowRow
import com.google.android.material.composethemeadapter.MdcTheme
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
@ -27,16 +11,14 @@ import com.todoroo.astrid.data.Task
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.billing.Inventory
import org.tasks.data.TagData
import org.tasks.compose.Chip
import org.tasks.compose.FilterChip
import org.tasks.data.TaskContainer
import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.extensions.formatNumber
import org.tasks.filters.PlaceFilter
import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons
import org.tasks.themes.CustomIcons.getIconResId
import org.tasks.themes.ThemeColor
import org.tasks.time.DateTimeUtils.startOfDay
import java.time.format.FormatStyle
import java.util.*
@ -79,13 +61,14 @@ class ChipProvider @Inject constructor(
false
)
}
TasksChip(
Chip(
R.drawable.ic_pending_actions_24px,
text,
0,
showText = true,
showIcon = true,
onClick = {},
colorProvider = this::getColor,
)
}
@ -95,7 +78,7 @@ class ChipProvider @Inject constructor(
compact: Boolean,
onClick: () -> Unit,
) {
TasksChip(
Chip(
if (task.isCollapsed) R.drawable.ic_keyboard_arrow_down_black_24dp else R.drawable.ic_keyboard_arrow_up_black_24dp,
if (compact) locale.formatNumber(task.children) else activity
.resources
@ -104,24 +87,7 @@ class ChipProvider @Inject constructor(
showText = true,
showIcon = true,
onClick = onClick,
)
}
@Composable
fun FilterChip(
filter: Filter,
defaultIcon: Int,
showText: Boolean = this@ChipProvider.showText,
showIcon: Boolean = this@ChipProvider.showIcon,
onClick: (Any) -> Unit,
) {
TasksChip(
getIcon(filter.icon, defaultIcon),
filter.listingTitle,
filter.tint,
showText,
showIcon,
onClick = { onClick(filter) },
colorProvider = this::getColor,
)
}
@ -144,7 +110,10 @@ class ChipProvider @Inject constructor(
FilterChip(
filter = PlaceFilter(location.place),
defaultIcon = R.drawable.ic_outline_place_24px,
onClick = onClick
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
if (!isSubtask && preferences.showListChip) {
@ -153,7 +122,10 @@ class ChipProvider @Inject constructor(
FilterChip(
filter = list,
defaultIcon = R.drawable.ic_list_24px,
onClick = onClick
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
} else if (!isNullOrEmpty(task.caldav) && filter !is CaldavFilter) {
@ -161,7 +133,10 @@ class ChipProvider @Inject constructor(
FilterChip(
filter = list,
defaultIcon = R.drawable.ic_list_24px,
onClick = onClick
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
}
@ -178,157 +153,22 @@ class ChipProvider @Inject constructor(
FilterChip(
filter = it,
defaultIcon = R.drawable.ic_outline_label_24px,
onClick = onClick
onClick = onClick,
showText = showText,
showIcon = showIcon,
colorProvider = this::getColor,
)
}
}
}
@Composable
fun TagChip(tag: TagData, onClick: () -> Unit) {
TasksChip(
getIcon(tag.getIcon()!!, R.drawable.ic_outline_label_24px),
tag.name,
tag.getColor()!!,
showText = true,
showIcon = true,
onClick = onClick,
)
}
@Composable
fun TasksChip(
@DrawableRes icon: Int?,
name: String?,
theme: Int,
showText: Boolean,
showIcon: Boolean,
onClick: () -> Unit,
) {
val color =
getColor(theme)?.primaryColor ?: activity.getColor(R.color.default_chip_background)
TasksChip(
color = Color(color),
text = if (showText) name else null,
icon = if (showIcon && icon != null) icon else null,
onClick = onClick,
)
}
@DrawableRes
private fun getIcon(index: Int, def: Int) = getIconResId(index) ?: def
private fun getColor(theme: Int): ThemeColor? {
fun getColor(theme: Int): Int {
if (theme != 0) {
val color = colorProvider.getThemeColor(theme, true)
if (color.isFree || inventory.purchasedThemes()) {
return color
return color.primaryColor
}
}
return null
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun TasksChip(
text: String? = null,
icon: Int? = null,
color: Color,
onClick: () -> Unit = {},
) {
CompositionLocalProvider(
LocalMinimumTouchTargetEnforcement provides false
) {
Chip(
onClick = onClick,
border = BorderStroke(1.dp, color = color),
leadingIcon = {
if (text != null) {
ChipIcon(iconRes = icon)
}
},
modifier = Modifier.defaultMinSize(minHeight = 26.dp),
colors = ChipDefaults.chipColors(
backgroundColor = color.copy(alpha = .1f),
contentColor = MaterialTheme.colors.onSurface
),
) {
if (text == null) {
ChipIcon(iconRes = icon)
}
text?.let {
Text(
text = it,
style = MaterialTheme.typography.caption,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}
@Composable
fun ChipGroup(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
FlowRow(
mainAxisSpacing = 4.dp,
crossAxisSpacing = 4.dp,
modifier = modifier,
) {
content()
}
}
@Composable
fun ChipIcon(iconRes: Int?) {
iconRes?.let {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
modifier = Modifier.size(18.dp)
)
}
}
@ExperimentalComposeUiApi
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun TasksChipIconAndTextPreview() {
MdcTheme {
TasksChip(
text = "Home",
icon = getIconResId(CustomIcons.LABEL),
color = Color.Red,
)
}
}
@ExperimentalComposeUiApi
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun TasksChipIconPreview() {
MdcTheme {
TasksChip(
text = null,
icon = getIconResId(CustomIcons.LABEL),
color = Color.Red,
)
}
}
@ExperimentalComposeUiApi
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun TasksChipTextPreview() {
MdcTheme {
TasksChip(
text = "Home",
icon = null,
color = Color.Red,
)
return activity.getColor(R.color.default_chip_background)
}
}

@ -2,10 +2,10 @@ package org.tasks.ui
import android.app.Activity
import android.content.Intent
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import com.google.android.material.composethemeadapter.MdcTheme
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
@ -13,39 +13,36 @@ import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.activities.ListPicker
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.ListRow
import javax.inject.Inject
@AndroidEntryPoint
class ListFragment : TaskEditControlComposeFragment() {
@Inject lateinit var chipProvider: ChipProvider
@Composable
override fun Body() {
val list = viewModel.selectedList.collectAsStateLifecycleAware()
val selectedList = list.value ?: return
ChipGroup(modifier = Modifier.padding(vertical = 20.dp)) {
chipProvider.FilterChip(
filter = selectedList,
defaultIcon = R.drawable.ic_list_24px,
showText = true,
showIcon = true,
onClick = { openPicker() }
)
override fun bind(parent: ViewGroup?): View =
(parent as ComposeView).apply {
setContent {
MdcTheme {
ListRow(
list = viewModel.selectedList.collectAsStateLifecycleAware().value,
colorProvider = { chipProvider.getColor(it) },
onClick = {
ListPicker.newListPicker(
viewModel.selectedList.value!!,
this@ListFragment,
REQUEST_CODE_SELECT_LIST
)
.show(parentFragmentManager, FRAG_TAG_GOOGLE_TASK_LIST_SELECTION)
}
)
}
}
}
}
override val icon = R.drawable.ic_list_24px
override fun controlId() = TAG
override fun onRowClick() = openPicker()
override val isClickable = true
private fun openPicker() =
ListPicker.newListPicker(viewModel.selectedList.value!!, this, REQUEST_CODE_SELECT_LIST)
.show(parentFragmentManager, FRAG_TAG_GOOGLE_TASK_LIST_SELECTION)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CODE_SELECT_LIST) {
if (resultCode == Activity.RESULT_OK) {
@ -67,4 +64,4 @@ class ListFragment : TaskEditControlComposeFragment() {
private const val FRAG_TAG_GOOGLE_TASK_LIST_SELECTION = "frag_tag_google_task_list_selection"
private const val REQUEST_CODE_SELECT_LIST = 10101
}
}
}

Loading…
Cancel
Save