summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2023-12-15 09:37:11 +0100
committerJoas Schilling <coding@schilljs.com>2023-12-15 09:40:28 +0100
commitbfa2c83fcee9d6b510b608b1c0474fb6c6cf0afb (patch)
tree261d1d116fb6722c2f8f2801be5d2f0e30e17939
parent9cc8f782ac9322e451c7acdde2921723ae9163b5 (diff)
feat(shares): Add notifications for caption mentions and replies
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--lib/Chat/ChatManager.php37
-rw-r--r--lib/Chat/ReactionManager.php4
-rw-r--r--lib/Chat/SystemMessage/Listener.php11
-rw-r--r--tests/integration/features/chat-1/notifications.feature42
-rw-r--r--tests/php/Chat/ChatManagerTest.php4
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));