diff options
-rw-r--r-- | lib/Chat/ChatManager.php | 37 | ||||
-rw-r--r-- | lib/Chat/ReactionManager.php | 4 | ||||
-rw-r--r-- | lib/Chat/SystemMessage/Listener.php | 11 | ||||
-rw-r--r-- | tests/integration/features/chat-1/notifications.feature | 42 | ||||
-rw-r--r-- | tests/php/Chat/ChatManagerTest.php | 4 |
5 files changed, 85 insertions, 13 deletions
diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index fe2471151..99473b1d1 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -127,7 +127,7 @@ class ChatManager { \DateTime $creationDateTime, bool $sendNotifications, ?string $referenceId = null, - ?int $parentId = null, + ?IComment $replyTo = null, bool $shouldSkipLastMessageUpdate = false, bool $silent = false, ): IComment { @@ -140,8 +140,8 @@ class ChatManager { $comment->setReferenceId($referenceId); } } - if ($parentId !== null) { - $comment->setParentId((string) $parentId); + if ($replyTo !== null) { + $comment->setParentId($replyTo->getId()); } $messageDecoded = json_decode($message, true); @@ -155,6 +155,8 @@ class ChatManager { $this->setMessageExpiration($chat, $comment); + $shouldFlush = $this->notificationManager->defer(); + $event = new BeforeSystemMessageSentEvent($chat, $comment, silent: $silent, skipLastActivityUpdate: $shouldSkipLastMessageUpdate); $this->dispatcher->dispatchTyped($event); try { @@ -167,6 +169,29 @@ class ChatManager { } if ($sendNotifications) { + /** @var ?IComment $captionComment */ + $captionComment = null; + $alreadyNotifiedUsers = $usersDirectlyMentioned = []; + if ($messageType === 'file_shared') { + if (isset($messageDecoded['parameters']['metaData']['caption'])) { + $captionComment = clone $comment; + $captionComment->setMessage($messageDecoded['parameters']['metaData']['caption'], self::MAX_CHAT_LENGTH); + $usersDirectlyMentioned = $this->notifier->getMentionedUserIds($captionComment); + } + if ($replyTo instanceof IComment) { + $alreadyNotifiedUsers = $this->notifier->notifyReplyToAuthor($chat, $comment, $replyTo, $silent); + if ($replyTo->getActorType() === Attendee::ACTOR_USERS) { + $usersDirectlyMentioned[] = $replyTo->getActorId(); + } + } + } + + $alreadyNotifiedUsers = $this->notifier->notifyMentionedUsers($chat, $captionComment ?? $comment, $alreadyNotifiedUsers, $silent); + if (!empty($alreadyNotifiedUsers)) { + $userIds = array_column($alreadyNotifiedUsers, 'id'); + $this->participantService->markUsersAsMentioned($chat, $userIds, (int) $comment->getId(), $usersDirectlyMentioned); + } + $this->notifier->notifyOtherParticipant($chat, $comment, [], $silent); } @@ -187,6 +212,10 @@ class ChatManager { } $this->cache->remove($chat->getToken()); + if ($shouldFlush) { + $this->notificationManager->flush(); + } + if ($messageType === 'object_shared' || $messageType === 'file_shared') { $this->attachmentService->createAttachmentEntry($chat, $comment, $messageType, $messageDecoded['parameters'] ?? []); } @@ -442,7 +471,7 @@ class ChatManager { $this->timeFactory->getDateTime(), false, null, - (int) $comment->getId(), + $comment, true ); } diff --git a/lib/Chat/ReactionManager.php b/lib/Chat/ReactionManager.php index e825d7ec6..b1f174b6e 100644 --- a/lib/Chat/ReactionManager.php +++ b/lib/Chat/ReactionManager.php @@ -110,7 +110,7 @@ class ReactionManager { */ public function deleteReactionMessage(Room $chat, string $actorType, string $actorId, int $messageId, string $reaction): IComment { // Just to verify that messageId is part of the room and throw error if not. - $this->getCommentToReact($chat, (string) $messageId); + $parentComment = $this->getCommentToReact($chat, (string) $messageId); $comment = $this->commentsManager->getReactionComment( $messageId, @@ -136,7 +136,7 @@ class ReactionManager { $this->timeFactory->getDateTime(), false, null, - $messageId, + $parentComment, true ); diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index f35a264a0..80af7f69b 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -460,17 +460,17 @@ class Listener implements IEventListener { $referenceId = (string) $referenceId; } + $parent = null; $replyTo = $parameters['metaData']['replyTo'] ?? null; if ($replyTo !== null) { try { $parentComment = $this->chatManager->getParentComment($room, (string) $replyTo); $parentMessage = $this->messageParser->createMessage($room, $participant, $parentComment, $this->l); $this->messageParser->parseMessage($parentMessage); - if (!$parentMessage->isReplyable()) { - $replyTo = null; + if ($parentMessage->isReplyable()) { + $parent = $parentComment; } } catch (NotFoundException) { - $replyTo = null; } } @@ -478,9 +478,10 @@ class Listener implements IEventListener { return $this->chatManager->addSystemMessage( $room, $actorType, $actorId, json_encode(['message' => $message, 'parameters' => $parameters]), - $this->timeFactory->getDateTime(), $message === 'file_shared', + $this->timeFactory->getDateTime(), + $message === 'file_shared', $referenceId, - $replyTo, + $parent, $shouldSkipLastMessageUpdate, $silent, ); diff --git a/tests/integration/features/chat-1/notifications.feature b/tests/integration/features/chat-1/notifications.feature index 0549f2b4d..8d66570e2 100644 --- a/tests/integration/features/chat-1/notifications.feature +++ b/tests/integration/features/chat-1/notifications.feature @@ -373,6 +373,48 @@ Feature: chat/notifications | app | object_type | object_id | subject | | spreed | chat | room/Hi @all @participant2 @"group/attendees1" bye | participant1-displayname replied to your message in conversation room | + Scenario: Replying with a captioned file gives a reply notification + When user "participant1" creates room "room" (v4) + | roomType | 2 | + | roomName | room | + And user "participant1" adds user "participant2" to room "room" with 200 (v4) + And user "participant1" adds group "attendees1" to room "room" with 200 (v4) + # Join and leave to clear the invite notification + Given user "participant2" joins room "room" with 200 (v4) + Given user "participant2" leaves room "room" with 200 (v4) + When user "participant2" sends message "Message 1" to room "room" with 201 + 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 | [] | | + When user "participant1" shares "welcome.txt" with room "room" + | talkMetaData.caption | Caption 1-1 | + | talkMetaData.replyTo | Message 1 | + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | + | room | users | participant1 | participant1-displayname | Caption 1-1 | "IGNORE" | Message 1 | + | room | users | participant2 | participant2-displayname | Message 1 | [] | | + Then user "participant2" has the following notifications + | app | object_type | object_id | subject | + | spreed | chat | room/Caption 1-1 | participant1-displayname replied to your message in conversation room | + + Scenario: Mentions in captions trigger normal mention notifications + When user "participant1" creates room "room" (v4) + | roomType | 2 | + | roomName | room | + And user "participant1" adds user "participant2" to room "room" with 200 (v4) + And user "participant1" adds group "attendees1" to room "room" with 200 (v4) + # Join and leave to clear the invite notification + Given user "participant2" joins room "room" with 200 (v4) + Given user "participant2" leaves room "room" with 200 (v4) + When user "participant1" shares "welcome.txt" with room "room" + | talkMetaData.caption | @participant2 | + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | + | room | users | participant1 | participant1-displayname | {mention-user1} | "IGNORE" | | + Then user "participant2" has the following notifications + | app | object_type | object_id | subject | + | spreed | chat | room/{mention-user1} | participant1-displayname mentioned you in conversation room | + Scenario: Delete notification when the message is deleted When user "participant1" creates room "one-to-one room" (v4) | roomType | 1 | diff --git a/tests/php/Chat/ChatManagerTest.php b/tests/php/Chat/ChatManagerTest.php index 7ba54a45b..dca10dd31 100644 --- a/tests/php/Chat/ChatManagerTest.php +++ b/tests/php/Chat/ChatManagerTest.php @@ -469,7 +469,7 @@ class ChatManagerTest extends TestCase { $chatManager = $this->getManager(['addSystemMessage']); $chatManager->expects($this->once()) ->method('addSystemMessage') - ->with($chat, Attendee::ACTOR_USERS, 'user', $this->anything(), $this->anything(), false, null, 123456) + ->with($chat, Attendee::ACTOR_USERS, 'user', $this->anything(), $this->anything(), false, null, $comment) ->willReturn($systemMessage); $this->assertSame($systemMessage, $chatManager->deleteMessage($chat, $comment, $participant, $date)); @@ -549,7 +549,7 @@ class ChatManagerTest extends TestCase { $chatManager = $this->getManager(['addSystemMessage']); $chatManager->expects($this->once()) ->method('addSystemMessage') - ->with($chat, Attendee::ACTOR_USERS, 'user', $this->anything(), $this->anything(), false, null, 123456) + ->with($chat, Attendee::ACTOR_USERS, 'user', $this->anything(), $this->anything(), false, null, $comment) ->willReturn($systemMessage); $this->assertSame($systemMessage, $chatManager->deleteMessage($chat, $comment, $participant, $date)); |