refactor: delete _tasksByResidence and per-residence task cache plumbing

All readers and writers gone after the previous commits. Single source
of truth = DataManager._allTasks; residence views derive via
getTasksForResidence(id). Net deletion across DataManager, APILayer,
DataManagerObservable, Kotlin TaskViewModel, and the now-unused
TaskViewModel test.

Closes gitea#2
This commit is contained in:
Trey t
2026-04-25 10:48:38 -05:00
parent 1b001323e4
commit cec521b3e3
7 changed files with 244 additions and 83 deletions
@@ -62,8 +62,6 @@ object DataManager {
private set
var tasksCacheTime: Long = 0L
private set
var tasksByResidenceCacheTime: MutableMap<Int, Long> = mutableMapOf()
private set
var contractorsCacheTime: Long = 0L
private set
var documentsCacheTime: Long = 0L
@@ -138,8 +136,6 @@ object DataManager {
private val _allTasks = MutableStateFlow<TaskColumnsResponse?>(null)
val allTasks: StateFlow<TaskColumnsResponse?> = _allTasks.asStateFlow()
private val _tasksByResidence = MutableStateFlow<Map<Int, TaskColumnsResponse>>(emptyMap())
val tasksByResidence: StateFlow<Map<Int, TaskColumnsResponse>> = _tasksByResidence.asStateFlow()
// ==================== DOCUMENTS ====================
@@ -414,7 +410,6 @@ object DataManager {
fun removeResidence(residenceId: Int) {
_residences.value = _residences.value.filter { it.id != residenceId }
_tasksByResidence.value = _tasksByResidence.value - residenceId
_documentsByResidence.value = _documentsByResidence.value - residenceId
_residenceSummaries.value = _residenceSummaries.value - residenceId
@@ -445,16 +440,10 @@ object DataManager {
persistToDisk()
}
fun setTasksForResidence(residenceId: Int, response: TaskColumnsResponse) {
_tasksByResidence.value = _tasksByResidence.value + (residenceId to response)
tasksByResidenceCacheTime[residenceId] = currentTimeMs()
persistToDisk()
}
/**
* Filter cached allTasks by residence ID to avoid separate API call.
* Returns null if allTasks not cached.
* This enables client-side filtering when we already have all tasks loaded.
* Filter cached allTasks by residence ID. Single source of truth for
* residence-scoped kanban data; returns null when _allTasks is null
* (caller must hit the API to populate).
*/
fun getTasksForResidence(residenceId: Int): TaskColumnsResponse? {
val allTasksData = _allTasks.value ?: return null
@@ -544,15 +533,6 @@ object DataManager {
_allTasks.value = current.copy(columns = newColumns)
}
// Remove from all residence task caches
_tasksByResidence.value = _tasksByResidence.value.mapValues { (_, tasks) ->
val newColumns = tasks.columns.map { column ->
val filteredTasks = column.tasks.filter { it.id != taskId }
column.copy(tasks = filteredTasks, count = filteredTasks.size)
}
tasks.copy(columns = newColumns)
}
// Refresh summary from updated kanban data (API no longer returns summaries for CRUD)
refreshSummaryFromKanban()
persistToDisk()
@@ -795,7 +775,6 @@ object DataManager {
_totalSummary.value = null
_residenceSummaries.value = emptyMap()
_allTasks.value = null
_tasksByResidence.value = emptyMap()
_documents.value = emptyList()
_documentsByResidence.value = emptyMap()
_contractors.value = emptyList()
@@ -826,7 +805,6 @@ object DataManager {
residencesCacheTime = 0L
myResidencesCacheTime = 0L
tasksCacheTime = 0L
tasksByResidenceCacheTime.clear()
contractorsCacheTime = 0L
documentsCacheTime = 0L
summaryCacheTime = 0L
@@ -848,7 +826,6 @@ object DataManager {
_totalSummary.value = null
_residenceSummaries.value = emptyMap()
_allTasks.value = null
_tasksByResidence.value = emptyMap()
_documents.value = emptyList()
_documentsByResidence.value = emptyMap()
_contractors.value = emptyList()
@@ -861,7 +838,6 @@ object DataManager {
residencesCacheTime = 0L
myResidencesCacheTime = 0L
tasksCacheTime = 0L
tasksByResidenceCacheTime.clear()
contractorsCacheTime = 0L
documentsCacheTime = 0L
summaryCacheTime = 0L
@@ -17,9 +17,6 @@ class TaskViewModel : ViewModel() {
private val _tasksState = MutableStateFlow<ApiResult<TaskColumnsResponse>>(ApiResult.Idle)
val tasksState: StateFlow<ApiResult<TaskColumnsResponse>> = _tasksState
private val _tasksByResidenceState = MutableStateFlow<ApiResult<TaskColumnsResponse>>(ApiResult.Idle)
val tasksByResidenceState: StateFlow<ApiResult<TaskColumnsResponse>> = _tasksByResidenceState
private val _taskAddNewCustomTaskState = MutableStateFlow<ApiResult<CustomTask>>(ApiResult.Idle)
val taskAddNewCustomTaskState: StateFlow<ApiResult<CustomTask>> = _taskAddNewCustomTaskState
@@ -35,16 +32,6 @@ class TaskViewModel : ViewModel() {
}
}
fun loadTasksByResidence(residenceId: Int, forceRefresh: Boolean = false) {
viewModelScope.launch {
_tasksByResidenceState.value = ApiResult.Loading
_tasksByResidenceState.value = APILayer.getTasksByResidence(
residenceId = residenceId,
forceRefresh = forceRefresh
)
}
}
fun createNewTask(request: TaskCreateRequest) {
println("TaskViewModel: createNewTask called with $request")
viewModelScope.launch {
@@ -135,21 +135,6 @@ class DataManagerTaskCacheTest {
assertEquals(null, DataManager.getTasksForResidence(100))
}
/// Lockdown: updateTask must NOT touch `_tasksByResidence`. That cache
/// is being deleted in Phase 3; until then, updateTask must leave it
/// alone. If a future commit re-introduces the conditional write
/// branch this test catches it.
@Test
fun updateTask_doesNotMutate_tasksByResidence() {
val before = DataManager.tasksByResidence.value
DataManager.updateTask(sampleTask(id = 1, residenceId = 100, column = "upcoming_tasks"))
assertEquals(
before,
DataManager.tasksByResidence.value,
"updateTask must not write to _tasksByResidence — that cache is deprecated"
)
}
private fun sampleTask(
id: Int,
residenceId: Int,
@@ -18,15 +18,6 @@ class TaskViewModelTest {
assertIs<ApiResult.Idle>(viewModel.tasksState.value)
}
@Test
fun testInitialTasksByResidenceState() {
// Given
val viewModel = TaskViewModel()
// Then
assertIs<ApiResult.Idle>(viewModel.tasksByResidenceState.value)
}
@Test
fun testInitialAddNewCustomTaskState() {
// Given