summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <213943+nickvergessen@users.noreply.github.com>2021-11-03 14:37:30 +0100
committerGitHub <noreply@github.com>2021-11-03 14:37:30 +0100
commit3b3fc8b25ae3af36129dca21134ad96285b826b8 (patch)
tree89a4e35b6b03f7a20cb9ff2effa2e0514550f6ff
parent2819892f317609a4a5fee86692e7ffa007a11730 (diff)
parent1e1cd5e25f785c32f33fc8af63b9d887d9d2a408 (diff)
Merge pull request #5981 from nextcloud/enh/5395/end-meeting-for-all
📅 End meeting for all
-rw-r--r--docs/chat.md1
-rw-r--r--lib/Activity/Listener.php25
-rw-r--r--lib/Chat/Parser/SystemMessage.php86
-rw-r--r--lib/Chat/SystemMessage/Listener.php6
-rw-r--r--lib/Controller/CallController.php9
-rw-r--r--lib/Events/ModifyEveryoneEvent.php27
-rw-r--r--lib/Events/ModifyRoomEvent.php14
-rw-r--r--lib/Room.php2
-rw-r--r--lib/Service/ParticipantService.php25
-rw-r--r--src/components/TopBar/CallButton.vue121
-rw-r--r--src/services/callsService.js5
-rw-r--r--src/store/participantsStore.js4
-rw-r--r--src/store/participantsStore.spec.js2
-rw-r--r--src/utils/signaling.js12
-rw-r--r--src/utils/webrtc/index.js5
-rw-r--r--src/utils/webrtc/webrtc.js36
-rw-r--r--tests/php/Chat/Parser/SystemMessageTest.php150
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