fix(calls): Make starting a call an explicit event

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2024-07-31 15:34:45 +02:00
parent 12d062fe21
commit 1c673cd896
No known key found for this signature in database
GPG key ID: 74434EFE0D2E2205
15 changed files with 123 additions and 146 deletions

View file

@ -34,6 +34,14 @@ See the general [Nextcloud Developers - Events](https://docs.nextcloud.com/serve
* After event: `OCA\Talk\Events\LobbyModifiedEvent`
* Since: 18.0.0
### Call started
* Before event: `OCA\Talk\Events\BeforeCallStartedEvent`
* After event: `OCA\Talk\Events\CallStartedEvent`
The after event might be skipped if the request lost the race to update the database.
A parallel request will have triggered the before and after events in the meantime.
* Since: 20.0.0
### Call ended for everyone
* Before event: `OCA\Talk\Events\BeforeCallEndedForEveryoneEvent`
@ -47,12 +55,6 @@ Allows to verify a password and set a redirect URL for the invalid case
* Event: `OCA\Talk\Events\RoomPasswordVerifyEvent`
* Since: 18.0.0
### Active since modified
* Before event: `OCA\Talk\Events\BeforeActiveSinceModifiedEvent`
* After event: `OCA\Talk\Events\ActiveSinceModifiedEvent`
* Since: 20.0.0
## Participant related events
### Attendees added

View file

@ -61,24 +61,6 @@ class Listener implements IEventListener {
};
}
protected function setActive(ParticipantModifiedEvent $event): void {
if ($event->getProperty() !== AParticipantModifiedEvent::PROPERTY_IN_CALL) {
return;
}
if ($event->getOldValue() !== Participant::FLAG_DISCONNECTED
|| $event->getNewValue() === Participant::FLAG_DISCONNECTED) {
return;
}
$participant = $event->getParticipant();
$this->roomService->setActiveSince(
$event->getRoom(),
$this->timeFactory->getDateTime(),
$participant->getSession() ? $participant->getSession()->getInCall() : Participant::FLAG_DISCONNECTED
);
}
protected function handleParticipantModified(ParticipantModifiedEvent $event): void {
if ($event->getProperty() !== AParticipantModifiedEvent::PROPERTY_IN_CALL) {
return;
@ -86,7 +68,6 @@ class Listener implements IEventListener {
if ($event->getOldValue() === Participant::FLAG_DISCONNECTED
|| $event->getNewValue() !== Participant::FLAG_DISCONNECTED) {
$this->setActive($event);
return;
}

View file

@ -30,7 +30,8 @@ use OCA\Talk\Collaboration\Resources\Listener as ResourceListener;
use OCA\Talk\Config;
use OCA\Talk\Dashboard\TalkWidget;
use OCA\Talk\Deck\DeckPluginLoader;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\BeforeCallStartedEvent;
use OCA\Talk\Events\CallStartedEvent;
use OCA\Talk\Events\AttendeeRemovedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
@ -246,8 +247,8 @@ class Application extends App implements IBootstrap {
// Notification listeners
$context->registerEventListener(AttendeesAddedEvent::class, NotificationListener::class);
$context->registerEventListener(ActiveSinceModifiedEvent::class, NotificationListener::class);
$context->registerEventListener(BeforeParticipantModifiedEvent::class, NotificationListener::class);
$context->registerEventListener(BeforeCallStartedEvent::class, NotificationListener::class);
$context->registerEventListener(CallStartedEvent::class, NotificationListener::class);
$context->registerEventListener(CallNotificationSendEvent::class, NotificationListener::class);
$context->registerEventListener(ParticipantModifiedEvent::class, NotificationListener::class);
$context->registerEventListener(UserJoinedRoomEvent::class, NotificationListener::class);
@ -265,7 +266,7 @@ class Application extends App implements IBootstrap {
// Federation listeners
$context->registerEventListener(BeforeRoomDeletedEvent::class, TalkV1BeforeRoomDeletedListener::class);
$context->registerEventListener(ActiveSinceModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(CallStartedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(LobbyModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(RoomModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(ChatMessageSentEvent::class, TalkV1MessageSentListener::class);

View file

@ -163,10 +163,11 @@ class CallController extends AEnvironmentAwareController {
$this->roomService->setPermissions($this->room, 'call', Attendee::PERMISSIONS_MODIFY_SET, $forcePermissions, true);
}
$joined = $this->participantService->changeInCall($this->room, $this->participant, $flags, false, $silent);
if (!$joined) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
try {
$this->participantService->changeInCall($this->room, $this->participant, $flags, silent: $silent);
$this->roomService->setActiveSince($this->room, $this->participant, $this->timeFactory->getDateTime(), $flags, silent: $silent);
} catch (\InvalidArgumentException $e) {
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
return new DataResponse();
}
@ -226,8 +227,10 @@ class CallController extends AEnvironmentAwareController {
return new DataResponse(['error' => 'consent'], Http::STATUS_BAD_REQUEST);
}
$joined = $this->participantService->changeInCall($this->room, $this->participant, $flags, false, $silent);
if (!$joined) {
try {
$this->participantService->changeInCall($this->room, $this->participant, $flags, false, $silent);
$this->roomService->setActiveSince($this->room, $this->participant, $this->timeFactory->getDateTime(), $flags, silent: $silent);
} catch (\InvalidArgumentException $e) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}

View file

@ -8,21 +8,26 @@ declare(strict_types=1);
namespace OCA\Talk\Events;
use OCA\Talk\Participant;
use OCA\Talk\Room;
abstract class AActiveSinceModifiedEvent extends ARoomModifiedEvent {
abstract class ACallStartedEvent extends ARoomModifiedEvent {
/**
* @param array<AParticipantModifiedEvent::DETAIL_*, bool> $details
*/
public function __construct(
Room $room,
?\DateTime $newValue,
?\DateTime $oldValue,
protected int $callFlag,
protected int $oldCallFlag,
protected array $details,
?Participant $actor,
) {
parent::__construct(
$room,
self::PROPERTY_ACTIVE_SINCE,
$newValue,
$oldValue,
null,
$actor,
);
}
@ -30,7 +35,10 @@ abstract class AActiveSinceModifiedEvent extends ARoomModifiedEvent {
return $this->callFlag;
}
public function getOldCallFlag(): int {
return $this->oldCallFlag;
/**
* @param AParticipantModifiedEvent::DETAIL_* $detail
*/
public function getDetail(string $detail): ?bool {
return $this->details[$detail] ?? null;
}
}

View file

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Events;
use OCA\Talk\Room;
class ActiveSinceModifiedEvent extends AActiveSinceModifiedEvent {
public function __construct(
Room $room,
?\DateTime $newValue,
?\DateTime $oldValue,
int $callFlag,
int $oldCallFlag,
protected bool $updatedActiveSince,
) {
parent::__construct(
$room,
$newValue,
$oldValue,
$callFlag,
$oldCallFlag,
);
}
public function hasUpdatedActiveSince(): bool {
return $this->updatedActiveSince;
}
}

View file

@ -8,5 +8,5 @@ declare(strict_types=1);
namespace OCA\Talk\Events;
class BeforeActiveSinceModifiedEvent extends AActiveSinceModifiedEvent {
class BeforeCallStartedEvent extends ACallStartedEvent {
}

View file

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Events;
class CallStartedEvent extends ACallStartedEvent {
}

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace OCA\Talk\Federation;
use OCA\FederatedFileSharing\AddressHandler;
use OCA\Talk\Events\ACallStartedEvent;
use OCA\Talk\Exceptions\RoomHasNoModeratorException;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\RetryNotification;
@ -243,27 +244,22 @@ class BackendNotifier {
/**
* Send information to remote participants that "active since" was updated
* Sent from Host server to Remote participant server
*
* @psalm-param array<AParticipantModifiedEvent::DETAIL_*, bool> $details
*/
public function sendRoomModifiedActiveSinceUpdate(
public function sendCallStarted(
string $remoteServer,
int $localAttendeeId,
#[SensitiveParameter]
string $accessToken,
string $localToken,
string $changedProperty,
?\DateTime $newValue,
?\DateTime $oldValue,
\DateTime $activeSince,
int $callFlag,
array $details,
): ?bool {
$remote = $this->prepareRemoteUrl($remoteServer);
if ($newValue instanceof \DateTime) {
$newValue = (string) $newValue->getTimestamp();
}
if ($oldValue instanceof \DateTime) {
$oldValue = (string) $oldValue->getTimestamp();
}
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
$notification->setMessage(
FederationManager::NOTIFICATION_ROOM_MODIFIED,
@ -274,9 +270,10 @@ class BackendNotifier {
'sharedSecret' => $accessToken,
'remoteToken' => $localToken,
'changedProperty' => $changedProperty,
'newValue' => $newValue,
'oldValue' => $oldValue,
'newValue' => $activeSince->getTimestamp(),
'oldValue' => null,
'callFlag' => $callFlag,
'details' => $details,
],
);

View file

@ -14,6 +14,7 @@ use OCA\Talk\AppInfo\Application;
use OCA\Talk\CachePrefix;
use OCA\Talk\Config;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Exceptions\CannotReachRemoteException;
@ -288,7 +289,7 @@ class CloudFederationProviderTalk implements ICloudFederationProvider {
/**
* @param int $remoteAttendeeId
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, changedProperty: string, newValue: string|int|bool|null, oldValue: string|int|bool|null, callFlag?: int, dateTime?: string, timerReached?: bool} $notification
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, changedProperty: string, newValue: string|int|bool|null, oldValue: string|int|bool|null, callFlag?: int, dateTime?: string, timerReached?: bool, details?: array<AParticipantModifiedEvent::DETAIL_*, bool>} $notification
* @return array
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
@ -311,15 +312,15 @@ class CloudFederationProviderTalk implements ICloudFederationProvider {
if ($notification['newValue'] === null) {
$this->roomService->resetActiveSince($room);
} else {
$activeSince = \DateTime::createFromFormat('U', $notification['newValue']);
$this->roomService->setActiveSince($room, $activeSince, $notification['callFlag']);
$activeSince = $this->timeFactory->getDateTime('@' . $notification['newValue']);
$this->roomService->setActiveSince($room, null, $activeSince, $notification['callFlag'], !empty($notification['details'][AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT]));
}
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_AVATAR) {
$this->roomService->setAvatar($room, $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_DESCRIPTION) {
$this->roomService->setDescription($room, $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_IN_CALL) {
$this->roomService->setActiveSince($room, $room->getActiveSince(), $notification['newValue']);
$this->roomService->setActiveSince($room, null, $room->getActiveSince(), $notification['newValue'], true);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_LOBBY) {
$dateTime = !empty($notification['dateTime']) ? \DateTime::createFromFormat('U', $notification['dateTime']) : null;
$this->roomService->setLobby($room, $notification['newValue'], $dateTime, $notification['timerReached'] ?? false);

View file

@ -40,7 +40,7 @@ class CallController {
* @psalm-param int-mask-of<Participant::FLAG_*> $flags
* @param bool $silent Join the call silently
* @param bool $recordingConsent Agreement to be recorded
* @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, array<empty>, array{}>
* @return DataResponse<Http::STATUS_OK|Http::STATUS_NOT_FOUND, array<empty>, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error?: string}, array{}>
* @throws CannotReachRemoteException
*
* 200: Federated user is now in the call

View file

@ -10,9 +10,12 @@ namespace OCA\Talk\Federation\Proxy\TalkV1\Notifier;
use OCA\Talk\Events\AActiveSinceModifiedEvent;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\ALobbyModifiedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\CallEndedEvent;
use OCA\Talk\Events\CallEndedForEveryoneEvent;
use OCA\Talk\Events\CallStartedEvent;
use OCA\Talk\Events\LobbyModifiedEvent;
use OCA\Talk\Events\RoomModifiedEvent;
use OCA\Talk\Federation\BackendNotifier;
@ -36,7 +39,7 @@ class RoomModifiedListener implements IEventListener {
}
public function handle(Event $event): void {
if (!$event instanceof ActiveSinceModifiedEvent
if (!$event instanceof CallStartedEvent
&& !$event instanceof LobbyModifiedEvent
&& !$event instanceof RoomModifiedEvent) {
return;
@ -60,8 +63,8 @@ class RoomModifiedListener implements IEventListener {
foreach ($participants as $participant) {
$cloudId = $this->cloudIdManager->resolveCloudId($participant->getAttendee()->getActorId());
if ($event instanceof AActiveSinceModifiedEvent) {
$success = $this->notifyActiveSinceModified($cloudId, $participant, $event);
if ($event instanceof CallStartedEvent) {
$success = $this->notifyCallStarted($cloudId, $participant, $event);
} elseif ($event instanceof ALobbyModifiedEvent) {
$success = $this->notifyLobbyModified($cloudId, $participant, $event);
} else {
@ -74,16 +77,21 @@ class RoomModifiedListener implements IEventListener {
}
}
private function notifyActiveSinceModified(ICloudId $cloudId, Participant $participant, AActiveSinceModifiedEvent $event) {
return $this->backendNotifier->sendRoomModifiedActiveSinceUpdate(
private function notifyCallStarted(ICloudId $cloudId, Participant $participant, CallStartedEvent $event) {
$details = [];
if ($event->getDetail(AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT)) {
$details = [AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT => true];
}
return $this->backendNotifier->sendCallStarted(
$cloudId->getRemote(),
$participant->getAttendee()->getId(),
$participant->getAttendee()->getAccessToken(),
$event->getRoom()->getToken(),
$event->getProperty(),
$event->getNewValue(),
$event->getOldValue(),
$event->getCallFlag(),
$details,
);
}

View file

@ -10,7 +10,8 @@ namespace OCA\Talk\Notification;
use OCA\Talk\AppInfo\Application;
use OCA\Talk\Controller\ChatController;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\BeforeCallStartedEvent;
use OCA\Talk\Events\CallStartedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\BeforeParticipantModifiedEvent;
@ -60,9 +61,9 @@ class Listener implements IEventListener {
CallNotificationSendEvent::class => $this->sendCallNotification($event->getRoom(), $event->getActor()->getAttendee(), $event->getTarget()->getAttendee()),
AttendeesAddedEvent::class => $this->generateInvitation($event->getRoom(), $event->getAttendees()),
UserJoinedRoomEvent::class => $this->handleUserJoinedRoomEvent($event),
BeforeParticipantModifiedEvent::class => $this->checkCallNotifications($event),
BeforeCallStartedEvent::class => $this->checkCallNotifications($event),
ParticipantModifiedEvent::class => $this->afterParticipantJoinedCall($event),
ActiveSinceModifiedEvent::class => $this->afterActiveSinceModified($event),
CallStartedEvent::class => $this->afterCallStarted($event),
};
}
@ -178,29 +179,13 @@ class Listener implements IEventListener {
/**
* Call notification: "{user} wants to talk with you"
*/
protected function checkCallNotifications(BeforeParticipantModifiedEvent $event): void {
if ($event->getProperty() !== AParticipantModifiedEvent::PROPERTY_IN_CALL) {
return;
}
if ($event->getOldValue() !== Participant::FLAG_DISCONNECTED
|| $event->getNewValue() === Participant::FLAG_DISCONNECTED) {
return;
}
protected function checkCallNotifications(BeforeCallStartedEvent $event): void {
if ($event->getDetail(AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT)) {
$this->shouldSendCallNotification = false;
return;
}
$room = $event->getRoom();
if ($room->getActiveSince() instanceof \DateTime) {
// Call already active => No new notifications
$this->shouldSendCallNotification = false;
return;
}
if ($room->getObjectType() === Room::OBJECT_TYPE_FILE) {
if ($event->getRoom()->getObjectType() === Room::OBJECT_TYPE_FILE) {
$this->shouldSendCallNotification = false;
return;
}
@ -218,22 +203,18 @@ class Listener implements IEventListener {
return;
}
// Purge received call notifications on joining
$this->markCallNotificationsRead($event->getRoom());
if ($this->shouldSendCallNotification) {
$this->sendCallNotifications($event->getRoom());
}
}
protected function afterActiveSinceModified(ActiveSinceModifiedEvent $event): void {
if (!$event->hasUpdatedActiveSince()) {
protected function afterCallStarted(CallStartedEvent $event): void {
if ($event->getDetail(AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT)) {
return;
}
if (!$event->getRoom()->isFederatedConversation()) {
return;
if ($this->shouldSendCallNotification || $event->getRoom()->isFederatedConversation()) {
$this->sendCallNotifications($event->getRoom());
}
$this->sendCallNotifications($event->getRoom());
}
/**

View file

@ -1103,7 +1103,7 @@ class ParticipantService {
$changedSessionIds = [];
$changedUserIds = [];
// kick out all participants out of the call
// kick all participants out of the call
foreach ($participants as $participant) {
$changedSessionIds[] = $participant->getSession()->getSessionId();
if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
@ -1118,16 +1118,20 @@ class ParticipantService {
$this->dispatcher->dispatchTyped($event);
}
public function changeInCall(Room $room, Participant $participant, int $flags, bool $endCallForEveryone = false, bool $silent = false): bool {
/**
* @psalm-param int-mask-of<Participant::FLAG_*> $flags
* @throws \InvalidArgumentException
*/
public function changeInCall(Room $room, Participant $participant, int $flags, bool $endCallForEveryone = false, bool $silent = false): void {
if ($room->getType() === Room::TYPE_CHANGELOG
|| $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER
|| $room->getType() === Room::TYPE_NOTE_TO_SELF) {
return false;
throw new \InvalidArgumentException('type');
}
$session = $participant->getSession();
if (!$session instanceof Session) {
return false;
throw new \InvalidArgumentException('session');
}
$permissions = $participant->getPermissions();
@ -1166,8 +1170,6 @@ class ParticipantService {
$event = new ParticipantModifiedEvent($room, $participant, AParticipantModifiedEvent::PROPERTY_IN_CALL, $flags, $oldFlags, $details);
$this->dispatcher->dispatchTyped($event);
return true;
}
/**
@ -1295,6 +1297,8 @@ class ParticipantService {
$session->setInCall($flags);
$this->sessionMapper->update($session);
// FIXME Missing potential update of call flags on room level
$event = new ParticipantModifiedEvent($room, $participant, AParticipantModifiedEvent::PROPERTY_IN_CALL, $flags, $oldFlags);
$this->dispatcher->dispatchTyped($event);
}

View file

@ -10,9 +10,10 @@ namespace OCA\Talk\Service;
use InvalidArgumentException;
use OCA\Talk\Config;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\BeforeCallStartedEvent;
use OCA\Talk\Events\CallStartedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\BeforeActiveSinceModifiedEvent;
use OCA\Talk\Events\BeforeLobbyModifiedEvent;
use OCA\Talk\Events\BeforeRoomDeletedEvent;
use OCA\Talk\Events\BeforeRoomModifiedEvent;
@ -841,7 +842,7 @@ class RoomService {
return false;
}
$event = new BeforeActiveSinceModifiedEvent($room, null, $oldActiveSince, Participant::FLAG_DISCONNECTED, $oldCallFlag);
$event = new BeforeCallStartedEvent($room, null, $oldActiveSince, Participant::FLAG_DISCONNECTED, $oldCallFlag);
$this->dispatcher->dispatchTyped($event);
$update = $this->db->getQueryBuilder();
@ -856,25 +857,31 @@ class RoomService {
$result = (bool) $update->executeStatement();
$event = new ActiveSinceModifiedEvent($room, null, $oldActiveSince, Participant::FLAG_DISCONNECTED, $oldCallFlag, $result);
$event = new CallStartedEvent($room, null, $oldActiveSince, Participant::FLAG_DISCONNECTED, $oldCallFlag, $result);
$this->dispatcher->dispatchTyped($event);
return $result;
}
public function setActiveSince(Room $room, \DateTime $since, int $callFlag): bool {
$oldActiveSince = $room->getActiveSince();
public function setActiveSince(Room $room, ?Participant $participant, \DateTime $since, int $callFlag, bool $silent): bool {
$oldCallFlag = $room->getCallFlag();
$callFlag |= $oldCallFlag; // Merge the callFlags, so events and response are with the best values
if ($room->getActiveSince() instanceof \DateTime && $oldCallFlag === $callFlag) {
// Call flags of the conversation are unchanged and it's already marked active
return false;
}
if ($room->getActiveSince() instanceof \DateTime) {
$event = new BeforeRoomModifiedEvent($room, ARoomModifiedEvent::PROPERTY_IN_CALL, $callFlag, $oldCallFlag);
// Call is already active, just someone upgrading the call flags
$event = new BeforeRoomModifiedEvent($room, ARoomModifiedEvent::PROPERTY_IN_CALL, $callFlag, $oldCallFlag, $participant);
$this->dispatcher->dispatchTyped($event);
} else {
$event = new BeforeActiveSinceModifiedEvent($room, $since, $oldActiveSince, $callFlag, $oldCallFlag);
$details = [];
if ($silent) {
$details[AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT] = true;
}
$event = new BeforeCallStartedEvent($room, $since, $callFlag, $details, $participant);
$this->dispatcher->dispatchTyped($event);
}
@ -888,6 +895,7 @@ class RoomService {
$update->executeStatement();
if ($room->getActiveSince() instanceof \DateTime) {
// Call is already active, just someone upgrading the call flags
$room->setActiveSince($room->getActiveSince(), $callFlag);
$event = new RoomModifiedEvent($room, ARoomModifiedEvent::PROPERTY_IN_CALL, $callFlag, $oldCallFlag);
@ -905,10 +913,15 @@ class RoomService {
$room->setActiveSince($since, $callFlag);
$event = new ActiveSinceModifiedEvent($room, $since, $oldActiveSince, $callFlag, $oldCallFlag, $result);
if (!$result) {
// Lost the race, someone else updated the database
return false;
}
$event = new CallStartedEvent($room, $since, $callFlag, $details, $participant);
$this->dispatcher->dispatchTyped($event);
return $result;
return true;
}
public function setLastMessage(Room $room, IComment $message): void {