diff --git a/frontend/src/html/pages/settings.html b/frontend/src/html/pages/settings.html
index 945469999..2e1a828ba 100644
--- a/frontend/src/html/pages/settings.html
+++ b/frontend/src/html/pages/settings.html
@@ -538,13 +538,16 @@
- Shows typos that you've made. Below shows what you typed below the
- letters and replace will replace the letters with the ones you typed.
+ Shows typos that you've made. "Below" shows what you typed below the
+ letters, "replace" will replace the letters with the ones you typed and
+ "both" will do the same as replace and below, but it will show the
+ correct letters below your mistakes.
off
below
replace
+ both
diff --git a/frontend/src/ts/controllers/input-controller.ts b/frontend/src/ts/controllers/input-controller.ts
index ce69932a6..32ef91efc 100644
--- a/frontend/src/ts/controllers/input-controller.ts
+++ b/frontend/src/ts/controllers/input-controller.ts
@@ -691,7 +691,11 @@ async function handleChar(
!TestUI.lineTransition
// TestInput.input.current.length > 1
) {
- if (Config.mode === "zen" || Config.indicateTypos === "replace") {
+ if (
+ Config.mode === "zen" ||
+ Config.indicateTypos === "replace" ||
+ Config.indicateTypos === "both"
+ ) {
if (!Config.showAllLines) void TestUI.lineJump(activeWordTopBeforeJump);
} else {
TestInput.input.current = TestInput.input.current.slice(0, -1);
diff --git a/frontend/src/ts/test/test-ui.ts b/frontend/src/ts/test/test-ui.ts
index b51fd955d..226d62f26 100644
--- a/frontend/src/ts/test/test-ui.ts
+++ b/frontend/src/ts/test/test-ui.ts
@@ -331,7 +331,7 @@ async function updateHintsPosition(): Promise {
if (
ActivePage.get() !== "test" ||
TestState.resultVisible ||
- Config.indicateTypos !== "below"
+ (Config.indicateTypos !== "below" && Config.indicateTypos !== "both")
)
return;
@@ -436,7 +436,7 @@ function updateWordWrapperClasses(): void {
$("#wordsWrapper").removeClass("blind");
}
- if (Config.indicateTypos === "below") {
+ if (Config.indicateTypos === "below" || Config.indicateTypos === "both") {
$("#words").addClass("indicateTyposBelow");
$("#wordsWrapper").addClass("indicateTyposBelow");
} else {
@@ -791,7 +791,7 @@ export async function updateActiveWordLetters(
!(containsKorean && !correctSoFar)
) {
ret += `${
- Config.indicateTypos === "replace"
+ Config.indicateTypos === "replace" || Config.indicateTypos === "both"
? inputChars[i] === " "
? "_"
: inputChars[i]
@@ -806,13 +806,16 @@ export async function updateActiveWordLetters(
} else {
ret +=
`` +
- (Config.indicateTypos === "replace"
+ (Config.indicateTypos === "replace" || Config.indicateTypos === "both"
? inputChars[i] === " "
? "_"
: inputChars[i]
: currentLetter) +
" ";
- if (Config.indicateTypos === "below") {
+ if (
+ Config.indicateTypos === "below" ||
+ Config.indicateTypos === "both"
+ ) {
const lastBlock = hintIndices[hintIndices.length - 1];
if (lastBlock && lastBlock[lastBlock.length - 1] === i - 1)
lastBlock.push(i);
@@ -839,7 +842,12 @@ export async function updateActiveWordLetters(
if (hintIndices?.length) {
const activeWordLetters = activeWord.querySelectorAll("letter");
- const hintsHtml = createHintsHtml(hintIndices, activeWordLetters, input);
+ let hintsHtml;
+ if (Config.indicateTypos === "both") {
+ hintsHtml = createHintsHtml(hintIndices, activeWordLetters, currentWord);
+ } else {
+ hintsHtml = createHintsHtml(hintIndices, activeWordLetters, input);
+ }
activeWord.insertAdjacentHTML("beforeend", hintsHtml);
const hintElements = activeWord.getElementsByTagName("hint");
await joinOverlappingHints(hintIndices, activeWordLetters, hintElements);
diff --git a/packages/schemas/src/configs.ts b/packages/schemas/src/configs.ts
index 020a17007..605c55630 100644
--- a/packages/schemas/src/configs.ts
+++ b/packages/schemas/src/configs.ts
@@ -50,7 +50,7 @@ export type CaretStyle = z.infer;
export const ConfidenceModeSchema = z.enum(["off", "on", "max"]);
export type ConfidenceMode = z.infer;
-export const IndicateTyposSchema = z.enum(["off", "below", "replace"]);
+export const IndicateTyposSchema = z.enum(["off", "below", "replace", "both"]);
export type IndicateTypos = z.infer;
export const TimerStyleSchema = z.enum(["off", "bar", "text", "mini"]);