diff --git a/app/js/controllers.js b/app/js/controllers.js index a054bb8c..723f2c8f 100644 --- a/app/js/controllers.js +++ b/app/js/controllers.js @@ -2291,11 +2291,8 @@ angular.module('myApp.controllers', ['myApp.i18n']) return } done[userID] = true - var user = AppUsersManager.getUser(userID) - if (user.username) { - mentionUsers.push(user) - SearchIndexManager.indexObject(user.id, AppUsersManager.getUserSearchText(user.id), mentionIndex) - } + mentionUsers.push(AppUsersManager.getUser(userID)) + SearchIndexManager.indexObject(userID, AppUsersManager.getUserSearchText(userID), mentionIndex) }) safeReplaceObject($scope.mentions, { diff --git a/app/js/lib/ng_utils.js b/app/js/lib/ng_utils.js index 625e1069..b60ba817 100644 --- a/app/js/lib/ng_utils.js +++ b/app/js/lib/ng_utils.js @@ -1227,7 +1227,7 @@ angular.module('izhukov.utils', []) var soundcloudRegExp = /^https?:\/\/(?:soundcloud\.com|snd\.sc)\/([a-zA-Z0-9%\-\_]+)\/([a-zA-Z0-9%\-\_]+)/i var spotifyRegExp = /(https?:\/\/(open\.spotify\.com|play\.spotify\.com|spoti\.fi)\/(.+)|spotify:(.+))/i - var markdownRegExp = /(^|\s)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)`([^\n]+?)`([\s\.,:?!;]|$)/ + var markdownRegExp = /(^|\s)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)`([^\n]+?)`([\s\.,:?!;]|$)|@(\d+)\s*\((.+?)\)/ var siteHashtags = { Telegram: 'tg://search_hashtag?hashtag={1}', @@ -1391,7 +1391,7 @@ angular.module('izhukov.utils', []) } function parseMarkdown (text, entities) { - if (text.indexOf('`') == -1) { + if (text.indexOf('`') == -1 && text.indexOf('@') == -1) { return text.trim() } var raw = text @@ -1403,7 +1403,7 @@ angular.module('izhukov.utils', []) matchIndex = rawOffset + match.index newText.push(raw.substr(0, match.index)) - var text = (match[3] || match[7]) + var text = (match[3] || match[7] || match[10]) rawOffset -= text.length text = text.replace(/^\s+|\s+$/g, '') rawOffset += text.length @@ -1424,7 +1424,7 @@ angular.module('izhukov.utils', []) length: text.length }) rawOffset -= match[2].length + match[4].length - } else { // code + } else if (match[7]) { // code newText.push(match[6] + text + match[8]) entities.push({ _: 'messageEntityCode', @@ -1432,6 +1432,16 @@ angular.module('izhukov.utils', []) length: text.length }) rawOffset -= 2 + } else if (match[10]) { // custom mention + console.log(match); + newText.push(text) + entities.push({ + _: 'messageEntityMentionName', + user_id: match[9], + offset: matchIndex, + length: text.length + }) + rawOffset -= match[0] - text.length } raw = raw.substr(match.index + match[0].length) rawOffset += match.index + match[0].length @@ -1446,6 +1456,8 @@ angular.module('izhukov.utils', []) if (!entities.length) { newText = newText.trim() } + console.warn(dT(), newText, entities); + // throw new Error(11); return newText } @@ -1584,6 +1596,21 @@ angular.module('izhukov.utils', []) ) break + case 'messageEntityMentionName': + if (!options.noLinks) { + skipEntity = true + break + } + var username = entityText.substr(1) + html.push( + '', + encodeEntities(entityText), + '' + ) + break + case 'messageEntityHashtag': var contextUrl = !options.noLinks && siteHashtags[contextSite] if (!contextUrl) { @@ -1780,6 +1807,12 @@ angular.module('izhukov.utils', []) ) break + case 'messageEntityMentionName': + code.push( + '@', entity.user_id, ' (', entityText, ')' + ) + break + default: skipEntity = true } diff --git a/app/js/message_composer.js b/app/js/message_composer.js index 2c0b8be3..1a118a9b 100644 --- a/app/js/message_composer.js +++ b/app/js/message_composer.js @@ -777,7 +777,7 @@ MessageComposer.prototype.setUpAutoComplete = function () { EmojiHelper.pushPopularEmoji(code) } if (mention = target.attr('data-mention')) { - self.onMentionSelected(mention) + self.onMentionSelected(mention, target.attr('data-name')) } if (command = target.attr('data-command')) { if (self.onCommandSelected) { @@ -903,7 +903,7 @@ MessageComposer.prototype.onKeyEvent = function (e) { return cancelEvent(e) } if (mention = currentSel.attr('data-mention')) { - this.onMentionSelected(mention) + this.onMentionSelected(mention, currentSel.attr('data-name')) return cancelEvent(e) } if (command = currentSel.attr('data-command')) { @@ -1272,7 +1272,14 @@ MessageComposer.prototype.onMentionsUpdated = function (username) { } } -MessageComposer.prototype.onMentionSelected = function (username) { +MessageComposer.prototype.onMentionSelected = function (username, firstName) { + var hasUsername = true; + if (username.charAt(0) == '#') { + hasUsername = false; + username = username.substr(1); + firstName = firstName.replace(/\(\)@/, '') + } + if (this.richTextareaEl) { var textarea = this.richTextareaEl[0] if (!this.isActive) { @@ -1293,20 +1300,26 @@ MessageComposer.prototype.onMentionSelected = function (username) { } else { newValuePrefix = prefix + '@' + username } - textarea.value = newValue var html - if (suffix.length) { - this.selId = (this.selId || 0) + 1 - html = this.getRichHtml(newValuePrefix) + ' ' + this.getRichHtml(suffix) - this.richTextareaEl.html(html) - setRichFocus(textarea, $('#composer_sel' + this.selId)[0]) + if (hasUsername) { + if (suffix.length) { + this.selId = (this.selId || 0) + 1 + html = this.getRichHtml(newValuePrefix) + ' ' + this.getRichHtml(suffix) + this.richTextareaEl.html(html) + setRichFocus(textarea, $('#composer_sel' + this.selId)[0]) + } else { + html = this.getRichHtml(newValuePrefix) + ' ' + this.richTextareaEl.html(html) + setRichFocus(textarea) + } } else { - html = this.getRichHtml(newValuePrefix) + ' ' + this.selId = (this.selId || 0) + 1 + html = this.getRichHtml(newValuePrefix) + ' (' + encodeEntities(firstName) + ') ' + this.getRichHtml(suffix) this.richTextareaEl.html(html) - setRichFocus(textarea) + setRichFocus(textarea, $('#composer_sel' + this.selId)[0], true) } - }else { + } else { var textarea = this.textareaEl[0] var fullValue = textarea.value var pos = this.isActive ? getFieldSelection(textarea) : fullValue.length @@ -1314,15 +1327,26 @@ MessageComposer.prototype.onMentionSelected = function (username) { var prefix = fullValue.substr(0, pos) var matches = prefix.match(/@([A-Za-z0-9\-\+\*_]*)$/) + var newValuePrefix + var newValue + var newPos + var newPosTo if (matches && matches[0]) { - var newValue = prefix.substr(0, matches.index) + '@' + username + ' ' + suffix - var newPos = matches.index + username.length + 2 + newValuePrefix = prefix.substr(0, matches.index) + '@' + username + } else { + newValuePrefix = prefix + '@' + username + } + + if (hasUsername) { + newValue = newValuePrefix + '@' + username + ' ' + suffix + newPos = matches.index + username.length + 2 } else { - var newValue = prefix + ':' + username + ': ' + suffix - var newPos = prefix.length + username.length + 2 + newValue = newValuePrefix + '@' + username + ' (' + firstName + ') ' + suffix + newPos = matches.index + username.length + 2 + newPosTo = newPos + firstName.length } textarea.value = newValue - setFieldSelection(textarea, newPos) + setFieldSelection(textarea, newPos, newPosTo) } this.hideSuggestions() diff --git a/app/js/messages_manager.js b/app/js/messages_manager.js index 385543d5..6c35ca11 100644 --- a/app/js/messages_manager.js +++ b/app/js/messages_manager.js @@ -1258,6 +1258,17 @@ angular.module('myApp.services') if (!options.viaBotID) { text = RichTextProcessor.parseMarkdown(text, entities) } + var sendEntites = entities + if (entities.length) { + sendEntites = angular.copy(entities) + angular.forEach(sendEntites, function (entity) { + if (entity._ == 'messageEntityMentionName') { + entity._ = 'inputMessageEntityMentionName' + entity.user_id = AppUsersManager.getUserInput(entity.user_id) + } + }) + } + if (!text.length) { return } @@ -1308,7 +1319,7 @@ angular.module('myApp.services') reply_to_msg_id: replyToMsgID, via_bot_id: options.viaBotID, reply_markup: options.reply_markup, - entities: entities, + entities: sendEntites, views: asChannel && 1, pending: true } diff --git a/app/partials/desktop/composer_dropdown.html b/app/partials/desktop/composer_dropdown.html index f1d5e4ed..e50c05a4 100644 --- a/app/partials/desktop/composer_dropdown.html +++ b/app/partials/desktop/composer_dropdown.html @@ -2,10 +2,10 @@