fix(app): hide pending-delete conversations from refresh result#8053
Merged
Conversation
Swipe-to-delete queues a 3-second undo timer before the DELETE request fires. A pull-to-refresh inside that window re-fetches the server list, which still contains the conversation, so it reappears — users read this as "delete didn't work". Confirmed via GCP LB logs that the eventual DELETE succeeds (204 on every call in the last 24h). Filter `memoriesToDelete` IDs out of any list we adopt from the server (fresh fetch, paginated fetch, cached fallback) so the conversation stays hidden until the actual DELETE lands.
There was a problem hiding this comment.
1 issue found across 1 file
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Cubic flagged that `_filterPendingDeletes` can leave `conversations.length` non-multiple-of-50, blocking `getMoreConversationsFromServer` (which gates on `length % 50 == 0`) until the pending delete resolves. The offset would also be wrong by the pending-delete count, skipping items. Compute a server-equivalent length (local + pending-delete count) and use that for both the gate and the offset. The pending deletes still exist server-side until the 3-second undo timer fires, so this matches reality.
There was a problem hiding this comment.
1 issue found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/lib/providers/conversation_provider.dart">
<violation number="1" location="app/lib/providers/conversation_provider.dart:773">
P2: Pending-delete filtering stops too early because IDs are cleared before DELETE completion. On slow network, pull-to-refresh can still reintroduce a just-deleted conversation.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| // or in-flight HTTP). Without this, a pull-to-refresh during that window | ||
| // re-surfaces the just-deleted conversation, which users read as "delete didn't work". | ||
| List<ServerConversation> _filterPendingDeletes(List<ServerConversation> items) { | ||
| if (memoriesToDelete.isEmpty) return items; |
There was a problem hiding this comment.
P2: Pending-delete filtering stops too early because IDs are cleared before DELETE completion. On slow network, pull-to-refresh can still reintroduce a just-deleted conversation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/lib/providers/conversation_provider.dart, line 773:
<comment>Pending-delete filtering stops too early because IDs are cleared before DELETE completion. On slow network, pull-to-refresh can still reintroduce a just-deleted conversation.</comment>
<file context>
@@ -761,6 +766,14 @@ class ConversationProvider extends ChangeNotifier {
+ // or in-flight HTTP). Without this, a pull-to-refresh during that window
+ // re-surfaces the just-deleted conversation, which users read as "delete didn't work".
+ List<ServerConversation> _filterPendingDeletes(List<ServerConversation> items) {
+ if (memoriesToDelete.isEmpty) return items;
+ return items.where((c) => !memoriesToDelete.containsKey(c.id)).toList();
+ }
</file context>
kodjima33
approved these changes
Jun 20, 2026
kodjima33
left a comment
Collaborator
There was a problem hiding this comment.
mobile bug fix conf 4/5: filter pending-delete conversations from refresh/load-more so they don't re-surface during the 3s undo window
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Users reported that deleting a conversation in the app and then pulling-to-refresh "a few seconds later" makes the conversation reappear, as if the delete failed.
The backend isn't failing. Verified via GCP HTTPS LB access logs: 331/331 DELETE
/v1/conversations/*requests in the last 24h returned 204 — every delete that reaches the server succeeds.The actual bug is a client-side race: swipe-to-delete in
deleteConversationLocallyremoves the conversation from the local list and schedules aFuture.delayed(3s, sendDelete)for the undo window. A pull-to-refresh inside that 3-second window re-fetches the server list, which still has the conversation (DELETE hasn't fired yet), andfetchConversations()overwritesconversationswith the fresh server list without filtering anything pending-delete — so the just-deleted conversation reappears. After the 3s timer fires, the DELETE actually goes out and succeeds, but the user has already seen "delete didn't work".Fix
Add a tiny
_filterPendingDeletes()helper and apply it to every list assignment that comes from the server:fetchConversations).getMoreConversationsFromServer).The conversation stays hidden until either (a) the undo timer fires and the server DELETE lands, at which point it disappears for real, or (b) the user taps Undo, at which point
undoDeletedConversationremoves it frommemoriesToDeleteand the next refresh shows it normally.12 lines changed (1 helper + 4 call sites), no public API change, no backend change.
Test plan
🤖 Generated with Claude Code