Display mention syntax in publisher instead of username
This commit is contained in:
parent
408645cccc
commit
b3c412d38f
2 changed files with 39 additions and 51 deletions
|
|
@ -2,13 +2,8 @@
|
|||
|
||||
app.views.PublisherMention = app.views.SearchBase.extend({
|
||||
triggerChar: "@",
|
||||
invisibleChar: "\u200B", // zero width space
|
||||
mentionRegex: /@([^@\s]+)$/,
|
||||
|
||||
templates: {
|
||||
mentionItemSyntax: _.template("@{<%= handle %>}"),
|
||||
mentionItemHighlight: _.template("<strong><span><%= name %></span></strong>")
|
||||
},
|
||||
mentionSyntaxTemplate: function(person) { return "@{" + person.handle + "}"; },
|
||||
|
||||
events: {
|
||||
"keydown #status_message_fake_text": "onInputBoxKeyDown",
|
||||
|
|
@ -55,8 +50,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({
|
|||
cleanMentionedPeople: function() {
|
||||
var inputText = this.inputBox.val();
|
||||
this.mentionedPeople = this.mentionedPeople.filter(function(person) {
|
||||
return person.name && inputText.indexOf(person.name) > -1;
|
||||
});
|
||||
return person.handle && inputText.indexOf(this.mentionSyntaxTemplate(person)) > -1;
|
||||
}.bind(this));
|
||||
this.ignoreDiasporaIds = this.mentionedPeople.map(function(person) { return person.handle; });
|
||||
},
|
||||
|
||||
|
|
@ -70,39 +65,22 @@ app.views.PublisherMention = app.views.SearchBase.extend({
|
|||
this.addPersonToMentions(person);
|
||||
this.closeSuggestions();
|
||||
|
||||
messageText = messageText.substring(0, triggerCharPosition) +
|
||||
this.invisibleChar + person.name + messageText.substring(caretPosition);
|
||||
var mentionText = this.mentionSyntaxTemplate(person);
|
||||
|
||||
messageText = messageText.substring(0, triggerCharPosition) + mentionText + messageText.substring(caretPosition);
|
||||
|
||||
this.inputBox.val(messageText);
|
||||
this.updateMessageTexts();
|
||||
|
||||
this.inputBox.focus();
|
||||
var newCaretPosition = triggerCharPosition + person.name.length + 1;
|
||||
var newCaretPosition = triggerCharPosition + mentionText.length;
|
||||
this.inputBox[0].setSelectionRange(newCaretPosition, newCaretPosition);
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces every combination of this.invisibleChar + mention.name by the
|
||||
* correct syntax for both hidden text and visible one.
|
||||
*
|
||||
* For instance, the text "Hello \u200Buser1" will be tranformed to
|
||||
* "Hello @{user1 ; user1@pod.tld}" in the hidden element and
|
||||
* "Hello <strong><span>user1</span></strong>" in the element visible to the user.
|
||||
*/
|
||||
updateMessageTexts: function() {
|
||||
var fakeMessageText = this.inputBox.val(),
|
||||
mentionBoxText = _.escape(fakeMessageText),
|
||||
messageText = fakeMessageText;
|
||||
|
||||
this.mentionedPeople.forEach(function(person) {
|
||||
var mentionName = this.invisibleChar + person.name;
|
||||
messageText = messageText.replace(mentionName, this.templates.mentionItemSyntax(person));
|
||||
var textHighlight = this.templates.mentionItemHighlight({name: _.escape(person.name)});
|
||||
mentionBoxText = mentionBoxText.replace(mentionName, textHighlight);
|
||||
}, this);
|
||||
|
||||
var messageText = this.inputBox.val();
|
||||
this.inputBox.data("messageText", messageText);
|
||||
this.mentionsBox.find(".mentions").html(mentionBoxText);
|
||||
this.mentionsBox.find(".mentions").html(_.escape(messageText));
|
||||
},
|
||||
|
||||
updateTypeaheadInput: function() {
|
||||
|
|
@ -128,7 +106,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({
|
|||
prefillMention: function(persons) {
|
||||
persons.forEach(function(person) {
|
||||
this.addPersonToMentions(person);
|
||||
var text = this.invisibleChar + person.name;
|
||||
var text = this.mentionSyntaxTemplate(person);
|
||||
if(this.inputBox.val().length !== 0) {
|
||||
text = this.inputBox.val() + " " + text;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ describe("app.views.PublisherMention", function() {
|
|||
it("initializes object properties", function() {
|
||||
this.view = new app.views.PublisherMention({ el: "#publisher" });
|
||||
expect(this.view.mentionedPeople).toEqual([]);
|
||||
expect(this.view.invisibleChar).toBe("\u200B");
|
||||
expect(this.view.triggerChar).toBe("@");
|
||||
});
|
||||
|
||||
|
|
@ -29,6 +28,17 @@ describe("app.views.PublisherMention", function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("mentionSyntaxTemplate", function() {
|
||||
beforeEach(function() {
|
||||
this.view = new app.views.PublisherMention({el: "#publisher"});
|
||||
this.person = {handle: "alice@pod.tld", name: "Alice Awesome"};
|
||||
});
|
||||
|
||||
it("returns the correct mention syntax", function() {
|
||||
expect(this.view.mentionSyntaxTemplate(this.person)).toBe("@{alice@pod.tld}");
|
||||
});
|
||||
});
|
||||
|
||||
describe("bindTypeaheadEvents", function() {
|
||||
beforeEach(function() {
|
||||
this.view = new app.views.PublisherMention({ el: "#publisher" });
|
||||
|
|
@ -92,30 +102,30 @@ describe("app.views.PublisherMention", function() {
|
|||
});
|
||||
|
||||
it("removes person from mentioned people if not mentioned anymore", function() {
|
||||
this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
|
||||
this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
|
||||
expect(this.view.mentionedPeople.length).toBe(1);
|
||||
this.view.cleanMentionedPeople();
|
||||
expect(this.view.mentionedPeople.length).toBe(0);
|
||||
});
|
||||
|
||||
it("removes person from ignored people if not mentioned anymore", function() {
|
||||
this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
|
||||
this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
|
||||
expect(this.view.ignoreDiasporaIds.length).toBe(1);
|
||||
this.view.cleanMentionedPeople();
|
||||
expect(this.view.ignoreDiasporaIds.length).toBe(0);
|
||||
});
|
||||
|
||||
it("keeps mentioned persons", function() {
|
||||
this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
|
||||
this.view.inputBox.val("user1");
|
||||
this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
|
||||
this.view.inputBox.val("@{user1@pod.tld}");
|
||||
expect(this.view.mentionedPeople.length).toBe(1);
|
||||
this.view.cleanMentionedPeople();
|
||||
expect(this.view.mentionedPeople.length).toBe(1);
|
||||
});
|
||||
|
||||
it("keeps mentioned persons for ignored diaspora ids", function() {
|
||||
this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
|
||||
this.view.inputBox.val("user1");
|
||||
this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
|
||||
this.view.inputBox.val("@{user1@pod.tld}");
|
||||
expect(this.view.ignoreDiasporaIds.length).toBe(1);
|
||||
this.view.cleanMentionedPeople();
|
||||
expect(this.view.ignoreDiasporaIds.length).toBe(1);
|
||||
|
|
@ -151,20 +161,20 @@ describe("app.views.PublisherMention", function() {
|
|||
|
||||
it("correctly formats the text", function() {
|
||||
this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"});
|
||||
expect(this.view.inputBox.val()).toBe("@user1337 Text before \u200Buser1337 text after");
|
||||
expect(this.view.inputBox.val()).toBe("@user1337 Text before @{user1@pod.tld} text after");
|
||||
});
|
||||
|
||||
it("replaces the correct mention", function() {
|
||||
this.view.inputBox.val("@user1337 123 user2 @user2 456 @user3 789");
|
||||
this.view.inputBox[0].setSelectionRange(26, 26);
|
||||
this.view.onSuggestionSelection({name: "user23", handle: "user2@pod.tld"});
|
||||
expect(this.view.inputBox.val()).toBe("@user1337 123 user2 \u200Buser23 456 @user3 789");
|
||||
expect(this.view.inputBox.val()).toBe("@user1337 123 user2 @{user2@pod.tld} 456 @user3 789");
|
||||
this.view.inputBox[0].setSelectionRange(9, 9);
|
||||
this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"});
|
||||
expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 @user3 789");
|
||||
this.view.inputBox[0].setSelectionRange(38, 38);
|
||||
expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @user3 789");
|
||||
this.view.inputBox[0].setSelectionRange(54, 54);
|
||||
this.view.onSuggestionSelection({name: "user32", handle: "user3@pod.tld"});
|
||||
expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 \u200Buser32 789");
|
||||
expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @{user3@pod.tld} 789");
|
||||
});
|
||||
|
||||
it("calls updateMessageTexts", function() {
|
||||
|
|
@ -175,7 +185,7 @@ describe("app.views.PublisherMention", function() {
|
|||
|
||||
it("places the caret at the right position", function() {
|
||||
this.view.onSuggestionSelection({"name": "user1WithLongName", "handle": "user1@pod.tld"});
|
||||
var expectedCaretPosition = ("@user1337 Text before \u200Buser1WithLongName").length;
|
||||
var expectedCaretPosition = ("@user1337 Text before @{user1@pod.tld}").length;
|
||||
expect(this.view.inputBox[0].selectionStart).toBe(expectedCaretPosition);
|
||||
});
|
||||
});
|
||||
|
|
@ -183,7 +193,7 @@ describe("app.views.PublisherMention", function() {
|
|||
describe("updateMessageTexts", function() {
|
||||
beforeEach(function() {
|
||||
this.view = new app.views.PublisherMention({ el: "#publisher" });
|
||||
this.view.inputBox.val("@user1 Text before \u200Buser1\ntext after");
|
||||
this.view.inputBox.val("@user1 Text before @{user1@pod.tld}\ntext after");
|
||||
this.view.mentionedPeople.push({"name": "user1", "handle": "user1@pod.tld"});
|
||||
});
|
||||
|
||||
|
|
@ -195,14 +205,14 @@ describe("app.views.PublisherMention", function() {
|
|||
it("formats overlay text to HTML", function() {
|
||||
this.view.updateMessageTexts();
|
||||
expect(this.view.mentionsBox.find(".mentions").html())
|
||||
.toBe("@user1 Text before <strong><span>user1</span></strong>\ntext after");
|
||||
.toBe("@user1 Text before @{user1@pod.tld}\ntext after");
|
||||
});
|
||||
|
||||
it("properly escapes the user input", function() {
|
||||
this.view.inputBox.val("<img src=\"/default.png\"> @user1 Text before \u200Buser1\ntext after");
|
||||
this.view.inputBox.val("<img src=\"/default.png\"> @user1 Text before @{user1@pod.tld}\ntext after");
|
||||
this.view.updateMessageTexts();
|
||||
expect(this.view.mentionsBox.find(".mentions").html())
|
||||
.toBe("<img src=\"/default.png\"> @user1 Text before <strong><span>user1</span></strong>\ntext after");
|
||||
.toBe("<img src=\"/default.png\"> @user1 Text before @{user1@pod.tld}\ntext after");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -264,7 +274,7 @@ describe("app.views.PublisherMention", function() {
|
|||
this.view.prefillMention([{"name": "user1", "handle": "user1@pod.tld"}]);
|
||||
expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"});
|
||||
expect(this.view.updateMessageTexts).toHaveBeenCalled();
|
||||
expect(this.view.inputBox.val()).toBe("\u200Buser1");
|
||||
expect(this.view.inputBox.val()).toBe("@{user1@pod.tld}");
|
||||
});
|
||||
|
||||
it("prefills multiple mentions", function() {
|
||||
|
|
@ -276,7 +286,7 @@ describe("app.views.PublisherMention", function() {
|
|||
expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"});
|
||||
expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user2", "handle": "user2@pod.tld"});
|
||||
expect(this.view.updateMessageTexts).toHaveBeenCalled();
|
||||
expect(this.view.inputBox.val()).toBe("\u200Buser1 \u200Buser2");
|
||||
expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} @{user2@pod.tld}");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue