feat: bundle ID migration + gitea#2 task-cache fix (recovered from fix/task-cache-unification) #4

Merged
admin merged 13 commits from feat/bundle-id-and-task-cache into master 2026-05-01 20:48:29 -05:00
Showing only changes of commit 1884853e4b - Show all commits
@@ -70,15 +70,26 @@ class ResidenceViewModel(
/** Drives the residence-scoped projections. */
private val _selectedResidenceId = MutableStateFlow<Int?>(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<ApiResult<TaskColumnsResponse>> =
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,
)