Fix state loss issues in list settings activities

pull/3207/head
Alex Baker 11 months ago
parent e48f7e61c3
commit 60a9b018ec

@ -6,16 +6,17 @@ import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.utils.colorInt
@ -51,39 +52,20 @@ abstract class BaseListSettingsActivity : AppCompatActivity(), ColorPalettePicke
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
@Inject lateinit var firebase: Firebase
protected abstract val defaultIcon: String
protected var selectedColor = 0
protected var selectedIcon = mutableStateOf<String?>(null)
protected val baseViewModel: BaseListSettingsViewModel by viewModels()
protected val textState = mutableStateOf("")
protected val errorState = mutableStateOf("")
protected val colorState = mutableStateOf(Color.Unspecified)
protected val showProgress = mutableStateOf(false)
protected val promptDelete = mutableStateOf(false)
protected val promptDiscard = mutableStateOf(false)
protected abstract val defaultIcon: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/* defaultIcon is initialized in the descendant's constructor so it can not be used
in constructor of the base class. So valid initial value for iconState is set here */
selectedIcon.value = defaultIcon
baseViewModel.setIcon(defaultIcon)
if (savedInstanceState != null) {
selectedColor = savedInstanceState.getInt(EXTRA_SELECTED_THEME)
selectedIcon.value = savedInstanceState.getString(EXTRA_SELECTED_ICON) ?: defaultIcon
}
addBackPressedCallback {
discard()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt(EXTRA_SELECTED_THEME, selectedColor)
outState.putString(EXTRA_SELECTED_ICON, selectedIcon.value)
}
protected abstract fun hasChanges(): Boolean
protected abstract suspend fun save()
protected val isNew: Boolean
@ -93,8 +75,11 @@ abstract class BaseListSettingsActivity : AppCompatActivity(), ColorPalettePicke
protected abstract val toolbarTitle: String?
protected abstract suspend fun delete()
protected open fun discard() {
if (hasChanges()) promptDiscard.value = true
else finish()
if (hasChanges()) {
baseViewModel.promptDiscard(true)
} else {
finish()
}
}
protected fun clearColor() {
@ -102,34 +87,36 @@ abstract class BaseListSettingsActivity : AppCompatActivity(), ColorPalettePicke
}
protected fun showThemePicker() {
newColorPalette(null, 0, selectedColor, Palette.COLORS)
newColorPalette(null, 0, baseViewModel.color, Palette.COLORS)
.show(supportFragmentManager, FRAG_TAG_COLOR_PICKER)
}
val launcher = registerForIconPickerResult { selected ->
selectedIcon.value = selected
baseViewModel.setIcon(selected)
}
fun showIconPicker() {
launcher.launchIconPicker(this, selectedIcon.value)
launcher.launchIconPicker(this, baseViewModel.icon)
}
override fun onColorPicked(color: Int) {
selectedColor = color
baseViewModel.setColor(color)
updateTheme()
}
protected open fun promptDelete() { promptDelete.value = true }
protected open fun promptDelete() { baseViewModel.promptDelete(true) }
protected fun updateTheme() {
val selectedColor = baseViewModel.color
val themeColor: ThemeColor =
if (selectedColor == 0) tasksTheme.themeColor
else colorProvider.getThemeColor(selectedColor, true)
colorState.value =
baseViewModel.setColorState(
if (selectedColor == 0) Color.Unspecified
else Color((colorProvider.getThemeColor(selectedColor, true)).primaryColor)
)
//iconState.intValue = (getIconResId(selectedIcon) ?: getIconResId(defaultIcon))!!
@ -147,30 +134,31 @@ abstract class BaseListSettingsActivity : AppCompatActivity(), ColorPalettePicke
fab: @Composable () -> Unit = {},
extensionContent: @Composable ColumnScope.() -> Unit = {},
) {
val viewState = baseViewModel.viewState.collectAsStateWithLifecycle().value
ListSettingsScaffold(
title = title,
theme = if (colorState.value == Color.Unspecified)
theme = if (viewState.colorState == Color.Unspecified)
Color(tasksTheme.themeColor.primaryColor)
else
colorState.value,
promptDiscard = promptDiscard.value,
showProgress = showProgress.value,
dismissDiscardPrompt = { promptDiscard.value = false },
viewState.colorState,
promptDiscard = viewState.promptDiscard,
showProgress = viewState.showProgress,
dismissDiscardPrompt = { baseViewModel.promptDiscard(false) },
save = { lifecycleScope.launch { save() } },
discard = { finish() },
actions = optionButton,
fab = fab,
) {
ListSettingsContent(
color = colorState.value,
icon = selectedIcon.value ?: defaultIcon,
text = textState.value,
error = errorState.value,
color = viewState.colorState,
icon = viewState.icon ?: defaultIcon,
text = viewState.title,
error = viewState.error,
requestKeyboard = requestKeyboard,
isNew = isNew,
setText = {
textState.value = it
errorState.value = ""
baseViewModel.setTitle(it)
baseViewModel.setError("")
},
pickColor = { showThemePicker() },
clearColor = { clearColor() },
@ -184,14 +172,14 @@ abstract class BaseListSettingsActivity : AppCompatActivity(), ColorPalettePicke
protected fun createShortcut() {
filter?.let {
val filterId = defaultFilterProvider.getFilterPreferenceValue(it)
val iconColor = if (colorState.value == Color.Unspecified)
val iconColor = if (baseViewModel.colorState == Color.Unspecified)
Color(tasksTheme.themeColor.primaryColor)
else
colorState.value
baseViewModel.colorState
val shortcutInfo = ShortcutInfoCompat.Builder(this, UUIDHelper.newUUID())
.setShortLabel(title)
.setShortLabel(baseViewModel.title)
.setIcon(
selectedIcon.value
baseViewModel.icon
?.let { icon ->
try {
createShortcutIcon(
@ -234,8 +222,6 @@ abstract class BaseListSettingsActivity : AppCompatActivity(), ColorPalettePicke
}
companion object {
private const val EXTRA_SELECTED_THEME = "extra_selected_theme"
private const val EXTRA_SELECTED_ICON = "extra_selected_icon"
private const val FRAG_TAG_COLOR_PICKER = "frag_tag_color_picker"
fun createShortcutIcon(context: Context, backgroundColor: Color): IconCompat {

@ -0,0 +1,68 @@
package org.tasks.activities
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
class BaseListSettingsViewModel : ViewModel() {
data class ViewState(
val title: String = "",
val error: String = "",
val colorState: Color = Color.Unspecified,
val showProgress: Boolean = false,
val promptDelete: Boolean = false,
val promptDiscard: Boolean = false,
val icon: String? = null,
val color: Int = 0,
)
private val _viewState = MutableStateFlow(ViewState())
val viewState: StateFlow<ViewState> = _viewState
fun setTitle(title: String) {
_viewState.update { it.copy(title = title) }
}
fun setColor(color: Int) {
_viewState.update { it.copy(color = color) }
}
fun setIcon(icon: String) {
_viewState.update { it.copy(icon = icon) }
}
fun setError(error: String) {
_viewState.update { it.copy(error = error) }
}
fun showProgress(showProgress: Boolean) {
_viewState.update { it.copy(showProgress = showProgress) }
}
fun promptDiscard(promptDiscard: Boolean) {
_viewState.update { it.copy(promptDiscard = promptDiscard) }
}
fun promptDelete(promptDelete: Boolean) {
_viewState.update { it.copy(promptDelete = promptDelete) }
}
fun setColorState(colorState: Color) {
_viewState.update { it.copy(colorState = colorState) }
}
val title: String
get() = _viewState.value.title
val icon: String?
get() = _viewState.value.icon
val color: Int
get() = _viewState.value.color
val colorState: Color
get() = _viewState.value.colorState
}

@ -70,13 +70,11 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
filter?.let {
selectedColor = it.tint
selectedIcon.value = it.icon
textState.value = it.title ?: ""
baseViewModel.setColor(it.tint)
baseViewModel.setIcon(it.icon)
baseViewModel.setTitle(it.title ?: "")
}
}
if (savedInstanceState != null) {
intent.getStringExtra(EXTRA_TITLE)?.let { textState.value = it }
intent.getStringExtra(EXTRA_TITLE)?.let { baseViewModel.setTitle(it) }
}
updateTheme()
@ -102,7 +100,7 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
override suspend fun save() {
val newName = newName
if (Strings.isNullOrEmpty(newName)) {
errorState.value = getString(R.string.name_cannot_be_empty)
baseViewModel.setError(getString(R.string.name_cannot_be_empty))
return
}
@ -111,8 +109,8 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
var f = Filter(
id = filter?.id ?: 0L,
title = newName,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
values = criteria.values,
criterion = CriterionInstance.serialize(criteria),
sql = criteria.sql,
@ -138,16 +136,17 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
}
private val newName: String
get() = textState.value.trim { it <= ' ' }
get() = baseViewModel.title.trim { it <= ' ' }
override fun hasChanges(): Boolean {
val viewState = baseViewModel.viewState.value
val criteria = viewModel.viewState.value.criteria
return if (isNew) {
(!Strings.isNullOrEmpty(newName)
|| selectedColor != 0 || selectedIcon.value?.isBlank() == false || criteria.size > 1)
|| viewState.color != 0 || viewState.icon?.isBlank() == false || criteria.size > 1)
} else newName != filter!!.title
|| selectedColor != filter!!.tint
|| selectedIcon.value != filter!!.icon
|| viewState.color != filter!!.tint
|| viewState.icon != filter!!.icon
|| CriterionInstance.serialize(criteria) != filter!!.criterion!!.trim()
|| criteria.values != filter!!.valuesForNewTasks
|| criteria.sql != filter!!.sql

@ -53,11 +53,11 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
}
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
selectedColor = gtasksList.color
selectedIcon.value = gtasksList.icon ?: defaultIcon
baseViewModel.setColor(gtasksList.color)
baseViewModel.setIcon(gtasksList.icon ?: defaultIcon)
}
if (!isNewList) textState.value = gtasksList.name!!
if (!isNewList) baseViewModel.setTitle(gtasksList.name!!)
if (createListViewModel.inProgress
|| renameListViewModel.inProgress
@ -86,14 +86,14 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
get() = if (isNew) getString(R.string.new_list) else gtasksList.name!!
private fun showProgressIndicator() {
showProgress.value = true
baseViewModel.showProgress(true)
}
private fun hideProgressIndicator() {
showProgress.value = false
baseViewModel.showProgress(false)
}
private fun requestInProgress() = showProgress.value
private fun requestInProgress() = baseViewModel.viewState.value.showProgress
override suspend fun save() {
if (requestInProgress()) {
@ -101,7 +101,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
}
val newName = newName
if (isNullOrEmpty(newName)) {
errorState.value = getString(R.string.name_cannot_be_empty)
baseViewModel.setError(getString(R.string.name_cannot_be_empty))
return
}
when {
@ -115,10 +115,10 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
}
else -> {
if (colorChanged() || iconChanged()) {
gtasksList.color = selectedColor
gtasksList.color = baseViewModel.color
googleTaskListDao.insertOrReplace(
gtasksList.copy(
icon = selectedIcon.value
icon = baseViewModel.icon
)
)
localBroadcastManager.broadcastRefresh()
@ -150,16 +150,16 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
}
private val newName: String
get() = textState.value.trim { it <= ' ' }
get() = baseViewModel.title.trim { it <= ' ' }
override fun hasChanges(): Boolean =
if (isNewList) {
selectedColor >= 0 || !isNullOrEmpty(newName)
baseViewModel.color != 0 || !isNullOrEmpty(newName)
} else colorChanged() || nameChanged() || iconChanged()
private fun colorChanged() = selectedColor != gtasksList.color
private fun colorChanged() = baseViewModel.color != gtasksList.color
private fun iconChanged() = selectedIcon.value != (gtasksList.icon ?: TasksIcons.LIST)
private fun iconChanged() = baseViewModel.icon != (gtasksList.icon ?: TasksIcons.LIST)
private fun nameChanged() = newName != gtasksList.name
@ -167,8 +167,8 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
val result = gtasksList.copy(
uuid = taskList.id,
name = taskList.title,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
)
val id = googleTaskListDao.insertOrReplace(result)
@ -193,8 +193,8 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private suspend fun onListRenamed(taskList: TaskList) {
val result = gtasksList.copy(
name = taskList.title,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
)
googleTaskListDao.insertOrReplace(result)

@ -83,9 +83,9 @@ class PlaceSettingsActivity : BaseListSettingsActivity(),
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
textState.value = place.displayName
selectedColor = place.color
selectedIcon.value = place.icon ?: defaultIcon
baseViewModel.setTitle(place.displayName)
baseViewModel.setColor(place.color)
baseViewModel.setIcon(place.icon ?: defaultIcon)
}
sliderPos.floatValue = (place.radius / STEP * STEP).toFloat()
@ -157,22 +157,22 @@ class PlaceSettingsActivity : BaseListSettingsActivity(),
}
}
override fun hasChanges() = textState.value != place.displayName
|| selectedColor != place.color
|| selectedIcon.value != (place.icon ?: TasksIcons.PLACE)
override fun hasChanges() = baseViewModel.title != place.displayName
|| baseViewModel.color != place.color
|| baseViewModel.icon != (place.icon ?: TasksIcons.PLACE)
override suspend fun save() {
val newName: String = textState.value
val newName: String = baseViewModel.title
if (isNullOrEmpty(newName)) {
errorState.value = getString(R.string.name_cannot_be_empty)
baseViewModel.setError(getString(R.string.name_cannot_be_empty))
return
}
place = place.copy(
name = newName,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
radius = sliderPos.floatValue.roundToInt(),
)
locationDao.update(place)

@ -39,13 +39,13 @@ class TagSettingsActivity : BaseListSettingsActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
tagData = intent.getParcelableExtra(EXTRA_TAG_DATA) ?: TagData()
if (!isNewTag) textState.value = tagData.name!!
if (!isNewTag) baseViewModel.setTitle(tagData.name!!)
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
selectedColor = tagData.color ?: 0
selectedIcon.value = tagData.icon ?: defaultIcon
baseViewModel.setColor(tagData.color ?: 0)
baseViewModel.setIcon(tagData.icon ?: defaultIcon)
}
setContent {
@ -63,7 +63,7 @@ class TagSettingsActivity : BaseListSettingsActivity() {
get() = if (isNew) getString(R.string.new_tag) else tagData.name!!
private val newName: String
get() = textState.value.trim { it <= ' ' }
get() = baseViewModel.title.trim { it <= ' ' }
private suspend fun clashes(newName: String): Boolean {
return ((isNewTag || !newName.equals(tagData.name, ignoreCase = true))
@ -73,19 +73,19 @@ class TagSettingsActivity : BaseListSettingsActivity() {
override suspend fun save() {
val newName = newName
if (isNullOrEmpty(newName)) {
errorState.value = getString(R.string.name_cannot_be_empty)
baseViewModel.setError(getString(R.string.name_cannot_be_empty))
return
}
if (clashes(newName)) {
errorState.value = getString(R.string.tag_already_exists)
baseViewModel.setError(getString(R.string.tag_already_exists))
return
}
if (isNewTag) {
tagData
.copy(
name = newName,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
)
.let { it.copy(id = tagDataDao.insert(it)) }
.let {
@ -99,8 +99,8 @@ class TagSettingsActivity : BaseListSettingsActivity() {
tagData
.copy(
name = newName,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
)
.let {
tagDataDao.update(it)
@ -118,10 +118,10 @@ class TagSettingsActivity : BaseListSettingsActivity() {
override fun hasChanges(): Boolean {
return if (isNewTag) {
selectedColor >= 0 || selectedIcon.value?.isBlank() == false || !isNullOrEmpty(newName)
baseViewModel.color != 0 || baseViewModel.icon?.isBlank() == false || !isNullOrEmpty(newName)
} else {
selectedColor != (tagData.color ?: 0)
|| selectedIcon.value != (tagData.icon ?: TasksIcons.LABEL)
baseViewModel.color != (tagData.color ?: 0)
|| baseViewModel.icon != (tagData.icon ?: TasksIcons.LABEL)
|| newName != tagData.name
}
}

@ -51,9 +51,9 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
}
if (savedInstanceState == null) {
if (caldavCalendar != null) {
textState.value = caldavCalendar!!.name ?: ""
selectedColor = caldavCalendar!!.color
selectedIcon.value = caldavCalendar?.icon ?: defaultIcon
baseViewModel.setTitle(caldavCalendar!!.name ?: "")
baseViewModel.setColor(caldavCalendar!!.color)
baseViewModel.setIcon(caldavCalendar?.icon ?: defaultIcon)
}
}
updateTheme()
@ -71,17 +71,17 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
}
val name = newName
if (isNullOrEmpty(name)) {
errorState.value = getString(R.string.name_cannot_be_empty)
baseViewModel.setError(getString(R.string.name_cannot_be_empty))
return
}
when {
caldavCalendar == null -> {
showProgressIndicator()
createCalendar(caldavAccount, name, selectedColor)
createCalendar(caldavAccount, name, baseViewModel.color)
}
nameChanged() || colorChanged() -> {
showProgressIndicator()
updateNameAndColor(caldavAccount, caldavCalendar!!, name, selectedColor)
updateNameAndColor(caldavAccount, caldavCalendar!!, name, baseViewModel.color)
}
iconChanged() -> updateCalendar()
else -> finish()
@ -97,11 +97,11 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar
)
private fun showProgressIndicator() { showProgress.value = true }
private fun showProgressIndicator() { baseViewModel.showProgress(true) }
private fun hideProgressIndicator() { showProgress.value = false }
private fun hideProgressIndicator() { baseViewModel.showProgress(false) }
protected fun requestInProgress(): Boolean = showProgress.value
protected fun requestInProgress(): Boolean = baseViewModel.viewState.value.showProgress
protected fun requestFailed(t: Throwable) {
hideProgressIndicator()
@ -129,8 +129,8 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
account = caldavAccount.uuid,
url = url,
name = newName,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
)
caldavDao.insert(caldavCalendar)
setResult(
@ -142,8 +142,8 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
protected suspend fun updateCalendar() {
val result = caldavCalendar!!.copy(
name = newName,
color = selectedColor,
icon = selectedIcon.value,
color = baseViewModel.color,
icon = baseViewModel.icon,
)
caldavDao.update(result)
setResult(
@ -154,19 +154,19 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
}
override fun hasChanges(): Boolean =
if (caldavCalendar == null)
!isNullOrEmpty(newName) || selectedColor != 0 || selectedIcon.value?.isBlank() == false
else
nameChanged() || iconChanged() || colorChanged()
if (caldavCalendar == null)
!isNullOrEmpty(newName) || baseViewModel.color != 0 || baseViewModel.icon?.isBlank() == false
else
nameChanged() || iconChanged() || colorChanged()
private fun nameChanged(): Boolean = caldavCalendar!!.name != newName
private fun colorChanged(): Boolean = selectedColor != caldavCalendar!!.color
private fun colorChanged(): Boolean = baseViewModel.color != caldavCalendar!!.color
private fun iconChanged(): Boolean = selectedIcon.value != (caldavCalendar!!.icon ?: TasksIcons.LIST)
private fun iconChanged(): Boolean = baseViewModel.icon != (caldavCalendar!!.icon ?: TasksIcons.LIST)
private val newName: String
get() = textState.value.trim { it <= ' '}
get() = baseViewModel.title.trim { it <= ' '}
override fun finish() {
// hideKeyboard(name)

@ -53,7 +53,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.inFlight.observe(this) { showProgress.value = it }
viewModel.inFlight.observe(this) { baseViewModel.showProgress(it) }
viewModel.error.observe(this) { throwable ->
throwable?.let {
@ -163,7 +163,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
}
override suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) {
caldavCalendar = viewModel.createCalendar(caldavAccount, name, color, selectedIcon.value)
caldavCalendar = viewModel.createCalendar(caldavAccount, name, color, baseViewModel.icon)
}
override suspend fun updateNameAndColor(
@ -172,7 +172,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
name: String,
color: Int
) {
viewModel.updateCalendar(account, calendar, name, color, selectedIcon.value)
viewModel.updateCalendar(account, calendar, name, color, baseViewModel.icon)
}
override suspend fun deleteCalendar(

@ -3,6 +3,7 @@ package org.tasks.opentasks
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@ -23,19 +24,20 @@ class OpenTasksListSettingsActivity : BaseCaldavCalendarSettingsActivity() {
setContent {
TasksTheme {
val viewState = baseViewModel.viewState.collectAsStateWithLifecycle().value
ListSettingsScaffold(
title = toolbarTitle,
theme = if (colorState.value == Color.Unspecified)
theme = if (viewState.colorState == Color.Unspecified)
Color(tasksTheme.themeColor.primaryColor)
else
colorState.value,
promptDiscard = promptDiscard.value,
showProgress = showProgress.value,
dismissDiscardPrompt = { promptDiscard.value = false },
viewState.colorState,
promptDiscard = viewState.promptDiscard,
showProgress = viewState.showProgress,
dismissDiscardPrompt = { baseViewModel.promptDiscard(false) },
save = { lifecycleScope.launch { save() } },
discard = { finish() },
) {
SelectIconRow(icon = selectedIcon.value?: defaultIcon) { showIconPicker() }
SelectIconRow(icon = viewState.icon ?: defaultIcon) { showIconPicker() }
AddToHomeRow(onClick = { createShortcut() })
}
Toaster(state = snackbar)

Loading…
Cancel
Save