From 17971cd34a6ecb0cdf4e926e41414f13a2bd4c41 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 1 Dec 2020 11:56:54 +0100 Subject: [PATCH 01/34] Add listable flags attribute for conversations Added ability to set a conversation as listable for regular users and/or guest users from the guest app. This only implements the flag, endpoint and UI to manage it but not yet making it appear in search results. Signed-off-by: Vincent Petry --- appinfo/routes.php | 9 +++ docs/capabilities.md | 1 + docs/chat.md | 5 +- docs/constants.md | 5 ++ docs/conversation.md | 18 ++++++ docs/events.md | 7 +++ lib/Capabilities.php | 1 + lib/Chat/Parser/SystemMessage.php | 21 +++++++ lib/Chat/SystemMessage/Listener.php | 18 ++++++ lib/Command/Room/Create.php | 17 +++++ lib/Command/Room/TRoomCommand.php | 16 +++++ lib/Command/Room/Update.php | 17 +++++ lib/Controller/RoomController.php | 17 +++++ lib/Manager.php | 2 + .../Version2100Date20201201102528.php | 60 ++++++++++++++++++ lib/Room.php | 62 +++++++++++++++++++ lib/Signaling/Listener.php | 1 + .../ModerationSettings.vue | 48 ++++++++++++++ src/constants.js | 5 ++ src/services/conversationsService.js | 17 +++++ src/store/conversationsStore.js | 14 +++++ .../features/bootstrap/FeatureContext.php | 30 +++++++++ .../features/command/create.feature | 4 +- tests/php/CapabilitiesTest.php | 2 + tests/php/RoomTest.php | 1 + tests/php/Signaling/BackendNotifierTest.php | 31 ++++++++++ 26 files changed, 426 insertions(+), 3 deletions(-) create mode 100644 lib/Migration/Version2100Date20201201102528.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 1148c4db9e3..f702840f1e8 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -254,6 +254,15 @@ 'token' => '^[a-z0-9]{4,30}$', ], ], + [ + 'name' => 'Room#setListable', + 'url' => '/api/{apiVersion}/room/{token}/listable', + 'verb' => 'PUT', + 'requirements' => [ + 'apiVersion' => 'v3', + 'token' => '^[a-z0-9]{4,30}$', + ], + ], [ 'name' => 'Room#setPassword', 'url' => '/api/{apiVersion}/room/{token}/password', diff --git a/docs/capabilities.md b/docs/capabilities.md index 6bf6a30eca0..22fca01ff04 100644 --- a/docs/capabilities.md +++ b/docs/capabilities.md @@ -59,3 +59,4 @@ title: Capabilities * `config => previews => max-gif-size` - Maximum size in bytes below which a GIF can be embedded directly in the page at render time. Bigger files will be rendered statically using the preview endpoint instead. Can be set with `occ config:app:set spreed max-gif-size --value=X` where X is the new value in bytes. Defaults to 3 MB. * `chat-read-status` - On conversation API v3 and the chat API the last common read message is exposed which can be used to update the "read status" flag of own chat messages. The info should be shown only when the user also shares their read status. The user's value can be found in `config => chat => read-privacy`. * `config => chat => read-privacy` - See `chat-read-status` +* `listable-rooms` - Conversations can searched for even when not joined. A "listable" attribute set on rooms defines the scope of who can find it. diff --git a/docs/chat.md b/docs/chat.md index 11191c68ff7..736a199f176 100644 --- a/docs/chat.md +++ b/docs/chat.md @@ -149,7 +149,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` `status` | string | Optional: Only available with `includeStatus=true` and for users with a set status `statusIcon` | string | Optional: Only available with `includeStatus=true` and for users with a set status `statusMessage` | string | Optional: Only available with `includeStatus=true` and for users with a set status - + ## System messages * `conversation_created` - {actor} created the conversation @@ -160,6 +160,9 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1` * `call_ended` - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23) * `read_only_off` - {actor} unlocked the conversation * `read_only` - {actor} locked the conversation +* `listable_participants` - {actor} made the conversation listable only for participants +* `listable_users` - {actor} made the conversation listable for regular users +* `listable_all` - {actor} made the conversation listable for everone which includes users and guest users * `lobby_timer_reached` - The conversation is now open to everyone * `lobby_none` - {actor} opened the conversation to everyone * `lobby_non_moderators` - {actor} restricted the conversation to moderators diff --git a/docs/constants.md b/docs/constants.md index 2304240d580..8a250c02c8d 100644 --- a/docs/constants.md +++ b/docs/constants.md @@ -12,6 +12,11 @@ title: Constants * `0` read-write * `1` read-only +## Listable scope +* `0` participants only +* `1` regular users only, excluding guests +* `2` everyone + ## Participant types * `1` owner * `2` moderator diff --git a/docs/conversation.md b/docs/conversation.md index 4c495507f65..10899e69b9f 100644 --- a/docs/conversation.md +++ b/docs/conversation.md @@ -38,6 +38,7 @@ `participantInCall` | bool | 🏴 v1 | Flag if the current user is in the call (deprecated, use `participantFlags` instead) `participantFlags` | int | * | Flags of the current user (only available with `in-call-flags` capability) `readOnly` | int | * | Read-only state for the current user (only available with `read-only-rooms` capability) + `listable` | int | * | Listable scope for the room (only available with `listable-rooms` capability) `count` | int | 🏴 v1 | **Deprecated:** ~~Number of active users~~ - always returns `0` `numGuests` | int | 🏴 v1 | Number of active guests `lastPing` | int | * | Timestamp of the last ping of the current user (should be used for sorting) @@ -266,3 +267,20 @@ + `400 Bad Request` When the the given level is invalid + `401 Unauthorized` When the participant is a guest + `404 Not Found` When the conversation could not be found for the participant + +## Set listable scope for a conversation + +* Method: `PUT` +* Endpoint: `/room/{token}/listable` +* Data: + + field | type | Description + ------|------|------------ + `scope` | int | New flags for the conversation + +* Response: + - Status code: + + `200 OK` + + `400 Bad Request` When the conversation type does not support making it listable (only group and public conversation) + + `403 Forbidden` When the current user is not a moderator/owner or the conversation is not a public conversation + + `404 Not Found` When the conversation could not be found for the participant diff --git a/docs/events.md b/docs/events.md index c4701df75b1..227326a8565 100644 --- a/docs/events.md +++ b/docs/events.md @@ -54,6 +54,13 @@ Explanations: * After event name: `OCA\Talk\Room::EVENT_AFTER_READONLY_SET` * Since: 8.0.0 +### Set listable + +* Event class: `OCA\Talk\Events\ModifyRoomEvent` +* Before event name: `OCA\Talk\Room::EVENT_BEFORE_LISTABLE_SET` +* After event name: `OCA\Talk\Room::EVENT_AFTER_LISTABLE_SET` +* Since: 11.0.0 + ### Set lobby * Event class: `OCA\Talk\Events\ModifyLobbyEvent` diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 8dd4cca51e1..a95bc55311c 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -74,6 +74,7 @@ public function getCapabilities(): array { 'invite-groups-and-mails', 'locked-one-to-one-rooms', 'read-only-rooms', + 'listable-rooms', 'chat-read-marker', 'webinary-lobby', 'start-call-flag', diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php index b840dd8d248..48e9fa1f60a 100644 --- a/lib/Chat/Parser/SystemMessage.php +++ b/lib/Chat/Parser/SystemMessage.php @@ -165,6 +165,27 @@ public function parseMessage(Message $chatMessage): void { } elseif ($cliIsActor) { $parsedMessage = $this->l->t('An administrator locked the conversation'); } + } elseif ($message === 'listable_participants') { + $parsedMessage = $this->l->t('{actor} made the conversation listable for participants only'); + if ($currentUserIsActor) { + $parsedMessage = $this->l->t('You made the conversation listable for participants only'); + } elseif ($cliIsActor) { + $parsedMessage = $this->l->t('An administrator made the conversation listable for participants only'); + } + } elseif ($message === 'listable_users') { + $parsedMessage = $this->l->t('{actor} made the conversation listable for users only'); + if ($currentUserIsActor) { + $parsedMessage = $this->l->t('You made the conversation listable for users only'); + } elseif ($cliIsActor) { + $parsedMessage = $this->l->t('An administrator made the conversation listable for users only'); + } + } elseif ($message === 'listable_all') { + $parsedMessage = $this->l->t('{actor} made the conversation listable for everyone'); + if ($currentUserIsActor) { + $parsedMessage = $this->l->t('You made the conversation listable for everyone'); + } elseif ($cliIsActor) { + $parsedMessage = $this->l->t('An administrator made the conversation listable for everyone'); + } } elseif ($message === 'lobby_timer_reached') { $parsedMessage = $this->l->t('The conversation is now open to everyone'); } elseif ($message === 'lobby_none') { diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index 6c019b90aba..3672aa25eae 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -176,6 +176,24 @@ public static function register(IEventDispatcher $dispatcher): void { $listener->sendSystemMessage($room, 'read_only_off'); } }); + $dispatcher->addListener(Room::EVENT_AFTER_LISTABLE_SET, static function (ModifyRoomEvent $event) { + $room = $event->getRoom(); + + if ($room->getType() === Room::CHANGELOG_CONVERSATION) { + return; + } + + /** @var self $listener */ + $listener = \OC::$server->query(self::class); + + if ($event->getNewValue() === Room::LISTABLE_PARTICIPANTS) { + $listener->sendSystemMessage($room, 'listable_participants'); + } elseif ($event->getNewValue() === Room::LISTABLE_USERS) { + $listener->sendSystemMessage($room, 'listable_users'); + } elseif ($event->getNewValue() === Room::LISTABLE_ALL) { + $listener->sendSystemMessage($room, 'listable_all'); + } + }); $dispatcher->addListener(Room::EVENT_AFTER_LOBBY_STATE_SET, static function (ModifyLobbyEvent $event) { if ($event->getNewValue() === $event->getOldValue()) { return; diff --git a/lib/Command/Room/Create.php b/lib/Command/Room/Create.php index 7d595cb2f7a..eaaae0396e2 100644 --- a/lib/Command/Room/Create.php +++ b/lib/Command/Room/Create.php @@ -70,6 +70,11 @@ protected function configure(): void { null, InputOption::VALUE_NONE, 'Creates the room with read-only access only if set' + )->addOption( + 'listable', + null, + InputOption::VALUE_NONE, + 'Creates the room with the given listable scope' )->addOption( 'password', null, @@ -95,10 +100,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int $groups = $input->getOption('group'); $public = $input->getOption('public'); $readonly = $input->getOption('readonly'); + $listable = $input->getOption('listable'); $password = $input->getOption('password'); $owner = $input->getOption('owner'); $moderators = $input->getOption('moderator'); + if (!in_array($readOnly, [null, '0', '1'], true)) { + $output->writeln('Invalid value for option "--readonly" given.'); + return 1; + } + + if (!in_array($listable, [null, '0', '1', '2', '3'], true)) { + $output->writeln('Invalid value for option "--listable" given.'); + return 1; + } + $roomType = $public ? Room::PUBLIC_CALL : Room::GROUP_CALL; try { $room = $this->roomService->createConversation($roomType, $name); @@ -116,6 +132,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $this->setRoomReadOnly($room, $readonly); + $this->setListable($room, $listable); if ($password !== null) { $this->setRoomPassword($room, $password); diff --git a/lib/Command/Room/TRoomCommand.php b/lib/Command/Room/TRoomCommand.php index f2986232025..68c3d238c21 100644 --- a/lib/Command/Room/TRoomCommand.php +++ b/lib/Command/Room/TRoomCommand.php @@ -151,6 +151,22 @@ protected function setRoomReadOnly(Room $room, bool $readOnly): void { } } + /** + * @param Room $room + * @param int $listable + * + * @throws InvalidArgumentException + */ + protected function setRoomListable(Room $room, int $listable): void { + if ($room->getListable() === $listable) { + return; + } + + if (!$room->setListable($listable)) { + throw new InvalidArgumentException('Unable to change room state.'); + } + } + /** * @param Room $room * @param string $password diff --git a/lib/Command/Room/Update.php b/lib/Command/Room/Update.php index 76480a116a6..af87053e5cd 100644 --- a/lib/Command/Room/Update.php +++ b/lib/Command/Room/Update.php @@ -66,6 +66,11 @@ protected function configure(): void { null, InputOption::VALUE_REQUIRED, 'Modifies the room to be read-only (value 1) or read-write (value 0)' + )->addOption( + 'listable', + null, + InputOption::VALUE_NONE, + 'Modifies the room\'s listable scope' )->addOption( 'password', null, @@ -85,6 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $description = $input->getOption('description'); $public = $input->getOption('public'); $readOnly = $input->getOption('readonly'); + $listable = $input->getOption('listable'); $password = $input->getOption('password'); $owner = $input->getOption('owner'); @@ -98,6 +104,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } + if (!in_array($listable, [null, '0', '1', '2', '3'], true)) { + $output->writeln('Invalid value for option "--listable" given.'); + return 1; + } + try { $room = $this->manager->getRoomByToken($token); } catch (RoomNotFoundException $e) { @@ -127,6 +138,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->setRoomReadOnly($room, ($readOnly === '1')); } + if ($listable !== null) { + $this->setRoomListable($room, (int)$listable); + } + if ($password !== null) { $this->setRoomPassword($room, $password); } @@ -152,6 +167,8 @@ public function completeOptionValues($optionName, CompletionContext $context) { case 'public': case 'readonly': return ['1', '0']; + case 'listable': + return ['2', '1', '0']; case 'owner': return $this->completeParticipantValues($context); diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 06d7e6334e0..c05c98bddfd 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -531,6 +531,7 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan 'participantType' => Participant::GUEST, 'participantFlags' => Participant::FLAG_DISCONNECTED, 'readOnly' => Room::READ_WRITE, + 'listable' => $room->getListable(), 'hasPassword' => $room->hasPassword(), 'hasCall' => false, 'canStartCall' => false, @@ -605,6 +606,7 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan 'objectId' => $room->getObjectId(), 'participantType' => $attendee->getParticipantType(), 'readOnly' => $room->getReadOnly(), + 'listable' => $room->getListable(), 'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface, 'lastActivity' => $lastActivity, 'isFavorite' => $attendee->isFavorite(), @@ -1469,6 +1471,21 @@ public function setReadOnly(int $state): DataResponse { return new DataResponse(); } + /** + * @NoAdminRequired + * @RequireModeratorParticipant + * + * @param int $state + * @return DataResponse + */ + public function setListable(int $scope): DataResponse { + if (!$this->room->setListable($scope)) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); + } + + return new DataResponse(); + } + /** * @PublicPage * @RequireModeratorParticipant diff --git a/lib/Manager.php b/lib/Manager.php index f5ea5ccd6d1..62389cda3d2 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -167,6 +167,7 @@ public function createRoomObject(array $row): Room { (int) $row['r_id'], (int) $row['type'], (int) $row['read_only'], + (int) $row['listable'], (int) $row['lobby_state'], (int) $row['sip_enabled'], $assignedSignalingServer, @@ -704,6 +705,7 @@ public function getChangelogRoom(string $userId): Room { if ($row === false) { $room = $this->createRoom(Room::CHANGELOG_CONVERSATION, $userId); $room->setReadOnly(Room::READ_ONLY); + $room->setListable(Room::LISTABLE_PARTICIPANTS); $this->participantService->addUsers($room,[[ 'actorType' => Attendee::ACTOR_USERS, diff --git a/lib/Migration/Version2100Date20201201102528.php b/lib/Migration/Version2100Date20201201102528.php new file mode 100644 index 00000000000..b59fcb5d1ab --- /dev/null +++ b/lib/Migration/Version2100Date20201201102528.php @@ -0,0 +1,60 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Talk\Migration; + +use Closure; +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Add listable column to the rooms table. + */ +class Version2100Date20201201102528 extends SimpleMigrationStep { + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if ($schema->hasTable('talk_rooms')) { + $table = $schema->getTable('talk_rooms'); + + if (!$table->hasColumn('listable')) { + $table->addColumn('listable', Type::INTEGER, [ + 'notnull' => true, + 'length' => 6, + 'default' => 0, + ]); + } + } + + return $schema; + } +} diff --git a/lib/Room.php b/lib/Room.php index 8f9ed227806..7a3cf28851c 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -62,6 +62,21 @@ class Room { public const READ_WRITE = 0; public const READ_ONLY = 1; + /** + * Only visible when joined + */ + public const LISTABLE_PARTICIPANTS = 0; + + /** + * Searchable by all regular users and moderators, even when not joined, excluding guest users + */ + public const LISTABLE_USERS = 1; + + /** + * Searchable by everyone, which includes guest users (from guest app), even when not joined + */ + public const LISTABLE_ALL = 2; + public const START_CALL_EVERYONE = 0; public const START_CALL_USERS = 1; public const START_CALL_MODERATORS = 2; @@ -82,6 +97,8 @@ class Room { public const EVENT_AFTER_TYPE_SET = self::class . '::postSetType'; public const EVENT_BEFORE_READONLY_SET = self::class . '::preSetReadOnly'; public const EVENT_AFTER_READONLY_SET = self::class . '::postSetReadOnly'; + public const EVENT_BEFORE_LISTABLE_SET = self::class . '::preSetListable'; + public const EVENT_AFTER_LISTABLE_SET = self::class . '::postSetListable'; public const EVENT_BEFORE_LOBBY_STATE_SET = self::class . '::preSetLobbyState'; public const EVENT_AFTER_LOBBY_STATE_SET = self::class . '::postSetLobbyState'; public const EVENT_BEFORE_SIP_ENABLED_SET = self::class . '::preSetSIPEnabled'; @@ -131,6 +148,8 @@ class Room { /** @var int */ private $readOnly; /** @var int */ + private $listable; + /** @var int */ private $lobbyState; /** @var int */ private $sipEnabled; @@ -175,6 +194,7 @@ public function __construct(Manager $manager, int $id, int $type, int $readOnly, + int $listable, int $lobbyState, int $sipEnabled, ?int $assignedSignalingServer, @@ -199,6 +219,7 @@ public function __construct(Manager $manager, $this->id = $id; $this->type = $type; $this->readOnly = $readOnly; + $this->listable = $listable; $this->lobbyState = $lobbyState; $this->sipEnabled = $sipEnabled; $this->assignedSignalingServer = $assignedSignalingServer; @@ -228,6 +249,10 @@ public function getReadOnly(): int { return $this->readOnly; } + public function getListable(): int { + return $this->listable; + } + public function getLobbyState(): int { $this->validateTimer(); return $this->lobbyState; @@ -346,6 +371,7 @@ public function getPropertiesForSignaling(string $userId, bool $roomModified = t 'lobby-state' => $this->getLobbyState(), 'lobby-timer' => $this->getLobbyTimer(), 'read-only' => $this->getReadOnly(), + 'listable' => $this->getListable(), 'active-since' => $this->getActiveSince(), 'sip-enabled' => $this->getSIPEnabled(), ]; @@ -780,6 +806,42 @@ public function setReadOnly(int $newState): bool { return true; } + /** + * @param int $newState New listable scope from self::LISTABLE_* + * Also it's only allowed on rooms of type + * `self::GROUP_CALL` and `self::PUBLIC_CALL` + * @return bool True when the change was valid, false otherwise + */ + public function setListable(int $newState): bool { + $oldState = $this->getListable(); + if ($newState === $oldState) { + return true; + } + + if (!in_array($this->getType(), [self::GROUP_CALL, self::PUBLIC_CALL, self::CHANGELOG_CONVERSATION], true)) { + return false; + } + + if ($newState < 0 || $newState > 3) { + return false; + } + + $event = new ModifyRoomEvent($this, 'listable', $newState, $oldState); + $this->dispatcher->dispatch(self::EVENT_BEFORE_LISTABLE_SET, $event); + + $query = $this->db->getQueryBuilder(); + $query->update('talk_rooms') + ->set('listable', $query->createNamedParameter($newState, IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT))); + $query->execute(); + + $this->listable = $newState; + + $this->dispatcher->dispatch(self::EVENT_AFTER_LISTABLE_SET, $event); + + return true; + } + /** * @param int $newState Currently it is only allowed to change between * `Webinary::LOBBY_NON_MODERATORS` and `Webinary::LOBBY_NONE` diff --git a/lib/Signaling/Listener.php b/lib/Signaling/Listener.php index f62d3200522..d5625d1676a 100644 --- a/lib/Signaling/Listener.php +++ b/lib/Signaling/Listener.php @@ -140,6 +140,7 @@ protected static function registerExternalSignaling(IEventDispatcher $dispatcher $dispatcher->addListener(Room::EVENT_AFTER_PASSWORD_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_TYPE_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_READONLY_SET, $listener); + $dispatcher->addListener(Room::EVENT_AFTER_LISTABLE_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_LOBBY_STATE_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_SIP_ENABLED_SET, $listener); // TODO remove handler with "roomModified" in favour of handler with diff --git a/src/components/ConversationSettings/ModerationSettings.vue b/src/components/ConversationSettings/ModerationSettings.vue index e49305e11b1..596e67476bb 100644 --- a/src/components/ConversationSettings/ModerationSettings.vue +++ b/src/components/ConversationSettings/ModerationSettings.vue @@ -21,6 +21,23 @@ diff --git a/src/components/LeftSidebar/ConversationsList/ConversationsList.vue b/src/components/LeftSidebar/ConversationsList/ConversationsList.vue index 543104d0f4c..682b9b0d1b6 100644 --- a/src/components/LeftSidebar/ConversationsList/ConversationsList.vue +++ b/src/components/LeftSidebar/ConversationsList/ConversationsList.vue @@ -76,16 +76,21 @@ export default { mounted() { EventBus.$on('routeChange', this.onRouteChange) EventBus.$on('newMessagePosted', this.onMessagePosted) + EventBus.$on('joinedConversation', this.onJoinedConversation) }, beforeDestroy() { EventBus.$off('routeChange', this.onRouteChange) EventBus.$off('newMessagePosted', this.onMessagePosted) + EventBus.$off('joinedConversation', this.onJoinedConversation) }, methods: { - onMessagePosted({ token }) { + scrollToConversation(token) { const conversation = document.getElementById(`conversation_${token}`) + if (!conversation) { + return + } this.$nextTick(() => { conversation.scrollIntoView({ behavior: 'smooth', @@ -94,6 +99,12 @@ export default { }) }) }, + onJoinedConversation({ token }) { + this.scrollToConversation(token) + }, + onMessagePosted({ token }) { + this.scrollToConversation(token) + }, onRouteChange({ from, to }) { if (from.name === 'conversation' && to.name === 'conversation' diff --git a/src/components/LeftSidebar/LeftSidebar.vue b/src/components/LeftSidebar/LeftSidebar.vue index b4f9b7e6e0d..81c0f1fe082 100644 --- a/src/components/LeftSidebar/LeftSidebar.vue +++ b/src/components/LeftSidebar/LeftSidebar.vue @@ -52,7 +52,7 @@ :key="item.id" :item="item" :is-search-result="true" - @click="joinListedConversation" /> + @click="joinListedConversation(item)" />