diff --git a/src/components/emoji-input/emoji-input.js b/src/components/emoji-input/emoji-input.js index 2a32b33be4..c425fdf525 100644 --- a/src/components/emoji-input/emoji-input.js +++ b/src/components/emoji-input/emoji-input.js @@ -31,11 +31,11 @@ const EmojiInput = { * Suggestion is an object containing following properties: * displayText: string. Main display text, what actual suggestion * represents (user's screen name/emoji shortcode) - * replacementText: string. Text that should replace the textAtCaret + * replacement: string. Text that should replace the textAtCaret * detailText: string, optional. Subtitle text, providing additional info * if present (user's nickname) * imageUrl: string, optional. Image to display alongside with suggestion, - * currently if no image is provided, replacementText will be used (for + * currently if no image is provided, replacement will be used (for * unicode emojis) * * TODO: make it asynchronous when adding proper server-provided user @@ -98,22 +98,22 @@ const EmojiInput = { if (!input) return this.input = input this.resize() - input.elm.addEventListener('transitionend', this.onTransition) input.elm.addEventListener('blur', this.onBlur) input.elm.addEventListener('focus', this.onFocus) input.elm.addEventListener('paste', this.onPaste) input.elm.addEventListener('keyup', this.onKeyUp) input.elm.addEventListener('keydown', this.onKeyDown) + input.elm.addEventListener('transitionend', this.onTransition) }, unmounted () { const { input } = this if (input) { - input.elm.removeEventListener('transitionend', this.onTransition) input.elm.removeEventListener('blur', this.onBlur) input.elm.removeEventListener('focus', this.onFocus) input.elm.removeEventListener('paste', this.onPaste) input.elm.removeEventListener('keyup', this.onKeyUp) input.elm.removeEventListener('keydown', this.onKeyDown) + input.elm.removeEventListener('transitionend', this.onTransition) } }, methods: { @@ -132,6 +132,8 @@ const EmojiInput = { this.$emit('input', newValue) this.caret = 0 this.highlighted = 0 + // Re-focus inputbox after clicking suggestion + this.input.elm.focus() e.preventDefault() } }, @@ -163,9 +165,13 @@ const EmojiInput = { this.resize(e) }, onBlur (e) { - this.focused = false - this.setCaret(e) - this.resize(e) + // Clicking on any suggestion removes focus from autocomplete, + // preventing click handler ever executing. + setTimeout(() => { + this.focused = false + this.setCaret(e) + this.resize(e) + }, 200) }, onFocus (e) { this.focused = true diff --git a/src/components/emoji-input/emoji-input.vue b/src/components/emoji-input/emoji-input.vue index 7756295736..8437a49594 100644 --- a/src/components/emoji-input/emoji-input.vue +++ b/src/components/emoji-input/emoji-input.vue @@ -6,7 +6,7 @@
diff --git a/src/components/emoji-input/suggestor.js b/src/components/emoji-input/suggestor.js index 40c7aa3d01..eb70f29928 100644 --- a/src/components/emoji-input/suggestor.js +++ b/src/components/emoji-input/suggestor.js @@ -1,3 +1,13 @@ +/** + * suggest - generates a suggestor function to be used by emoji-input + * data: object providing source information for specific types of suggestions: + * data.emoji - optional, an array of all emoji available i.e. + * (state.instance.emoji + state.instance.customEmoji) + * data.users - optional, an array of all known users + * + * Depending on data present one or both (or none) can be present, so if field + * doesn't support user linking you can just provide only emoji. + */ export default function suggest (data) { return input => { const firstChar = input[0] @@ -39,7 +49,11 @@ function suggestUsers (users) { user => user.screen_name.toLowerCase().startsWith(noPrefix) || user.name.toLowerCase().startsWith(noPrefix) - /* eslint-disable camelcase */ + + /* taking only 20 results so that sorting is a bit cheaper, we display + * only 5 anyway. could be inaccurate, but we ideally we should query + * backend anyway + */ ).slice(0, 20).sort((a, b) => { let aScore = 0 let bScore = 0 @@ -59,11 +73,12 @@ function suggestUsers (users) { const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1 return diff + nameAlphabetically + screenNameAlphabetically + /* eslint-disable camelcase */ }).map(({ screen_name, name, profile_image_url_original }) => ({ displayText: screen_name, detailText: name, imageUrl: profile_image_url_original, - replacement: '@' + screen_name + replacement: '@' + screen_name + ' ' })) /* eslint-enable camelcase */ }