Skip to content

Commit 9af44d8

Browse files
feat: localize federated user mention in card comment
Signed-off-by: Luka Trovic <luka@nextcloud.com>
1 parent 6a1172e commit 9af44d8

4 files changed

Lines changed: 55 additions & 9 deletions

File tree

lib/Service/CommentService.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use OCP\Comments\MessageTooLongException;
2020
use OCP\Comments\NotFoundException as CommentNotFoundException;
2121
use OCP\Federation\ICloudIdManager;
22+
use OCP\IURLGenerator;
2223
use OCP\IUserManager;
2324
use OutOfBoundsException;
2425
use Psr\Log\LoggerInterface;
@@ -32,6 +33,7 @@ public function __construct(
3233
private IUserManager $userManager,
3334
private LoggerInterface $logger,
3435
private ICloudIdManager $cloudIdManager,
36+
private IURLGenerator $urlGenerator,
3537
private ?string $userId,
3638
) {
3739
}
@@ -172,16 +174,23 @@ private function formatComment(IComment $comment, bool $addReplyTo = false): arr
172174
'actorDisplayName' => $actorDisplayName,
173175
'creationDateTime' => $comment->getCreationDateTime()->format(\DateTime::ATOM),
174176
'mentions' => array_map(function ($mention) {
177+
$remote = $this->cloudIdManager->isValidCloudId($mention['id']) ? $this->cloudIdManager->resolveCloudId($mention['id'])->getRemote() : null;
178+
175179
try {
176180
$displayName = $this->commentsManager->resolveDisplayName($mention['type'], $mention['id']);
177181
} catch (OutOfBoundsException $e) {
178182
$this->logger->warning('Mention type not registered, can not resolve display name.', ['exception' => $e, 'mention_type' => $mention['type']]);
179183
// No display name, upon client's discretion what to display.
180184
$displayName = $mention['id'] ?? '';
185+
if ($remote === $this->urlGenerator->getBaseUrl()) {
186+
$uid = $this->cloudIdManager->resolveCloudId($mention['id'])->getUser();
187+
$displayName = $this->commentsManager->resolveDisplayName('user', $uid);
188+
}
181189
}
182190

183191
return [
184192
'mentionId' => $mention['id'],
193+
'mentionRemote' => $remote,
185194
'mentionType' => $mention['type'],
186195
'mentionDisplayName' => $displayName
187196
];

lib/Service/ExternalBoardService.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public function LocalizeRemoteBoard(array $remoteBoard, Board $localBoard) {
108108
$remoteBoard['acl'] = $localBoard->getAcl();
109109
$remoteBoard['permissions'] = $localBoard->getPermissions();
110110
$remoteBoard['users'] = $this->localizeRemoteUsers($remoteBoard['users'], $localBoard);
111+
$remoteBoard['externalId'] = $localBoard->getExternalId();
111112
return $remoteBoard;
112113
}
113114

@@ -122,6 +123,7 @@ public function localizeRemoteUsers(array $users, Board $localBoard) {
122123

123124
public function localizeRemoteComments(Board $localBoard, array $comments): array {
124125
foreach ($comments as $i => $comment) {
126+
// Localize actors
125127
$localizedActor = $this->localizeRemoteUser($localBoard, ['uid' => $comment['actorId'], 'remote' => $comment['actorRemote']]);
126128
if ($localizedActor instanceof FederatedUser) {
127129
$comments[$i]['actorDisplayName'] = $localizedActor->getCloudId()->getId();
@@ -146,6 +148,25 @@ public function localizeRemoteComments(Board $localBoard, array $comments): arra
146148
$comments[$i]['replyTo']['actorRemote'] = null;
147149
}
148150
}
151+
152+
// Localize mentions
153+
foreach ($comment['mentions'] as $j => $mention) {
154+
$localizedMention = $this->localizeRemoteUser($localBoard, ['uid' => $mention['mentionId'], 'remote' => $mention['mentionRemote']]);
155+
if ($localizedMention instanceof User) {
156+
$comments[$i]['message'] = str_replace('@"federated_user/' . $mention['mentionId'], '@"' . $localizedMention->getUID(), $comment['message']);
157+
$comments[$i]['mentions'][$j]['mentionDisplayName'] = $localizedMention->getDisplayName();
158+
$comments[$i]['mentions'][$j]['mentionId'] = $localizedMention->getUID();
159+
$comments[$i]['mentions'][$j]['mentionRemote'] = null;
160+
$comments[$i]['mentions'][$j]['mentionType'] = 'user';
161+
}
162+
if ($localizedMention instanceof FederatedUser) {
163+
$comments[$i]['message'] = str_replace('@' . $mention['mentionId'], '@federated_user/' . $localizedMention->getUID(), $comment['message']);
164+
$comments[$i]['mentions'][$j]['mentionDisplayName'] = $localizedMention->getCloudId()->getId();
165+
$comments[$i]['mentions'][$j]['mentionId'] = $localizedMention->getCloudId()->getId();
166+
$comments[$i]['mentions'][$j]['mentionRemote'] = $localizedMention->getCloudId()->getRemote();
167+
$comments[$i]['mentions'][$j]['mentionType'] = 'federated_user';
168+
}
169+
}
149170
}
150171
return $comments;
151172
}
@@ -499,6 +520,7 @@ public function createCardCommentOnRemote(Board $localBoard, int $cardId, string
499520
$participantCloudId = $this->cloudIdManager->getCloudId($this->userId, null);
500521
$ownerCloudId = $this->cloudIdManager->resolveCloudId($localBoard->getOwner());
501522
$url = $ownerCloudId->getRemote() . '/ocs/v2.php/apps/deck/api/v1.0/cards/' . $cardId . '/comments';
523+
502524
$params = [
503525
'boardId' => $localBoard->getExternalId(),
504526
'message' => $message,

src/components/card/CommentForm.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,17 @@ export default {
5858
members() {
5959
const obj = {}
6060
this.currentBoard.users.forEach(user => {
61-
obj[user.remote ? `federated_user/${user.uid}` : user.uid] = {
61+
let uid = user.uid
62+
if (user.remote) {
63+
uid = `federated_user/${user.uid}`
64+
} else if (this.currentBoard.externalId) {
65+
uid = `federated_user/${user.uid}@${window.location.origin}`
66+
}
67+
obj[uid] = {
6268
icon: 'icon-user',
63-
id: user.remote ? `federated_user/${user.uid}` : user.uid,
69+
id: uid,
6470
label: user.remote ? user.uid : user.displayname,
65-
source: user.remote ? 'federated_user' : 'users',
71+
source: 'users',
6672
}
6773
})
6874
return obj

src/components/card/CommentItem.vue

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,17 @@ export default {
149149
richText() {
150150
return (comment) => {
151151
let message = this.parsedMessage(comment.message)
152+
message = message.replace('federated_user/', '')
152153
comment.mentions.forEach((mention, index) => {
154+
let mentionId = mention.mentionId
155+
if (mention.mentionRemote === window.location.origin) {
156+
mentionId = mention.mentionId.replace('@' + window.location.origin, '')
157+
message = message.replace(mention.mentionId, mentionId)
158+
}
153159
// Currently only [a-z\-_0-9] are allowed inside of placeholders so we use a hash of the mention id as a unique identifier
154-
const hash = md5(mention.mentionId)
155-
message = message.replace('federated_user/', '')
156-
message = message.split('@' + mention.mentionId + '').join(`{user-${hash}}`)
157-
message = message.split('@"' + mention.mentionId + '"').join(`{user-${hash}}`)
160+
const hash = md5(mentionId)
161+
message = message.split('@' + mentionId + '').join(`{user-${hash}}`)
162+
message = message.split('@"' + mentionId + '"').join(`{user-${hash}}`)
158163
})
159164
return message
160165
}
@@ -163,11 +168,15 @@ export default {
163168
return (comment) => {
164169
const mentions = [...comment.mentions]
165170
const result = mentions.reduce((result, item, index) => {
166-
const itemKey = 'user-' + md5(item.mentionId)
171+
let mentionId = item.mentionId
172+
if (item.mentionRemote === window.location.origin) {
173+
mentionId = item.mentionId.replace('@' + window.location.origin, '')
174+
}
175+
const itemKey = 'user-' + md5(mentionId)
167176
result[itemKey] = {
168177
component: AtMention,
169178
props: {
170-
user: (item.mentionType === 'federated_user' ? 'federated_user/' : '') + item.mentionId,
179+
user: mentionId,
171180
displayName: item.mentionDisplayName,
172181
},
173182
}

0 commit comments

Comments
 (0)