diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php index e4b4c8b644c..beb57a10935 100644 --- a/lib/Chat/Parser/SystemMessage.php +++ b/lib/Chat/Parser/SystemMessage.php @@ -573,7 +573,12 @@ protected function parseMessage(Message $chatMessage, $allowInaccurate): void { $parsedMessage = $this->l->t('You set up Matterbridge to synchronize this conversation with other chats'); } } elseif ($message === 'thread_created') { - $parsedMessage = $this->l->t('{actor} created a thread'); + $parsedMessage = $this->l->t('{actor} created thread {title}'); + $parsedParameters['title'] = [ + 'type' => 'highlight', + 'id' => 'thread/' . $parameters['thread'], + 'name' => $parameters['title'] ?? (string)$parameters['thread'], + ]; } elseif ($message === 'matterbridge_config_edited') { $parsedMessage = $this->l->t('{actor} updated the Matterbridge configuration'); if ($currentUserIsActor) { diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index 982deb4f9be..4b5858cedaa 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -396,6 +396,12 @@ protected function fixMimeTypeOfVoiceMessage(ShareCreatedEvent|BeforeDuplicateSh $silent = false; } + $replyTo = null; + if (isset($metaData['replyTo'])) { + $replyTo = (int)$metaData['replyTo']; + unset($metaData['replyTo']); + } + $threadTitle = ''; if (isset($metaData['threadTitle'])) { if (is_string($metaData['threadTitle']) && trim($metaData['threadTitle']) !== '') { @@ -404,7 +410,13 @@ protected function fixMimeTypeOfVoiceMessage(ShareCreatedEvent|BeforeDuplicateSh unset($metaData['threadTitle']); } - $comment = $this->sendSystemMessage($room, 'file_shared', ['share' => $share->getId(), 'metaData' => $metaData], silent: $silent); + $comment = $this->sendSystemMessage( + $room, + 'file_shared', + ['share' => $share->getId(), 'metaData' => $metaData], + silent: $silent, + replyTo: $replyTo, + ); if ($threadTitle !== '' && $comment->getTopmostParentId() === '0') { $this->threadService->createThread($room, (int)$comment->getId(), $threadTitle); @@ -412,9 +424,10 @@ protected function fixMimeTypeOfVoiceMessage(ShareCreatedEvent|BeforeDuplicateSh $this->sendSystemMessage( $room, 'thread_created', - ['thread' => (int)$comment->getId()], + ['thread' => (int)$comment->getId(), 'title' => $threadTitle], shouldSkipLastMessageUpdate: true, silent: true, + parent: $comment, ); } } @@ -451,7 +464,17 @@ protected function attendeesRemovedEvent(AttendeesRemovedEvent $event): void { } } - protected function sendSystemMessage(Room $room, string $message, array $parameters = [], ?Participant $participant = null, bool $shouldSkipLastMessageUpdate = false, bool $silent = false, bool $forceSystemAsActor = false): IComment { + protected function sendSystemMessage( + Room $room, + string $message, + array $parameters = [], + ?Participant $participant = null, + bool $shouldSkipLastMessageUpdate = false, + bool $silent = false, + bool $forceSystemAsActor = false, + ?int $replyTo = null, + ?IComment $parent = null, + ): IComment { if ($participant instanceof Participant) { $actorType = $participant->getAttendee()->getActorType(); $actorId = $participant->getAttendee()->getActorId(); @@ -486,9 +509,7 @@ protected function sendSystemMessage(Room $room, string $message, array $paramet $referenceId = (string)$referenceId; } - $parent = null; - $replyTo = $parameters['metaData']['replyTo'] ?? null; - if ($replyTo !== null) { + if ($parent === null && $replyTo !== null) { try { $parentComment = $this->chatManager->getParentComment($room, (string)$replyTo); $parentMessage = $this->messageParser->createMessage($room, $participant, $parentComment, $this->l); diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php index d591598b437..9e6da96e5c7 100644 --- a/lib/Controller/ChatController.php +++ b/lib/Controller/ChatController.php @@ -270,7 +270,7 @@ public function sendMessage(string $message, string $actorDisplayName = '', stri $this->room, $this->participant->getAttendee()->getActorType(), $this->participant->getAttendee()->getActorId(), - json_encode(['message' => 'thread_created', 'parameters' => ['thread' => (int)$comment->getId()]]), + json_encode(['message' => 'thread_created', 'parameters' => ['thread' => (int)$comment->getId(), 'title' => $threadTitle]]), $this->timeFactory->getDateTime(), false, null, diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 5b216ecdee4..d038c34cd1e 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -2916,6 +2916,10 @@ public function userSeesTheFollowingSystemMessagesInRoom(string $user, string $i if ($result) { $message['messageParameters'] = str_replace($matches[0], '"' . self::$questionToPollId[$matches[1]] . '"', $message['messageParameters']); } + $result = preg_match('/THREAD_ID\(([^)]+)\)/', $message['messageParameters'], $matches); + if ($result) { + $message['messageParameters'] = str_replace($matches[0], '"thread\/' . self::$titleToThreadId[$matches[1]] . '"', $message['messageParameters']); + } $message['messageParameters'] = str_replace('{$REMOTE_URL}', trim(json_encode(trim($this->remoteServerUrl, '/')), '"'), $message['messageParameters']); } return $message; diff --git a/tests/integration/features/chat-4/threads.feature b/tests/integration/features/chat-4/threads.feature index 4e87a284508..0c7a52d2812 100644 --- a/tests/integration/features/chat-4/threads.feature +++ b/tests/integration/features/chat-4/threads.feature @@ -23,6 +23,15 @@ Feature: chat-4/threads Then user "participant1" sees the following recent threads in room "room" with 200 | t.id | t.title | t.numReplies | t.lastMessage | a.notificationLevel | firstMessage | lastMessage | | Message 1 | Thread 1 | 1 | Message 1-1 | 0 | Message 1 | Message 1-1 | + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | + | room | users | participant2 | participant2-displayname | Message 1-1 | [] | Message 1 | + | room | users | participant1 | participant1-displayname | Message 1 | [] | | + Then user "participant1" sees the following system messages in room "room" with 200 + | room | actorType | actorId | systemMessage | message | silent | messageParameters | + | room | users | participant1 | thread_created | {actor} created thread {title} | true | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname","mention-id":"participant1"},"title":{"type":"highlight","id":THREAD_ID(Thread 1),"name":"Thread 1"}} | + | room | users | participant1 | user_added | You added {user} | !ISSET | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname","mention-id":"participant1"},"user":{"type":"user","id":"participant2","name":"participant2-displayname","mention-id":"participant2"}} | + | room | users | participant1 | conversation_created | You created the conversation | !ISSET | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname","mention-id":"participant1"}} | Scenario: Recent threads are sorted by last activity Given user "participant1" creates room "room" (v4)