Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Archive conversations #13357

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* 🌉 **Sync with other chat solutions** With [Matterbridge](https://github.com/42wim/matterbridge/) being integrated in Talk, you can easily sync a lot of other chat solutions to Nextcloud Talk and vice-versa.
]]></description>

<version>21.0.0-dev.0</version>
<version>21.0.0-dev.1</version>
<licence>agpl</licence>

<author>Daniel Calviño Sánchez</author>
Expand Down
4 changes: 4 additions & 0 deletions appinfo/routes/routesRoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,9 @@
['name' => 'Room#getCapabilities', 'url' => '/api/{apiVersion}/room/{token}/capabilities', 'verb' => 'GET', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::setMentionPermissions() */
['name' => 'Room#setMentionPermissions', 'url' => '/api/{apiVersion}/room/{token}/mention-permissions', 'verb' => 'PUT', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::archiveConversation() */
['name' => 'Room#archiveConversation', 'url' => '/api/{apiVersion}/room/{token}/archive', 'verb' => 'POST', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::unarchiveConversation() */
['name' => 'Room#unarchiveConversation', 'url' => '/api/{apiVersion}/room/{token}/archive', 'verb' => 'DELETE', 'requirements' => $requirementsWithToken],
],
];
3 changes: 3 additions & 0 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,6 @@
* `mention-permissions` - Whether non-moderators are allowed to mention `@all`
* `federation-v2` - Whether federated session ids are used and calls are possible with federation
* `edit-messages-note-to-self` - Messages in note-to-self conversations can be edited indefinitely

## 20.1
* `archived-conversations` (local) - Conversations can be marked as archived which will hide them from the conversation list by default
1 change: 1 addition & 0 deletions docs/conversation.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
| `callRecording` | int | v4 | | Type of call recording (see [Constants - Call recording status](constants.md#call-recording-status)) (only available with `recording-v1` capability) |
| `recordingConsent` | int | v4 | | Whether recording consent is required before joining a call (Only 0 and 1 will be returned, see [constants list](constants.md#recording-consent-required)) (only available with `recording-consent` capability) |
| `mentionPermissions` | int | v4 | | Whether all participants can mention using `@all` or only moderators (see [constants list](constants.md#mention-permissions)) (only available with `mention-permissions` capability) |
| `isArchived` | bool | v4 | | Flag if the conversation is archived by the user (only available with `archived-conversations` capability) | |

## Creating a new conversation

Expand Down
2 changes: 2 additions & 0 deletions lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class Capabilities implements IPublicCapability {
'chat-reference-id',
'mention-permissions',
'edit-messages-note-to-self',
'archived-conversations',
];

public const LOCAL_FEATURES = [
Expand All @@ -115,6 +116,7 @@ class Capabilities implements IPublicCapability {
'avatar',
'remind-me-later',
'note-to-self',
'archived-conversations',
];

public const LOCAL_CONFIGS = [
Expand Down
17 changes: 7 additions & 10 deletions lib/Chat/Notifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@ public function notifyMentionedUsers(Room $chat, IComment $comment, array $alrea
$shouldFlush = $this->notificationManager->defer();
}


foreach ($usersToNotify as $mentionedUser) {
if ($this->shouldMentionedUserBeNotified($mentionedUser['id'], $comment, $chat, $mentionedUser['attendee'] ?? null)) {
if ($this->shouldMentionedUserBeNotified($mentionedUser['id'], $comment, $chat, $mentionedUser['attendee'] ?? null, $mentionedUser['reason'])) {
if (!$silent) {
$notification->setUser($mentionedUser['id']);
if (isset($mentionedUser['reason'])) {
Expand Down Expand Up @@ -210,7 +209,7 @@ public function notifyReplyToAuthor(Room $chat, IComment $comment, IComment $rep
];
}

if (!$this->shouldMentionedUserBeNotified($replyTo->getActorId(), $comment, $chat)) {
if (!$this->shouldMentionedUserBeNotified($replyTo->getActorId(), $comment, $chat, null, 'reply')) {
return [];
}

Expand Down Expand Up @@ -565,14 +564,8 @@ protected function getDefaultGroupNotification(): int {
* 2. The user must exist
* 3. The user must be a participant of the room
* 4. The user must not be active in the room
*
* @param string $userId
* @param IComment $comment
* @param Room $room
* @param Attendee|null $attendee
* @return bool
*/
protected function shouldMentionedUserBeNotified(string $userId, IComment $comment, Room $room, ?Attendee $attendee = null): bool {
protected function shouldMentionedUserBeNotified(string $userId, IComment $comment, Room $room, ?Attendee $attendee, string $reason): bool {
if ($comment->getActorType() === Attendee::ACTOR_USERS && $userId === $comment->getActorId()) {
// Do not notify the user if they mentioned themselves
return false;
Expand All @@ -590,6 +583,10 @@ protected function shouldMentionedUserBeNotified(string $userId, IComment $comme
$participant = new Participant($room, $attendee, null);
}

if ($reason === 'all' && $attendee->isArchived()) {
return false;
}

if ($room->getLobbyState() !== Webinary::LOBBY_NONE &&
!($participant->getPermissions() & Attendee::PERMISSIONS_LOBBY_IGNORE)) {
return false;
Expand Down
30 changes: 30 additions & 0 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,36 @@ public function setPassword(string $password): DataResponse {
return new DataResponse();
}

/**
* Archive a conversation
*
* @return DataResponse<Http::STATUS_OK, TalkRoom, array{}>
*
* 200: Conversation was archived
*/
#[NoAdminRequired]
#[FederationSupported]
#[RequireLoggedInParticipant]
public function archiveConversation(): DataResponse {
$this->participantService->archiveConversation($this->participant);
return new DataResponse($this->formatRoom($this->room, $this->participant));
}

/**
* Unarchive a conversation
*
* @return DataResponse<Http::STATUS_OK, TalkRoom, array{}>
*
* 200: Conversation was unarchived
*/
#[NoAdminRequired]
#[FederationSupported]
#[RequireLoggedInParticipant]
public function unarchiveConversation(): DataResponse {
$this->participantService->unarchiveConversation($this->participant);
return new DataResponse($this->formatRoom($this->room, $this->participant));
}

/**
* Join a room
*
Expand Down
40 changes: 40 additions & 0 deletions lib/Migration/Version21000Date20240919222538.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version21000Date20240919222538 extends SimpleMigrationStep {

/**
* @param IOutput $output
* @param Closure(): ISchemaWrapper $schemaClosure
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

$table = $schema->getTable('talk_attendees');
if (!$table->hasColumn('archived')) {
$table->addColumn('archived', Types::BOOLEAN, [
'default' => 0,
'notnull' => false,
]);
}

return $schema;
}
}
4 changes: 4 additions & 0 deletions lib/Model/Attendee.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
* @method void setReadPrivacy(int $readPrivacy)
* @method int getReadPrivacy()
* @method void setPermissions(int $permissions)
* @method void setArchived(bool $archived)
* @method bool isArchived()
* @internal
* @method int getPermissions()
* @method void setAccessToken(string $accessToken)
Expand Down Expand Up @@ -108,6 +110,7 @@ class Attendee extends Entity {
protected bool $favorite = false;
protected int $notificationLevel = 0;
protected int $notificationCalls = 0;
protected bool $archived = false;
protected int $lastJoinedCall = 0;
protected int $lastReadMessage = 0;
protected int $lastMentionMessage = 0;
Expand All @@ -131,6 +134,7 @@ public function __construct() {
$this->addType('pin', 'string');
$this->addType('participantType', 'int');
$this->addType('favorite', 'bool');
$this->addType('archived', 'bool');
$this->addType('notificationLevel', 'int');
$this->addType('notificationCalls', 'int');
$this->addType('lastJoinedCall', 'int');
Expand Down
1 change: 1 addition & 0 deletions lib/Model/AttendeeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ public function createAttendeeFromRow(array $row): Attendee {
'state' => (int)$row['state'],
'unread_messages' => (int)$row['unread_messages'],
'last_attendee_activity' => (int)$row['last_attendee_activity'],
'archived' => (bool)$row['archived'],
]);
}
}
1 change: 1 addition & 0 deletions lib/Model/SelectHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public function selectAttendeesTable(IQueryBuilder $query, string $alias = 'a'):
->addSelect($alias . 'state')
->addSelect($alias . 'unread_messages')
->addSelect($alias . 'last_attendee_activity')
->addSelect($alias . 'archived')
->selectAlias($alias . 'id', 'a_id');
}

Expand Down
1 change: 1 addition & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
* unreadMention: bool,
* unreadMentionDirect: bool,
* unreadMessages: int,
* isArchived: bool,
* }
*
* @psalm-type TalkSignalingSession = array{
Expand Down
21 changes: 21 additions & 0 deletions lib/Service/ParticipantService.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,26 @@ public function updateNotificationCalls(Participant $participant, int $level): v
$this->attendeeMapper->update($attendee);
}

/**
* @param Participant $participant
*/
public function archiveConversation(Participant $participant): void {
$attendee = $participant->getAttendee();
$attendee->setArchived(true);
$attendee->setLastAttendeeActivity($this->timeFactory->getTime());
$this->attendeeMapper->update($attendee);
}

/**
* @param Participant $participant
*/
public function unarchiveConversation(Participant $participant): void {
$attendee = $participant->getAttendee();
$attendee->setArchived(false);
$attendee->setLastAttendeeActivity($this->timeFactory->getTime());
$this->attendeeMapper->update($attendee);
}

/**
* @param RoomService $roomService
* @param Room $room
Expand Down Expand Up @@ -1733,6 +1753,7 @@ public function getParticipantUserIdsForCallNotifications(Room $room): array {
->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)))
->andWhere($query->expr()->eq('a.notification_calls', $query->createNamedParameter(Participant::NOTIFY_CALLS_ON)))
->andWhere($query->expr()->eq('a.archived', $query->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->andWhere($query->expr()->isNull('s.in_call'));

if ($room->getLobbyState() !== Webinary::LOBBY_NONE) {
Expand Down
2 changes: 2 additions & 0 deletions lib/Service/RoomFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public function formatRoomV4(
'breakoutRoomStatus' => BreakoutRoom::STATUS_STOPPED,
'recordingConsent' => $this->talkConfig->recordingConsentRequired() === RecordingService::CONSENT_REQUIRED_OPTIONAL ? $room->getRecordingConsent() : $this->talkConfig->recordingConsentRequired(),
'mentionPermissions' => Room::MENTION_PERMISSIONS_EVERYONE,
'isArchived' => false,
];

if ($room->isFederatedConversation()) {
Expand Down Expand Up @@ -223,6 +224,7 @@ public function formatRoomV4(
'breakoutRoomMode' => $room->getBreakoutRoomMode(),
'breakoutRoomStatus' => $room->getBreakoutRoomStatus(),
'mentionPermissions' => $room->getMentionPermissions(),
'isArchived' => $attendee->isArchived(),
]);

if ($room->isFederatedConversation()) {
Expand Down
6 changes: 5 additions & 1 deletion openapi-backend-sipbridge.json
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,8 @@
"type",
"unreadMention",
"unreadMentionDirect",
"unreadMessages"
"unreadMessages",
"isArchived"
],
"properties": {
"actorId": {
Expand Down Expand Up @@ -769,6 +770,9 @@
"unreadMessages": {
"type": "integer",
"format": "int64"
},
"isArchived": {
"type": "boolean"
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion openapi-federation.json
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,8 @@
"type",
"unreadMention",
"unreadMentionDirect",
"unreadMessages"
"unreadMessages",
"isArchived"
],
"properties": {
"actorId": {
Expand Down Expand Up @@ -823,6 +824,9 @@
"unreadMessages": {
"type": "integer",
"format": "int64"
},
"isArchived": {
"type": "boolean"
}
}
},
Expand Down
Loading
Loading