From f9e4f291008654a112a6b21b71a97313d1f99307 Mon Sep 17 00:00:00 2001 From: Lordmau5 Date: Wed, 31 Jul 2019 22:25:21 +0200 Subject: [PATCH] Fix sorting (again) and implement favorite prioritization support (#619) * Implement favorite prioritization and fix sorting once and for all * Use favorites array instead of single call per emote No idea about provider-specific emotes yet * Fix sorting and rendering of emote / emoji suggestions --- .../twitch-twilight/modules/chat/input.jsx | 132 +++++++++++++++--- 1 file changed, 115 insertions(+), 17 deletions(-) diff --git a/src/sites/twitch-twilight/modules/chat/input.jsx b/src/sites/twitch-twilight/modules/chat/input.jsx index 92d36ee0..e91f8471 100644 --- a/src/sites/twitch-twilight/modules/chat/input.jsx +++ b/src/sites/twitch-twilight/modules/chat/input.jsx @@ -61,6 +61,15 @@ export default class Input extends Module { } }); + this.settings.add('chat.tab-complete.prioritize-favorites', { + default: false, + ui: { + path: 'Chat > Input >> Tab Completion', + title: 'Prioritize favorite emotes at the top.', + component: 'setting-check-box' + } + }); + // Components @@ -83,6 +92,34 @@ export default class Input extends Module { n => n && n.getMentions && n.renderMention, Twilight.CHAT_ROUTES ); + + + // Implement Twitch's unfinished emote usage object for prioritizing sorting + this.EmoteUsageCount = { + TriHard: 196568036, + Kappa: 192158118, + '4Head': 155758710, + PogChamp: 151485090, + cmonBruh: 146352878, + BibleThump: 56472964, + WutFace: 45069031, + Kreygasm: 41387580, + DansGame: 38097659, + SMOrc: 34734484, + KappaPride: 34262839, + VoHiYo: 27886434, + SwiftRage: 24561900, + ResidentSleeper: 24438298, + EleGiggle: 19891526, + FailFish: 19118343, + NotLikeThis: 18802905, + Keepo: 18351415, + BabyRage: 18220906, + MingLee: 18026207, + HeyGuys: 14851569, + ANELE: 14648986, + PJSalt: 14438861 + }; } async onEnable() { @@ -214,7 +251,7 @@ export default class Input extends Module { const limitResults = t.chat.context.get('chat.tab-complete.limit-results'); let results = t.getTwitchEmoteSuggestions(input, this); if ( limitResults && results.length >= 25 ) - return results.slice(0, 25); + return t.sortFavorites(results).slice(0, 25); if ( t.chat.context.get('chat.tab-complete.ffz-emotes') ) { const ffz_emotes = t.getEmoteSuggestions(input, this); @@ -223,7 +260,7 @@ export default class Input extends Module { } if ( limitResults && results.length >= 25 ) - return results.slice(0, 25); + return t.sortFavorites(results).slice(0, 25); if ( ! t.chat.context.get('chat.tab-complete.emoji') ) return results; @@ -232,6 +269,7 @@ export default class Input extends Module { if ( Array.isArray(emoji) && emoji.length ) results = Array.isArray(results) ? results.concat(emoji) : emoji; + results = t.sortFavorites(results); return limitResults && results.length > 25 ? results.slice(0, 25) : results; } @@ -240,18 +278,56 @@ export default class Input extends Module { inst.renderFFZEmojiSuggestion = function(data) { return ( -
+
+ {data.favorite &&
}
-
+
{data.token}
); } + + inst.renderEmoteSuggestion = function(emote) { + return ( +
+ + {emote.favorite &&
} +
+
+ {emote.token} +
+
); + } + } + + + // eslint-disable-next-line class-methods-use-this + sortFavorites(results) { + if (!this.chat.context.get('chat.tab-complete.prioritize-favorites')) { + return results; + } + + return results.sort((a, b) => { + const a_fav = a.favorite; + const b_fav = b.favorite; + if (a_fav) { + return b_fav ? a.replacement.localeCompare(b.replacement) : -1; + } + else if (b_fav) { + return 1; + } + else { + a.replacement.localeCompare(b.replacement) + } + }); } @@ -262,19 +338,31 @@ export default class Input extends Module { return []; } - const startingResults = [], otherResults = []; - const search = input.startsWith(':') ? input.slice(1) : input; + const usageResults = [], + startingResults = [], + otherResults = [], + favorites = this.emotes.getFavorites('twitch'), + search = input.startsWith(':') ? input.slice(1) : input; + for (const set of hydratedEmotes) { if (set && Array.isArray(set.emotes)) { for (const emote of set.emotes) { if (inst.doesEmoteMatchTerm(emote, search)) { + const favorite = favorites.includes(parseInt(emote.id, 10)); const element = { current: input, replacement: emote.token, - element: inst.renderEmoteSuggestion(emote) + element: inst.renderEmoteSuggestion({ + ...emote, + favorite + }), + favorite }; - if (emote.token.toLowerCase().startsWith(search)) { + if (this.EmoteUsageCount[emote.token]) { + usageResults.push(element); + } + else if (emote.token.toLowerCase().startsWith(search)) { startingResults.push(element); } else { @@ -285,10 +373,11 @@ export default class Input extends Module { } } - startingResults.sort((a, b) => a.replacement < b.replacement ? -1 : a.replacement > b.replacement ? 1 : 0); - otherResults.sort((a, b) => a.replacement < b.replacement ? -1 : a.replacement > b.replacement ? 1 : 0); + usageResults.sort((a, b) => this.EmoteUsageCount[b.replacement] - this.EmoteUsageCount[a.replacement]); + startingResults.sort((a, b) => a.replacement.localeCompare(b.replacement)); + otherResults.sort((a, b) => a.replacement.localeCompare(b.replacement)); - return startingResults.concat(otherResults); + return usageResults.concat(startingResults).concat(otherResults); } @@ -300,6 +389,7 @@ export default class Input extends Module { let search = input.slice(1).toLowerCase(); const style = this.chat.context.get('chat.emoji.style'), tone = this.settings.provider.get('emoji-tone', null), + favorites = this.emotes.getFavorites('emoji'), results = [], has_colon = search.endsWith(':'); @@ -312,7 +402,8 @@ export default class Input extends Module { toned = emoji.variants && emoji.variants[tone], source = toned || emoji; - if ( emoji && (style === 0 || source.has[style]) ) + if ( emoji && (style === 0 || source.has[style]) ) { + const favorite = favorites.includes(emoji.code); results.push({ current: input, replacement: source.raw, @@ -320,9 +411,12 @@ export default class Input extends Module { token: `:${name}:`, id: `emoji-${emoji.code}`, src: this.emoji.getFullImage(source.image, style), - srcSet: this.emoji.getFullImageSet(source.image, style) - }) + srcSet: this.emoji.getFullImageSet(source.image, style), + favorite + }), + favorite }); + } } return results; @@ -353,16 +447,20 @@ export default class Input extends Module { ); for(const emote of Object.values(emotes)) - if ( inst.doesEmoteMatchTerm(emote, search) ) + if ( inst.doesEmoteMatchTerm(emote, search) ) { + const favorite = this.emotes.isFavorite(emote.token.provider, emote.id); results.push({ current: input, replacement: emote.name, element: inst.renderEmoteSuggestion({ token: emote.name, id: `${emote.token.provider}-${emote.id}`, - srcSet: emote.srcSet - }) + srcSet: emote.srcSet, + favorite + }), + favorite }); + } return results; }