diff --git a/frontend/src/ts/input/handlers/insert-text.ts b/frontend/src/ts/input/handlers/insert-text.ts index 0dd3d55ccf2a..953d0938ae46 100644 --- a/frontend/src/ts/input/handlers/insert-text.ts +++ b/frontend/src/ts/input/handlers/insert-text.ts @@ -62,12 +62,12 @@ type OnInsertTextParams = { export async function onInsertText(options: OnInsertTextParams): Promise { const { now, lastInMultiIndex, isCompositionEnding } = options; - const { inputValue } = getInputElementValue(); if (options.data.length > 1) { // remove the entire data from the input value // make sure to not call TestInput.input.syncWithInputElement in here // it will be updated later in the body of onInsertText + const { inputValue } = getInputElementValue(); setInputElementValue(inputValue.slice(0, -options.data.length)); for (let i = 0; i < options.data.length; i++) { const char = options.data[i] as string; @@ -95,19 +95,17 @@ export async function onInsertText(options: OnInsertTextParams): Promise { return; } + // input and target word + const testInput = TestInput.input.current; + const currentWord = TestWords.words.getCurrent(); + // if the character is visually equal, replace it with the target character // this ensures all future equivalence checks work correctly - let normalizedData: string | null = null; - const targetChar = - TestWords.words.getCurrent()[TestInput.input.current.length]; - if ( - targetChar !== undefined && - areCharactersVisuallyEqual(options.data, targetChar, Config.language) - ) { - replaceInputElementLastValueChar(targetChar); - normalizedData = targetChar; - } - + const normalizedData = normalizeDataAndUpdateInputIfNeeded( + options.data, + testInput, + currentWord + ); const data = normalizedData ?? options.data; // start if needed @@ -118,8 +116,6 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // helper consts const lastInMultiOrSingle = lastInMultiIndex === true || lastInMultiIndex === undefined; - const testInput = TestInput.input.current; - const currentWord = TestWords.words.getCurrent(); const wordIndex = TestState.activeWordIndex; const charIsSpace = isSpace(data); const charIsNewline = data === "\n"; @@ -135,7 +131,10 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // is char correct const funboxCorrect = findSingleActiveFunboxWithFunction( "isCharCorrect" - )?.functions.isCharCorrect(data, currentWord[inputValue.length] ?? ""); + )?.functions.isCharCorrect( + data, + currentWord[(testInput + data).length - 1] ?? "" + ); const correct = funboxCorrect ?? isCharCorrect({ @@ -148,7 +147,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise { // word navigation check const noSpaceForce = isFunboxActiveWithProperty("nospace") && - TestInput.input.current.length === TestWords.words.getCurrent().length; + (testInput + data).length === TestWords.words.getCurrent().length; const shouldGoToNextWord = ((charIsSpace || charIsNewline) && !shouldInsertSpace) || noSpaceForce; @@ -286,6 +285,23 @@ export async function onInsertText(options: OnInsertTextParams): Promise { } } +function normalizeDataAndUpdateInputIfNeeded( + data: string, + testInput: string, + currentWord: string +): string | null { + let normalizedData: string | null = null; + const targetChar = currentWord[testInput.length]; + if ( + targetChar !== undefined && + areCharactersVisuallyEqual(data, targetChar, Config.language) + ) { + replaceInputElementLastValueChar(targetChar); + normalizedData = targetChar; + } + return normalizedData; +} + export async function emulateInsertText( options: OnInsertTextParams ): Promise { diff --git a/frontend/src/ts/test/funbox/funbox-functions.ts b/frontend/src/ts/test/funbox/funbox-functions.ts index 2b66718afc86..d26512871475 100644 --- a/frontend/src/ts/test/funbox/funbox-functions.ts +++ b/frontend/src/ts/test/funbox/funbox-functions.ts @@ -257,25 +257,34 @@ const list: Partial> = { }, isCharCorrect(char: string, originalChar: string): boolean { if ( - (char === "a" || char === "ArrowLeft" || char === "j") && + (char === "a" || + char === "ArrowLeft" || + char === "j" || + char === "←") && originalChar === "←" ) { return true; } if ( - (char === "s" || char === "ArrowDown" || char === "k") && + (char === "s" || + char === "ArrowDown" || + char === "k" || + char === "↓") && originalChar === "↓" ) { return true; } if ( - (char === "w" || char === "ArrowUp" || char === "i") && + (char === "w" || char === "ArrowUp" || char === "i" || char === "↑") && originalChar === "↑" ) { return true; } if ( - (char === "d" || char === "ArrowRight" || char === "l") && + (char === "d" || + char === "ArrowRight" || + char === "l" || + char === "→") && originalChar === "→" ) { return true;