1 Commits

Author SHA1 Message Date
areumwoo
d6efa9bcaa InfoScreen 체크박스 상태 저장 2026-03-02 12:45:05 +09:00
4 changed files with 98 additions and 31 deletions

View File

@@ -88,4 +88,7 @@ interface Preference {
suspend fun getPowerSupplySerialListFromPreference(): Flow<List<String>>
/////
}
suspend fun saveInfoChartLineStates(states: Map<String, Boolean>)
suspend fun getInfoChartLineStates(): Flow<Map<String, Boolean>>
}

View File

@@ -68,6 +68,9 @@ class PreferenceRepository(private val context: Context) : Preference {
val PRODUCT_SERIAL = stringPreferencesKey("PRODUCT_SERIAL")
val LASER_HAND_SERIAL = stringPreferencesKey("LASER_HAND_SERIAL")
val POWER_SUPPLY_SERIAL = stringPreferencesKey("POWER_SUPPLY_SERIAL")
// InfoScreen Chart Checkboxes
val INFO_CHART_LINE_STATES = stringPreferencesKey("INFO_CHART_LINE_STATES")
}
override suspend fun clearAllPreferences() {
@@ -559,4 +562,31 @@ class PreferenceRepository(private val context: Context) : Preference {
emit(listOf("B", "U", "O", "C", "L", "D"))
}
}
}
override suspend fun saveInfoChartLineStates(states: Map<String, Boolean>) {
try {
val stateJson = gson.toJson(states)
context.datastore.edit { preferences ->
preferences[INFO_CHART_LINE_STATES] = stateJson
}
} catch (e: Exception) {
Timber.e(e, "Failed to serialize INFO_CHART_LINE_STATES to JSON.")
}
}
override suspend fun getInfoChartLineStates(): Flow<Map<String, Boolean>> {
return context.datastore.data.map { preferences ->
preferences[INFO_CHART_LINE_STATES]
}.distinctUntilChanged().map { jsonString ->
if (!jsonString.isNullOrBlank()) {
val type = object : TypeToken<Map<String, Boolean>>() {}.type
gson.fromJson<Map<String, Boolean>>(jsonString, type) ?: emptyMap()
} else {
emptyMap()
}
}.catch { e ->
Timber.e(e, "Failed to get or parse INFO_CHART_LINE_STATES. Emitting default.")
emit(emptyMap())
}
}
}

View File

@@ -646,7 +646,7 @@ fun PresetLoadPopup(
Timber.d("onClick - Confirm Save")
// Check empty names and conflict priority exist in the preset viewmodel's presetList
var listToValidate = presetViewModel.presetList.value
val listToValidate = presetViewModel.presetList.value
// Check for any presets with an empty name
val hasEmptyName =
@@ -678,32 +678,18 @@ fun PresetLoadPopup(
}
// Check for duplicate priorities (ignoring priority 0)
val duplicatePriorityGroups = listToValidate
.filter { it.priority > 0 }
.groupBy { it.priority }
.filter { it.value.size > 1 }
val priorityConflicts = listToValidate
.filter { it.priority > 0 } // Only consider prioritized items
.groupBy { it.priority } // Group them by priority
.any { it.value.size > 1 } // Check if any group is larger than 1
if (duplicatePriorityGroups.isNotEmpty()) {
val resolvedList = listToValidate.map { it.copy() }.toMutableList()
val selectedPreset = resolvedList.getOrNull(selectedPresetIndex)
duplicatePriorityGroups.forEach { (priorityValue, presets) ->
val keeperId = presets
.firstOrNull { preset ->
selectedPreset != null && preset.id == selectedPreset.id
}
?.id
?: presets.first().id
resolvedList.forEachIndexed { index, preset ->
if (preset.priority == priorityValue && preset.id != keeperId) {
resolvedList[index] = preset.copy(priority = 0)
}
}
}
presetViewModel.setPresetList(resolvedList)
listToValidate = resolvedList
if (priorityConflicts) {
Toast.makeText(
context,
"There are duplicate priorities. Please ensure each priority is unique.",
Toast.LENGTH_LONG
).show()
return@noRippleClickable // Stop the process
}
Timber.d("Validation successful. Saving list to MainViewModel.")

View File

@@ -1,10 +1,14 @@
package com.laseroptek.raman.ui.screens.info
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import com.laseroptek.raman.repository.PreferenceRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -25,10 +29,13 @@ data class ChartUiState(
val chamber2State: Boolean = true,
val basePlateState: Boolean = true,
val waterState: Boolean = true,
)
) {
companion object
}
@HiltViewModel
class InfoViewModel @Inject constructor(
private val preferenceRepository: PreferenceRepository,
) : ViewModel() {
// This is the single source of truth for the checkbox states.
@@ -39,7 +46,7 @@ class InfoViewModel @Inject constructor(
fun toggleLine(line: ChartLine) {
// .update is a thread-safe way to update the state.
_chartUiState.update { currentState ->
when (line) {
val updatedState = when (line) {
ChartLine.INT_TEMP -> currentState.copy(intTempState = !currentState.intTempState)
ChartLine.EXT_TEMP -> currentState.copy(extTempState = !currentState.extTempState)
ChartLine.INT_HUMIDITY -> currentState.copy(intHumidityState = !currentState.intHumidityState)
@@ -50,10 +57,51 @@ class InfoViewModel @Inject constructor(
ChartLine.BASE_PLATE -> currentState.copy(basePlateState = !currentState.basePlateState)
ChartLine.WATER -> currentState.copy(waterState = !currentState.waterState)
}
persistChartUiState(updatedState)
updatedState
}
}
init {
Timber.d("InfoViewModel init")
viewModelScope.launch {
preferenceRepository.getInfoChartLineStates().collectLatest { savedStates ->
if (savedStates.isEmpty()) return@collectLatest
_chartUiState.update { ChartUiState.fromPreference(savedStates) }
}
}
}
}
private fun persistChartUiState(state: ChartUiState) {
viewModelScope.launch {
preferenceRepository.saveInfoChartLineStates(state.toPreferenceMap())
}
}
}
private fun ChartUiState.toPreferenceMap(): Map<String, Boolean> = mapOf(
ChartLine.INT_TEMP.name to intTempState,
ChartLine.EXT_TEMP.name to extTempState,
ChartLine.INT_HUMIDITY.name to intHumidityState,
ChartLine.EXT_HUMIDITY.name to extHumidityState,
ChartLine.KTP.name to ktpState,
ChartLine.CHAMBER1.name to chamber1State,
ChartLine.CHAMBER2.name to chamber2State,
ChartLine.BASE_PLATE.name to basePlateState,
ChartLine.WATER.name to waterState,
)
private fun ChartUiState.Companion.fromPreference(savedStates: Map<String, Boolean>): ChartUiState {
val defaults = ChartUiState()
return ChartUiState(
intTempState = savedStates[ChartLine.INT_TEMP.name] ?: defaults.intTempState,
extTempState = savedStates[ChartLine.EXT_TEMP.name] ?: defaults.extTempState,
intHumidityState = savedStates[ChartLine.INT_HUMIDITY.name] ?: defaults.intHumidityState,
extHumidityState = savedStates[ChartLine.EXT_HUMIDITY.name] ?: defaults.extHumidityState,
ktpState = savedStates[ChartLine.KTP.name] ?: defaults.ktpState,
chamber1State = savedStates[ChartLine.CHAMBER1.name] ?: defaults.chamber1State,
chamber2State = savedStates[ChartLine.CHAMBER2.name] ?: defaults.chamber2State,
basePlateState = savedStates[ChartLine.BASE_PLATE.name] ?: defaults.basePlateState,
waterState = savedStates[ChartLine.WATER.name] ?: defaults.waterState,
)
}