Skip to content

Commit

Permalink
refactor color selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Razeeman committed Apr 6, 2024
1 parent cd76dfe commit 9d8ae72
Show file tree
Hide file tree
Showing 21 changed files with 212 additions and 293 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.example.util.simpletimetracker.core.delegates

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.example.util.simpletimetracker.core.base.ViewModelDelegate
import com.example.util.simpletimetracker.core.extension.set
import com.example.util.simpletimetracker.core.interactor.ColorViewDataInteractor
import com.example.util.simpletimetracker.core.mapper.ColorMapper
import com.example.util.simpletimetracker.domain.extension.orFalse
import com.example.util.simpletimetracker.domain.model.AppColor
import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType
import com.example.util.simpletimetracker.feature_base_adapter.color.ColorViewData
import com.example.util.simpletimetracker.navigation.Router
import com.example.util.simpletimetracker.navigation.params.screen.ColorSelectionDialogParams
import kotlinx.coroutines.launch
import javax.inject.Inject

interface ColorSelectionViewModelDelegate {
val colors: LiveData<List<ViewHolderType>>

fun attach(parent: Parent)
fun onColorClick(item: ColorViewData)
fun onColorPaletteClick()
fun onCustomColorSelected(colorInt: Int)
suspend fun update()

interface Parent {
suspend fun update()
suspend fun onColorSelected() = Unit
suspend fun isColorSelectedCheck(): Boolean = true
}
}

class ColorSelectionViewModelDelegateImpl @Inject constructor(
private val router: Router,
private val colorMapper: ColorMapper,
private val colorViewDataInteractor: ColorViewDataInteractor,
) : ColorSelectionViewModelDelegate,
ViewModelDelegate() {

override val colors: LiveData<List<ViewHolderType>> by lazy {
return@lazy MutableLiveData<List<ViewHolderType>>().let { initial ->
delegateScope.launch { initial.value = loadColorsViewData() }
initial
}
}
var newColor: AppColor = AppColor(
colorId = (0..ColorMapper.colorsNumber).random(),
colorInt = "",
)

private var parent: ColorSelectionViewModelDelegate.Parent? = null

override fun attach(parent: ColorSelectionViewModelDelegate.Parent) {
this.parent = parent
}

override suspend fun update() {
updateColors()
}

override fun onColorClick(item: ColorViewData) {
delegateScope.launch {
if (item.colorId != newColor.colorId || newColor.colorInt.isNotEmpty()) {
newColor = AppColor(colorId = item.colorId, colorInt = "")
parent?.onColorSelected()
parent?.update()
updateColors()
}
}
}

override fun onColorPaletteClick() {
ColorSelectionDialogParams(
preselectedColor = colorMapper.mapToColorInt(
color = newColor,
isDarkTheme = false, // Pass original, not darkened color.
),
).let(router::navigate)
}

override fun onCustomColorSelected(colorInt: Int) {
delegateScope.launch {
if (colorInt.toString() != newColor.colorInt) {
newColor = AppColor(colorId = 0, colorInt = colorInt.toString())
parent?.onColorSelected()
parent?.update()
updateColors()
}
}
}

private suspend fun updateColors() {
val data = loadColorsViewData()
colors.set(data)
}

private suspend fun loadColorsViewData(): List<ViewHolderType> {
val currentColor = newColor.takeIf { parent?.isColorSelectedCheck().orFalse() }
return colorViewDataInteractor.getColorsViewData(currentColor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.example.util.simpletimetracker.feature_views.extension.rotateUp

object UpdateViewChooserState {

inline fun <STATE, reified T: STATE, reified CLOSED: STATE> updateChooser(
inline fun <STATE, reified T : STATE, reified CLOSED : STATE> updateChooser(
stateCurrent: STATE,
statePrevious: STATE,
chooserData: View,
Expand All @@ -27,22 +27,4 @@ object UpdateViewChooserState {
if (closing) rotateUp()
}
}

// inline fun <reified T : ChangeRecordTypeChooserState.State> updateChooser(
// state: ChangeRecordTypeChooserState,
// chooserData: View,
// chooserView: CardView,
// chooserArrow: View,
// ) {
// val opened = state.current is T
// val opening = state.previous is Closed && state.current is T
// val closing = state.previous is T && state.current is Closed
//
// chooserData.isVisible = opened
// chooserView.setChooserColor(opened)
// chooserArrow.apply {
// if (opening) rotateDown()
// if (closing) rotateUp()
// }
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class AppDatabaseMigrations {
// Just in case. Better leave tags with no colors and icons than loose all data.
runCatching {
database.execSQL(
"UPDATE recordTags SET icon_color_source = type_id"
"UPDATE recordTags SET icon_color_source = type_id",
)
database.execSQL(
"UPDATE recordTags SET color = (SELECT recordTypes.color FROM recordTypes WHERE recordTypes.id = recordTags.type_id), icon = (SELECT recordTypes.icon FROM recordTypes WHERE recordTypes.id = recordTags.type_id) WHERE EXISTS (SELECT * FROM recordTypes WHERE recordTypes.id = recordTags.type_id)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.util.simpletimetracker.data_local.model.RecordTypeCategoryDBO
import com.example.util.simpletimetracker.data_local.model.RecordTypeToTagDBO

@Dao
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.example.util.simpletimetracker.data_local.database.RecordTypeToTagDao
import com.example.util.simpletimetracker.data_local.mapper.RecordTypeToTagDataLocalMapper
import com.example.util.simpletimetracker.data_local.utils.removeIf
import com.example.util.simpletimetracker.data_local.utils.withLockedCache
import com.example.util.simpletimetracker.domain.model.RecordTypeCategory
import com.example.util.simpletimetracker.domain.model.RecordTypeToTag
import com.example.util.simpletimetracker.domain.repo.RecordTypeToTagRepo
import kotlinx.coroutines.sync.Mutex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,29 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.util.simpletimetracker.core.delegates.ColorSelectionViewModelDelegate
import com.example.util.simpletimetracker.core.delegates.ColorSelectionViewModelDelegateImpl
import com.example.util.simpletimetracker.core.extension.addOrRemove
import com.example.util.simpletimetracker.core.extension.set
import com.example.util.simpletimetracker.core.interactor.ColorViewDataInteractor
import com.example.util.simpletimetracker.core.interactor.SnackBarMessageNavigationInteractor
import com.example.util.simpletimetracker.core.mapper.ActivityFilterViewDataMapper
import com.example.util.simpletimetracker.core.mapper.ColorMapper
import com.example.util.simpletimetracker.core.view.buttonsRowView.ButtonsRowViewData
import com.example.util.simpletimetracker.domain.extension.flip
import com.example.util.simpletimetracker.domain.extension.orTrue
import com.example.util.simpletimetracker.domain.extension.orZero
import com.example.util.simpletimetracker.domain.interactor.ActivityFilterInteractor
import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor
import com.example.util.simpletimetracker.domain.model.ActivityFilter
import com.example.util.simpletimetracker.domain.model.AppColor
import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType
import com.example.util.simpletimetracker.feature_base_adapter.activityFilter.ActivityFilterViewData
import com.example.util.simpletimetracker.feature_base_adapter.category.CategoryViewData
import com.example.util.simpletimetracker.feature_base_adapter.color.ColorViewData
import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData
import com.example.util.simpletimetracker.feature_change_activity_filter.R
import com.example.util.simpletimetracker.feature_change_activity_filter.interactor.ChangeActivityFilterViewDataInteractor
import com.example.util.simpletimetracker.feature_change_activity_filter.mapper.ChangeActivityFilterMapper
import com.example.util.simpletimetracker.feature_change_activity_filter.viewData.ChangeActivityFilterTypeSwitchViewData
import com.example.util.simpletimetracker.navigation.Router
import com.example.util.simpletimetracker.navigation.params.screen.ChangeActivityFilterParams
import com.example.util.simpletimetracker.navigation.params.screen.ColorSelectionDialogParams
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -39,13 +36,13 @@ class ChangeActivityFilterViewModel @Inject constructor(
private val router: Router,
private val changeActivityFilterViewDataInteractor: ChangeActivityFilterViewDataInteractor,
private val activityFilterInteractor: ActivityFilterInteractor,
private val colorViewDataInteractor: ColorViewDataInteractor,
private val prefsInteractor: PrefsInteractor,
private val activityFilterViewDataMapper: ActivityFilterViewDataMapper,
private val changeActivityFilterMapper: ChangeActivityFilterMapper,
private val snackBarMessageNavigationInteractor: SnackBarMessageNavigationInteractor,
private val colorMapper: ColorMapper,
) : ViewModel() {
private val colorSelectionViewModelDelegateImpl: ColorSelectionViewModelDelegateImpl,
) : ViewModel(),
ColorSelectionViewModelDelegate by colorSelectionViewModelDelegateImpl {

lateinit var extra: ChangeActivityFilterParams

Expand All @@ -58,12 +55,6 @@ class ChangeActivityFilterViewModel @Inject constructor(
initial
}
}
val colors: LiveData<List<ViewHolderType>> by lazy {
return@lazy MutableLiveData<List<ViewHolderType>>().let { initial ->
viewModelScope.launch { initial.value = loadColorsViewData() }
initial
}
}
val filterTypeViewData: LiveData<List<ViewHolderType>> by lazy {
return@lazy MutableLiveData<List<ViewHolderType>>().let { initial ->
viewModelScope.launch {
Expand Down Expand Up @@ -99,9 +90,12 @@ class ChangeActivityFilterViewModel @Inject constructor(
private var newCategoryIds: MutableList<Long> = mutableListOf()
private var newType: ActivityFilter.Type = ActivityFilter.Type.Activity
private var newName: String = ""
private var newColor: AppColor = AppColor(colorId = (0..ColorMapper.colorsNumber).random(), colorInt = "")
private var wasSelected: Boolean = true

init {
colorSelectionViewModelDelegateImpl.attach(getColorSelectionDelegateParent())
}

fun onNameChange(name: String) {
viewModelScope.launch {
if (name != newName) {
Expand Down Expand Up @@ -131,35 +125,6 @@ class ChangeActivityFilterViewModel @Inject constructor(
}
}

fun onColorClick(item: ColorViewData) {
viewModelScope.launch {
if (item.colorId != newColor.colorId || newColor.colorInt.isNotEmpty()) {
newColor = AppColor(colorId = item.colorId, colorInt = "")
updateActivityFilterPreview()
updateColors()
}
}
}

fun onColorPaletteClick() {
ColorSelectionDialogParams(
preselectedColor = colorMapper.mapToColorInt(
color = newColor,
isDarkTheme = false, // Pass original, not darkened color.
),
).let(router::navigate)
}

fun onCustomColorSelected(colorInt: Int) {
viewModelScope.launch {
if (colorInt.toString() != newColor.colorInt) {
newColor = AppColor(colorId = 0, colorInt = colorInt.toString())
updateActivityFilterPreview()
updateColors()
}
}
}

fun onFilterTypeClick(viewData: ButtonsRowViewData) {
if (viewData !is ChangeActivityFilterTypeSwitchViewData) return
viewModelScope.launch {
Expand Down Expand Up @@ -209,7 +174,7 @@ class ChangeActivityFilterViewModel @Inject constructor(
selectedIds = newSelectedIds,
type = newType,
name = newName,
color = newColor,
color = colorSelectionViewModelDelegateImpl.newColor,
selected = wasSelected,
).let {
activityFilterInteractor.add(it)
Expand All @@ -223,9 +188,9 @@ class ChangeActivityFilterViewModel @Inject constructor(
if (extra is ChangeActivityFilterParams.Change) {
activityFilterInteractor.get(filterId)?.let {
newName = it.name
newColor = it.color
colorSelectionViewModelDelegateImpl.newColor = it.color
wasSelected = it.selected
updateColors()
colorSelectionViewModelDelegateImpl.update()
}
}
}
Expand All @@ -246,6 +211,14 @@ class ChangeActivityFilterViewModel @Inject constructor(
}
}

private fun getColorSelectionDelegateParent(): ColorSelectionViewModelDelegate.Parent {
return object : ColorSelectionViewModelDelegate.Parent {
override suspend fun update() {
updateActivityFilterPreview()
}
}
}

private fun updateActivityFilterPreview() = viewModelScope.launch {
(filterPreview as MutableLiveData).value = loadActivityFilterPreviewViewData()
}
Expand All @@ -257,20 +230,11 @@ class ChangeActivityFilterViewModel @Inject constructor(
selectedIds = newSelectedIds,
type = newType,
name = newName,
color = newColor,
color = colorSelectionViewModelDelegateImpl.newColor,
selected = true,
).let { activityFilterViewDataMapper.map(it, isDarkTheme) }
}

private fun updateColors() = viewModelScope.launch {
val data = loadColorsViewData()
colors.set(data)
}

private suspend fun loadColorsViewData(): List<ViewHolderType> {
return colorViewDataInteractor.getColorsViewData(newColor)
}

private fun updateTagTypeViewData() {
filterTypeViewData.set(loadTagTypeViewData())
}
Expand Down
Loading

0 comments on commit 9d8ae72

Please sign in to comment.