UPSTREAM BASELINE: nextcloud/spreed v22.0.12 (без изменений)
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
Источник: https://github.com/nextcloud/spreed/archive/refs/tags/v22.0.12.tar.gz С этого коммита ветка официального Nextcloud Talk отрезана (решение владельца 2026-07-06). Все дальнейшие изменения — только наши; версии релизов: 22.0.12-f7.N.
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Dashboard;
|
||||
|
||||
use OCA\Talk\ResponseDefinitions;
|
||||
|
||||
/**
|
||||
* @psalm-import-type TalkDashboardEvent from ResponseDefinitions
|
||||
* @psalm-import-type TalkDashboardEventCalendar from ResponseDefinitions
|
||||
* @psalm-import-type TalkDashboardEventAttachment from ResponseDefinitions
|
||||
*/
|
||||
class Event implements \JsonSerializable {
|
||||
/** @var non-empty-list<TalkDashboardEventCalendar> */
|
||||
protected array $calendars = [];
|
||||
protected string $eventName = '';
|
||||
protected string $eventLink = '';
|
||||
protected int $start = 0;
|
||||
protected int $end = 0;
|
||||
protected string $roomToken = '';
|
||||
protected string $roomAvatarVersion = '';
|
||||
protected string $roomName = '';
|
||||
protected string $roomDisplayName = '';
|
||||
protected int $roomType = 0;
|
||||
protected ?string $eventDescription = null;
|
||||
/** @var array<string, TalkDashboardEventAttachment> */
|
||||
protected array $eventAttachments = [];
|
||||
protected ?int $roomActiveSince = null;
|
||||
protected ?int $accepted = null;
|
||||
protected ?int $tentative = null;
|
||||
protected ?int $declined = null;
|
||||
protected ?int $invited = null;
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-list<TalkDashboardEventCalendar>
|
||||
*/
|
||||
public function getCalendars(): array {
|
||||
return $this->calendars;
|
||||
}
|
||||
|
||||
public function getEventName(): string {
|
||||
return $this->eventName;
|
||||
}
|
||||
|
||||
public function setEventName(string $eventName): void {
|
||||
$this->eventName = $eventName;
|
||||
}
|
||||
|
||||
public function getEventDescription(): ?string {
|
||||
return $this->eventDescription;
|
||||
}
|
||||
|
||||
public function setEventDescription(?string $eventDescription): void {
|
||||
$this->eventDescription = $eventDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, TalkDashboardEventAttachment>
|
||||
*/
|
||||
public function getEventAttachments(): array {
|
||||
return $this->eventAttachments;
|
||||
}
|
||||
|
||||
public function setEventLink(string $eventLink): void {
|
||||
$this->eventLink = $eventLink;
|
||||
}
|
||||
|
||||
public function getStart(): int {
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
public function setStart(int $start): void {
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
public function getEnd(): int {
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
public function setEnd(int $end): void {
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
public function setRoomToken(string $roomToken): void {
|
||||
$this->roomToken = $roomToken;
|
||||
}
|
||||
|
||||
public function setRoomAvatarVersion(string $roomAvatarVersion): void {
|
||||
$this->roomAvatarVersion = $roomAvatarVersion;
|
||||
}
|
||||
|
||||
public function setRoomName(string $roomName): void {
|
||||
$this->roomName = $roomName;
|
||||
}
|
||||
|
||||
public function setRoomDisplayName(string $roomDisplayName): void {
|
||||
$this->roomDisplayName = $roomDisplayName;
|
||||
}
|
||||
|
||||
public function setRoomType(int $roomType): void {
|
||||
$this->roomType = $roomType;
|
||||
}
|
||||
|
||||
public function setRoomActiveSince(?int $roomActiveSince): void {
|
||||
$this->roomActiveSince = $roomActiveSince;
|
||||
}
|
||||
|
||||
public function generateAttendance(array $attendees): void {
|
||||
foreach ($attendees as $attendee) {
|
||||
if (!isset($attendee[1]['PARTSTAT'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($attendee[1]['PARTSTAT']->getValue()) {
|
||||
case 'ACCEPTED':
|
||||
(int)$this->accepted++;
|
||||
break;
|
||||
case 'TENTATIVE':
|
||||
(int)$this->tentative++;
|
||||
break;
|
||||
case 'DECLINED':
|
||||
(int)$this->declined++;
|
||||
break;
|
||||
case 'NEEDS-ACTION':
|
||||
(int)$this->invited++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isAttendee(array $attendees, string $email): bool {
|
||||
foreach ($attendees as $attendee) {
|
||||
if (!isset($attendee[1]['PARTSTAT'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calendar emails start with 'mailto:'
|
||||
if (substr($attendee[0], 7) === $email) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function isOrganizer(array $organizer, string $email): bool {
|
||||
// Calendar emails start with 'mailto:'
|
||||
return substr($organizer[0], 7) === $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the room token, start and end time and attendees to build an identifier
|
||||
* If the identifier already exists, another event is happening at the same time
|
||||
* in the same room
|
||||
*
|
||||
* We only return duplicates if the attendees are different
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateEventIdentifier(): string {
|
||||
return $this->roomToken . '#' . $this->start . '#' . $this->end . '#' . (int)$this->accepted . '#' . (int)$this->tentative . '#' . (int)$this->declined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $calendarName
|
||||
* @param array $attachments
|
||||
* @return void
|
||||
*/
|
||||
public function handleCalendarAttachments(string $calendarName, array $attachments): void {
|
||||
foreach ($attachments as $attachment) {
|
||||
$params = $attachment[1];
|
||||
if (!isset($params['X-NC-FILE-ID'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->eventAttachments[$attachment[0]] = [
|
||||
'calendars' => [$calendarName],
|
||||
'fmttype' => $params['FMTTYPE']?->getValue() ?? '',
|
||||
'filename' => $params['FILENAME']?->getValue() ?? '',
|
||||
'fileid' => $params['X-NC-FILE-ID']->getValue(),
|
||||
'preview' => $params['X-NC-HAS-PREVIEW']?->getValue() ?? false,
|
||||
'previewLink' => $params['X-NC-HAS-PREVIEW']?->getValue() ? $attachment[0] : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $principalUri
|
||||
* @param string $calendarName
|
||||
* @param string|null $calendarColor
|
||||
* @return void
|
||||
*/
|
||||
public function addCalendar(string $principalUri, string $calendarName, ?string $calendarColor): void {
|
||||
$this->calendars[] = [
|
||||
'principalUri' => $principalUri,
|
||||
'calendarName' => $calendarName,
|
||||
'calendarColor' => $calendarColor,
|
||||
];
|
||||
}
|
||||
|
||||
public function mergeAttachments(self $event): void {
|
||||
$attachments = $event->getEventAttachments();
|
||||
|
||||
if (empty($attachments) === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($this->eventAttachments) === true) {
|
||||
$this->eventAttachments = $attachments;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($attachments as $filename => $attachment) {
|
||||
if (isset($this->eventAttachments[$filename])) {
|
||||
$this->eventAttachments[$filename]['calendars']
|
||||
= array_merge($this->eventAttachments[$filename]['calendars'], $attachment['calendars']);
|
||||
} else {
|
||||
$this->eventAttachments[$filename] = $attachment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getEventLink(): string {
|
||||
return $this->eventLink;
|
||||
}
|
||||
|
||||
public function getRoomToken(): string {
|
||||
return $this->roomToken;
|
||||
}
|
||||
|
||||
public function getRoomAvatarVersion(): string {
|
||||
return $this->roomAvatarVersion;
|
||||
}
|
||||
|
||||
public function getRoomName(): string {
|
||||
return $this->roomName;
|
||||
}
|
||||
|
||||
public function getRoomDisplayName(): string {
|
||||
return $this->roomDisplayName;
|
||||
}
|
||||
|
||||
public function getRoomType(): int {
|
||||
return $this->roomType;
|
||||
}
|
||||
|
||||
public function getRoomActiveSince(): ?int {
|
||||
return $this->roomActiveSince;
|
||||
}
|
||||
|
||||
public function getAccepted(): ?int {
|
||||
return $this->accepted;
|
||||
}
|
||||
|
||||
public function getTentative(): ?int {
|
||||
return $this->tentative;
|
||||
}
|
||||
|
||||
public function getDeclined(): ?int {
|
||||
return $this->declined;
|
||||
}
|
||||
|
||||
public function getInvited(): ?int {
|
||||
return $this->invited;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TalkDashboardEvent
|
||||
*/
|
||||
#[\Override]
|
||||
public function jsonSerialize(): array {
|
||||
return [
|
||||
'calendars' => $this->getCalendars(),
|
||||
'eventName' => $this->getEventName(),
|
||||
'eventLink' => $this->getEventLink(),
|
||||
'start' => $this->getStart(),
|
||||
'end' => $this->getEnd(),
|
||||
'roomToken' => $this->getRoomToken(),
|
||||
'roomAvatarVersion' => $this->getRoomAvatarVersion(),
|
||||
'roomName' => $this->getRoomName(),
|
||||
'roomDisplayName' => $this->getRoomDisplayName(),
|
||||
'roomType' => $this->getRoomType(),
|
||||
'eventDescription' => $this->getEventDescription(),
|
||||
'eventAttachments' => $this->getEventAttachments(),
|
||||
'roomActiveSince' => $this->getRoomActiveSince(),
|
||||
'accepted' => $this->getAccepted(),
|
||||
'tentative' => $this->getTentative(),
|
||||
'declined' => $this->getDeclined(),
|
||||
'invited' => $this->getInvited(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Dashboard;
|
||||
|
||||
use OCA\Talk\Chat\ChatManager;
|
||||
use OCA\Talk\Chat\MessageParser;
|
||||
use OCA\Talk\Config;
|
||||
use OCA\Talk\Events\BeforeRoomsFetchEvent;
|
||||
use OCA\Talk\Manager;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Model\BreakoutRoom;
|
||||
use OCA\Talk\Model\Message;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\AvatarService;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCA\Talk\Service\ProxyCacheMessageService;
|
||||
use OCA\Talk\Webinary;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Dashboard\IAPIWidget;
|
||||
use OCP\Dashboard\IButtonWidget;
|
||||
use OCP\Dashboard\IConditionalWidget;
|
||||
use OCP\Dashboard\IIconWidget;
|
||||
use OCP\Dashboard\IOptionWidget;
|
||||
use OCP\Dashboard\IReloadableWidget;
|
||||
use OCP\Dashboard\Model\WidgetButton;
|
||||
use OCP\Dashboard\Model\WidgetItem;
|
||||
use OCP\Dashboard\Model\WidgetItems;
|
||||
use OCP\Dashboard\Model\WidgetOptions;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Util;
|
||||
|
||||
class TalkWidget implements IAPIWidget, IIconWidget, IButtonWidget, IOptionWidget, IConditionalWidget, IReloadableWidget {
|
||||
|
||||
public function __construct(
|
||||
protected IUserSession $userSession,
|
||||
protected Config $talkConfig,
|
||||
protected IURLGenerator $url,
|
||||
protected IL10N $l10n,
|
||||
protected Manager $manager,
|
||||
protected AvatarService $avatarService,
|
||||
protected ParticipantService $participantService,
|
||||
protected MessageParser $messageParser,
|
||||
protected ChatManager $chatManager,
|
||||
protected ProxyCacheMessageService $pcmService,
|
||||
protected IEventDispatcher $dispatcher,
|
||||
protected ITimeFactory $timeFactory,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getId(): string {
|
||||
return 'spreed';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getTitle(): string {
|
||||
return $this->l10n->t('Talk mentions');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getOrder(): int {
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getIconClass(): string {
|
||||
return 'dashboard-talk-icon';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function isEnabled(): bool {
|
||||
$user = $this->userSession->getUser();
|
||||
return !($user instanceof IUser && $this->talkConfig->isDisabledForUser($user));
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function getWidgetOptions(): WidgetOptions {
|
||||
return new WidgetOptions(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<WidgetButton>
|
||||
*/
|
||||
#[\Override]
|
||||
public function getWidgetButtons(string $userId): array {
|
||||
$buttons = [];
|
||||
$buttons[] = new WidgetButton(
|
||||
WidgetButton::TYPE_MORE,
|
||||
$this->url->linkToRouteAbsolute('spreed.Page.index'),
|
||||
$this->l10n->t('More conversations')
|
||||
);
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getIconUrl(): string {
|
||||
return $this->url->getAbsoluteURL($this->url->imagePath('spreed', 'app-dark.svg'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getUrl(): ?string {
|
||||
return $this->url->linkToRouteAbsolute('spreed.Page.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function load(): void {
|
||||
Util::addStyle('spreed', 'talk-icons');
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function getItems(string $userId, ?string $since = null, int $limit = 7): array {
|
||||
$event = new BeforeRoomsFetchEvent($userId);
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
|
||||
$rooms = $this->manager->getRoomsForUser($userId, [], true);
|
||||
|
||||
$rooms = array_filter($rooms, function (Room $room) use ($userId) {
|
||||
if ($room->getObjectType() === BreakoutRoom::PARENT_OBJECT_TYPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$participant = $this->participantService->getParticipant($room, $userId);
|
||||
$attendee = $participant->getAttendee();
|
||||
|
||||
if ($room->getLobbyState() !== Webinary::LOBBY_NONE
|
||||
&& !($participant->getPermissions() & Attendee::PERMISSIONS_LOBBY_IGNORE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$attendee->isArchived() && $room->getCallFlag() !== Participant::FLAG_DISCONNECTED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (($room->isFederatedConversation() && $attendee->getLastMentionMessage())
|
||||
|| (!$room->isFederatedConversation() && $attendee->getLastMentionMessage() > $attendee->getLastReadMessage())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($room->getType() === Room::TYPE_ONE_TO_ONE || $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER)
|
||||
&& $room->getLastMessageId() > $attendee->getLastReadMessage()
|
||||
&& $this->chatManager->getUnreadCount($room, $attendee->getLastReadMessage()) > 0;
|
||||
});
|
||||
|
||||
uasort($rooms, [$this, 'sortRooms']);
|
||||
|
||||
$rooms = array_slice($rooms, 0, $limit);
|
||||
|
||||
$result = [];
|
||||
foreach ($rooms as $room) {
|
||||
$result[] = $this->prepareRoom($room, $userId);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getItemsV2(string $userId, ?string $since = null, int $limit = 7): WidgetItems {
|
||||
$event = new BeforeRoomsFetchEvent($userId);
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
|
||||
$allRooms = $this->manager->getRoomsForUser($userId, [], true);
|
||||
|
||||
$rooms = [];
|
||||
$mentions = [];
|
||||
foreach ($allRooms as $room) {
|
||||
if ($room->getObjectType() === BreakoutRoom::PARENT_OBJECT_TYPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$participant = $this->participantService->getParticipant($room, $userId);
|
||||
$attendee = $participant->getAttendee();
|
||||
|
||||
if ($room->getLobbyState() !== Webinary::LOBBY_NONE
|
||||
&& !($participant->getPermissions() & Attendee::PERMISSIONS_LOBBY_IGNORE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$attendee->isArchived()) {
|
||||
$rooms[] = $room;
|
||||
|
||||
if ($room->getCallFlag() !== Participant::FLAG_DISCONNECTED) {
|
||||
// Call in progress
|
||||
$mentions[] = $room;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (($room->isFederatedConversation() && $attendee->getLastMentionMessage())
|
||||
|| (!$room->isFederatedConversation() && $attendee->getLastMentionMessage() > $attendee->getLastReadMessage())) {
|
||||
// Really mentioned
|
||||
$mentions[] = $room;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (($room->getType() === Room::TYPE_ONE_TO_ONE || $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER)
|
||||
&& $room->getLastMessageId() > $attendee->getLastReadMessage()) {
|
||||
// If there are "unread" messages in one-to-one or former one-to-one
|
||||
// we check if they are actual messages or system messages not
|
||||
// considered by the read-marker
|
||||
if ($this->chatManager->getUnreadCount($room, $attendee->getLastReadMessage()) > 0) {
|
||||
// Unread message in one-to-one are considered "mentions"
|
||||
$mentions[] = $room;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$roomsToReturn = $rooms;
|
||||
if (!empty($mentions)) {
|
||||
$roomsToReturn = $mentions;
|
||||
}
|
||||
|
||||
uasort($roomsToReturn, [$this, 'sortRooms']);
|
||||
$roomsToReturn = array_slice($roomsToReturn, 0, $limit);
|
||||
|
||||
$result = [];
|
||||
foreach ($roomsToReturn as $room) {
|
||||
$result[] = $this->prepareRoom($room, $userId);
|
||||
}
|
||||
|
||||
return new WidgetItems(
|
||||
$result,
|
||||
empty($result) ? $this->l10n->t('Say hi to your friends and colleagues!') : '',
|
||||
empty($mentions) ? $this->l10n->t('No unread mentions') : '',
|
||||
);
|
||||
}
|
||||
|
||||
protected function prepareRoom(Room $room, string $userId): WidgetItem {
|
||||
$participant = $this->participantService->getParticipant($room, $userId);
|
||||
$attendee = $participant->getAttendee();
|
||||
$subtitle = '';
|
||||
|
||||
if ($attendee->isSensitive()) {
|
||||
// Don't leak sensitive last messages on dashboard
|
||||
} elseif ($room->getLastMessageId() && $room->isFederatedConversation()) {
|
||||
try {
|
||||
$cachedMessage = $this->pcmService->findByRemote(
|
||||
$room->getRemoteServer(),
|
||||
$room->getRemoteToken(),
|
||||
$room->getLastMessageId(),
|
||||
);
|
||||
$message = $this->messageParser->createMessageFromProxyCache($room, $participant, $cachedMessage, $this->l10n);
|
||||
$subtitle = $this->getSubtitleFromMessage($message);
|
||||
} catch (DoesNotExistException) {
|
||||
// Fallback to empty subtitle
|
||||
}
|
||||
} elseif ($room->getLastMessageId() && $room->getLastMessage() && !$room->isFederatedConversation()) {
|
||||
$message = $this->messageParser->createMessage($room, $participant, $room->getLastMessage(), $this->l10n);
|
||||
$this->messageParser->parseMessage($message, true);
|
||||
$subtitle = $this->getSubtitleFromMessage($message);
|
||||
}
|
||||
|
||||
if ($room->getCallFlag() !== Participant::FLAG_DISCONNECTED) {
|
||||
$subtitle = $this->l10n->t('Call in progress');
|
||||
} elseif (($room->isFederatedConversation() && $attendee->getLastMentionMessage())
|
||||
|| (!$room->isFederatedConversation() && $attendee->getLastMentionMessage() > $attendee->getLastReadMessage())) {
|
||||
$subtitle = $this->l10n->t('You were mentioned');
|
||||
}
|
||||
|
||||
return new WidgetItem(
|
||||
$room->getDisplayName($userId),
|
||||
$subtitle,
|
||||
$this->url->linkToRouteAbsolute('spreed.Page.showCall', ['token' => $room->getToken()]),
|
||||
$this->avatarService->getAvatarUrl($room)
|
||||
);
|
||||
}
|
||||
|
||||
protected function getSubtitleFromMessage(Message $message): string {
|
||||
$expireDate = $message->getExpirationDateTime();
|
||||
if ($expireDate instanceof \DateTimeInterface
|
||||
&& $expireDate <= $this->timeFactory->getDateTime()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$message->getVisibility()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$placeholders = $replacements = [];
|
||||
foreach ($message->getMessageParameters() as $placeholder => $parameter) {
|
||||
$placeholders[] = '{' . $placeholder . '}';
|
||||
if ($parameter['type'] === 'user' || $parameter['type'] === 'guest') {
|
||||
$replacements[] = '@' . $parameter['name'];
|
||||
} else {
|
||||
$replacements[] = $parameter['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return str_replace($placeholders, $replacements, $message->getMessage());
|
||||
}
|
||||
|
||||
protected function sortRooms(Room $roomA, Room $roomB): int {
|
||||
if ($roomA->getCallFlag() !== $roomB->getCallFlag()) {
|
||||
return $roomA->getCallFlag() !== Participant::FLAG_DISCONNECTED ? -1 : 1;
|
||||
}
|
||||
|
||||
return $roomA->getLastActivity() >= $roomB->getLastActivity() ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\Override]
|
||||
public function getReloadInterval(): int {
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user