mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-02 07:58:31 +00:00
Fixes and improves tab-completion hook (#613)
* Fixes tab-completion for emotes added by FFZ * Implement tab-completion of emotes without the need of the colon If enabled this will prevent username tab-completion without the @ in-front of the name, but will allow emotes to be tab-completed without the need of the colon in-front * Implement result limit of 25 with setting
This commit is contained in:
parent
f1c527b721
commit
3120d586d2
1 changed files with 94 additions and 7 deletions
|
@ -42,12 +42,31 @@ export default class Input extends Module {
|
|||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.tab-complete.emotes-without-colon', {
|
||||
default: false,
|
||||
ui: {
|
||||
path: 'Chat > Input >> Tab Completion',
|
||||
title: 'Allow tab-completion of emotes without typing a colon. (:)',
|
||||
description: 'This will prevent the tab-completion of usernames without the @ prefix.',
|
||||
component: 'setting-check-box'
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.tab-complete.limit-results', {
|
||||
default: true,
|
||||
ui: {
|
||||
path: 'Chat > Input >> Tab Completion',
|
||||
title: 'Limit tab-completion results to 25.',
|
||||
component: 'setting-check-box'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Components
|
||||
|
||||
this.ChatInput = this.fine.define(
|
||||
'chat-input',
|
||||
n => n && n.setChatInputRef && n.setAutocompleteInputRef,
|
||||
n => n && n.setChatInputRef && n.setLocalAutocompleteInputRef,
|
||||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
|
||||
|
@ -57,10 +76,24 @@ export default class Input extends Module {
|
|||
n => n && n.getMatchedEmotes,
|
||||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
|
||||
|
||||
this.MentionSuggestions = this.fine.define(
|
||||
'tab-mention-suggestions',
|
||||
n => n && n.getMentions && n.renderMention,
|
||||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
}
|
||||
|
||||
async onEnable() {
|
||||
this.chat.context.on('changed:chat.actions.room', () => this.ChatInput.forceUpdate());
|
||||
this.chat.context.on('changed:chat.tab-complete.emotes-without-colon', enabled => {
|
||||
for (const inst of this.EmoteSuggestions.instances)
|
||||
inst.canBeTriggeredByTab = enabled;
|
||||
|
||||
for (const inst of this.MentionSuggestions.instances)
|
||||
inst.canBeTriggeredByTab = !enabled;
|
||||
});
|
||||
|
||||
const React = await this.web_munch.findModule('react'),
|
||||
createElement = React && React.createElement;
|
||||
|
@ -119,8 +152,14 @@ export default class Input extends Module {
|
|||
this.overrideEmoteMatcher(inst);
|
||||
});
|
||||
|
||||
this.MentionSuggestions.ready((cls, instances) => {
|
||||
for(const inst of instances)
|
||||
this.overrideMentionMatcher(inst);
|
||||
});
|
||||
|
||||
this.ChatInput.on('update', this.updateEmoteCompletion, this);
|
||||
this.EmoteSuggestions.on('mount', this.overrideEmoteMatcher, this);
|
||||
this.MentionSuggestions.on('mount', this.overrideMentionMatcher, this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,12 +175,28 @@ export default class Input extends Module {
|
|||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
overrideMentionMatcher(inst) {
|
||||
if ( inst._ffz_override )
|
||||
return;
|
||||
|
||||
inst.canBeTriggeredByTab = !this.chat.context.get('chat.tab-complete.emotes-without-colon');
|
||||
}
|
||||
|
||||
|
||||
overrideEmoteMatcher(inst) {
|
||||
if ( inst._ffz_override )
|
||||
return;
|
||||
|
||||
const t = this,
|
||||
old_get_matched = inst.getMatchedEmotes;
|
||||
const t = this;
|
||||
|
||||
inst.canBeTriggeredByTab = this.chat.context.get('chat.tab-complete.emotes-without-colon');
|
||||
|
||||
inst.getMatches = function(input, pressedTab) {
|
||||
return pressedTab
|
||||
? input.length < 2 ? null : inst.getMatchedEmotes(input)
|
||||
: input.startsWith(':') ? input.length < 3 ? null : inst.getMatchedEmotes(input) : null;
|
||||
}
|
||||
|
||||
inst.doesEmoteMatchTerm = function(emote, term) {
|
||||
const emote_name = emote.name || emote.token,
|
||||
|
@ -157,7 +212,9 @@ export default class Input extends Module {
|
|||
}
|
||||
|
||||
inst.getMatchedEmotes = function(input) {
|
||||
let results = old_get_matched.call(this, input);
|
||||
const limitResults = t.chat.context.get('chat.tab-complete.limit-results');
|
||||
|
||||
let results = t.getTwitchEmoteSuggestions(input, this);
|
||||
|
||||
if ( t.chat.context.get('chat.tab-complete.ffz-emotes') ) {
|
||||
const ffz_emotes = t.getEmoteSuggestions(input, this);
|
||||
|
@ -166,13 +223,13 @@ export default class Input extends Module {
|
|||
}
|
||||
|
||||
if ( ! t.chat.context.get('chat.tab-complete.emoji') )
|
||||
return results;
|
||||
return limitResults && results.length > 25 ? results.slice(0, 25) : results;
|
||||
|
||||
const emoji = t.getEmojiSuggestions(input, this);
|
||||
if ( Array.isArray(emoji) && emoji.length )
|
||||
results = Array.isArray(results) ? results.concat(emoji) : emoji;
|
||||
|
||||
return results;
|
||||
return limitResults && results.length > 25 ? results.slice(0, 25) : results;
|
||||
}
|
||||
|
||||
const React = this.web_munch.getModule('react'),
|
||||
|
@ -194,8 +251,38 @@ export default class Input extends Module {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getTwitchEmoteSuggestions(input, inst) {
|
||||
const hydratedEmotes = inst.hydrateEmotes(inst.props.emotes);
|
||||
if (!Array.isArray(hydratedEmotes)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const results = [];
|
||||
const 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)) {
|
||||
results.push({
|
||||
current: input,
|
||||
replacement: emote.token,
|
||||
element: inst.renderEmoteSuggestion(emote)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
getEmojiSuggestions(input, inst) {
|
||||
if (!input.startsWith(':')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let search = input.slice(1).toLowerCase();
|
||||
const style = this.chat.context.get('chat.emoji.style'),
|
||||
tone = this.settings.provider.get('emoji-tone', null),
|
||||
|
@ -242,7 +329,7 @@ export default class Input extends Module {
|
|||
return [];
|
||||
}
|
||||
|
||||
const search = input.slice(1),
|
||||
const search = input.startsWith(':') ? input.slice(1) : input,
|
||||
results = [],
|
||||
emotes = this.emotes.getEmotes(
|
||||
user && user.id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue