chore: block typing when test is not initialised correctly, show message

This commit is contained in:
Miodec 2025-05-05 13:21:55 +02:00
parent 499754a933
commit dc6d4518a9
7 changed files with 102 additions and 17 deletions

View file

@ -99,6 +99,17 @@
Test settings
</button>
</div>
<div id="testInitFailed" class="content-grid hidden">
<div class="message">
Test initialization failed. Please try different settings or refreshing
the page. If the problem persists, please contact support.
<div class="error"></div>
<button class="active restart">
<i class="fas fa-fw fa-redo-alt"></i>
Restart
</button>
</div>
</div>
<div id="typingTest" class="content-grid full-width-padding">
<div id="capsWarning" class="hidden">
<i class="fas fa-lock"></i>

View file

@ -74,6 +74,24 @@
.pageTest {
position: relative;
#testInitFailed {
margin-top: 2rem;
font-size: 1rem;
text-align: center;
.message {
max-width: 800px;
grid-area: content;
justify-self: center;
}
.error {
margin-top: 2rem;
}
button {
padding: 1rem 2rem;
margin-top: 2rem;
}
}
#typingTest {
position: relative;
width: 100%;

View file

@ -873,7 +873,8 @@ $("#wordsInput").on("keydown", (event) => {
!popupVisible &&
!TestUI.resultVisible &&
event.key !== "Enter" &&
!awaitingNextWord;
!awaitingNextWord &&
TestState.testInitSuccess;
if (!allowTyping) {
event.preventDefault();

View file

@ -63,7 +63,6 @@ class QuotesController {
const { data, error } = await tryCatch(
cachedFetchJson<QuoteData>(`quotes/${normalizedLanguage}.json`)
);
if (error) {
if (
error instanceof Error &&

View file

@ -0,0 +1,33 @@
const elem = document.querySelector<HTMLElement>(".pageTest #testInitFailed");
const testElem = document.querySelector<HTMLElement>(".pageTest #typingTest");
const errorElem = document.querySelector<HTMLElement>(
".pageTest #testInitFailed .error"
);
export function show(): void {
if (elem && testElem) {
elem.classList.remove("hidden");
testElem.classList.add("hidden");
}
}
function hideError(): void {
if (errorElem) {
errorElem.classList.add("hidden");
}
}
export function showError(text: string): void {
if (errorElem) {
errorElem.classList.remove("hidden");
errorElem.innerText = text;
}
}
export function hide(): void {
if (elem && testElem) {
hideError();
elem.classList.add("hidden");
testElem.classList.remove("hidden");
}
}

View file

@ -77,6 +77,7 @@ import { WordGenError } from "../utils/word-gen-error";
import { tryCatch } from "@monkeytype/util/trycatch";
import { captureException } from "../sentry";
import * as Loader from "../elements/loader";
import * as TestInitFailed from "../elements/test-init-failed";
let failReason = "";
const koInputVisual = document.getElementById("koInputVisual") as HTMLElement;
@ -338,7 +339,15 @@ export function restart(options = {} as RestartOptions): void {
TestState.setRepeated(options.withSameWordset ?? false);
TestState.setPaceRepeat(repeatWithPace);
await init();
TestInitFailed.hide();
TestState.setTestInitSuccess(true);
const initResult = await init();
if (initResult === null) {
TestUI.setTestRestarting(false);
return;
}
await PaceCaret.init();
for (const fb of getActiveFunboxesWithFunction("restart")) {
@ -385,22 +394,28 @@ export function restart(options = {} as RestartOptions): void {
let lastInitError: Error | null = null;
let rememberLazyMode: boolean;
let testReinitCount = 0;
export async function init(): Promise<void> {
export async function init(): Promise<void | null> {
console.debug("Initializing test");
testReinitCount++;
if (testReinitCount >= 4) {
if (testReinitCount > 3) {
if (lastInitError) {
captureException(lastInitError);
TestInitFailed.showError(
`${lastInitError.name}: ${lastInitError.message}`
);
}
TestInitFailed.show();
TestUI.setTestRestarting(false);
Notifications.add(
"Too many test reinitialization attempts. Something is going very wrong. Please contact support.",
-1,
{
important: true,
}
);
return;
TestState.setTestInitSuccess(false);
Focus.set(false);
// Notifications.add(
// "Too many test reinitialization attempts. Something is going very wrong. Please contact support.",
// -1,
// {
// important: true,
// }
// );
return null;
}
MonkeyPower.reset();
@ -426,8 +441,7 @@ export async function init(): Promise<void> {
if (!language || language.name !== Config.language) {
UpdateConfig.setLanguage("english");
await init();
return;
return await init();
}
if (ActivePage.get() === "test") {
@ -492,6 +506,7 @@ export async function init(): Promise<void> {
wordsHaveTab = gen.hasTab;
wordsHaveNewline = gen.hasNewline;
} catch (e) {
Loader.hide();
if (e instanceof WordGenError || e instanceof Error) {
lastInitError = e;
}
@ -512,8 +527,7 @@ export async function init(): Promise<void> {
);
}
await init();
return;
return await init();
}
const beforeHasNumbers = TestWords.hasNumbers;
@ -1348,6 +1362,10 @@ $(".pageTest").on("click", "#testModesNotice .textButton.restart", () => {
restart();
});
$(".pageTest").on("click", "#testInitFailed button.restart", () => {
restart();
});
$(".pageTest").on("click", "#restartTestButton", () => {
ManualRestart.set();
if (TestUI.resultCalculating) return;

View file

@ -8,6 +8,7 @@ export let savingEnabled = true;
export let bailedOut = false;
export let selectedQuoteId = 1;
export let activeWordIndex = 0;
export let testInitSuccess = true;
export function setRepeated(tf: boolean): void {
isRepeated = tf;
@ -48,3 +49,7 @@ export function increaseActiveWordIndex(): void {
export function decreaseActiveWordIndex(): void {
activeWordIndex--;
}
export function setTestInitSuccess(tf: boolean): void {
testInitSuccess = tf;
}