Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added an 'always on' emote autocompletion option #1121

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/options/views/Onboarding/OnboardingConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ const questions = ref<Question[]>([
id: "chatter-config-autocompletion",
kind: "config",
configEffect: [
"chat_input.autocomplete.colon",
"chat_input.autocomplete.colon.emoji",
"chat_input.autocomplete",
"chat_input.autocomplete.emoji",
"chat_input.autocomplete.carousel",
"chat_input.autocomplete.carousel_arrow_keys",
"chat_input.autocomplete.chatters",
Expand Down
49 changes: 42 additions & 7 deletions src/site/twitch.tv/modules/chat-input/ChatInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ const props = defineProps<{
instance: HookedInstance<Twitch.ChatAutocompleteComponent>;
}>();

interface AutocompleteResult {
current: string;
type: string;
element: unknown;
replacement: string;
}

const mod = getModule<"TWITCH", "chat-input">("chat-input");
const store = useStore();
const ctx = useChannelContext(props.instance.component.componentRef.props.channelID, true);
Expand All @@ -47,12 +54,12 @@ const emotes = useChatEmotes(ctx);
const cosmetics = useCosmetics(store.identity?.id ?? "");
const ua = useUserAgent();

const shouldUseColonComplete = useConfig("chat_input.autocomplete.colon");
const shouldColonCompleteEmoji = useConfig("chat_input.autocomplete.colon.emoji");
const autocompletionMode = useConfig("chat_input.autocomplete");
const shouldColonCompleteEmoji = useConfig("chat_input.autocomplete.emoji");
const shouldAutocompleteChatters = useConfig("chat_input.autocomplete.chatters");
const shouldRenderAutocompleteCarousel = useConfig("chat_input.autocomplete.carousel");
const mayUseControlEnter = useConfig("chat_input.spam.rapid_fire_send");
const colonCompletionMode = useConfig<number>("chat_input.autocomplete.colon.mode");
const colonCompletionMode = useConfig<number>("chat_input.autocomplete.mode");
const tabCompletionMode = useConfig<number>("chat_input.autocomplete.carousel.mode");

const providers = ref<Record<string, Twitch.ChatAutocompleteProvider>>({});
Expand Down Expand Up @@ -407,13 +414,41 @@ function onKeyDown(ev: KeyboardEvent) {
}

function getMatchesHook(this: unknown, native: ((...args: unknown[]) => object[]) | null, str: string, ...args: []) {
if (!str.startsWith(":") || str.length < 3) return;
if (!shouldUseColonComplete.value) return;
let completionMode;
switch (autocompletionMode.value) {
case 0:
completionMode = "off";
break;
case 1:
completionMode = "colon";
break;
case 2:
completionMode = "on";
break;

default:
break;
}

const results = native?.call(this, str, ...args) ?? [];
if (completionMode === "off") return;

if (completionMode === "colon" && !str.startsWith(":")) return;

const search = str.startsWith(":") ? str.substring(1) : str;

if (search.length < 2) {
return;
}

const results = (native?.call(this, `:${search}`, ...args) ?? []) as AutocompleteResult[];

if (completionMode === "on") {
results.map((r) => (r.current = str));
}

const allEmotes = { ...cosmetics.emotes, ...emotes.active, ...emotes.emojis };
const tokens = findMatchingTokens(str.substring(1), "colon", 25);

const tokens = findMatchingTokens(search, "colon", 25);

for (let i = tokens.length - 1; i > -1; i--) {
const token = tokens[i].token;
Expand Down
36 changes: 22 additions & 14 deletions src/site/twitch.tv/modules/chat-input/ChatInputModule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,29 @@ markAsReady();

<script lang="ts">
export const config = [
declareConfig("chat_input.autocomplete.colon", "TOGGLE", {
declareConfig("chat_input.autocomplete", "DROPDOWN", {
path: ["Chat", "Autocompletion"],
label: "Colon-completion",
hint: "Allows the use of a colon (:) to open a list of partially matching emotes",
defaultValue: true,
label: "Autocompletion",
hint: "Enables a list of partially matching emotes when writing a message (Setting this to 'Always on' will disable the Tab-completion Carousel)",
options: [
["Disabled", 0],
["Require the ':' prefix", 1],
["Always on", 2],
],
defaultValue: 1,
}),
declareConfig("chat_input.autocomplete.colon.emoji", "TOGGLE", {
declareConfig("chat_input.autocomplete.emoji", "TOGGLE", {
path: ["Chat", "Autocompletion"],
label: "Colon-completion: Emoji",
disabledIf: () => !useConfig("chat_input.autocomplete.colon").value,
hint: "Whether or not to also include emojis in the colon-completion list (This may impact performance)",
label: "Autocompletion: Emoji",
disabledIf: () => useConfig("chat_input.autocomplete").value === 0,
hint: "Whether or not to also include emojis in the autocompletion list (This may impact performance)",
defaultValue: false,
}),
declareConfig("chat_input.autocomplete.colon.mode", "DROPDOWN", {
declareConfig("chat_input.autocomplete.mode", "DROPDOWN", {
path: ["Chat", "Autocompletion"],
label: "Colon-completion: Mode",
disabledIf: () => !useConfig("chat_input.autocomplete.colon").value,
hint: "What emotes should be displayed in the colon-completion list",
label: "Autocompletion: Mode",
disabledIf: () => useConfig("chat_input.autocomplete").value === 0,
hint: "What emotes should be displayed in the autocompletion list",
options: [
["Must start with input", 0],
["Must include input", 1],
Expand All @@ -157,20 +162,23 @@ export const config = [
declareConfig("chat_input.autocomplete.carousel", "TOGGLE", {
path: ["Chat", "Autocompletion"],
label: "Tab-completion Carousel",
disabledIf: () => useConfig("chat_input.autocomplete").value === 2,
hint: "Show a carousel visualization of previous and next tab-completion matches",
defaultValue: true,
}),
declareConfig("chat_input.autocomplete.carousel_arrow_keys", "TOGGLE", {
path: ["Chat", "Autocompletion"],
label: "Tab-completion Carousel: Arrow Keys",
disabledIf: () => !useConfig("chat_input.autocomplete.carousel").value,
disabledIf: () =>
!useConfig("chat_input.autocomplete.carousel").value || useConfig("chat_input.autocomplete").value === 2,
hint: "Whether or not to allow using left/right arrow keys to navigate the tab-completion carousel",
defaultValue: true,
}),
declareConfig("chat_input.autocomplete.carousel.mode", "DROPDOWN", {
path: ["Chat", "Autocompletion"],
label: "Tab-completion: Mode",
disabledIf: () => !useConfig("chat_input.autocomplete.carousel").value,
disabledIf: () =>
!useConfig("chat_input.autocomplete.carousel").value || useConfig("chat_input.autocomplete").value === 2,
hint: "What emotes should be displayed in the tab-completion carousel",
options: [
["Must start with input", 0],
Expand Down
Loading