diff --git a/CHANGES.md b/CHANGES.md index 7f2fdac83..9ea7adeaf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,9 @@ To add custom emojis, edit the `emojis.json` file. - Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`. - New API [\_converse.api.headlines](https://conversejs.org/docs/html/api/-_converse.api.headlines.html#.get) +- New config option [muc_mention_autocomplete_filter](https://conversejs.org/docs/html/configuration.html#muc_mention_autocomplete_filter) +- New config option [muc_mention_autocomplete_show_avatar](https://conversejs.org/docs/html/configuration.html#muc_mention_autocomplete_show_avatar) + ### Breaking changes diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 1b523f285..f6b0d3aa7 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -941,6 +941,21 @@ muc_mention_autocomplete_min_chars The number of characters that need to be entered before the auto-complete list of matching nicknames is shown. +muc_mention_autocomplete_filter +------------------------------- + +* Default: ``contains`` + +The method used for filtering MUC participants when using auto-complete. +Valid values are ``contains`` and ``starts_with``. + +muc_mention_autocomplete_show_avatar +------------------------------- + +* Default: ``true`` + +Show avatars of MUC participants when using auto-complete. + message_archiving ----------------- diff --git a/sass/_core.scss b/sass/_core.scss index 55cfe4afc..7a0271571 100644 --- a/sass/_core.scss +++ b/sass/_core.scss @@ -504,6 +504,11 @@ body.converse-fullscreen { background-color: var(--avatar-background-color); } + .avatar-autocomplete { + margin-right: 0.5em; + vertical-align: middle; + } + .activated { display: block !important; } diff --git a/src/converse-muc-views.js b/src/converse-muc-views.js index 96f35a292..3e4efa634 100644 --- a/src/converse-muc-views.js +++ b/src/converse-muc-views.js @@ -111,6 +111,8 @@ converse.plugins.add('converse-muc-views', { 'muc_show_join_leave': true, 'muc_show_join_leave_status': true, 'muc_mention_autocomplete_min_chars': 0, + 'muc_mention_autocomplete_filter': 'contains', + 'muc_mention_autocomplete_show_avatar': true, 'roomconfig_whitelist': [], 'visible_toolbar_buttons': { 'toggle_occupants': true @@ -744,6 +746,42 @@ converse.plugins.add('converse-muc-views', { return this.model.occupants.filter('nick').map(o => ({'label': o.get('nick'), 'value': `@${o.get('nick')}`})); }, + getAutoCompleteListItem(text, input) { + input = input.trim(); + const element = document.createElement("li"); + element.setAttribute("aria-selected", "false"); + + if (_converse.muc_mention_autocomplete_show_avatar) { + const img = document.createElement("img"); + let dataUri = "data:" + _converse.DEFAULT_IMAGE_TYPE + ";base64," + _converse.DEFAULT_IMAGE; + + if (_converse.vcards) { + const vcard = _converse.vcards.findWhere({'nickname': text}); + if (vcard) dataUri = "data:" + vcard.get('image_type') + ";base64," + vcard.get('image'); + } + + img.setAttribute("src", dataUri); + img.setAttribute("width", "22"); + img.setAttribute("class", "avatar avatar-autocomplete"); + element.appendChild(img); + } + + const regex = new RegExp("(" + input + ")", "ig"); + const parts = input ? text.split(regex) : [text]; + + parts.forEach(txt => { + if (input && txt.match(regex)) { + const match = document.createElement("mark"); + match.textContent = txt; + element.appendChild(match); + } else { + element.appendChild(document.createTextNode(txt)); + } + }); + + return element; + }, + initMentionAutoComplete () { this.mention_auto_complete = new _converse.AutoComplete(this.el, { 'auto_first': true, @@ -751,9 +789,10 @@ converse.plugins.add('converse-muc-views', { 'min_chars': _converse.muc_mention_autocomplete_min_chars, 'match_current_word': true, 'list': () => this.getAutoCompleteList(), - 'filter': _converse.FILTER_STARTSWITH, + 'filter': _converse.muc_mention_autocomplete_filter == 'contains' ? _converse.FILTER_CONTAINS : _converse.FILTER_STARTSWITH, 'ac_triggers': ["Tab", "@"], - 'include_triggers': [] + 'include_triggers': [], + 'item': this.getAutoCompleteListItem }); this.mention_auto_complete.on('suggestion-box-selectcomplete', () => (this.auto_completing = false)); },