Repository navigation
Let marking unread, favoriting and archiving survive being offline or killed - #6719
AndyScherzinger wants to merge 3 commits into
Conversation
93bea38 to
0e97e99
Compare
1af1d9f to
d969345
Compare
0e97e99 to
0f19149
Compare
d969345 to
02badb4
Compare
0f19149 to
bf571a9
Compare
02badb4 to
bf571a9
Compare
bf571a9 to
a0740e5
Compare
2a32aa9 to
c980541
Compare
a0740e5 to
08df497
Compare
c980541 to
71269d5
Compare
08df497 to
00d3a61
Compare
71269d5 to
d080ec3
Compare
00d3a61 to
8200d2c
Compare
d080ec3 to
1837ca3
Compare
8200d2c to
57e7e04
Compare
1837ca3 to
828811a
Compare
57e7e04 to
2fb50b7
Compare
828811a to
bdda654
Compare
2fb50b7 to
85883e2
Compare
bdda654 to
bbc0813
Compare
85883e2 to
c7fd3fb
Compare
bbc0813 to
174f1e7
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
📝 Walkthrough
Priority: ⬇️ Low Merge Risk: 🔵 Low · up to
|
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
4b8a2ed5-4202-4dd2-9df8-d30ddb44aa1a
📒 Files selected for processing (3)
app/src/main/java/com/nextcloud/talk/conversationlist/viewmodels/ConversationsListViewModel.ktapp/src/main/java/com/nextcloud/talk/jobs/ConversationActionWorker.ktapp/src/test/java/com/nextcloud/talk/jobs/ConversationActionWorkerTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.
c7fd3fb to
dcc3a79
Compare
174f1e7 to
c22cead
Compare
dcc3a79 to
415f322
Compare
c22cead to
ff5a37a
Compare
|
@mahibi this PR now sits on top of your work in #6715, and rebasing it surfaced a design question I don't think I should answer on my own, because it's about which of our two contracts should win. What happensThis branch (B8) moves favoriting, archiving and marking-unread out of the view model and into Your new They fail with Worth saying clearly: git merges this without reporting a conflict, and GitHub shows the PR as mergeable. The incompatibility is only visible when the tests run. What is actually in conflictThe user-visible contract your tests pin down is unchanged by this branch — the change is still applied at once, still taken back when it finally fails, and the pending guard is still released. What differs is the mechanism, and one consequence of it:
The questionWhich contract do you want to keep?
I'd lean towards 1, because the offline case is the whole point of B8 and the seam makes the view model testable rather than less tested. But it is your call, since the tests and the reasoning behind them are yours. Happy to take 2 without argument if you think the added indirection is not worth it. |
415f322 to
465d034
Compare
ff5a37a to
67b9320
Compare
465d034 to
3d8dd2a
Compare
67b9320 to
9168d65
Compare
3d8dd2a to
eebc67e
Compare
9168d65 to
90b15c5
Compare
eebc67e to
7026c43
Compare
90b15c5 to
8c978cc
Compare
7026c43 to
5886cba
Compare
8c978cc to
917264d
Compare
5886cba to
c6db06c
Compare
917264d to
b58125a
Compare
Both used an Observable with a disposable that the chat throws away when it is paused, so backgrounding the app while the request was in flight dropped it silently. They now run in the view model scope like every other request that has to finish. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
A reminder the server refused was only logged, and the chat says "Message sent" the moment a share to notes starts, before the answer arrives - so a share that failed was reported as a success. Both now show what happened. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
… app All three reverted themselves when the request did not come back, so a tap taken offline flickered and a tap taken just before the app was killed was lost. They now go to a worker, the way the read marker does, which waits for a connection and survives the process. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
c6db06c to
6840143
Compare
b58125a to
bb86a52
Compare
6840143 to
aa0d8cc
Compare
Stacked on #6717 — review that one first. #6715 and #6694 have merged; this branch still targets
feat/noid/optimisticRemindersand will be retargeted tomasteronce #6717 lands.Marking a conversation unread, favoriting it and archiving it were optimistic but not durable. The local entry changed at once, then the request had two attempts in the view model's scope, and anything that stopped it there reverted the change. Two cases that made worse:
feat(conversation list): let unread, favorite and archive outlive the app— the three actions now hand the request to a newConversationActionWorker, the way the read marker already goes throughReadMarkerSyncWorker. The worker carries aNetworkType.CONNECTEDconstraint, so a change made offline waits for a connection instead of being discarded, and it retries with exponential backoff across process death. Work is unique per conversation and action withREPLACE, so favoriting and unfavoriting in quick succession sends only the last intent, while archiving and marking unread on the same conversation stay independent.This is only safe because each of these sets a value rather than moving one. Verified against a Nextcloud 36 dev instance running Talk
main:POST …/favorite,POST …/archiveandDELETE …/chat/{token}/readeach answer200twice in a row and leave the same state, so a retry can never overshoot. That is the opposite of the note-to-self share in #6717, which has no such guarantee and therefore reads back before retrying.Failure handling keeps both halves. While the list is still on screen it observes the work and, when the worker has used up its attempts, puts the conversation back and shows the error snackbar exactly as before. When the list is gone the worker releases the pending guard instead, and the next room list sync restores the server state.
Known limitation, deliberately not solved here. The pending guard lives in memory in
ConversationListUpdater. If the process dies before the worker runs, the guard is gone, so a room list sync between the restart and the worker finishing can show the old value for a moment before the worker's success brings it back. Making the guard durable means persisting it next to the conversation entry, which is a schema change and its own review.🖼️ Screenshots
No UI was added or changed. The archive snackbar now appears when the row moves rather than when the server answers.
🏁 Checklist
🤖 AI (if applicable)