From dc494b8f8f4a25afde4fce20e147fc3fd25594b5 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Mon, 22 Dec 2025 14:36:58 +0100 Subject: [PATCH 1/4] refactor(cmdline): change getList to support commands for configKeys (@fehmer) --- frontend/src/ts/commandline/commandline.ts | 8 +- frontend/src/ts/commandline/lists.ts | 98 +++++++++------------- frontend/src/ts/elements/modes-notice.ts | 6 +- frontend/src/ts/event-handlers/footer.ts | 2 +- frontend/src/ts/event-handlers/keymap.ts | 2 +- frontend/src/ts/event-handlers/test.ts | 4 +- frontend/src/ts/modals/support.ts | 2 +- 7 files changed, 56 insertions(+), 66 deletions(-) diff --git a/frontend/src/ts/commandline/commandline.ts b/frontend/src/ts/commandline/commandline.ts index f76a33b3d..9d6202008 100644 --- a/frontend/src/ts/commandline/commandline.ts +++ b/frontend/src/ts/commandline/commandline.ts @@ -20,6 +20,7 @@ import { } from "../elements/input-validation"; import { isInputElementFocused } from "../input/input-element"; import { qs } from "../utils/dom"; +import { ConfigKey } from "@monkeytype/schemas/configs"; type CommandlineMode = "search" | "input"; type InputModeParams = { @@ -70,7 +71,10 @@ function addCommandlineBackground(): void { } type ShowSettings = { - subgroupOverride?: CommandsSubgroup | string; + subgroupOverride?: + | CommandsSubgroup + | CommandlineLists.ListsObjectKeys + | ConfigKey; commandOverride?: string; singleListOverride?: boolean; }; @@ -102,7 +106,7 @@ export function show( if (exists) { Loader.show(); subgroupOverride = await CommandlineLists.getList( - settings.subgroupOverride as CommandlineLists.ListsObjectKeys, + settings.subgroupOverride, ); Loader.hide(); } else { diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index 09894ad90..f37e4359f 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -32,6 +32,7 @@ import { Command, CommandsSubgroup } from "./types"; import { buildCommandForConfigKey } from "./util"; import { CommandlineConfigMetadataObject } from "./commandline-metadata"; import { isAuthAvailable, isAuthenticated, signOut } from "../firebase"; +import { ConfigKey } from "@monkeytype/schemas/configs"; const challengesPromise = JSONData.getChallengeList(); challengesPromise @@ -44,23 +45,6 @@ challengesPromise ); }); -const languageCommand = buildCommandForConfigKey("language"); -const difficultyCommand = buildCommandForConfigKey("difficulty"); -const blindModeCommand = buildCommandForConfigKey("blindMode"); -const oppositeShiftModeCommand = buildCommandForConfigKey("oppositeShiftMode"); -const stopOnErrorCommand = buildCommandForConfigKey("stopOnError"); -const confidenceModeCommand = buildCommandForConfigKey("confidenceMode"); -const lazyModeCommand = buildCommandForConfigKey("lazyMode"); -const layoutCommand = buildCommandForConfigKey("layout"); -const showAverageCommand = buildCommandForConfigKey("showAverage"); -const showPbCommand = buildCommandForConfigKey("showPb"); -const keymapLayoutCommand = buildCommandForConfigKey("keymapLayout"); -const customThemeCommand = buildCommandForConfigKey("customTheme"); -const adsCommand = buildCommandForConfigKey("ads"); -const minSpeedCommand = buildCommandForConfigKey("minWpm"); -const minAccCommand = buildCommandForConfigKey("minAcc"); -const paceCaretCommand = buildCommandForConfigKey("paceCaret"); - export const commands: CommandsSubgroup = { title: "", list: [ @@ -68,13 +52,15 @@ export const commands: CommandsSubgroup = { ...ResultScreenCommands, //test screen - buildCommandForConfigKey("punctuation"), - buildCommandForConfigKey("numbers"), - buildCommandForConfigKey("mode"), - buildCommandForConfigKey("time"), - buildCommandForConfigKey("words"), - buildCommandForConfigKey("quoteLength"), - languageCommand, + ...buildCommands( + "punctuation", + "numbers", + "mode", + "time", + "words", + "quoteLength", + "language", + ), { id: "changeCustomModeText", display: "Change custom text", @@ -111,14 +97,14 @@ export const commands: CommandsSubgroup = { //behavior ...buildCommands( - difficultyCommand, + "difficulty", "quickRestart", "repeatQuotes", - blindModeCommand, + "blindMode", "alwaysShowWordsHistory", "singleListCommandLine", - minSpeedCommand, - minAccCommand, + "minWpm", + "minAcc", ...MinBurstCommands, "britishEnglish", ...FunboxCommands, @@ -130,15 +116,15 @@ export const commands: CommandsSubgroup = { ...buildCommands( "freedomMode", "strictSpace", - oppositeShiftModeCommand, - stopOnErrorCommand, - confidenceModeCommand, + "oppositeShiftMode", + "stopOnError", + "confidenceMode", "quickEnd", "indicateTypos", "compositionDisplay", "hideExtraLetters", - lazyModeCommand, - layoutCommand, + "lazyMode", + "layout", "codeUnindentOnBackspace", ), @@ -154,7 +140,7 @@ export const commands: CommandsSubgroup = { ...buildCommands( "smoothCaret", "caretStyle", - paceCaretCommand, + "paceCaret", "repeatedPace", "paceCaretStyle", ), @@ -184,14 +170,14 @@ export const commands: CommandsSubgroup = { "keymapStyle", "keymapLegendStyle", "keymapSize", - keymapLayoutCommand, + "keymapLayout", "keymapShowTopRow", ), //theme ...buildCommands( ...ThemesCommands, - customThemeCommand, + "customTheme", ...CustomThemesListCommands, "flipTestColors", @@ -218,14 +204,14 @@ export const commands: CommandsSubgroup = { "showKeyTips", "showOutOfFocusWarning", "capsLockWarning", - showAverageCommand, - showPbCommand, + "showAverage", + "showPb", "monkeyPowerLevel", "monkey", ), //danger zone - adsCommand, + ...buildCommands("ads"), //other ...LoadChallengeCommands, @@ -381,41 +367,39 @@ export const commands: CommandsSubgroup = { ], }; +function findCommandById(key: string): Command | undefined { + const id = "change" + key.charAt(0).toUpperCase() + key.slice(1); + return commands.list.find((it) => it.id === id); +} + const lists = { - keymapLayouts: keymapLayoutCommand.subgroup, - enableAds: adsCommand.subgroup, - customThemesList: customThemeCommand.subgroup, themes: ThemesCommands[0]?.subgroup, loadChallenge: LoadChallengeCommands[0]?.subgroup, - languages: languageCommand.subgroup, - difficulty: difficultyCommand.subgroup, - lazyMode: lazyModeCommand.subgroup, - paceCaretMode: paceCaretCommand.subgroup, - showAverage: showAverageCommand.subgroup, - showPb: showPbCommand.subgroup, - minWpm: minSpeedCommand.subgroup, - minAcc: minAccCommand.subgroup, minBurst: MinBurstCommands[0]?.subgroup, funbox: FunboxCommands[0]?.subgroup, - confidenceMode: confidenceModeCommand.subgroup, - stopOnError: stopOnErrorCommand.subgroup, - layouts: layoutCommand.subgroup, - oppositeShiftMode: oppositeShiftModeCommand.subgroup, tags: TagsCommands[0]?.subgroup, resultSaving: ResultSavingCommands[0]?.subgroup, - blindMode: blindModeCommand.subgroup, }; export function doesListExist(listName: string): boolean { + if (findCommandById(listName)) { + return true; + } + return lists[listName as ListsObjectKeys] !== undefined; } export async function getList( - listName: ListsObjectKeys, + listName: ListsObjectKeys | ConfigKey, ): Promise { await Promise.allSettled([challengesPromise]); - const list = lists[listName]; + const commandList = findCommandById(listName); + if (commandList !== undefined && commandList.subgroup !== undefined) { + return commandList.subgroup; + } + + const list = lists[listName as ListsObjectKeys]; if (!list) { Notifications.add(`List not found: ${listName}`, -1); throw new Error(`List ${listName} not found`); diff --git a/frontend/src/ts/elements/modes-notice.ts b/frontend/src/ts/elements/modes-notice.ts index e2091b9c4..cac27c4e3 100644 --- a/frontend/src/ts/elements/modes-notice.ts +++ b/frontend/src/ts/elements/modes-notice.ts @@ -106,7 +106,7 @@ export async function update(): Promise { if (Config.mode !== "zen" && !usingPolyglot) { testModesNotice.appendHtml( - ``, @@ -158,7 +158,7 @@ export async function update(): Promise { }); testModesNotice.appendHtml( - ``, diff --git a/frontend/src/ts/event-handlers/footer.ts b/frontend/src/ts/event-handlers/footer.ts index 8e288c970..949cca104 100644 --- a/frontend/src/ts/event-handlers/footer.ts +++ b/frontend/src/ts/event-handlers/footer.ts @@ -65,7 +65,7 @@ document } setConfig("customTheme", true); } else { - const subgroup = Config.customTheme ? "customThemesList" : "themes"; + const subgroup = Config.customTheme ? "customTheme" : "themes"; Commandline.show({ subgroupOverride: subgroup, }); diff --git a/frontend/src/ts/event-handlers/keymap.ts b/frontend/src/ts/event-handlers/keymap.ts index 807ea0552..90eb7e8f4 100644 --- a/frontend/src/ts/event-handlers/keymap.ts +++ b/frontend/src/ts/event-handlers/keymap.ts @@ -2,6 +2,6 @@ import * as Commandline from "../commandline/commandline"; $("#keymap").on("click", ".r5 .layoutIndicator", async () => { Commandline.show({ - subgroupOverride: "keymapLayouts", + subgroupOverride: "keymapLayout", }); }); diff --git a/frontend/src/ts/event-handlers/test.ts b/frontend/src/ts/event-handlers/test.ts index fa839c1b6..072c212cd 100644 --- a/frontend/src/ts/event-handlers/test.ts +++ b/frontend/src/ts/event-handlers/test.ts @@ -15,11 +15,13 @@ import * as PractiseWordsModal from "../modals/practise-words"; import { navigate } from "../controllers/route-controller"; import { getMode2 } from "../utils/misc"; import * as ShareTestSettingsPopup from "../modals/share-test-settings"; +import { ConfigKey } from "@monkeytype/schemas/configs"; +import { ListsObjectKeys } from "../commandline/lists"; $(".pageTest").on("click", "#testModesNotice .textButton", async (event) => { const attr = $(event.currentTarget).attr("commands"); if (attr === undefined) return; - Commandline.show({ subgroupOverride: attr }); + Commandline.show({ subgroupOverride: attr as ConfigKey | ListsObjectKeys }); }); $(".pageTest").on("click", "#testModesNotice .textButton", async (event) => { diff --git a/frontend/src/ts/modals/support.ts b/frontend/src/ts/modals/support.ts index e1b0bb770..2a49ce007 100644 --- a/frontend/src/ts/modals/support.ts +++ b/frontend/src/ts/modals/support.ts @@ -10,7 +10,7 @@ const modal = new AnimatedModal({ setup: async (modalEl): Promise => { modalEl.querySelector("button.ads")?.addEventListener("click", async () => { Commandline.show( - { subgroupOverride: "enableAds" }, + { subgroupOverride: "ads" }, { modalChain: modal, }, From 0aaa7db0944104ec4bffc3e5f2021c2e23d67471 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Mon, 22 Dec 2025 14:53:47 +0100 Subject: [PATCH 2/4] map lookup --- frontend/src/ts/commandline/lists.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index f37e4359f..fed08e8f3 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -367,11 +367,6 @@ export const commands: CommandsSubgroup = { ], }; -function findCommandById(key: string): Command | undefined { - const id = "change" + key.charAt(0).toUpperCase() + key.slice(1); - return commands.list.find((it) => it.id === id); -} - const lists = { themes: ThemesCommands[0]?.subgroup, loadChallenge: LoadChallengeCommands[0]?.subgroup, @@ -381,8 +376,14 @@ const lists = { resultSaving: ResultSavingCommands[0]?.subgroup, }; +const subGroupByConfigKey = Object.fromEntries( + commands.list + .filter((it) => it.id.startsWith("change")) + .map((it) => [it.id.slice("change".length).toLowerCase(), it.subgroup]), +); + export function doesListExist(listName: string): boolean { - if (findCommandById(listName)) { + if (subGroupByConfigKey[listName] !== undefined) { return true; } @@ -394,9 +395,9 @@ export async function getList( ): Promise { await Promise.allSettled([challengesPromise]); - const commandList = findCommandById(listName); - if (commandList !== undefined && commandList.subgroup !== undefined) { - return commandList.subgroup; + const subGroup = subGroupByConfigKey[listName]; + if (subGroup !== undefined) { + return subGroup; } const list = lists[listName as ListsObjectKeys]; From 4d50af516b5c49f23df58b3239bfe1085181d6cb Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Mon, 22 Dec 2025 15:26:37 +0100 Subject: [PATCH 3/4] cleanup subgroupByConfigKey --- frontend/src/ts/commandline/lists.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index fed08e8f3..1461c59f1 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -378,9 +378,9 @@ const lists = { const subGroupByConfigKey = Object.fromEntries( commands.list - .filter((it) => it.id.startsWith("change")) - .map((it) => [it.id.slice("change".length).toLowerCase(), it.subgroup]), -); + .filter((it) => it.subgroup?.configKey !== undefined) + .map((it) => [it.subgroup?.configKey, it.subgroup]), +) as Record; export function doesListExist(listName: string): boolean { if (subGroupByConfigKey[listName] !== undefined) { From 815717adbd073163c96f07ba94b0852cd558d11d Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Mon, 22 Dec 2025 15:29:13 +0100 Subject: [PATCH 4/4] rename --- frontend/src/ts/commandline/lists.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index 1461c59f1..cefee0c7b 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -376,14 +376,14 @@ const lists = { resultSaving: ResultSavingCommands[0]?.subgroup, }; -const subGroupByConfigKey = Object.fromEntries( +const subgroupByConfigKey = Object.fromEntries( commands.list .filter((it) => it.subgroup?.configKey !== undefined) .map((it) => [it.subgroup?.configKey, it.subgroup]), ) as Record; export function doesListExist(listName: string): boolean { - if (subGroupByConfigKey[listName] !== undefined) { + if (subgroupByConfigKey[listName] !== undefined) { return true; } @@ -395,7 +395,7 @@ export async function getList( ): Promise { await Promise.allSettled([challengesPromise]); - const subGroup = subGroupByConfigKey[listName]; + const subGroup = subgroupByConfigKey[listName]; if (subGroup !== undefined) { return subGroup; }