diff --git a/frontend/src/html/pages/settings.html b/frontend/src/html/pages/settings.html index 8abbd84c2..3640a70d7 100644 --- a/frontend/src/html/pages/settings.html +++ b/frontend/src/html/pages/settings.html @@ -568,6 +568,26 @@ +
+
+ + composition display + +
+
+ Change how composition is displayed. "off" will just underline the + letter if composition is active. "below" will show the composed + character below the test. "replace" will replace the letter in the test + with the composed character. +
+
+ + + +
+
diff --git a/frontend/src/ts/commandline/commandline-metadata.ts b/frontend/src/ts/commandline/commandline-metadata.ts index 199658377..68ed146e4 100644 --- a/frontend/src/ts/commandline/commandline-metadata.ts +++ b/frontend/src/ts/commandline/commandline-metadata.ts @@ -323,6 +323,11 @@ export const commandlineConfigMetadata: CommandlineConfigMetadataObject = { options: "fromSchema", }, }, + compositionDisplay: { + subgroup: { + options: "fromSchema", + }, + }, hideExtraLetters: { subgroup: { options: "fromSchema", diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index b303fbda4..dae0636b6 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -134,6 +134,7 @@ export const commands: CommandsSubgroup = { confidenceModeCommand, "quickEnd", "indicateTypos", + "compositionDisplay", "hideExtraLetters", lazyModeCommand, layoutCommand, diff --git a/frontend/src/ts/config-metadata.ts b/frontend/src/ts/config-metadata.ts index 1cd44f864..2dfa38ae0 100644 --- a/frontend/src/ts/config-metadata.ts +++ b/frontend/src/ts/config-metadata.ts @@ -365,6 +365,11 @@ export const configMetadata: ConfigMetadataObject = { displayString: "indicate typos", changeRequiresRestart: false, }, + compositionDisplay: { + icon: "fa-language", + displayString: "composition display", + changeRequiresRestart: false, + }, hideExtraLetters: { icon: "fa-eye-slash", displayString: "hide extra letters", diff --git a/frontend/src/ts/constants/default-config.ts b/frontend/src/ts/constants/default-config.ts index 0fb967fb5..8c14cc3bb 100644 --- a/frontend/src/ts/constants/default-config.ts +++ b/frontend/src/ts/constants/default-config.ts @@ -42,6 +42,7 @@ const obj: Config = { funbox: [], confidenceMode: "off", indicateTypos: "off", + compositionDisplay: "replace", timerStyle: "mini", liveSpeedStyle: "off", liveAccStyle: "off", diff --git a/frontend/src/ts/elements/composition-display.ts b/frontend/src/ts/elements/composition-display.ts index 13b2a6b7d..987bfef7f 100644 --- a/frontend/src/ts/elements/composition-display.ts +++ b/frontend/src/ts/elements/composition-display.ts @@ -1,15 +1,7 @@ -import Config from "../config"; - const compositionDisplay = document.getElementById( "compositionDisplay", ) as HTMLElement; -const languagesToShow = ["korean", "japanese", "chinese"]; - -export function shouldShow(): boolean { - return languagesToShow.some((lang) => Config.language.startsWith(lang)); -} - export function update(data: string): void { compositionDisplay.innerText = data; } diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 61368477b..7e18d3527 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -83,7 +83,6 @@ import * as Loader from "../elements/loader"; import * as TestInitFailed from "../elements/test-init-failed"; import { canQuickRestart } from "../utils/quick-restart"; import { animate } from "animejs"; -import * as CompositionDisplay from "../elements/composition-display"; import { getInputElement, isInputElementFocused, @@ -329,13 +328,6 @@ export function restart(options = {} as RestartOptions): void { getInputElement().style.left = "0"; setInputElementValue(""); - if (CompositionDisplay.shouldShow()) { - CompositionDisplay.update(" "); - CompositionDisplay.show(); - } else { - CompositionDisplay.hide(); - } - Focus.set(false); if (ActivePage.get() === "test") { AdController.updateFooterAndVerticalAds(false); @@ -381,8 +373,9 @@ export function restart(options = {} as RestartOptions): void { if (isInputElementFocused()) OutOfFocus.hide(); TestUI.focusWords(true); - const typingTestEl = document.querySelector("#typingTest") as HTMLElement; + TestUI.onTestRestart(); + const typingTestEl = document.querySelector("#typingTest") as HTMLElement; animate(typingTestEl, { opacity: [0, 1], onBegin: () => { diff --git a/frontend/src/ts/test/test-ui.ts b/frontend/src/ts/test/test-ui.ts index f98ab36c3..0b3f727c8 100644 --- a/frontend/src/ts/test/test-ui.ts +++ b/frontend/src/ts/test/test-ui.ts @@ -49,6 +49,7 @@ import { } from "../input/input-element"; import * as MonkeyPower from "../elements/monkey-power"; import * as SlowTimer from "../states/slow-timer"; +import * as CompositionDisplay from "../elements/composition-display"; const debouncedZipfCheck = debounce(250, async () => { const supports = await JSONData.checkIfLanguageSupportsZipf(Config.language); @@ -89,10 +90,9 @@ ConfigEvent.subscribe((eventKey, eventValue, nosave) => { debouncedZipfCheck(); } if (eventKey === "fontSize") { - $("#caret, #paceCaret, #liveStatsMini, #typingTest, #wordsInput").css( - "fontSize", - (eventValue as number) + "rem", - ); + $( + "#caret, #paceCaret, #liveStatsMini, #typingTest, #wordsInput, #compositionDisplay", + ).css("fontSize", (eventValue as number) + "rem"); if (!nosave) { OutOfFocus.hide(); updateWordWrapperClasses(); @@ -880,7 +880,7 @@ export async function updateWordLetters({ let charToShow = currentWordChars[input.length + i] ?? compositionChar; - if (Config.indicateTypos === "replace") { + if (Config.compositionDisplay === "replace") { charToShow = compositionChar === " " ? "_" : compositionChar; } @@ -1919,6 +1919,15 @@ export function afterTestStart(): void { TimerProgress.update(); } +export function onTestRestart(): void { + if (Config.compositionDisplay === "below") { + CompositionDisplay.update(" "); + CompositionDisplay.show(); + } else { + CompositionDisplay.hide(); + } +} + $(".pageTest #copyWordsListButton").on("click", async () => { let words; if (Config.mode === "zen") { @@ -2043,4 +2052,12 @@ ConfigEvent.subscribe((key, value) => { if (key === "showOutOfFocusWarning" && value === false) { OutOfFocus.hide(); } + if (key === "compositionDisplay") { + if (value === "below") { + CompositionDisplay.update(" "); + CompositionDisplay.show(); + } else { + CompositionDisplay.hide(); + } + } }); diff --git a/packages/schemas/src/configs.ts b/packages/schemas/src/configs.ts index e7246854f..d8d1f54ab 100644 --- a/packages/schemas/src/configs.ts +++ b/packages/schemas/src/configs.ts @@ -54,6 +54,9 @@ export type ConfidenceMode = z.infer; export const IndicateTyposSchema = z.enum(["off", "below", "replace", "both"]); export type IndicateTypos = z.infer; +export const CompositionDisplaySchema = z.enum(["off", "below", "replace"]); +export type CompositionDisplay = z.infer; + export const TimerStyleSchema = z.enum([ "off", "bar", @@ -408,6 +411,7 @@ export const ConfigSchema = z confidenceMode: ConfidenceModeSchema, quickEnd: z.boolean(), indicateTypos: IndicateTyposSchema, + compositionDisplay: CompositionDisplaySchema, hideExtraLetters: z.boolean(), lazyMode: z.boolean(), layout: LayoutSchema, @@ -544,6 +548,7 @@ export const ConfigGroupsLiteral = { confidenceMode: "input", quickEnd: "input", indicateTypos: "input", + compositionDisplay: "input", hideExtraLetters: "input", lazyMode: "input", layout: "input",