diff --git a/apps/comments/js/commentstabview.js b/apps/comments/js/commentstabview.js
index ace0862ad2e8343b38f1112d3df76062837e54f6..3a20604326b0ee11f60e8d103cbb4fef4162df27 100644
Binary files a/apps/comments/js/commentstabview.js and b/apps/comments/js/commentstabview.js differ
diff --git a/apps/comments/tests/js/commentstabviewSpec.js b/apps/comments/tests/js/commentstabviewSpec.js
index c961548d8060ab708794afa3ba978eb23eccafba..63a27956f9f99e75cb81f7498a824ad0e00306c0 100644
--- a/apps/comments/tests/js/commentstabviewSpec.js
+++ b/apps/comments/tests/js/commentstabviewSpec.js
@@ -22,6 +22,7 @@
 describe('OCA.Comments.CommentsTabView tests', function() {
 	var view, fileInfoModel;
 	var fetchStub;
+	var avatarStub;
 	var testComments;
 	var clock;
 
@@ -42,6 +43,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 	beforeEach(function() {
 		clock = sinon.useFakeTimers(Date.UTC(2016, 1, 3, 10, 5, 9));
 		fetchStub = sinon.stub(OCA.Comments.CommentCollection.prototype, 'fetchNext');
+		avatarStub = sinon.stub($.fn, 'avatar');
 		view = new OCA.Comments.CommentsTabView();
 		fileInfoModel = new OCA.Files.FileInfoModel({
 			id: 5,
@@ -102,6 +104,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 		view.remove();
 		view = undefined;
 		fetchStub.restore();
+		avatarStub.restore();
 		clock.restore();
 	});
 	describe('rendering', function() {
@@ -151,9 +154,11 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 			expect($comment.length).toEqual(1);
 			expect($comment.find('.avatar[data-user=macbeth]').length).toEqual(1);
 			expect($comment.find('strong:first').text()).toEqual('Thane of Cawdor');
+			expect($comment.find('.avatar[data-user=macbeth] ~ .contactsmenu-popover').length).toEqual(1);
 
 			expect($comment.find('.avatar[data-user=banquo]').length).toEqual(1);
 			expect($comment.find('.avatar-name-wrapper:last-child strong').text()).toEqual('Lord Banquo');
+			expect($comment.find('.avatar[data-user=banquo] ~ .contactsmenu-popover').length).toEqual(1);
 		});
 
 	});
@@ -223,6 +228,10 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 				uid: 'testuser',
 				displayName: 'Test User'
 			});
+
+			// Required for the absolute selector used to find the new comment
+			// after a successful creation in _onSubmitSuccess.
+			$('#testArea').append(view.$el);
 		});
 		afterEach(function() {
 			createStub.restore();
@@ -243,6 +252,50 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 				creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
 			});
 		});
+		it('creates a new comment with mentions when clicking post button', function() {
+			view.$el.find('.message').val('New message @anotheruser');
+			view.$el.find('form').submit();
+
+			var createStubExpectedData = {
+				actorId: 'testuser',
+				actorDisplayName: 'Test User',
+				actorType: 'users',
+				verb: 'comment',
+				message: 'New message @anotheruser',
+				creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
+			};
+
+			expect(createStub.calledOnce).toEqual(true);
+			expect(createStub.lastCall.args[0]).toEqual(createStubExpectedData);
+
+			var model = new OCA.Comments.CommentModel(_.extend({id: 4}, createStubExpectedData));
+			var fetchStub = sinon.stub(model, 'fetch');
+			// simulate the fact that create adds the model to the collection
+			view.collection.add(model, {at: 0});
+			createStub.yieldTo('success', model);
+
+			expect(fetchStub.calledOnce).toEqual(true);
+
+			// simulate the fact that fetch sets the attribute
+			model.set('mentions', {
+				0: {
+					mentionDisplayName: "Another User",
+					mentionId: "anotheruser",
+					mentionTye: "user"
+				}
+			});
+			fetchStub.yieldTo('success', model);
+
+			// comment was added to the list
+			var $comment = view.$el.find('.comment[data-id=4]');
+			expect($comment.length).toEqual(1);
+			var $message = $comment.find('.message');
+			expect($message.html()).toContain('New message');
+			expect($message.find('.avatar').length).toEqual(1);
+			expect($message.find('.avatar[data-user=anotheruser]').length).toEqual(1);
+			expect($message.find('.avatar[data-user=anotheruser] ~ strong').text()).toEqual('Another User');
+			expect($message.find('.avatar[data-user=anotheruser] ~ .contactsmenu-popover').length).toEqual(1);
+		});
 		it('does not create a comment if the field is empty', function() {
 			view.$el.find('.message').val('   ');
 			view.$el.find('form').submit();
@@ -302,13 +355,11 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 	describe('editing comments', function() {
 		var saveStub;
 		var fetchStub;
-		var avatarStub;
 		var currentUserStub;
 
 		beforeEach(function() {
 			saveStub = sinon.stub(OCA.Comments.CommentModel.prototype, 'save');
 			fetchStub = sinon.stub(OCA.Comments.CommentModel.prototype, 'fetch');
-			avatarStub = sinon.stub($.fn, 'avatar');
 			currentUserStub = sinon.stub(OC, 'getCurrentUser');
 			currentUserStub.returns({
 				uid: 'testuser',
@@ -332,11 +383,31 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 				message: 'New message from another user',
 				creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString(),
 			});
+			view.collection.add({
+				id: 3,
+				actorId: 'testuser',
+				actorDisplayName: 'Test User',
+				actorType: 'users',
+				verb: 'comment',
+				message: 'Hail to thee, @macbeth. Yours faithfully, @banquo',
+				creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString(),
+				mentions: {
+					0: {
+						mentionDisplayName: "Thane of Cawdor",
+						mentionId: "macbeth",
+						mentionTye: "user"
+					},
+					1: {
+						mentionDisplayName: "Lord Banquo",
+						mentionId: "banquo",
+						mentionTye: "user"
+					}
+				}
+			});
 		});
 		afterEach(function() {
 			saveStub.restore();
 			fetchStub.restore();
-			avatarStub.restore();
 			currentUserStub.restore();
 		});
 
@@ -394,6 +465,53 @@ describe('OCA.Comments.CommentsTabView tests', function() {
 			expect($formRow.length).toEqual(0);
 		});
 
+		it('saves message and updates comment item with mentions when clicking save', function() {
+			var $comment = view.$el.find('.comment[data-id=3]');
+			$comment.find('.action.edit').click();
+
+			var $formRow = view.$el.find('.newCommentRow.comment[data-id=3]');
+			expect($formRow.length).toEqual(1);
+
+			$formRow.find('textarea').val('modified\nmessage @anotheruser');
+			$formRow.find('form').submit();
+
+			expect(saveStub.calledOnce).toEqual(true);
+			expect(saveStub.lastCall.args[0]).toEqual({
+				message: 'modified\nmessage @anotheruser'
+			});
+
+			var model = view.collection.get(3);
+			// simulate the fact that save sets the attribute
+			model.set('message', 'modified\nmessage @anotheruser');
+			saveStub.yieldTo('success', model);
+
+			expect(fetchStub.calledOnce).toEqual(true);
+
+			// simulate the fact that fetch sets the attribute
+			model.set('mentions', {
+				0: {
+					mentionDisplayName: "Another User",
+					mentionId: "anotheruser",
+					mentionTye: "user"
+				}
+			});
+			fetchStub.yieldTo('success', model);
+
+			// original comment element is visible again
+			expect($comment.hasClass('hidden')).toEqual(false);
+			// and its message was updated
+			var $message = $comment.find('.message');
+			expect($message.html()).toContain('modified<br>message');
+			expect($message.find('.avatar').length).toEqual(1);
+			expect($message.find('.avatar[data-user=anotheruser]').length).toEqual(1);
+			expect($message.find('.avatar[data-user=anotheruser] ~ strong').text()).toEqual('Another User');
+			expect($message.find('.avatar[data-user=anotheruser] ~ .contactsmenu-popover').length).toEqual(1);
+
+			// form row is gone
+			$formRow = view.$el.find('.newCommentRow.comment[data-id=3]');
+			expect($formRow.length).toEqual(0);
+		});
+
 		it('restores original comment when cancelling', function() {
 			var $comment = view.$el.find('.comment[data-id=1]');
 			$comment.find('.action.edit').click();