diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2021-11-03 14:37:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-03 14:37:30 +0100 |
commit | 3b3fc8b25ae3af36129dca21134ad96285b826b8 (patch) | |
tree | 89a4e35b6b03f7a20cb9ff2effa2e0514550f6ff | |
parent | 2819892f317609a4a5fee86692e7ffa007a11730 (diff) | |
parent | 1e1cd5e25f785c32f33fc8af63b9d887d9d2a408 (diff) |
Merge pull request #5981 from nextcloud/enh/5395/end-meeting-for-all
📅 End meeting for all
-rw-r--r-- | docs/chat.md | 1 | ||||
-rw-r--r-- | lib/Activity/Listener.php | 25 | ||||
-rw-r--r-- | lib/Chat/Parser/SystemMessage.php | 86 | ||||
-rw-r--r-- | lib/Chat/SystemMessage/Listener.php | 6 | ||||
-rw-r--r-- | lib/Controller/CallController.php | 9 | ||||
-rw-r--r-- | lib/Events/ModifyEveryoneEvent.php | 27 | ||||
-rw-r--r-- | lib/Events/ModifyRoomEvent.php | 14 | ||||
-rw-r--r-- | lib/Room.php | 2 | ||||
-rw-r--r-- | lib/Service/ParticipantService.php | 25 | ||||
-rw-r--r-- | src/components/TopBar/CallButton.vue | 121 | ||||
-rw-r--r-- | src/services/callsService.js | 5 | ||||
-rw-r--r-- | src/store/participantsStore.js | 4 | ||||
-rw-r--r-- | src/store/participantsStore.spec.js | 2 | ||||
-rw-r--r-- | src/utils/signaling.js | 12 | ||||
-rw-r--r-- | src/utils/webrtc/index.js | 5 | ||||
-rw-r--r-- | src/utils/webrtc/webrtc.js | 36 | ||||
-rw-r--r-- | tests/php/Chat/Parser/SystemMessageTest.php | 150 |
17 files changed, 462 insertions, 68 deletions
diff --git a/docs/chat.md b/docs/chat.md index f8a5e0762..b19573ecb 100644 --- a/docs/chat.md +++ b/docs/chat.md @@ -271,6 +271,7 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob * `call_joined` - {actor} joined the call * `call_left` - {actor} left the call * `call_ended` - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23) +* `call_ended_everyone` - {user1} ended the call with {user2}, {user3}, {user4} and {user5} (Duration 30:23) * `call_missed` - You missed a call from {user} * `call_tried` - You tried to call {user} * `read_only_off` - {actor} unlocked the conversation diff --git a/lib/Activity/Listener.php b/lib/Activity/Listener.php index 78f62dad1..d38bda37d 100644 --- a/lib/Activity/Listener.php +++ b/lib/Activity/Listener.php @@ -26,6 +26,7 @@ namespace OCA\Talk\Activity; use OCA\Talk\Chat\ChatManager; use OCA\Talk\Events\AddParticipantsEvent; use OCA\Talk\Events\ModifyParticipantEvent; +use OCA\Talk\Events\ModifyRoomEvent; use OCA\Talk\Events\RoomEvent; use OCA\Talk\Model\Attendee; use OCA\Talk\Participant; @@ -80,6 +81,13 @@ class Listener { }; $dispatcher->addListener(Room::EVENT_AFTER_SESSION_JOIN_CALL, $listener); + $listener = static function (ModifyRoomEvent $event): void { + /** @var self $listener */ + $listener = \OC::$server->query(self::class); + $listener->generateCallActivity($event->getRoom(), true, $event->getActor()); + }; + $dispatcher->addListener(Room::EVENT_BEFORE_END_CALL_FOR_EVERYONE, $listener); + $listener = static function (RoomEvent $event): void { /** @var self $listener */ $listener = \OC::$server->query(self::class); @@ -110,11 +118,13 @@ class Listener { * Call activity: "You attended a call with {user1} and {user2}" * * @param Room $room + * @param bool $endForEveryone + * @param Participant|null $actor * @return bool True if activity was generated, false otherwise */ - public function generateCallActivity(Room $room): bool { + public function generateCallActivity(Room $room, bool $endForEveryone = false, ?Participant $actor = null): bool { $activeSince = $room->getActiveSince(); - if (!$activeSince instanceof \DateTime || $this->participantService->hasActiveSessionsInCall($room)) { + if (!$activeSince instanceof \DateTime || (!$endForEveryone && $this->participantService->hasActiveSessionsInCall($room))) { return false; } @@ -130,6 +140,8 @@ class Listener { return false; } $message = 'call_missed'; + } elseif ($endForEveryone) { + $message = 'call_ended_everyone'; } if (!$room->resetActiveSince()) { @@ -137,8 +149,13 @@ class Listener { return false; } - $actorId = $userIds[0] ?? 'guests-only'; - $actorType = $actorId !== 'guests-only' ? Attendee::ACTOR_USERS : Attendee::ACTOR_GUESTS; + if ($actor instanceof Participant) { + $actorId = $actor->getAttendee()->getActorId(); + $actorType = $actor->getAttendee()->getActorType(); + } else { + $actorId = $userIds[0] ?? 'guests-only'; + $actorType = $actorId !== 'guests-only' ? Attendee::ACTOR_USERS : Attendee::ACTOR_GUESTS; + } $this->chatManager->addSystemMessage($room, $actorType, $actorId, json_encode([ 'message' => $message, 'parameters' => [ diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php index 50a8d6a44..c29da3421 100644 --- a/lib/Chat/Parser/SystemMessage.php +++ b/lib/Chat/Parser/SystemMessage.php @@ -177,8 +177,8 @@ class SystemMessage { } } elseif ($message === 'call_missed') { [$parsedMessage, $parsedParameters, $message] = $this->parseMissedCall($room, $parameters, $currentActorId); - } elseif ($message === 'call_ended') { - [$parsedMessage, $parsedParameters] = $this->parseCall($parameters); + } elseif ($message === 'call_ended' || $message === 'call_ended_everyone') { + [$parsedMessage, $parsedParameters] = $this->parseCall($message, $parameters, $parsedParameters); } elseif ($message === 'read_only_off') { $parsedMessage = $this->l->t('{actor} unlocked the conversation'); if ($currentUserIsActor) { @@ -734,50 +734,103 @@ class SystemMessage { } - protected function parseCall(array $parameters): array { + protected function parseCall(string $message, array $parameters, array $params): array { + if ($message === 'call_ended_everyone') { + if ($params['actor']['type'] === 'user') { + $flipped = array_flip($parameters['users']); + unset($flipped[$params['actor']['id']]); + $parameters['users'] = array_flip($flipped); + } else { + $parameters['guests']--; + } + } sort($parameters['users']); $numUsers = \count($parameters['users']); $displayedUsers = $numUsers; switch ($numUsers) { case 0: - $subject = $this->l->n( - 'Call with %n guest (Duration {duration})', - 'Call with %n guests (Duration {duration})', - $parameters['guests'] - ); + if ($message === 'call_ended') { + $subject = $this->l->n( + 'Call with %n guest (Duration {duration})', + 'Call with %n guests (Duration {duration})', + $parameters['guests'] + ); + } else { + $subject = $this->l->n( + '{actor} ended the call with %n guest (Duration {duration})', + '{actor} ended the call with %n guests (Duration {duration})', + $parameters['guests'] + ); + } break; case 1: - $subject = $this->l->t('Call with {user1} and {user2} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1} and {user2} (Duration {duration})'); + } else { + if ($parameters['guests'] === 0) { + $subject = $this->l->t('{actor} ended the call with {user1} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1} and {user2} (Duration {duration})'); + } + } $subject = str_replace('{user2}', $this->l->n('%n guest', '%n guests', $parameters['guests']), $subject); break; case 2: if ($parameters['guests'] === 0) { - $subject = $this->l->t('Call with {user1} and {user2} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1} and {user2} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1} and {user2} (Duration {duration})'); + } } else { - $subject = $this->l->t('Call with {user1}, {user2} and {user3} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1}, {user2} and {user3} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1}, {user2} and {user3} (Duration {duration})'); + } $subject = str_replace('{user3}', $this->l->n('%n guest', '%n guests', $parameters['guests']), $subject); } break; case 3: if ($parameters['guests'] === 0) { - $subject = $this->l->t('Call with {user1}, {user2} and {user3} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1}, {user2} and {user3} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1}, {user2} and {user3} (Duration {duration})'); + } } else { - $subject = $this->l->t('Call with {user1}, {user2}, {user3} and {user4} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1}, {user2}, {user3} and {user4} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1}, {user2}, {user3} and {user4} (Duration {duration})'); + } $subject = str_replace('{user4}', $this->l->n('%n guest', '%n guests', $parameters['guests']), $subject); } break; case 4: if ($parameters['guests'] === 0) { - $subject = $this->l->t('Call with {user1}, {user2}, {user3} and {user4} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1}, {user2}, {user3} and {user4} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1}, {user2}, {user3} and {user4} (Duration {duration})'); + } } else { - $subject = $this->l->t('Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration {duration})'); + } $subject = str_replace('{user5}', $this->l->n('%n guest', '%n guests', $parameters['guests']), $subject); } break; case 5: default: - $subject = $this->l->t('Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration {duration})'); + if ($message === 'call_ended') { + $subject = $this->l->t('Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration {duration})'); + } else { + $subject = $this->l->t('{actor} ended the call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration {duration})'); + } if ($numUsers === 5 && $parameters['guests'] === 0) { $displayedUsers = 5; } else { @@ -787,7 +840,6 @@ class SystemMessage { } } - $params = []; if ($displayedUsers > 0) { for ($i = 1; $i <= $displayedUsers; $i++) { $params['user' . $i] = $this->getUser($parameters['users'][$i - 1]); diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index 31f5a4ba6..f8fbd7d48 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -27,6 +27,7 @@ use OCA\Talk\Chat\ChatManager; use OCA\Talk\Events\AddParticipantsEvent; use OCA\Talk\Events\AttendeesAddedEvent; use OCA\Talk\Events\AttendeesRemovedEvent; +use OCA\Talk\Events\ModifyEveryoneEvent; use OCA\Talk\Events\ModifyLobbyEvent; use OCA\Talk\Events\ModifyParticipantEvent; use OCA\Talk\Events\ModifyRoomEvent; @@ -96,6 +97,11 @@ class Listener implements IEventListener { } }); $dispatcher->addListener(Room::EVENT_AFTER_SESSION_LEAVE_CALL, static function (ModifyParticipantEvent $event) { + if ($event instanceof ModifyEveryoneEvent) { + // No individual system message if the call is ended for everyone + return; + } + $room = $event->getRoom(); $session = $event->getParticipant()->getSession(); diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index 17f89d416..9b4af7ec1 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -157,15 +157,20 @@ class CallController extends AEnvironmentAwareController { * @PublicPage * @RequireParticipant * + * @param bool $all whether to also terminate the call for all participants * @return DataResponse */ - public function leaveCall(): DataResponse { + public function leaveCall(bool $all = false): DataResponse { $session = $this->participant->getSession(); if (!$session instanceof Session) { return new DataResponse([], Http::STATUS_NOT_FOUND); } - $this->participantService->changeInCall($this->room, $this->participant, Participant::FLAG_DISCONNECTED); + if ($all && $this->participant->hasModeratorPermissions()) { + $this->participantService->endCallForEveryone($this->room, $this->participant); + } else { + $this->participantService->changeInCall($this->room, $this->participant, Participant::FLAG_DISCONNECTED); + } return new DataResponse(); } diff --git a/lib/Events/ModifyEveryoneEvent.php b/lib/Events/ModifyEveryoneEvent.php new file mode 100644 index 000000000..5bcbe1596 --- /dev/null +++ b/lib/Events/ModifyEveryoneEvent.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2021 Joas Schilling <coding@schilljs.com> + * + * @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 <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Talk\Events; + +class ModifyEveryoneEvent extends ModifyParticipantEvent { +} diff --git a/lib/Events/ModifyRoomEvent.php b/lib/Events/ModifyRoomEvent.php index 7925fdb56..caaca0699 100644 --- a/lib/Events/ModifyRoomEvent.php +++ b/lib/Events/ModifyRoomEvent.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace OCA\Talk\Events; +use OCA\Talk\Participant; use OCA\Talk\Room; class ModifyRoomEvent extends RoomEvent { @@ -33,21 +34,22 @@ class ModifyRoomEvent extends RoomEvent { protected $newValue; /** @var int|string|bool|null */ protected $oldValue; + /** @var Participant|null */ + protected $actor; public function __construct(Room $room, string $parameter, $newValue, - $oldValue = null) { + $oldValue = null, + ?Participant $actor = null) { parent::__construct($room); $this->parameter = $parameter; $this->newValue = $newValue; $this->oldValue = $oldValue; + $this->actor = $actor; } - /** - * @return string - */ public function getParameter(): string { return $this->parameter; } @@ -65,4 +67,8 @@ class ModifyRoomEvent extends RoomEvent { public function getOldValue() { return $this->oldValue; } + + public function getActor(): ?Participant { + return $this->actor; + } } diff --git a/lib/Room.php b/lib/Room.php index f79d7aabc..f3f03880a 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -114,6 +114,8 @@ class Room { 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_END_CALL_FOR_EVERYONE = self::class . '::preEndCallForEveryone'; + public const EVENT_AFTER_END_CALL_FOR_EVERYONE = self::class . '::postEndCallForEveryone'; public const EVENT_BEFORE_SIP_ENABLED_SET = self::class . '::preSetSIPEnabled'; public const EVENT_AFTER_SIP_ENABLED_SET = self::class . '::postSetSIPEnabled'; public const EVENT_BEFORE_PERMISSIONS_SET = self::class . '::preSetPermissions'; diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 1d83fd3c2..da15b56ed 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -32,7 +32,9 @@ use OCA\Talk\Events\AttendeesAddedEvent; use OCA\Talk\Events\AttendeesRemovedEvent; use OCA\Talk\Events\JoinRoomGuestEvent; use OCA\Talk\Events\JoinRoomUserEvent; +use OCA\Talk\Events\ModifyEveryoneEvent; use OCA\Talk\Events\ModifyParticipantEvent; +use OCA\Talk\Events\ModifyRoomEvent; use OCA\Talk\Events\ParticipantEvent; use OCA\Talk\Events\RemoveParticipantEvent; use OCA\Talk\Events\RemoveUserEvent; @@ -906,7 +908,21 @@ class ParticipantService { $this->dispatcher->dispatch(Room::EVENT_AFTER_GUESTS_CLEAN, $event); } - public function changeInCall(Room $room, Participant $participant, int $flags): void { + public function endCallForEveryone(Room $room, Participant $moderator): void { + $event = new ModifyRoomEvent($room, 'in_call', Participant::FLAG_DISCONNECTED, null, $moderator); + $this->dispatcher->dispatch(Room::EVENT_BEFORE_END_CALL_FOR_EVERYONE, $event); + + $participants = $this->getParticipantsInCall |