From 73a60c886d0d816fbc827387225c54b528205e66 Mon Sep 17 00:00:00 2001 From: Trey T Date: Sat, 6 Jun 2026 09:17:20 -0500 Subject: [PATCH] Fix: invited members now see shared tasks immediately on join MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Product bug: when a user joined a shared residence, the residence appeared but its tasks (created by the owner) did not show in the Tasks tab until a manual refresh. Root cause was client-side — APILayer.joinWithCode updated the residence cache (addResidence) but never refreshed the tasks cache, and the optimistic addResidence suppressed getMyResidences' count-based task invalidation, so allTasks stayed a stale pre-join snapshot. The backend was correct (task list query already joins residence_residence_users). - APILayer.joinWithCode: call getTasks(forceRefresh = true) on success (mirrors bulkCreateTasks) so the joined residence's tasks load immediately. - ResidenceViewModel: corrected an inaccurate comment about join-time refresh. - SharingUITests.test03: un-quarantined — now passes (verified against live stack). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../kotlin/com/tt/honeyDue/network/APILayer.kt | 5 +++++ iosApp/HoneyDueUITests/Sharing/SharingUITests.swift | 12 ------------ iosApp/iosApp/Residence/ResidenceViewModel.swift | 6 +++--- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt index ddaccbb..deb91b7 100644 --- a/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt +++ b/composeApp/src/commonMain/kotlin/com/tt/honeyDue/network/APILayer.kt @@ -562,6 +562,11 @@ object APILayer { if (result is ApiResult.Success) { DataManager.setTotalSummary(result.data.summary) DataManager.addResidence(result.data.residence) + // Proactive refresh — the optimistic addResidence above suppresses + // getMyResidences' count-based task invalidation, so fetch fresh + // tasks here so the joined residence's tasks appear immediately + // without a manual refresh. + getTasks(forceRefresh = true) } return result diff --git a/iosApp/HoneyDueUITests/Sharing/SharingUITests.swift b/iosApp/HoneyDueUITests/Sharing/SharingUITests.swift index 35ef742..855472b 100644 --- a/iosApp/HoneyDueUITests/Sharing/SharingUITests.swift +++ b/iosApp/HoneyDueUITests/Sharing/SharingUITests.swift @@ -154,19 +154,7 @@ final class SharingUITests: AuthenticatedUITestCase { // MARK: - Test 03: Shared Tasks Visible in UI - /// Known issue: After joining a shared residence, the Tasks tab doesn't show - /// the shared tasks. The AllTasksView's residenceViewModel uses cached (empty) - /// data, which disables the refresh button and prevents task loading. - /// Fix: AllTasksView.onAppear should detect residence list changes or use - /// DataManager's already-refreshed cache. func test03_sharedTasksVisibleInTasksTab() throws { - // Known issue: after a user joins a shared residence, that residence's - // tasks (created by the owner) do not appear in the joining user's Tasks - // tab even after force-refresh — the residence itself shows, but its - // tasks aren't fetched for the joined member. Pre-existing app gap; - // skip until the shared-task fetch on join is fixed. - throw XCTSkip("App gap: joined member doesn't see the shared residence's tasks in the Tasks tab (residence shows, tasks don't).") - // Join via UI — this lands on Residences tab which triggers forceRefresh joinResidenceViaUI() diff --git a/iosApp/iosApp/Residence/ResidenceViewModel.swift b/iosApp/iosApp/Residence/ResidenceViewModel.swift index b144f7b..358c234 100644 --- a/iosApp/iosApp/Residence/ResidenceViewModel.swift +++ b/iosApp/iosApp/Residence/ResidenceViewModel.swift @@ -337,9 +337,9 @@ class ResidenceViewModel: ObservableObject { if result is ApiResultSuccess { self.isLoading = false - // APILayer updates DataManager with refreshMyResidences, - // which updates DataManagerObservable, which updates our - // @Published myResidences via Combine subscription + // APILayer.joinWithCode updates the residence cache and also + // force-refreshes the tasks cache, so the joined residence's + // shared tasks appear immediately via DataManagerObservable. completion(true) } else if let error = ApiResultBridge.error(from: result) { self.errorMessage = ErrorMessageParser.parse(error.message)