diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt index 8e1db03..9a3a850 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/viewmodel/ResidenceViewModel.kt @@ -70,15 +70,26 @@ class ResidenceViewModel( /** Drives the residence-scoped projections. */ private val _selectedResidenceId = MutableStateFlow(null) + /// Residence-scoped kanban derived from `DataManager.allTasks` filtered + /// by `_selectedResidenceId`. Single source of truth — eliminates the + /// gitea#2 race window where the per-residence cache slot could be + /// empty while `_allTasks` was populated. The per-residence cache + /// (`tasksByResidence`) was deleted in cec521b. val residenceTasksState: StateFlow> = - combine(_selectedResidenceId, dataManager.tasksByResidence) { id, map -> - if (id == null) ApiResult.Idle - else map[id]?.let { ApiResult.Success(it) } ?: ApiResult.Idle + combine(_selectedResidenceId, DataManager.allTasks) { id, all -> + when { + id == null -> ApiResult.Idle + all == null -> ApiResult.Loading + else -> { + val filtered = DataManager.getTasksForResidence(id) + if (filtered != null) ApiResult.Success(filtered) else ApiResult.Loading + } + } }.stateIn( viewModelScope, SharingStarted.Eagerly, _selectedResidenceId.value?.let { id -> - dataManager.tasksByResidence.value[id]?.let { ApiResult.Success(it) } + DataManager.getTasksForResidence(id)?.let { ApiResult.Success(it) } } ?: ApiResult.Idle, )