Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/Chat/ChatManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,11 @@ public function getUnreadCount(Room $chat, int $lastReadMessage): int {
$key = $chat->getId() . '-' . $chat->getLastMessageId() . '-' . $lastReadMessage;
$unreadCount = $this->unreadCountCache->get($key);
if ($unreadCount === null) {
$unreadCount = $this->commentsManager->getNumberOfCommentsWithVerbsForObjectSinceComment('chat', (string)$chat->getId(), $lastReadMessage, [self::VERB_MESSAGE, self::VERB_OBJECT_SHARED]);
$verbs = [self::VERB_MESSAGE, self::VERB_OBJECT_SHARED];
if ($chat->getType() === Room::TYPE_ONE_TO_ONE) {
$verbs[] = self::VERB_REACTION;
}
$unreadCount = $this->commentsManager->getNumberOfCommentsWithVerbsForObjectSinceComment('chat', (string)$chat->getId(), $lastReadMessage, $verbs);
$this->unreadCountCache->set($key, $unreadCount, 1800);
}
return $unreadCount;
Expand Down
20 changes: 20 additions & 0 deletions lib/Chat/ReactionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use OCA\Talk\Participant;
use OCA\Talk\ResponseDefinitions;
use OCA\Talk\Room;
use OCA\Talk\Service\RoomService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
use OCP\Comments\NotFoundException;
Expand All @@ -38,6 +39,7 @@ public function __construct(
private readonly Notifier $notifier,
private readonly IEventDispatcher $dispatcher,
private readonly ITimeFactory $timeFactory,
private readonly RoomService $roomService,
) {
}

Expand Down Expand Up @@ -80,6 +82,10 @@ public function addReactionMessage(Room $chat, string $actorType, string $actorI

$this->commentsManager->save($comment);

if ($chat->getType() === Room::TYPE_ONE_TO_ONE) {
$this->roomService->setLastMessage($chat, $comment);
}

$event = new ReactionAddedEvent($chat, $parentMessage, $actorType, $actorId, $actorDisplayName, $reaction, $comment);
$this->dispatcher->dispatchTyped($event);

Expand Down Expand Up @@ -123,6 +129,20 @@ public function deleteReactionMessage(Room $chat, string $actorType, string $act
$comment->setVerb(ChatManager::VERB_REACTION_DELETED);
$this->commentsManager->save($comment);

if ($chat->getType() === Room::TYPE_ONE_TO_ONE && $chat->getLastMessageId() === (int)$comment->getId()) {
try {
$previousMessage = $this->chatManager->getPreviousMessageWithVerb(
$chat,
(int)$comment->getId(),
[ChatManager::VERB_MESSAGE, ChatManager::VERB_OBJECT_SHARED],
true,
);
$this->roomService->setLastMessage($chat, $previousMessage);
} catch (NotFoundException) {
// No previous chat message, keep the deleted reaction as last message
}
}

$revokedComment = $this->chatManager->addSystemMessage(
$chat,
null,
Expand Down
7 changes: 6 additions & 1 deletion lib/Controller/ReactionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use OCA\Talk\Middleware\Attribute\RequireReadWriteConversation;
use OCA\Talk\ResponseDefinitions;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\PublicPage;
Expand All @@ -39,6 +40,7 @@ public function __construct(
IRequest $request,
private readonly ReactionManager $reactionManager,
private readonly SendService $matrixSendService,
private readonly ParticipantService $participantService,
) {
parent::__construct($appName, $request);
}
Expand Down Expand Up @@ -81,14 +83,17 @@ public function react(int $messageId, string $reaction): DataResponse {
if ($this->room->getObjectType() === Room::OBJECT_TYPE_MATRIX) {
$this->matrixSendService->addReaction($this->getRoom(), $this->getParticipant(), $messageId, $reaction);
} else {
$this->reactionManager->addReactionMessage(
$comment = $this->reactionManager->addReactionMessage(
$this->getRoom(),
$this->getParticipant()->getAttendee()->getActorType(),
$this->getParticipant()->getAttendee()->getActorId(),
$this->getParticipant()->getAttendee()->getDisplayName(),
$messageId,
$reaction
);
if ($this->getRoom()->getType() === Room::TYPE_ONE_TO_ONE) {
$this->participantService->updateLastReadMessage($this->getParticipant(), (int)$comment->getId());
}
}
$status = Http::STATUS_CREATED;
} catch (NotFoundException) {
Expand Down
17 changes: 17 additions & 0 deletions src/components/LeftSidebar/ConversationsList/Conversation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ describe('ConversationItem.vue', () => {
await testConversationLabel(item, 'Alice has joined the call')
})

test('displays own last reaction in one to one conversations', async () => {
item.type = CONVERSATION.TYPE.ONE_TO_ONE
item.lastMessage.actorId = 'actor-id-1'
item.lastMessage.message = 'πŸ‘'
item.lastMessage.systemMessage = MESSAGE.SYSTEM_TYPE.REACTION

await testConversationLabel(item, 'You reacted with πŸ‘')
})

test('displays other participant last reaction in one to one conversations', async () => {
item.type = CONVERSATION.TYPE.ONE_TO_ONE
item.lastMessage.message = 'πŸ‘'
item.lastMessage.systemMessage = MESSAGE.SYSTEM_TYPE.REACTION

await testConversationLabel(item, 'Reacted with πŸ‘')
})

test('displays last message without author in one to one conversations', async () => {
item.type = CONVERSATION.TYPE.ONE_TO_ONE
await testConversationLabel(item, 'hello')
Expand Down
15 changes: 15 additions & 0 deletions src/composables/useConversationInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ export function useConversationInfo({
}
}

if (lastMessage.value.systemMessage === MESSAGE.SYSTEM_TYPE.REACTION) {
const reaction = lastMessage.value.actorId === item.value.actorId && lastMessage.value.actorType === item.value.actorType
? t('spreed', 'You reacted with {reaction}', { reaction: lastMessage.value.message }, { escape: false, sanitize: false })
// TRANSLATORS The second person in one-to-one conversation has reacted with emoji '{reaction}'
: t('spreed', 'Reacted with {reaction}', {
Comment thread
nickvergessen marked this conversation as resolved.
Resolved
reaction: lastMessage.value.message,
}, { escape: false, sanitize: false })
return {
actor: null,
icon: null,
message: reaction,
title: reaction,
}
}

if (shortLastChatMessageAuthor.value === '') {
return {
actor: null,
Expand Down
12 changes: 12 additions & 0 deletions src/store/messagesStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,18 @@ const actions = {
reactionsStore.processReaction(token, message)
}

// One-to-one conversations show reactions as last message
if (fromRealtime && conversation?.type === CONVERSATION.TYPE.ONE_TO_ONE) {
if (message.systemMessage === MESSAGE.SYSTEM_TYPE.REACTION
&& message.id > conversation.lastMessage?.id) {
context.commit('updateConversationLastMessage', { token, lastMessage: message })
} else if (message.systemMessage === MESSAGE.SYSTEM_TYPE.REACTION_REVOKED
&& conversation.lastMessage?.systemMessage === MESSAGE.SYSTEM_TYPE.REACTION) {
// Server already rolled back lastMessage, store may not hold that message
context.dispatch('fetchConversation', { token })
}
}

if ([MESSAGE.SYSTEM_TYPE.MESSAGE_DELETED, MESSAGE.SYSTEM_TYPE.MESSAGE_EDITED].includes(message.systemMessage)) {
// update conversation lastMessage, if it was edited or deleted
if (message.parent.id === conversation.lastMessage?.id) {
Expand Down
43 changes: 43 additions & 0 deletions tests/integration/features/chat-3/reaction.feature
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,46 @@ Feature: chat-3/reaction
| actorType | actorId | actorDisplayName | reaction |
| deleted_users | deleted_users | | πŸ‘Ž |
| deleted_users | deleted_users | | πŸ‘ |

Scenario: Reaction marks one-to-one conversation unread
Given user "participant1" creates room "room" (v4)
| roomType | 1 |
| invite | participant2 |
And user "participant1" sends message "Message 1" to room "room" with 201
And user "participant2" reads message "Message 1" in room "room" with 200
Then user "participant1" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 1 | Message 1 | 0 |
And user "participant2" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 1 | Message 1 | 0 |
When user "participant2" react with "πŸ‘" on message "Message 1" to room "room" with 201
| actorType | actorId | actorDisplayName | reaction |
| users | participant2 | participant2-displayname | πŸ‘ |
Then user "participant1" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 1 | πŸ‘ | 1 |
And user "participant2" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 1 | πŸ‘ | 0 |
When user "participant2" delete react with "πŸ‘" on message "Message 1" to room "room" with 200
| actorType | actorId | actorDisplayName | reaction |
Then user "participant1" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 1 | Message 1 | 0 |
And user "participant2" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 1 | Message 1 | 0 |

Scenario: Reaction does not mark group conversation unread
Given user "participant1" creates room "room" (v4)
| roomType | 3 |
| roomName | room |
And user "participant1" adds user "participant2" to room "room" with 200 (v4)
And user "participant1" sends message "Message 1" to room "room" with 201
When user "participant2" react with "πŸ‘" on message "Message 1" to room "room" with 201
| actorType | actorId | actorDisplayName | reaction |
| users | participant2 | participant2-displayname | πŸ‘ |
Then user "participant1" is participant of the following rooms (v4)
| id | type | lastMessage | unreadMessages |
| room | 3 | Message 1 | 0 |
15 changes: 13 additions & 2 deletions tests/php/Chat/ChatManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -389,16 +389,27 @@ public function testWaitForNewMessagesWithWaiting(): void {
$this->assertEquals($expected, $comments);
}

public function testGetUnreadCount(): void {
public static function dataGetUnreadCount(): array {
return [
[Room::TYPE_ONE_TO_ONE, ['comment', 'object_shared', 'reaction']],
[Room::TYPE_GROUP, ['comment', 'object_shared']],
[Room::TYPE_PUBLIC, ['comment', 'object_shared']],
];
}

#[DataProvider('dataGetUnreadCount')]
public function testGetUnreadCount(int $roomType, array $verbs): void {
/** @var Room&MockObject $chat */
$chat = $this->createMock(Room::class);
$chat->expects($this->atLeastOnce())
->method('getId')
->willReturn(23);
$chat->method('getType')
->willReturn($roomType);

$this->commentsManager->expects($this->once())
->method('getNumberOfCommentsWithVerbsForObjectSinceComment')
->with('chat', 23, 42, ['comment', 'object_shared']);
->with('chat', 23, 42, $verbs);

$this->chatManager->getUnreadCount($chat, 42);
}
Expand Down
Loading