Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dashboard): Dashboard does not show mentions from federated conversations #12162

Merged
merged 1 commit into from
Apr 19, 2024
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
78 changes: 51 additions & 27 deletions lib/Dashboard/TalkWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
use OCA\Talk\Config;
use OCA\Talk\Manager;
use OCA\Talk\Model\BreakoutRoom;
use OCA\Talk\Model\Message;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\AvatarService;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\Service\ProxyCacheMessageService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
use OCP\Dashboard\IAPIWidget;
use OCP\Dashboard\IButtonWidget;
use OCP\Dashboard\IConditionalWidget;
Expand Down Expand Up @@ -64,6 +66,7 @@ public function __construct(
protected ParticipantService $participantService,
protected MessageParser $messageParser,
protected ChatManager $chatManager,
protected ProxyCacheMessageService $pcmService,
protected ITimeFactory $timeFactory,
) {
}
Expand Down Expand Up @@ -156,13 +159,13 @@ public function getItems(string $userId, ?string $since = null, int $limit = 7):
$participant = $this->participantService->getParticipant($room, $userId);
$attendee = $participant->getAttendee();

if ($attendee->getLastMentionMessage() > $attendee->getLastReadMessage()) {
if (($room->isFederatedConversation() && $attendee->getLastMentionMessage())
|| (!$room->isFederatedConversation() && $attendee->getLastMentionMessage() > $attendee->getLastReadMessage())) {
return true;
}

return ($room->getType() === Room::TYPE_ONE_TO_ONE || $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER)
&& $room->getLastMessage()
&& $room->getLastMessage()->getId() > $attendee->getLastReadMessage()
&& $room->getLastMessageId() > $attendee->getLastReadMessage()
&& $this->chatManager->getUnreadCount($room, $attendee->getLastReadMessage()) > 0;
});

Expand Down Expand Up @@ -200,14 +203,15 @@ public function getItemsV2(string $userId, ?string $since = null, int $limit = 7
continue;
}

if ($attendee->getLastMentionMessage() > $attendee->getLastReadMessage()) {
if (($room->isFederatedConversation() && $attendee->getLastMentionMessage())
|| (!$room->isFederatedConversation() && $attendee->getLastMentionMessage() > $attendee->getLastReadMessage())) {
// Really mentioned
$mentions[] = $room;
continue;
}

if (($room->getType() === Room::TYPE_ONE_TO_ONE || $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER)
&& $room->getLastMessage()?->getId() > $attendee->getLastReadMessage()) {
&& $room->getLastMessageId() > $attendee->getLastReadMessage()) {
// If there are "unread" messages in one-to-one or former one-to-one
// we check if they are actual messages or system messages not
// considered by the read-marker
Expand Down Expand Up @@ -242,33 +246,29 @@ protected function prepareRoom(Room $room, string $userId): WidgetItem {
$participant = $this->participantService->getParticipant($room, $userId);
$subtitle = '';

$lastMessage = $room->getLastMessage();
if ($lastMessage instanceof IComment) {
if ($room->getLastMessageId() && $room->isFederatedConversation()) {
try {
$cachedMessage = $this->pcmService->findByRemote(
$room->getRemoteServer(),
$room->getRemoteToken(),
$room->getLastMessageId(),
);
$message = $this->messageParser->createMessageFromProxyCache($room, $participant, $cachedMessage, $this->l10n);
$subtitle = $this->getSubtitleFromMessage($message);
} catch (DoesNotExistException $e) {
// Fallback to empty subtitle
}
} elseif ($room->getLastMessageId() && !$room->isFederatedConversation()) {
$message = $this->messageParser->createMessage($room, $participant, $room->getLastMessage(), $this->l10n);
$this->messageParser->parseMessage($message);

$now = $this->timeFactory->getDateTime();
$expireDate = $message->getComment()->getExpireDate();
if ((!$expireDate instanceof \DateTime || $expireDate >= $now)
&& $message->getVisibility()) {
$placeholders = $replacements = [];

foreach ($message->getMessageParameters() as $placeholder => $parameter) {
$placeholders[] = '{' . $placeholder . '}';
if ($parameter['type'] === 'user' || $parameter['type'] === 'guest') {
$replacements[] = '@' . $parameter['name'];
} else {
$replacements[] = $parameter['name'];
}
}

$subtitle = str_replace($placeholders, $replacements, $message->getMessage());
}
$subtitle = $this->getSubtitleFromMessage($message);
}

$attendee = $participant->getAttendee();
if ($room->getCallFlag() !== Participant::FLAG_DISCONNECTED) {
$subtitle = $this->l10n->t('Call in progress');
} elseif ($participant->getAttendee()->getLastMentionMessage() > $participant->getAttendee()->getLastReadMessage()) {
} elseif (($room->isFederatedConversation() && $attendee->getLastMentionMessage())
|| (!$room->isFederatedConversation() && $attendee->getLastMentionMessage() > $attendee->getLastReadMessage())) {
$subtitle = $this->l10n->t('You were mentioned');
}

Expand All @@ -280,6 +280,30 @@ protected function prepareRoom(Room $room, string $userId): WidgetItem {
);
}

protected function getSubtitleFromMessage(Message $message): string {
$expireDate = $message->getExpirationDateTime();
if ($expireDate instanceof \DateTimeInterface
&& $expireDate <= $this->timeFactory->getDateTime()) {
return '';
}

if (!$message->getVisibility()) {
return '';
}

$placeholders = $replacements = [];
foreach ($message->getMessageParameters() as $placeholder => $parameter) {
$placeholders[] = '{' . $placeholder . '}';
if ($parameter['type'] === 'user' || $parameter['type'] === 'guest') {
$replacements[] = '@' . $parameter['name'];
} else {
$replacements[] = $parameter['name'];
}
}

return str_replace($placeholders, $replacements, $message->getMessage());
}

protected function sortRooms(Room $roomA, Room $roomB): int {
if ($roomA->getCallFlag() !== $roomB->getCallFlag()) {
return $roomA->getCallFlag() !== Participant::FLAG_DISCONNECTED ? -1 : 1;
Expand Down
5 changes: 4 additions & 1 deletion lib/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -1326,7 +1326,10 @@ public function isGuestUser(string $userId): bool {
}

protected function loadLastMessageInfo(IQueryBuilder $query): void {
$query->leftJoin('r', 'comments', 'c', $query->expr()->eq('r.last_message', 'c.id'));
$query->leftJoin('r', 'comments', 'c', $query->expr()->andX(
$query->expr()->eq('r.last_message', 'c.id'),
$query->expr()->emptyString('r.remote_server'),
));
$query->selectAlias('c.id', 'comment_id');
$query->selectAlias('c.parent_id', 'comment_parent_id');
$query->selectAlias('c.topmost_parent_id', 'comment_topmost_parent_id');
Expand Down
6 changes: 5 additions & 1 deletion lib/Room.php
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,11 @@ public function setLastMessageId(int $lastMessageId): void {
}

public function getLastMessage(): ?IComment {
if ($this->lastMessageId && $this->lastMessage === null && !$this->isFederatedConversation()) {
if ($this->isFederatedConversation()) {
return null;
}

if ($this->lastMessageId && $this->lastMessage === null) {
$this->lastMessage = $this->manager->loadLastCommentInfo($this->lastMessageId);
if ($this->lastMessage === null) {
$this->lastMessageId = 0;
Expand Down
4 changes: 3 additions & 1 deletion tests/integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -2357,12 +2357,14 @@ public function userGetsDashboardWidgetItems($user, $widgetId, $apiVersion = 'v1
$actualItems = $data[$widgetId]['items'];
}

$actualItems = array_filter($actualItems, static fn ($item) => $item['title'] !== 'Note to self' && $item['title'] !== 'Talk updates βœ…');

if (empty($expectedItems)) {
Assert::assertEmpty($actualItems);
return;
}

Assert::assertCount(count($expectedItems), $actualItems);
Assert::assertCount(count($expectedItems), $actualItems, json_encode($actualItems, JSON_PRETTY_PRINT));

foreach ($expectedItems as $key => $item) {
$token = self::$identifierToToken[$item['link']];
Expand Down
11 changes: 11 additions & 0 deletions tests/integration/features/federation/chat.feature
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,18 @@ Feature: federation/chat
Given user "participant2" joins room "LOCAL::room" with 200 (v4)
Given user "participant2" leaves room "LOCAL::room" with 200 (v4)
And user "participant2" sends message "Message 1" to room "LOCAL::room" with 201
Then user "participant2" sees the following entries for dashboard widgets "spreed" (v1)
| title | subtitle | link | iconUrl | sinceId | overlayIconUrl |
Then user "participant2" sees the following entries for dashboard widgets "spreed" (v2)
| title | subtitle | link | iconUrl | sinceId | overlayIconUrl |
| room | Message 1 | LOCAL::room | {$BASE_URL}ocs/v2.php/apps/spreed/api/v1/room/{token}/avatar{version} | | |
When user "participant1" sends reply "Message 1-1" on message "Message 1" to room "room" with 201
Then user "participant2" sees the following entries for dashboard widgets "spreed" (v1)
| title | subtitle | link | iconUrl | sinceId | overlayIconUrl |
| room | You were mentioned | LOCAL::room | {$BASE_URL}ocs/v2.php/apps/spreed/api/v1/room/{token}/avatar{version} | | |
Then user "participant2" sees the following entries for dashboard widgets "spreed" (v2)
| title | subtitle | link | iconUrl | sinceId | overlayIconUrl |
| room | You were mentioned | LOCAL::room | {$BASE_URL}ocs/v2.php/apps/spreed/api/v1/room/{token}/avatar{version} | | |
And user "participant1" sends message 'Hi @"federated_user/participant2@{$REMOTE_URL}" bye' to room "room" with 201
And user "participant1" sends message 'Hi @all bye' to room "room" with 201
Then user "participant2" has the following notifications
Expand Down
Loading