Repository navigation
Put every optimistic action on one helper and fix the ones that failed silently - #6715
Conversation
36e1a8e to
ba3d4b7
Compare
📱 QA build
The QA build installs alongside a released Nextcloud app, so you can keep Downloading the file requires a GitHub account, so open this link on the |
ba3d4b7 to
ca9e10d
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 Walkthrough
Priority: ➖ Normal Merge Risk: 🔵 Low · up to
|
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 19.23% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 78 functions across 10 files. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
-
Check name Status Explanation Title check ✅ Passed The title clearly summarizes the shared optimistic-action helper and the fixes for actions that failed silently. Description check ✅ Passed The description explains the changes, dependency, and tests. It includes the checklist and AI disclosure. The template’s TODO section and before/after screenshot table are omitted, but the description… Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
- Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Autopilot is currently an internal CodeRabbit preview.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: aa64e2c5-e5ad-4a33-a5c5-9a28ff856db3
📒 Files selected for processing (10)
app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.ktapp/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.ktapp/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.ktapp/src/main/java/com/nextcloud/talk/conversationlist/viewmodels/ConversationsListViewModel.ktapp/src/main/java/com/nextcloud/talk/repositories/reactions/ReactionsRepositoryImpl.ktapp/src/main/java/com/nextcloud/talk/utils/OptimisticAction.ktapp/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModelTest.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/FakeConversationsRepository.ktapp/src/test/java/com/nextcloud/talk/utils/OptimisticActionTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
75b1f11 to
fdb65eb
Compare
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: 75f1df26-e584-410c-be35-c93ea9648855
📒 Files selected for processing (3)
app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.ktapp/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModelTest.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
fdb65eb to
4db6b67
Compare
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:
ed7f6f22-e259-4945-a91f-1584f3533dbf
📒 Files selected for processing (5)
app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.ktapp/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.ktapp/src/main/java/com/nextcloud/talk/conversationlist/viewmodels/ConversationsListViewModel.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModelTest.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/FakeConversationsRepository.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.
4db6b67 to
77b4de6
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
a0fc3847-19c8-4aa5-a024-568916ae8125
📒 Files selected for processing (3)
app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModelTest.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/FakeConversationsRepository.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.
77b4de6 to
24c3354
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
cef3d6ce-a5fe-4d85-968d-013083d8e28a
📒 Files selected for processing (3)
app/src/main/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModel.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/ConversationInfoViewModelTest.ktapp/src/test/java/com/nextcloud/talk/conversationinfo/viewmodel/FakeConversationsRepository.kt
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.
18a84d3 to
43377cb
Compare
|
@coderabbitai review |
|
|
For anyone reading the summary above: there are no open findings on this PR. All seven review threads are resolved, each with a reply pointing at the commit, the code and the test that covers it. Two things in that summary are not open issues and should not be read as such: The "Docstring Coverage" pre-merge check does not apply to this repository. It wants 80% of the 78 functions touched by this diff to carry a docstring.
The functions in this diff that carry a non-obvious invariant are documented — The "Merge Risk" and "Security architecture risk" banners are stale. Both are pinned to @coderabbitai please re-review the current head so those two banners reflect |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
git rev-parse HEAD
fd --hidden --exclude .git '^AGENTS\.md$' --exec sh -c 'printf "\n--- %s ---\n" "$1"; cat "$1"' sh {}Length of output: 13959
I’ll request a full re-review of the current head. The review should reassess the Merge Risk and Security architecture risk banners against ✏️ Learnings added
🧠 Learnings used
|
43377cb to
a238355
Compare
|
taking over |
a238355 to
09db8f2
Compare
09db8f2 to
c43e42d
Compare
Four call sites had each grown their own copy of "apply locally, retry once on a transient failure, revert when it finally fails, revert when cancelled", with the retry predicate spelled out twice and one of them shipping a guard bug. optimisticAction() now carries that shape, including the case where the server refuses in the payload rather than in the status code, and the case where an answer means the change was already applied - which must not revert anything. No behaviour change; the repository tests of reactions, deletions, edits, pinning and dismissals carry the migration. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Marking a conversation read or unread, favoriting, archiving and the important and sensitive toggles now go through the shared optimistic helper, so every one of them retries a connection problem once and takes its change back when the screen is left mid-request. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The notification level, the message expiration and the call notification switch logged their failure and left the screen showing a setting the server never accepted. They now go back to the previous value and say so. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
… once Deleting left the row in place until the worker had finished and the list had been fetched again. It now disappears on confirmation, reusing the guard that hides a conversation being left, and comes back if the delete fails. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The helper was only exercised through the repositories that use it, so the rules every optimistic action depends on - applied before the answer, taken back on a refusal or a cancellation, kept after one hiccup - had no test of their own. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
A refusal reported in the payload reverted inside the try block, so a revert that threw was caught and run a second time. The revert now runs after the request has been handled. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
…irmed The call notification switch, the notification level and the message expiration undid a failed change to the value shown when it started. Two changes that both failed left the second undo restoring the first one's optimistic value, which the server never held. They now restore the last value the server confirmed, as the important and sensitive toggles do. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
The undo of an optimistic change was spelled out as a raw function type, which made the helper's signature a closure returning a closure. Undo now names it, wherever an undo for optimisticAction() is built. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
onConversationRemoved still carried the doc comment of the function it replaced, and the important and sensitive toggles suppressed a generic exception catch they no longer have. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Moving reactions onto the optimistic helper dropped the warning for an answer with an unexpected status code, so only a request that threw left a trace. Both are logged again. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
The lock toggle was the last setting with its own try/catch. It now goes through the shared optimistic helper, so it retries a connection problem once, takes its change back when the server refuses in the payload or the screen is left mid-request, and undoes a failure to the value the server last confirmed. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
…be saved Without capabilities the change returned quietly and the screen kept a level that was never saved; it now fails, so the screen takes it back and says so. A server without notification levels is no longer sent a level that is stored locally instead, which matches how it behaved before. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
The read-only lock, the settings saved through DatabaseStorageModule and the conversation list's read, unread, favorite and archive actions had no test of their own, nor had hiding a conversation that is being left or deleted. Each now has one for the change standing, being taken back, and two failed changes going back to the value the server confirmed. The view model's storage module is visible to tests so a failing one can be put in. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Call notifications, the notification level and the message expiration only failed on an HTTP error, so a refusal reported in the OCS payload left the screen and the local copy showing a value the server never took. The save now fails on such a refusal before anything is remembered, and the screen takes the change back like any other failure. The acceptance rule the read-only lock and the important and sensitive toggles already used moves to GenericOverall, so all of them share it. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
c43e42d to
d440ed1
Compare
#6694 merged, so this now targets master and is ready to review on its own. #6717 and #6719 are stacked on top of it.
Since the rebase onto current master this branch also depends on #6744, which is merged.
onConversationRemovedcallsgetRooms(user, forceFullSync = true), andforceFullSyncarrived with themodifiedSincedelta sync. The dependency is not cosmetic: a delta response cannot express a removal, so a plain refresh after leaving or deleting would leave the row in the database and the entry would reappear the moment it stopped being hidden. Reverting #6744 would break this branch rather than merely conflict with it.#6694 shipped five optimistic chat actions, each with its own hand-rolled apply/retry/revert block. This branch pulls that shape into one helper, puts the conversation list and conversation info actions on it, and fixes the two places where an action told the user it had worked when it had not.
refactor(chat): extract the optimistic action pattern into one helper—optimisticAction(apply, isConfirmed, request)inutils/OptimisticAction.kt.applywrites the local state and returns its own undo action, or null when nothing changed, in which case nothing is undone later either. A transient failure is retried once, any failure or a cancellation takes the change back, and the undo runs underNonCancellableso a revert cannot itself be cancelled half-way. MigratingOfflineFirstChatRepositoryandReactionsRepositoryImplonto it removes 112 lines with no behaviour change.perf(conversations): keep list and info actions correct when they fail— mark as read, mark as unread, favorite, archive and the important and sensitive toggles now go through the same helper. The two toggles gain a retry they never had; all six gain cancellation safety, so leaving the screen mid-request no longer leaves the change applied although the server may never have heard of it.fix(conversation info): tell the user when a setting did not save—DatabaseStorageModule.saveStringandsaveBooleancaught every failure and only logged it, so the notification level, the message expiration and the call notification switch kept showing a setting the server had refused, with no error anywhere. The failure now reaches the view model, which puts the previous value back and shows the error snackbar.perf(conversation list): drop a deleted conversation from the list at once— the row stayed in the list until the worker had finished and the list had been fetched again. It now disappears on confirmation and comes back if the delete fails, reusing the guard that hides a conversation being left.test(utils): cover the optimistic action contract directly—optimisticActionwas only exercised through the repositories using it. Seven tests now assert the rules every optimistic action depends on: applied before the answer, taken back on a refusal, taken back on a refusal the server reports in the payload, taken back when the screen is left mid-request, nothing taken back when nothing was applied, and one hiccup retried without losing the change.🖼️ Screenshots
No UI was added or changed — the same controls, the same snackbars, applied earlier.
🏁 Checklist
🤖 AI (if applicable)