diff --git a/docs/api-v1.md b/docs/api-v1.md index 424b4954e4a..ed476154503 100644 --- a/docs/api-v1.md +++ b/docs/api-v1.md @@ -120,6 +120,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` `sessionId` | string | `'0'` if not connected, otherwise a 512 character long string `hasPassword` | bool | Flag if the room has a password `hasCall` | bool | Flag if the room has an active call + `unreadMessages` | int | Number of unread chat messages in the room (only available with `chat-v2` capability) ### Get single room (also for guests) diff --git a/js/views/roomlistview.js b/js/views/roomlistview.js index 734f9d66028..359248866dc 100644 --- a/js/views/roomlistview.js +++ b/js/views/roomlistview.js @@ -37,6 +37,7 @@ var ITEM_TEMPLATE = ' {{displayName}}'+ '
'+ @@ -80,6 +81,9 @@ 'change:participantType': function() { this.render(); }, + 'change:unreadMessages': function() { + this.render(); + }, 'change:type': function() { this.render(); } diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index dd0fb9b947f..82bd3f11b58 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -25,6 +25,7 @@ use OCP\Comments\IComment; use OCP\Comments\ICommentsManager; +use OCP\IUser; /** * Basic polling chat manager. @@ -76,6 +77,16 @@ public function sendMessage($chatId, $actorType, $actorId, $message, \DateTime $ $this->notifier->notifyMentionedUsers($comment); } + /** + * @param string $chatId + * @param IUser $userId + * @return int + */ + public function getUnreadCount($chatId, IUser $user) { + $unreadSince = $this->commentsManager->getReadMark('chat', $chatId, $user); + return $this->commentsManager->getNumberOfCommentsForObject('chat', $chatId, $unreadSince); + } + /** * Receive the history of a chat * @@ -104,13 +115,15 @@ public function getHistory($chatId, $offset, $limit) { * @param int $offset Last known message id * @param int $limit * @param int $timeout - * @param string $userId + * @param IUser|null $user * @return IComment[] the messages found (only the id, actor type and id, * creation date and message are relevant), or an empty array if the * timeout expired. */ - public function waitForNewMessages($chatId, $offset, $limit, $timeout, $userId) { - $this->notifier->markMentionNotificationsRead($chatId, $userId); + public function waitForNewMessages($chatId, $offset, $limit, $timeout, $user) { + if ($user instanceof IUser) { + $this->notifier->markMentionNotificationsRead($chatId, $user->getUID()); + } $elapsedTime = 0; $comments = $this->commentsManager->getForObjectSinceTalkVersion('chat', $chatId, $offset, 'asc', $limit); @@ -122,6 +135,10 @@ public function waitForNewMessages($chatId, $offset, $limit, $timeout, $userId) $comments = $this->commentsManager->getForObjectSinceTalkVersion('chat', $chatId, $offset, 'asc', $limit); } + if ($user instanceof IUser) { + $this->commentsManager->setReadMark('chat', $chatId, new \DateTime(), $user); + } + return $comments; } diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php index 74bc9c7c72f..44466101ebe 100644 --- a/lib/Controller/ChatController.php +++ b/lib/Controller/ChatController.php @@ -219,7 +219,8 @@ public function receiveMessages($token, $lookIntoFuture, $limit = 100, $lastKnow $timeout = min(60, $timeout); if ($lookIntoFuture) { - $comments = $this->chatManager->waitForNewMessages((string) $room->getId(), $lastKnownMessageId, $limit, $timeout, $this->userId); + $currentUser = $this->userManager->get($this->userId); + $comments = $this->chatManager->waitForNewMessages((string) $room->getId(), $lastKnownMessageId, $limit, $timeout, $currentUser); } else { $comments = $this->chatManager->getHistory((string) $room->getId(), $lastKnownMessageId, $limit); } diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index f2a042b27d9..271dc67a4c5 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -25,6 +25,7 @@ namespace OCA\Spreed\Controller; +use OCA\Spreed\Chat\ChatManager; use OCA\Spreed\Exceptions\InvalidPasswordException; use OCA\Spreed\Exceptions\ParticipantNotFoundException; use OCA\Spreed\Exceptions\RoomNotFoundException; @@ -59,6 +60,8 @@ class RoomController extends OCSController { private $manager; /** @var GuestManager */ private $guestManager; + /** @var ChatManager */ + private $chatManager; /** @var IL10N */ private $l10n; @@ -72,6 +75,7 @@ class RoomController extends OCSController { * @param ILogger $logger * @param Manager $manager * @param GuestManager $guestManager + * @param ChatManager $chatManager * @param IL10N $l10n */ public function __construct($appName, @@ -83,6 +87,7 @@ public function __construct($appName, ILogger $logger, Manager $manager, GuestManager $guestManager, + ChatManager $chatManager, IL10N $l10n) { parent::__construct($appName, $request); $this->session = $session; @@ -92,6 +97,7 @@ public function __construct($appName, $this->logger = $logger; $this->manager = $manager; $this->guestManager = $guestManager; + $this->chatManager = $chatManager; $this->l10n = $l10n; } @@ -170,6 +176,7 @@ protected function formatRoom(Room $room, Participant $participant = null) { 'count' => $room->getNumberOfParticipants(false, time() - 30), 'hasPassword' => $room->hasPassword(), 'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface, + 'unreadMessages' => 0, ]; if (!$participant instanceof Participant) { @@ -186,6 +193,11 @@ protected function formatRoom(Room $room, Participant $participant = null) { return $roomData; } + $currentUser = $this->userManager->get($this->userId); + if ($currentUser instanceof IUser) { + $roomData['unreadMessages'] = $this->chatManager->getUnreadCount($room->getId(), $currentUser); + } + // Sort by lastPing /** @var array[] $participants */ $participants = $room->getParticipants(); diff --git a/tests/php/Chat/ChatManagerTest.php b/tests/php/Chat/ChatManagerTest.php index 5aa91979627..47ca49cd779 100644 --- a/tests/php/Chat/ChatManagerTest.php +++ b/tests/php/Chat/ChatManagerTest.php @@ -28,6 +28,7 @@ use OCA\Spreed\Chat\Notifier; use OCP\Comments\IComment; use OCP\Comments\ICommentsManager; +use OCP\IUser; class ChatManagerTest extends \Test\TestCase { @@ -140,7 +141,13 @@ public function testWaitForNewMessages() { ->method('markMentionNotificationsRead') ->with('testChatId', 'userId'); - $comments = $this->chatManager->waitForNewMessages('testChatId', $offset, $limit, $timeout, 'userId'); + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user->expects($this->any()) + ->method('getUID') + ->willReturn('userId'); + + $comments = $this->chatManager->waitForNewMessages('testChatId', $offset, $limit, $timeout, $user); $this->assertEquals($expected, $comments); } @@ -167,7 +174,13 @@ public function testWaitForNewMessagesWithWaiting() { ->method('markMentionNotificationsRead') ->with('testChatId', 'userId'); - $comments = $this->chatManager->waitForNewMessages('testChatId', $offset, $limit, $timeout, 'userId'); + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user->expects($this->any()) + ->method('getUID') + ->willReturn('userId'); + + $comments = $this->chatManager->waitForNewMessages('testChatId', $offset, $limit, $timeout, $user); $this->assertEquals($expected, $comments); } diff --git a/tests/php/Controller/ChatControllerTest.php b/tests/php/Controller/ChatControllerTest.php index 8ae5e799339..f69a1ed8c9a 100644 --- a/tests/php/Controller/ChatControllerTest.php +++ b/tests/php/Controller/ChatControllerTest.php @@ -571,12 +571,20 @@ public function testWaitForNewMessagesByUser() { ->method('getId') ->willReturn(1234); + $testUser = $this->createMock(IUser::class); + $testUser->expects($this->any()) + ->method('getUID') + ->willReturn('testUser'); + $testUser->expects($this->exactly(2)) + ->method('getDisplayName') + ->willReturn('Test User'); + $offset = 23; $limit = 4; $timeout = 10; $this->chatManager->expects($this->once()) ->method('waitForNewMessages') - ->with('1234', $offset, $limit, $timeout, $this->userId) + ->with('1234', $offset, $limit, $timeout, $testUser) ->willReturn([ $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000004), 'testMessage1'), $this->newComment(109, 'guests', 'testSpreedSession', new \DateTime('@' . 1000000008), 'testMessage2'), @@ -584,15 +592,12 @@ public function testWaitForNewMessagesByUser() { $this->newComment(111, 'users', 'testUser', new \DateTime('@' . 1000000016), 'testMessage4'), ]); - $testUser = $this->createMock(IUser::class); - $testUser->expects($this->exactly(2)) - ->method('getDisplayName') - ->willReturn('Test User'); - - $this->userManager->expects($this->exactly(3)) + $this->userManager->expects($this->any()) ->method('get') - ->withConsecutive(['testUser'], ['testUnknownUser'], ['testUser']) - ->willReturn($testUser, null, $testUser); + ->willReturnMap([ + ['testUser', $testUser], + ['testUnknownUser', null] + ]); $response = $this->controller->receiveMessages('testToken', 1, $limit, $offset, $timeout); $expected = new DataResponse([ @@ -624,14 +629,24 @@ public function testWaitForNewMessagesTimeoutExpired() { ->method('getId') ->willReturn(1234); + $testUser = $this->createMock(IUser::class); + $testUser->expects($this->any()) + ->method('getUID') + ->willReturn('testUser'); + $offset = 23; $limit = 4; $timeout = 3; $this->chatManager->expects($this->once()) ->method('waitForNewMessages') - ->with('1234', $offset, $limit, $timeout, $this->userId) + ->with('1234', $offset, $limit, $timeout, $testUser) ->willReturn([]); + $this->userManager->expects($this->any()) + ->method('get') + ->with('testUser') + ->willReturn($testUser); + $response = $this->controller->receiveMessages('testToken', 1, $limit, $offset, $timeout); $expected = new DataResponse([], Http::STATUS_NOT_MODIFIED); @@ -656,15 +671,25 @@ public function testWaitForNewMessagesTimeoutTooLarge() { ->method('getId') ->willReturn(1234); + $testUser = $this->createMock(IUser::class); + $testUser->expects($this->any()) + ->method('getUID') + ->willReturn('testUser'); + $offset = 23; $timeout = 100000; $maximumTimeout = 60; $limit = 4; $this->chatManager->expects($this->once()) ->method('waitForNewMessages') - ->with('1234', $offset, $limit, $maximumTimeout, $this->userId) + ->with('1234', $offset, $limit, $maximumTimeout, $testUser) ->willReturn([]); + $this->userManager->expects($this->any()) + ->method('get') + ->with('testUser') + ->willReturn($testUser); + $response = $this->controller->receiveMessages('testToken', 1, $limit, $offset, $timeout); $expected = new DataResponse([], Http::STATUS_NOT_MODIFIED);