[FIX] mail: composer: correctly erase mentions

The problem was that mentions weren't correctly erased with DELETE key (in some
conditions), or when replacing mention text. When this happened, the mention
didn't appear in the message, but the message was even tough sent to the erased
mentioned people.

With this rev., we don't try to detect erasing on the fly anymore, but we
rather validate mentions before sending the message with the content of the
input.

opw 669362
This commit is contained in:
Aaron Bohy
2016-02-15 12:18:44 +01:00
parent cc319c0c08
commit 2f58e95a8d
+24 -34
View File
@@ -27,6 +27,8 @@ var accented_letters_mapping = {
' ': '[()\\[\\]]',
};
var NON_BREAKING_SPACE = '\u00a0';
var MENTION_PARTNER_DELIMITER = '@';
var MENTION_CHANNEL_DELIMITER = '#';
@@ -71,6 +73,8 @@ var MentionManager = Widget.extend({
var selected_suggestion = _.find(_.flatten(this.get('mention_suggestions')), function (s) {
return s.id === id;
});
// replace white spaces with non-breaking spaces to facilitate mentions detection in text
selected_suggestion.name = selected_suggestion.name.replace(/ /g, NON_BREAKING_SPACE);
var get_mention_index = function (matches, cursor_position) {
for (var i=0; i<matches.length; i++) {
if (cursor_position <= matches[i].index) {
@@ -121,9 +125,16 @@ var MentionManager = Widget.extend({
return this.open;
},
/**
* Returns the mentions of the given listener that haven't been erased from the composer's input
*/
get_listener_selection: function (delimiter) {
var listener = _.findWhere(this.listeners, {delimiter: delimiter});
return listener ? listener.selection : [];
if (listener) {
var input_mentions = this.composer.$input.val().match(new RegExp(delimiter+'[^ ]+', 'g'));
return this._validate_selection(listener.selection, input_mentions);
}
return [];
},
get_listener_selections: function () {
@@ -199,33 +210,6 @@ var MentionManager = Widget.extend({
}, this.options.typing_speed);
},
/**
* Checks if a listener's selection should be updated after DELETE or BACKSPACE keypress
*/
check_remove: function () {
var self = this;
var to_remove = [];
var selection = this._get_selection_positions();
var deleted_binf = selection.start;
var deleted_bsup = selection.end;
_.each(this.listeners, function (listener) {
var mention_selection = listener.selection;
var matches = self._get_match(self.composer.$input.val(), listener);
for (var i=0; i<matches.length; i++) {
var m = matches[i];
var m1 = m.index;
var m2 = m.index + m[0].length;
if (deleted_binf <= m2 && m1 < deleted_bsup) {
to_remove.push(mention_selection[i]);
}
}
if (to_remove.length) {
listener.selection = _.difference(mention_selection, to_remove);
}
});
},
/**
* Replaces mentions appearing in the string 's' by html links with proper redirection
*/
@@ -242,7 +226,8 @@ var MentionManager = Widget.extend({
for (var i=0; i<matches.length; i++) {
var match = matches[i];
var end_index = match.index + match[0].length;
var match_name = match[0].substring(1);
// put back white spaces instead of non-breaking spaces in mention's name
var match_name = match[0].substring(1).replace(new RegExp(NON_BREAKING_SPACE, 'g'), ' ');
var href = base_href + _.str.sprintf("#model=%s&id=%s", listener.model, selection[i].id);
var processed_text = _.str.sprintf(mention_link, href, listener.redirect_classname, selection[i].id, listener.model, listener.delimiter, match_name);
var subtext = s.substring(start_index, end_index).replace(match[0], processed_text);
@@ -303,6 +288,16 @@ var MentionManager = Widget.extend({
this.open = false;
}
},
_validate_selection: function (selection, input_mentions) {
var validated_selection = [];
_.each(input_mentions, function (mention) {
var validated_mention = _.findWhere(selection, {name: mention.slice(1)});
if (validated_mention) {
validated_selection.push(validated_mention);
}
});
return validated_selection;
},
// Cursor position and selection utils
_get_selection_positions: function () {
@@ -477,11 +472,6 @@ var BasicComposer = Widget.extend({
event.preventDefault();
}
break;
// BACKSPACE, DELETE: check if need to remove a mention
case $.ui.keyCode.BACKSPACE:
case $.ui.keyCode.DELETE:
this.mention_manager.check_remove();
break;
// ENTER: submit the message only if the dropdown mention proposition is not displayed
case $.ui.keyCode.ENTER:
if (this.mention_manager.is_open()) {