From e2967e6386493e865b71a15d56e17b734c072716 Mon Sep 17 00:00:00 2001 From: Albin David C Date: Fri, 27 Mar 2026 11:05:00 +0530 Subject: [PATCH 1/5] fix(challenge): add wingdings challenge to the list, update the controller and notification --- .../ts/controllers/challenge-controller.ts | 22 +++++++++++++++++-- frontend/src/ts/controllers/url-handler.tsx | 2 -- frontend/static/challenges/_list.json | 12 ++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/frontend/src/ts/controllers/challenge-controller.ts b/frontend/src/ts/controllers/challenge-controller.ts index 84339c1dd4db..a47d7bb849ee 100644 --- a/frontend/src/ts/controllers/challenge-controller.ts +++ b/frontend/src/ts/controllers/challenge-controller.ts @@ -368,6 +368,23 @@ export async function setup(challengeName: string): Promise { setConfig("keymapMode", "static", { nosave: true, }); + } else if (challenge.name === "wingdings") { + // Ten Words of Pain: 10-word Master mode test using the Wingdings custom font, no keymap + setConfig("mode", "words", { + nosave: true, + }); + setConfig("words", 10, { + nosave: true, + }); + setConfig("difficulty", "master", { + nosave: true, + }); + setConfig("fontFamily", "Wingdings", { + nosave: true, + }); + setConfig("keymapMode", "off", { + nosave: true, + }); } } notitext = challenge.message; @@ -375,9 +392,9 @@ export async function setup(challengeName: string): Promise { qs(".page.pageTest")?.show(); if (notitext === undefined) { - showNoticeNotification(`Challenge '${challenge.display}' loaded.`); + showSuccessNotification(`Challenge '${challenge.display}' loaded.`); } else { - showNoticeNotification("Challenge loaded. " + notitext); + showSuccessNotification("Challenge loaded. " + notitext); } setLoadedChallenge(challenge); challengeLoading = false; @@ -405,6 +422,7 @@ configEvent.subscribe(({ key }) => { "keymapMode", "keymapLayout", "layout", + "fontFamily", ].includes(key) ) { clearActive(); diff --git a/frontend/src/ts/controllers/url-handler.tsx b/frontend/src/ts/controllers/url-handler.tsx index 27b62003a14a..1577ef1dd1f9 100644 --- a/frontend/src/ts/controllers/url-handler.tsx +++ b/frontend/src/ts/controllers/url-handler.tsx @@ -315,11 +315,9 @@ export function loadChallengeFromUrl(getOverride?: string): void { ).toLowerCase(); if (getValue === "") return; - showNoticeNotification("Loading challenge"); ChallengeController.setup(getValue) .then((result) => { if (result) { - showSuccessNotification("Challenge loaded"); restartTest({ nosave: true, }); diff --git a/frontend/static/challenges/_list.json b/frontend/static/challenges/_list.json index 69d487158ea0..92f26a255e0a 100644 --- a/frontend/static/challenges/_list.json +++ b/frontend/static/challenges/_list.json @@ -722,5 +722,17 @@ "display": "Feet warrior", "type": "customTime", "parameters": [3600] + }, + { + "name": "wingdings", + "display": "Ten Words of Pain", + "type": "special", + "parameters": [], + "message": "Complete a 10-word Master mode test using the Wingdings custom font. No keymap allowed.", + "requirements": { + "wpm": { + "min": 1 + } + } } ] From c96334939b9c1fd0c8ae431d551edc2ae3fe6bd9 Mon Sep 17 00:00:00 2001 From: Albin David C Date: Fri, 27 Mar 2026 11:16:45 +0530 Subject: [PATCH 2/5] fix(challenge): rectify the error --- packages/schemas/src/challenges.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/schemas/src/challenges.ts b/packages/schemas/src/challenges.ts index a8b30853f80e..bc6c67a96be1 100644 --- a/packages/schemas/src/challenges.ts +++ b/packages/schemas/src/challenges.ts @@ -17,6 +17,7 @@ export const ChallengeSchema = z "script", "accuracy", "funbox", + "special", ]), message: z.string().optional(), parameters: z.array( From af66106a95cf81473e2df8d568e10b648eec59bf Mon Sep 17 00:00:00 2001 From: Albin David C Date: Fri, 27 Mar 2026 11:05:00 +0530 Subject: [PATCH 3/5] fix(challenge): add wingdings challenge to the list, update the controller and notification --- .../src/ts/controllers/challenge-controller.ts | 18 ++++++++++++++++++ frontend/src/ts/controllers/url-handler.tsx | 16 +++++++++++----- frontend/static/challenges/_list.json | 15 +++++++++++++++ packages/schemas/src/challenges.ts | 2 ++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/frontend/src/ts/controllers/challenge-controller.ts b/frontend/src/ts/controllers/challenge-controller.ts index 8544cfc2b354..a47d7bb849ee 100644 --- a/frontend/src/ts/controllers/challenge-controller.ts +++ b/frontend/src/ts/controllers/challenge-controller.ts @@ -368,6 +368,23 @@ export async function setup(challengeName: string): Promise { setConfig("keymapMode", "static", { nosave: true, }); + } else if (challenge.name === "wingdings") { + // Ten Words of Pain: 10-word Master mode test using the Wingdings custom font, no keymap + setConfig("mode", "words", { + nosave: true, + }); + setConfig("words", 10, { + nosave: true, + }); + setConfig("difficulty", "master", { + nosave: true, + }); + setConfig("fontFamily", "Wingdings", { + nosave: true, + }); + setConfig("keymapMode", "off", { + nosave: true, + }); } } notitext = challenge.message; @@ -405,6 +422,7 @@ configEvent.subscribe(({ key }) => { "keymapMode", "keymapLayout", "layout", + "fontFamily", ].includes(key) ) { clearActive(); diff --git a/frontend/src/ts/controllers/url-handler.tsx b/frontend/src/ts/controllers/url-handler.tsx index af7057d63e33..a2a97f3116db 100644 --- a/frontend/src/ts/controllers/url-handler.tsx +++ b/frontend/src/ts/controllers/url-handler.tsx @@ -317,12 +317,18 @@ export async function loadChallengeFromUrl( ).toLowerCase(); if (getValue === "") return; - const result = await ChallengeController.setup(getValue); - if (result) { - restartTest({ - nosave: true, + ChallengeController.setup(getValue) + .then((result) => { + if (result) { + restartTest({ + nosave: true, + }); + } + }) + .catch((e: unknown) => { + showErrorNotification("Failed to load challenge"); + console.error(e); }); - } } authEvent.subscribe(async (event) => { diff --git a/frontend/static/challenges/_list.json b/frontend/static/challenges/_list.json index 69d487158ea0..36df07029eb5 100644 --- a/frontend/static/challenges/_list.json +++ b/frontend/static/challenges/_list.json @@ -722,5 +722,20 @@ "display": "Feet warrior", "type": "customTime", "parameters": [3600] + }, + { + "name": "wingdings", + "display": "Ten Words of Pain", + "type": "special", + "parameters": [], + "message": "Complete a 10-word Master mode test using the Wingdings custom font. No keymap allowed. Minimum 60 WPM and 100% accuracy required.", + "requirements": { + "wpm": { + "min": 60 + }, + "acc": { + "min": 100 + } + } } ] diff --git a/packages/schemas/src/challenges.ts b/packages/schemas/src/challenges.ts index a8b30853f80e..d36fb4675d81 100644 --- a/packages/schemas/src/challenges.ts +++ b/packages/schemas/src/challenges.ts @@ -17,6 +17,8 @@ export const ChallengeSchema = z "script", "accuracy", "funbox", + "special", + "other", ]), message: z.string().optional(), parameters: z.array( From 46e94d282fb2b2d7813ae8a453ea4d6db9e606e9 Mon Sep 17 00:00:00 2001 From: Albin David C Date: Tue, 7 Apr 2026 19:01:43 +0530 Subject: [PATCH 4/5] fix(challenges): update schemas in the package and update challenges list in the frontend --- frontend/static/challenges/_list.json | 2 +- packages/schemas/src/challenges.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/static/challenges/_list.json b/frontend/static/challenges/_list.json index 36df07029eb5..15d430abeb95 100644 --- a/frontend/static/challenges/_list.json +++ b/frontend/static/challenges/_list.json @@ -726,7 +726,7 @@ { "name": "wingdings", "display": "Ten Words of Pain", - "type": "special", + "type": "other", "parameters": [], "message": "Complete a 10-word Master mode test using the Wingdings custom font. No keymap allowed. Minimum 60 WPM and 100% accuracy required.", "requirements": { diff --git a/packages/schemas/src/challenges.ts b/packages/schemas/src/challenges.ts index d36fb4675d81..8f4611ed74f1 100644 --- a/packages/schemas/src/challenges.ts +++ b/packages/schemas/src/challenges.ts @@ -17,7 +17,6 @@ export const ChallengeSchema = z "script", "accuracy", "funbox", - "special", "other", ]), message: z.string().optional(), From df53b8fe910e2c07054b4c144bd9d91783e85b34 Mon Sep 17 00:00:00 2001 From: Albin David C Date: Tue, 7 Apr 2026 19:12:50 +0530 Subject: [PATCH 5/5] fix(challenges): update the challenge controller --- frontend/src/ts/controllers/challenge-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/controllers/challenge-controller.ts b/frontend/src/ts/controllers/challenge-controller.ts index a47d7bb849ee..e36f23882040 100644 --- a/frontend/src/ts/controllers/challenge-controller.ts +++ b/frontend/src/ts/controllers/challenge-controller.ts @@ -341,7 +341,7 @@ export async function setup(challengeName: string): Promise { nosave: true, }); } - } else if (challenge.type === "special") { + } else if (challenge.type === "other") { if (challenge.name === "semimak") { // so can you make a link that sets up 120s, 10k, punct, stop on word, and semimak as the layout? setConfig("mode", "time", {