Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions frontend/src/ts/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { migrateConfig } from "./utils/config";
import { roundTo1 } from "@monkeytype/util/numbers";
import { getDefaultConfig } from "./constants/default-config";
import { parseWithSchema as parseJsonWithSchema } from "@monkeytype/util/json";
import * as TestState from "./test/test-state";

const configLS = new LocalStorageWithSchema({
key: "config",
Expand Down Expand Up @@ -91,8 +92,20 @@ export function saveFullConfigToLocalStorage(noDbCheck = false): void {
ConfigEvent.dispatch("saveToLocalStorage", stringified);
}

function isConfigChangeBlocked(): boolean {
if (TestState.isActive && config.funbox.includes("no_quit")) {
Notifications.add("No quit funbox is active. Please finish the test.", 0, {
important: true,
});
return true;
}
return false;
}

//numbers
export function setNumbers(numb: boolean, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValidBoolean("numbers", numb)) return false;

if (!canSetConfigWithCurrentFunboxes("numbers", numb, config.funbox)) {
Expand All @@ -111,6 +124,8 @@ export function setNumbers(numb: boolean, nosave?: boolean): boolean {

//punctuation
export function setPunctuation(punc: boolean, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValidBoolean("punctuation", punc)) return false;

if (!canSetConfigWithCurrentFunboxes("punctuation", punc, config.funbox)) {
Expand All @@ -128,6 +143,8 @@ export function setPunctuation(punc: boolean, nosave?: boolean): boolean {
}

export function setMode(mode: Mode, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("mode", mode, ModeSchema)) {
return false;
}
Expand Down Expand Up @@ -224,6 +241,8 @@ export function setDifficulty(
diff: ConfigSchemas.Difficulty,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("difficulty", diff, ConfigSchemas.DifficultySchema)) {
return false;
}
Expand Down Expand Up @@ -260,6 +279,8 @@ export function setFunbox(
funbox: ConfigSchemas.Funbox,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("funbox", funbox, ConfigSchemas.FunboxSchema))
return false;

Expand All @@ -277,6 +298,8 @@ export function setFunbox(
}

export function toggleFunbox(funbox: FunboxName, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!canSetFunboxWithConfig(funbox, config)) {
return false;
}
Expand Down Expand Up @@ -346,6 +369,8 @@ export function setStopOnError(
soe: ConfigSchemas.StopOnError,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (
!isConfigValueValid("stop on error", soe, ConfigSchemas.StopOnErrorSchema)
) {
Expand Down Expand Up @@ -484,6 +509,8 @@ export function setMinWpm(
minwpm: ConfigSchemas.MinimumWordsPerMinute,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (
!isConfigValueValid(
"min speed",
Expand All @@ -505,6 +532,8 @@ export function setMinWpmCustomSpeed(
val: ConfigSchemas.MinWpmCustomSpeed,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (
!isConfigValueValid(
"min speed custom",
Expand All @@ -527,6 +556,8 @@ export function setMinAcc(
min: ConfigSchemas.MinimumAccuracy,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("min acc", min, ConfigSchemas.MinimumAccuracySchema))
return false;

Expand All @@ -541,6 +572,8 @@ export function setMinAccCustom(
val: ConfigSchemas.MinimumAccuracyCustom,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

//migrate legacy configs
if (val > 100) val = 100;
if (
Expand All @@ -564,6 +597,8 @@ export function setMinBurst(
min: ConfigSchemas.MinimumBurst,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("min burst", min, ConfigSchemas.MinimumBurstSchema)) {
return false;
}
Expand All @@ -579,6 +614,8 @@ export function setMinBurstCustomSpeed(
val: ConfigSchemas.MinimumBurstCustomSpeed,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (
!isConfigValueValid(
"min burst custom speed",
Expand Down Expand Up @@ -732,6 +769,8 @@ export function setColorfulMode(extra: boolean, nosave?: boolean): boolean {

//strict space
export function setStrictSpace(val: boolean, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValidBoolean("strict space", val)) return false;

config.strictSpace = val;
Expand Down Expand Up @@ -1087,6 +1126,8 @@ export function setTimeConfig(
time: ConfigSchemas.TimeConfig,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

time = isNaN(time) || time < 0 ? getDefaultConfig().time : time;
if (!isConfigValueValid("time", time, ConfigSchemas.TimeConfigSchema))
return false;
Expand All @@ -1107,6 +1148,8 @@ export function setQuoteLength(
nosave?: boolean,
multipleMode?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (Array.isArray(len)) {
if (
!isConfigValueValid(
Expand Down Expand Up @@ -1159,6 +1202,8 @@ export function setWordCount(
wordCount: ConfigSchemas.WordCount,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

wordCount =
wordCount < 0 || wordCount > 100000 ? getDefaultConfig().words : wordCount;

Expand Down Expand Up @@ -1501,6 +1546,8 @@ export function setRandomTheme(
}

export function setBritishEnglish(val: boolean, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValidBoolean("british english", val)) return false;

if (!val) {
Expand All @@ -1514,6 +1561,8 @@ export function setBritishEnglish(val: boolean, nosave?: boolean): boolean {
}

export function setLazyMode(val: boolean, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValidBoolean("lazy mode", val)) return false;

if (!val) {
Expand Down Expand Up @@ -1566,6 +1615,8 @@ export function setCustomThemeColors(
}

export function setLanguage(language: Language, nosave?: boolean): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("language", language, LanguageSchema)) return false;

config.language = language;
Expand Down Expand Up @@ -1743,6 +1794,8 @@ export function setLayout(
layout: ConfigSchemas.Layout,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

if (!isConfigValueValid("layout", layout, ConfigSchemas.LayoutSchema))
return false;

Expand Down Expand Up @@ -1850,6 +1903,8 @@ export function setCustomLayoutfluid(
value: ConfigSchemas.CustomLayoutFluid,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

// Remove duplicates
const deduped = Array.from(new Set(value));
if (
Expand All @@ -1873,6 +1928,8 @@ export function setCustomPolyglot(
value: ConfigSchemas.CustomPolyglot,
nosave?: boolean
): boolean {
if (isConfigChangeBlocked()) return false;

// remove duplicates
const deduped = Array.from(new Set(value));
if (
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/ts/controllers/route-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import * as PageController from "./page-controller";
import * as TestUI from "../test/test-ui";
import * as PageTransition from "../states/page-transition";
import { Auth, isAuthenticated } from "../firebase";
import { isFunboxActive } from "../test/funbox/list";
import * as TestState from "../test/test-state";
import * as Notifications from "../elements/notifications";

//source: https://www.youtube.com/watch?v=OstALBk-jTc
// https://www.youtube.com/watch?v=OstALBk-jTc
Expand Down Expand Up @@ -157,6 +160,16 @@ export function navigate(
);
return;
}

const noQuit = isFunboxActive("no_quit");
if (TestState.isActive && noQuit) {
Notifications.add("No quit funbox is active. Please finish the test.", 0, {
important: true,
});
event?.preventDefault();
return;
}

url = url.replace(/\/$/, "");
if (url === "") url = "/";

Expand Down
9 changes: 9 additions & 0 deletions frontend/src/ts/test/funbox/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ export function isFunboxActiveWithProperty(property: FunboxProperty): boolean {
return getActiveFunboxesWithProperty(property).length > 0;
}

/**
* Check if the given funbox is active
* @param funbox funbox name
* @returns true if the funbox is active, false otherwise
*/
export function isFunboxActive(funbox: FunboxName): boolean {
return getActiveFunboxNames().includes(funbox);
}

type MandatoryFunboxFunction<F extends keyof FunboxFunctions> = Exclude<
FunboxFunctions[F],
undefined
Expand Down
52 changes: 34 additions & 18 deletions frontend/src/ts/test/test-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import {
findSingleActiveFunboxWithFunction,
getActiveFunboxes,
getActiveFunboxesWithFunction,
isFunboxActive,
} from "./funbox/list";
import { getFunbox } from "@monkeytype/funbox";
import * as CompositionState from "../states/composition";
Expand Down Expand Up @@ -163,6 +164,15 @@ export function restart(options = {} as RestartOptions): void {
options = { ...defaultOptions, ...options };
const animationTime = options.noAnim ? 0 : Misc.applyReducedMotion(125);

const noQuit = isFunboxActive("no_quit");
if (TestState.isActive && noQuit) {
Notifications.add("No quit funbox is active. Please finish the test.", 0, {
important: true,
});
event?.preventDefault();
return;
}

if (TestUI.testRestarting || TestUI.resultCalculating) {
event?.preventDefault();
return;
Expand Down Expand Up @@ -1402,28 +1412,31 @@ $(".pageTest").on("click", "#testConfig .mode .textButton", (e) => {
if ($(e.currentTarget).hasClass("active")) return;
const mode = ($(e.currentTarget).attr("mode") ?? "time") as Mode;
if (mode === undefined) return;
UpdateConfig.setMode(mode);
ManualRestart.set();
restart();
if (UpdateConfig.setMode(mode)) {
ManualRestart.set();
restart();
}
});

$(".pageTest").on("click", "#testConfig .wordCount .textButton", (e) => {
if (TestUI.testRestarting) return;
const wrd = $(e.currentTarget).attr("wordCount") ?? "15";
if (wrd !== "custom") {
UpdateConfig.setWordCount(parseInt(wrd));
ManualRestart.set();
restart();
if (UpdateConfig.setWordCount(parseInt(wrd))) {
ManualRestart.set();
restart();
}
}
});

$(".pageTest").on("click", "#testConfig .time .textButton", (e) => {
if (TestUI.testRestarting) return;
const mode = $(e.currentTarget).attr("timeConfig") ?? "10";
if (mode !== "custom") {
UpdateConfig.setTimeConfig(parseInt(mode));
ManualRestart.set();
restart();
if (UpdateConfig.setTimeConfig(parseInt(mode))) {
ManualRestart.set();
restart();
}
}
});

Expand All @@ -1436,24 +1449,27 @@ $(".pageTest").on("click", "#testConfig .quoteLength .textButton", (e) => {
if (len === -1) {
len = [0, 1, 2, 3];
}
UpdateConfig.setQuoteLength(len, false, e.shiftKey);
ManualRestart.set();
restart();
if (UpdateConfig.setQuoteLength(len, false, e.shiftKey)) {
ManualRestart.set();
restart();
}
}
});

$(".pageTest").on("click", "#testConfig .punctuationMode.textButton", () => {
if (TestUI.testRestarting) return;
UpdateConfig.setPunctuation(!Config.punctuation);
ManualRestart.set();
restart();
if (UpdateConfig.setPunctuation(!Config.punctuation)) {
ManualRestart.set();
restart();
}
});

$(".pageTest").on("click", "#testConfig .numbersMode.textButton", () => {
if (TestUI.testRestarting) return;
UpdateConfig.setNumbers(!Config.numbers);
ManualRestart.set();
restart();
if (UpdateConfig.setNumbers(!Config.numbers)) {
ManualRestart.set();
restart();
}
});

$("header").on("click", "nav #startTestButton, #logo", () => {
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/src/schemas/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ export const FunboxNameSchema = z.enum([
"ALL_CAPS",
"polyglot",
"asl",
"no_quit",
]);
export type FunboxName = z.infer<typeof FunboxNameSchema>;

Expand Down
6 changes: 6 additions & 0 deletions packages/funbox/src/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,12 @@ const list: Record<FunboxName, FunboxMetadata> = {
name: "asl",
cssModifications: ["words"],
},
no_quit: {
description: "You can't restart the test.",
canGetPb: true,
difficultyLevel: 0,
name: "no_quit",
},
};

export function getFunbox(name: FunboxName): FunboxMetadata;
Expand Down
Loading