commit: a7f836a64e334d6c46ed1e12c7bf9b2ff4a09c7e
parent a758e18dceb4cb11d84d6dff1cdfddb755af60db
Author: Tusooa Zhu <tusooa@kazv.moe>
Date: Wed, 21 Sep 2022 23:16:33 -0400
Make suggestor suggest according to cldr annotations
Diffstat:
3 files changed, 64 insertions(+), 19 deletions(-)
diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js
@@ -3,7 +3,7 @@ import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
import { take } from 'lodash'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
-
+import { ensureFinalFallback } from '../../i18n/languages.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faSmileBeam
@@ -143,6 +143,51 @@ const EmojiInput = {
const word = Completion.wordAtPosition(this.modelValue, this.caret - 1) || {}
return word
}
+ },
+ languages () {
+ return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)
+ },
+ maybeLocalizedEmojiNamesAndKeywords () {
+ return emoji => {
+ const names = [emoji.displayText]
+ const keywords = []
+
+ if (emoji.displayTextI18n) {
+ names.push(this.$t(emoji.displayTextI18n.key, emoji.displayTextI18n.args))
+ }
+
+ if (emoji.annotations) {
+ this.languages.forEach(lang => {
+ names.push(emoji.annotations[lang]?.name)
+
+ keywords.push(...(emoji.annotations[lang]?.keywords || []))
+ })
+ }
+
+ return {
+ names: names.filter(k => k),
+ keywords: keywords.filter(k => k)
+ }
+ }
+ },
+ maybeLocalizedEmojiName () {
+ return emoji => {
+ if (!emoji.annotations) {
+ return emoji.displayText
+ }
+
+ if (emoji.displayTextI18n) {
+ return this.$t(emoji.displayTextI18n.key, emoji.displayTextI18n.args)
+ }
+
+ for (const lang of this.languages) {
+ if (emoji.annotations[lang]?.name) {
+ return emoji.annotations[lang].name
+ }
+ }
+
+ return emoji.displayText
+ }
}
},
mounted () {
@@ -181,7 +226,7 @@ const EmojiInput = {
const firstchar = newWord.charAt(0)
this.suggestions = []
if (newWord === firstchar) return
- const matchedSuggestions = await this.suggest(newWord)
+ const matchedSuggestions = await this.suggest(newWord, this.maybeLocalizedEmojiNamesAndKeywords)
// Async: cancel if textAtCaret has changed during wait
if (this.textAtCaret !== newWord) return
if (matchedSuggestions.length <= 0) return
diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue
@@ -64,7 +64,7 @@
v-if="!suggestion.user"
class="displayText"
>
- {{ suggestion.displayText }}
+ {{ maybeLocalizedEmojiName(suggestion) }}
</span>
<span class="detailText">{{ suggestion.detailText }}</span>
</div>
diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js
@@ -13,10 +13,10 @@
export default data => {
const emojiCurry = suggestEmoji(data.emoji)
const usersCurry = data.store && suggestUsers(data.store)
- return input => {
+ return (input, nameKeywordLocalizer) => {
const firstChar = input[0]
if (firstChar === ':' && data.emoji) {
- return emojiCurry(input)
+ return emojiCurry(input, nameKeywordLocalizer)
}
if (firstChar === '@' && usersCurry) {
return usersCurry(input)
@@ -25,34 +25,34 @@ export default data => {
}
}
-export const suggestEmoji = emojis => input => {
+export const suggestEmoji = emojis => (input, nameKeywordLocalizer) => {
const noPrefix = input.toLowerCase().substr(1)
return emojis
- .filter(({ displayText }) => displayText.toLowerCase().match(noPrefix))
- .sort((a, b) => {
- let aScore = 0
- let bScore = 0
+ .map(emoji => ({ ...emoji, ...nameKeywordLocalizer(emoji) }))
+ .filter((emoji) => (emoji.names.concat(emoji.keywords)).filter(kw => kw.toLowerCase().match(noPrefix)).length)
+ .map(k => {
+ let score = 0
// An exact match always wins
- aScore += a.displayText.toLowerCase() === noPrefix ? 200 : 0
- bScore += b.displayText.toLowerCase() === noPrefix ? 200 : 0
+ score += Math.max(...k.names.map(name => name.toLowerCase() === noPrefix ? 200 : 0), 0)
// Prioritize custom emoji a lot
- aScore += a.imageUrl ? 100 : 0
- bScore += b.imageUrl ? 100 : 0
+ score += k.imageUrl ? 100 : 0
// Prioritize prefix matches somewhat
- aScore += a.displayText.toLowerCase().startsWith(noPrefix) ? 10 : 0
- bScore += b.displayText.toLowerCase().startsWith(noPrefix) ? 10 : 0
+ score += Math.max(...k.names.map(kw => kw.toLowerCase().startsWith(noPrefix) ? 10 : 0), 0)
// Sort by length
- aScore -= a.displayText.length
- bScore -= b.displayText.length
+ score -= k.displayText.length
+ k.score = score
+ return k
+ })
+ .sort((a, b) => {
// Break ties alphabetically
const alphabetically = a.displayText > b.displayText ? 0.5 : -0.5
- return bScore - aScore + alphabetically
+ return b.score - a.score + alphabetically
})
}