Skip to content

Commit

Permalink
Merge pull request #13357 from nextcloud/feat/noid/archive-conversations
Browse files Browse the repository at this point in the history
Archive conversations
  • Loading branch information
nickvergessen committed Sep 20, 2024
2 parents bd8b8a6 + e5d37de commit 271e520
Show file tree
Hide file tree
Showing 24 changed files with 668 additions and 15 deletions.
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

0 comments on commit 271e520

Please sign in to comment.