Repository navigation
feat(chat): select several messages and forward each on its own - #6926
ToteMeiSter wants to merge 4 commits into
Conversation
A long press on a chat row outside of the bubble starts a selection, a tap on the row there still opens the message menu. While messages are selected a tap anywhere on a row toggles it, the toolbar shows the number of selected messages with close, forward and copy actions, and back ends the selection. A tap and a long press on the bubble itself keep opening the message menu. Each selected message is forwarded as its own message in the order of the chat. Selected rows show their checkmark. Forwarded messages are sent while the chat opens, before the conversation has been read from the database, so the temporary message takes the room token of the chat instead of the conversation, and the user is told when a send fails. Every temporary message gets its own row key, so messages sent one after another do not replace each other in the list. Assisted-by: Claude-Code:claude-sonnet-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
📱 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 |
rapterjet2004
left a comment
There was a problem hiding this comment.
Thanks, this is a nice feature, and keying temporary messages by referenceId instead of the millisecond fixes a real loss of messages. Reusing showForward per message, sorting by id and sending through the existing queue all look good, and the forward extras are removed after reading so a recreation doesn't send again.
Change requested: crash when a selected message is still being sent. isSelectable() doesn't exclude temporary messages (negative ids). Select a message while it is pending; when its server copy arrives, the temporary row is deleted but the selection keeps the negative id. The next selection change (the toolbar's produceState → loadSelectedMessages, ChatActivity.kt:2152), or tapping forward or copy (:3700, :3718), calls getMessageById(-x). OfflineFirstChatRepository.getMessage doesn't find it locally and calls getContextForChatMessage(-x), which throws an HttpException on the error status, and nothing catches it, so the app crashes. The same happens for a selected message removed by the expiry cleanup. Please exclude temporary messages in isSelectable(), drop ids from the selection when they disappear from the list, and catch failures in loadSelectedMessages.
Non-blocking:
- Forwarded texts are the raw
message, so mentions arrive as{mention-user1}placeholders. Same as the single-message forward today, so fine for this PR. - A selection can only start from the empty part of a row, and full-width bubbles leave little of it. A "Select" entry in the message menu would make the feature easier to find.
- There's no limit on how many messages can be forwarded at once; each is its own send request.
…the selection A pending message has a negative id until the server answers. When it was selected, its row was replaced by the server copy, the selected id stayed, and the next look-up of the selected messages asked the server for the negative id. The request failed with an unhandled HttpException, which crashed the chat when the toolbar, forward or copy read the selection. Pending messages cannot be selected any more. Ids that are no longer in the list of the chat, e.g. replaced pending messages or messages removed by the expired cleanup, are dropped from the selection whenever the list changes. A selected message that still cannot be loaded is left out and logged instead of failing the whole selection. Assisted-by: Claude-Code:claude-sonnet-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
Make the message menu start the existing selection. Limit it to 100 messages and 32,000 forwarded characters. Both row gestures and the menu use the same check and show a notice when a limit is reached. Assisted-by: Claude-Code:claude-sonnet-5-5 Assisted-by: Codex:gpt-6.1-sol Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
|
Thanks for the review, the crash is real. I checked each step of the chain against the head of the PR (2f40e7d):
Fixed in one commit (fix and test together):
Non-blocking points:
The PR is updated with two commits: About "Select": you are right, selection starts only from the empty part of a row. A long press on the bubble opens the message menu ( |
…reachable The sheet used the default state and opened at the half-height peek; with the longer menu the Delete entry stayed below the screen edge. Assisted-by: Claude-Code:claude-sonnet-5-5 Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
|
One more commit, |
…elop fix(chat): open the message menu fully expanded (port f66dc9e from nextcloud#6926)
|
Thank you for you contributions. We will try to review this soon! |
Resolves #6925
What changes in the chat:
MessageSelectioninChatViewModel). While it is active a tap on any row toggles it, the toolbar (ChatToolbar) shows the count with close, forward and copy, and back ends it.planForward) goes to the conversation list and the chosen chat sends each text through the existing send queue (MessageInputViewModel.sendChatMessage). Only messages that the single-message menu would allow to forward are used; if some were left out (files, system messages) a toast says so. Copy reusescopyTextwith the texts joined by a new line.ChatItem.isChecked, passed byChatView); the forwarded messages are stored with the room token of the chat, so they are sent while the conversation is still loading, and a failed send shows an error toast. An empty forward plan (nothing forwardable) is reported with the same toast and does not leave the chat.OfflineFirstChatRepository.createChatMessageEntity): messages added within one millisecond, as a forward of several does, replaced each other and the earlier one was never sent.gradle/verification-metadata.xml: checksums ofespresso-core:3.5.0andrunner:1.5.0(pom and aar) that the newtestImplementationofui-test-junit4pulls in for the unit-test classpath.Tested on: Huawei DEL-LX9, Samsung SM-S926B.
🏁 Checklist
/backport to stable-xx.x🤖 AI (if applicable)
Commit trailer:
Assisted-by: Claude-Code:claude-sonnet-5-5.