Skip to content

Commit

Permalink
Merge pull request #805 from nextcloud/format-mentions-without-avatar…
Browse files Browse the repository at this point in the history
…s-in-the-message-list

Format mentions (without avatars) in the message list
  • Loading branch information
nickvergessen authored Apr 25, 2018
2 parents 09a7bd5 + 07d6e7b commit f24177e
Show file tree
Hide file tree
Showing 20 changed files with 669 additions and 113 deletions.
18 changes: 18 additions & 0 deletions css/comments.scss
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,21 @@
#commentsTabView .comment.showDate .authorRow {
display: block;
}

#commentsTabView .comment .message .mention-user {
/* Make the mention the positioning context of its child contacts menu */
position: relative;

font-weight: bold;
}

#commentsTabView .comment .message .mention-user:not(.current-user) {
cursor: pointer;
}

#commentsTabView .comment .message .contactsmenu-popover {
/* Override default positioning of the contacts menu from server, as it is
* based on an avatar plus a text instead of only '@' plus a text. */
left: -17px;
top: 140%;
}
10 changes: 9 additions & 1 deletion css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
border: 1px solid #eee;
}

.contactsmenu-popover li > a > img {
/* The app uses border-box sizing, so the size of the icon is the
* width/height plus the padding set by default in the server
* (16px + 11px*2). */
width: 38px;
height: 38px;
}

/**
* Sidebar styles
*/
Expand Down Expand Up @@ -630,7 +638,7 @@ video {
opacity: .3;
}

.bubble,
.bubble:not(.contactsmenu-popover),
#app-navigation .app-navigation-entry-menu {
right: 4px;
}
Expand Down
7 changes: 4 additions & 3 deletions docs/api-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
### 3.0 (Initial Talk release)
* `audio` - audio is supported
* `video` - video + screensharing is supported
* `chat` - simple text chat is supported
* `chat` - simple text chat is supported, superseded by `chat-v2`

### 3.1
* `guest-signaling` - Guests can do signaling via api endpoints
Expand All @@ -62,7 +62,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
### 3.2
* `guest-display-names` - Display names of guests are stored in the database, can be set via API (not WebRTC only) and are used on returned comments/participants/etc.
* `multi-room-users` - Users can be in multiple rooms at the same time now, therefor signaling now also requires the room/call token on the URL.
* `chat-v2` - Chat now has a decent offset, the previous `chat` is not available anymore.
* `chat-v2` - Chat messages are now [Rich Object Strings](https://github.com/nextcloud/server/issues/1706) and pagination is available, the previous `chat` is not available anymore.


## Room management
Expand Down Expand Up @@ -471,7 +471,8 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
`actorId` | string | User id of the message author
`actorDisplayName` | string | Display name of the message author
`timestamp` | int | Timestamp in seconds and UTC time zone
`message` | string | Message in plain text
`message` | string | Message string with placeholders (see [Rich Object String](https://github.com/nextcloud/server/issues/1706))
`messageParameters` | array | Message parameters for `message` (see [Rich Object String](https://github.com/nextcloud/server/issues/1706))

### Sending a new chat message

Expand Down
3 changes: 2 additions & 1 deletion js/models/chatmessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
actorId: '',
actorDisplayName: '',
timestamp: 0,
message: ''
message: '',
messageParameters: []
},

url: function() {
Expand Down
84 changes: 84 additions & 0 deletions js/richobjectstringparser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* global OC, OCA, Handlebars */

/**
* @copyright (c) 2016 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*/

(function(OC, OCA, Handlebars) {

OCA.SpreedMe.RichObjectStringParser = {

_userLocalTemplate: '<span class="mention-user {{#if isCurrentUser}}current-user{{/if}}" data-user="{{id}}">@{{name}}</span>',

_unknownTemplate: '<strong>{{name}}</strong>',
_unknownLinkTemplate: '<a href="{{link}}">{{name}}</a>',

/**
* @param {string} subject
* @param {Object} parameters
* @returns {string}
*/
parseMessage: function(subject, parameters) {
var self = this,
regex = /\{([a-z0-9-]+)\}/gi,
matches = subject.match(regex);

_.each(matches, function(parameter) {
parameter = parameter.substring(1, parameter.length - 1);
if (!parameters.hasOwnProperty(parameter) || !parameters[parameter]) {
// Malformed translation?
console.error('Potential malformed ROS string: parameter {' + parameter + '} was found in the string but is missing from the parameter list');
return;
}

var parsed = self.parseParameter(parameters[parameter]);
subject = subject.replace('{' + parameter + '}', parsed);
});

return subject;
},

/**
* @param {Object} parameter
* @param {string} parameter.type
* @param {string} parameter.id
* @param {string} parameter.name
* @param {string} parameter.link
*/
parseParameter: function(parameter) {
switch (parameter.type) {
case 'user':
if (!this.userLocalTemplate) {
this.userLocalTemplate = Handlebars.compile(this._userLocalTemplate);
}
if (!parameter.name) {
parameter.name = parameter.id;
}
if (OC.getCurrentUser().uid === parameter.id) {
parameter.isCurrentUser = true;
}
return this.userLocalTemplate(parameter);

default:
if (!_.isUndefined(parameter.link)) {
if (!this.unknownLinkTemplate) {
this.unknownLinkTemplate = Handlebars.compile(this._unknownLinkTemplate);
}
return this.unknownLinkTemplate(parameter);
}

if (!this.unknownTemplate) {
this.unknownTemplate = Handlebars.compile(this._unknownTemplate);
}
return this.unknownTemplate(parameter);
}
}

};

})(OC, OCA, Handlebars);
13 changes: 8 additions & 5 deletions js/views/chatview.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@

var formattedMessage = escapeHTML(commentModel.get('message')).replace(/\n/g, '<br/>');
formattedMessage = OCP.Comments.plainToRich(formattedMessage);
formattedMessage = OCA.SpreedMe.RichObjectStringParser.parseMessage(
formattedMessage, commentModel.get('messageParameters'));

var data = _.extend({}, commentModel.attributes, {
actorDisplayName: actorDisplayName,
Expand Down Expand Up @@ -373,12 +375,13 @@
},

_postRenderMessage: function($el) {
$el.find('.avatar').each(function() {
var avatar = $(this);
var strong = $(this).next();
var appendTo = $(this).parent();
$el.find('.mention-user').each(function() {
var $this = $(this);

$.merge(avatar, strong).contactsMenu(avatar.data('user'), 0, appendTo);
var user = $this.data('user');
if (user !== OC.getCurrentUser().uid) {
$this.contactsMenu(user, 0, $this);
}
});
},

Expand Down
99 changes: 99 additions & 0 deletions lib/Chat/RichMessageHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

/**
*
* @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Spreed\Chat;

use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;

/**
* Helper class to get a rich message from a plain text message.
*/
class RichMessageHelper {

/** @var ICommentsManager */
private $commentsManager;

/**
* @param ICommentsManager $commentsManager
*/
public function __construct(ICommentsManager $commentsManager) {
$this->commentsManager = $commentsManager;
}

/**
* Returns the equivalent rich message to the given comment.
*
* The mentions in the comment are replaced by "{mention-$type$index}" in
* the returned rich message; each "mention-$type$index" parameter contains
* the following attributes:
* -type: the type of the mention ("user")
* -id: the ID of the user
* -name: the display name of the user, or an empty string if it could
* not be resolved.
*
* @param IComment $comment
* @return Array first element, the rich message; second element, the
* parameters of the rich message (or an empty array if there are no
* parameters).
*/
public function getRichMessage(IComment $comment) {
$message = $comment->getMessage();
$messageParameters = [];

$mentionTypeCount = [];

$mentions = $comment->getMentions();
foreach ($mentions as $mention) {
if (!array_key_exists($mention['type'], $mentionTypeCount)) {
$mentionTypeCount[$mention['type']] = 0;
}
$mentionTypeCount[$mention['type']]++;

// To keep a limited character set in parameter IDs ([a-zA-Z0-9-])
// the mention parameter ID does not include the mention ID (which
// could contain characters like '@' for user IDs) but a one-based
// index of the mentions of that type.
$mentionParameterId = 'mention-' . $mention['type'] . $mentionTypeCount[$mention['type']];

$message = str_replace('@' . $mention['id'], '{' . $mentionParameterId . '}', $message);

try {
$displayName = $this->commentsManager->resolveDisplayName($mention['type'], $mention['id']);
} catch (\OutOfBoundsException $e) {
// There is no registered display name resolver for the mention
// type, so the client decides what to display.
$displayName = '';
}

$messageParameters[$mentionParameterId] = [
'type' => $mention['type'],
'id' => $mention['id'],
'name' => $displayName
];
}

return [$message, $messageParameters];
}

}
13 changes: 11 additions & 2 deletions lib/Controller/ChatController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
namespace OCA\Spreed\Controller;

use OCA\Spreed\Chat\ChatManager;
use OCA\Spreed\Chat\RichMessageHelper;
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\RoomNotFoundException;
use OCA\Spreed\GuestManager;
Expand Down Expand Up @@ -64,6 +65,9 @@ class ChatController extends OCSController {
/** @var string[] */
protected $guestNames;

/** @var RichMessageHelper */
private $richMessageHelper;

/**
* @param string $appName
* @param string $UserId
Expand All @@ -81,7 +85,8 @@ public function __construct($appName,
TalkSession $session,
Manager $manager,
ChatManager $chatManager,
GuestManager $guestManager) {
GuestManager $guestManager,
RichMessageHelper $richMessageHelper) {
parent::__construct($appName, $request);

$this->userId = $UserId;
Expand All @@ -90,6 +95,7 @@ public function __construct($appName,
$this->manager = $manager;
$this->chatManager = $chatManager;
$this->guestManager = $guestManager;
$this->richMessageHelper = $richMessageHelper;
}

/**
Expand Down Expand Up @@ -248,14 +254,17 @@ public function receiveMessages($token, $lookIntoFuture, $limit = 100, $lastKnow
$displayName = $guestNames[$comment->getActorId()];
}

list($message, $messageParameters) = $this->richMessageHelper->getRichMessage($comment);

return [
'id' => $comment->getId(),
'token' => $token,
'actorType' => $comment->getActorType(),
'actorId' => $comment->getActorId(),
'actorDisplayName' => $displayName,
'timestamp' => $comment->getCreationDateTime()->getTimestamp(),
'message' => $comment->getMessage()
'message' => $message,
'messageParameters' => $messageParameters,
];
}, $comments), Http::STATUS_OK);

Expand Down
1 change: 1 addition & 0 deletions templates/index-public.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
'views/roomlistview',
'views/sidebarview',
'views/tabview',
'richobjectstringparser',
'simplewebrtc',
'webrtc',
'signaling',
Expand Down
1 change: 1 addition & 0 deletions templates/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
'views/roomlistview',
'views/sidebarview',
'views/tabview',
'richobjectstringparser',
'simplewebrtc',
'webrtc',
'signaling',
Expand Down
Loading

0 comments on commit f24177e

Please sign in to comment.