mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-09-15 17:46:55 +00:00
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
This commit is contained in:
parent
37ef0c250e
commit
f9e4f29100
1 changed files with 115 additions and 17 deletions
|
@ -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
|
// Components
|
||||||
|
|
||||||
|
@ -83,6 +92,34 @@ export default class Input extends Module {
|
||||||
n => n && n.getMentions && n.renderMention,
|
n => n && n.getMentions && n.renderMention,
|
||||||
Twilight.CHAT_ROUTES
|
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() {
|
async onEnable() {
|
||||||
|
@ -214,7 +251,7 @@ export default class Input extends Module {
|
||||||
const limitResults = t.chat.context.get('chat.tab-complete.limit-results');
|
const limitResults = t.chat.context.get('chat.tab-complete.limit-results');
|
||||||
let results = t.getTwitchEmoteSuggestions(input, this);
|
let results = t.getTwitchEmoteSuggestions(input, this);
|
||||||
if ( limitResults && results.length >= 25 )
|
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') ) {
|
if ( t.chat.context.get('chat.tab-complete.ffz-emotes') ) {
|
||||||
const ffz_emotes = t.getEmoteSuggestions(input, this);
|
const ffz_emotes = t.getEmoteSuggestions(input, this);
|
||||||
|
@ -223,7 +260,7 @@ export default class Input extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( limitResults && results.length >= 25 )
|
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') )
|
if ( ! t.chat.context.get('chat.tab-complete.emoji') )
|
||||||
return results;
|
return results;
|
||||||
|
@ -232,6 +269,7 @@ export default class Input extends Module {
|
||||||
if ( Array.isArray(emoji) && emoji.length )
|
if ( Array.isArray(emoji) && emoji.length )
|
||||||
results = Array.isArray(results) ? results.concat(emoji) : emoji;
|
results = Array.isArray(results) ? results.concat(emoji) : emoji;
|
||||||
|
|
||||||
|
results = t.sortFavorites(results);
|
||||||
return limitResults && results.length > 25 ? results.slice(0, 25) : 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) {
|
inst.renderFFZEmojiSuggestion = function(data) {
|
||||||
return (<React.Fragment>
|
return (<React.Fragment>
|
||||||
<div class="tw-pd-r-05">
|
<div class="tw-relative tw-flex-shrink-0 tw-pd-r-05" title={data.token} favorite={data.favorite}>
|
||||||
<img
|
<img
|
||||||
class="emote-autocomplete-provider__image ffz-emoji"
|
class="emote-autocomplete-provider__image ffz-emoji"
|
||||||
src={data.src}
|
src={data.src}
|
||||||
srcSet={data.srcset}
|
srcSet={data.srcset}
|
||||||
/>
|
/>
|
||||||
|
{data.favorite && <figure class="ffz--favorite ffz-i-star" />}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="tw-ellipsis" title={data.token}>
|
||||||
{data.token}
|
{data.token}
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>);
|
</React.Fragment>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inst.renderEmoteSuggestion = function(emote) {
|
||||||
|
return (<React.Fragment>
|
||||||
|
<div class="tw-relative tw-flex-shrink-0 tw-pd-r-05" title={emote.token} favorite={emote.favorite}>
|
||||||
|
<img
|
||||||
|
class="emote-autocomplete-provider__image"
|
||||||
|
srcSet={emote.srcSet}
|
||||||
|
/>
|
||||||
|
{emote.favorite && <figure class="ffz--favorite ffz-i-star" />}
|
||||||
|
</div>
|
||||||
|
<div class="tw-ellipsis" title={emote.token}>
|
||||||
|
{emote.token}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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 [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const startingResults = [], otherResults = [];
|
const usageResults = [],
|
||||||
const search = input.startsWith(':') ? input.slice(1) : input;
|
startingResults = [],
|
||||||
|
otherResults = [],
|
||||||
|
favorites = this.emotes.getFavorites('twitch'),
|
||||||
|
search = input.startsWith(':') ? input.slice(1) : input;
|
||||||
|
|
||||||
for (const set of hydratedEmotes) {
|
for (const set of hydratedEmotes) {
|
||||||
if (set && Array.isArray(set.emotes)) {
|
if (set && Array.isArray(set.emotes)) {
|
||||||
for (const emote of set.emotes) {
|
for (const emote of set.emotes) {
|
||||||
if (inst.doesEmoteMatchTerm(emote, search)) {
|
if (inst.doesEmoteMatchTerm(emote, search)) {
|
||||||
|
const favorite = favorites.includes(parseInt(emote.id, 10));
|
||||||
const element = {
|
const element = {
|
||||||
current: input,
|
current: input,
|
||||||
replacement: emote.token,
|
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);
|
startingResults.push(element);
|
||||||
}
|
}
|
||||||
else {
|
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);
|
usageResults.sort((a, b) => this.EmoteUsageCount[b.replacement] - this.EmoteUsageCount[a.replacement]);
|
||||||
otherResults.sort((a, b) => a.replacement < b.replacement ? -1 : a.replacement > b.replacement ? 1 : 0);
|
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();
|
let search = input.slice(1).toLowerCase();
|
||||||
const style = this.chat.context.get('chat.emoji.style'),
|
const style = this.chat.context.get('chat.emoji.style'),
|
||||||
tone = this.settings.provider.get('emoji-tone', null),
|
tone = this.settings.provider.get('emoji-tone', null),
|
||||||
|
favorites = this.emotes.getFavorites('emoji'),
|
||||||
results = [],
|
results = [],
|
||||||
has_colon = search.endsWith(':');
|
has_colon = search.endsWith(':');
|
||||||
|
|
||||||
|
@ -312,7 +402,8 @@ export default class Input extends Module {
|
||||||
toned = emoji.variants && emoji.variants[tone],
|
toned = emoji.variants && emoji.variants[tone],
|
||||||
source = toned || emoji;
|
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({
|
results.push({
|
||||||
current: input,
|
current: input,
|
||||||
replacement: source.raw,
|
replacement: source.raw,
|
||||||
|
@ -320,10 +411,13 @@ export default class Input extends Module {
|
||||||
token: `:${name}:`,
|
token: `:${name}:`,
|
||||||
id: `emoji-${emoji.code}`,
|
id: `emoji-${emoji.code}`,
|
||||||
src: this.emoji.getFullImage(source.image, style),
|
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;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -353,16 +447,20 @@ export default class Input extends Module {
|
||||||
);
|
);
|
||||||
|
|
||||||
for(const emote of Object.values(emotes))
|
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({
|
results.push({
|
||||||
current: input,
|
current: input,
|
||||||
replacement: emote.name,
|
replacement: emote.name,
|
||||||
element: inst.renderEmoteSuggestion({
|
element: inst.renderEmoteSuggestion({
|
||||||
token: emote.name,
|
token: emote.name,
|
||||||
id: `${emote.token.provider}-${emote.id}`,
|
id: `${emote.token.provider}-${emote.id}`,
|
||||||
srcSet: emote.srcSet
|
srcSet: emote.srcSet,
|
||||||
})
|
favorite
|
||||||
|
}),
|
||||||
|
favorite
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue