refactor: add options object to setConfig (@miodec) (#7228)

This commit is contained in:
Jack 2025-12-12 16:55:33 +01:00 committed by GitHub
parent 2b380bb931
commit e0b5c465cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 253 additions and 97 deletions

View file

@ -212,7 +212,9 @@ describe("Config", () => {
replaceConfig({ numbers: false });
//WHEN
Config.setConfig("numbers", true, true);
Config.setConfig("numbers", true, {
nosave: true,
});
//THEN
//wait for debounce
@ -227,7 +229,9 @@ describe("Config", () => {
replaceConfig({ numbers: false });
//WHEN
Config.setConfig("numbers", true, true);
Config.setConfig("numbers", true, {
nosave: true,
});
//THEN
@ -241,21 +245,21 @@ describe("Config", () => {
it("triggers resize if property is set", () => {
///WHEN
Config.setConfig("maxLineWidth", 50, false);
Config.setConfig("maxLineWidth", 50);
expect(miscTriggerResizeMock).toHaveBeenCalled();
});
it("does not triggers resize if property is not set", () => {
///WHEN
Config.setConfig("startGraphsAtZero", true, false);
Config.setConfig("startGraphsAtZero", true);
expect(miscTriggerResizeMock).not.toHaveBeenCalled();
});
it("does not triggers resize if property on nosave", () => {
///WHEN
Config.setConfig("maxLineWidth", 50, true);
Config.setConfig("maxLineWidth", 50, { nosave: true });
expect(miscTriggerResizeMock).not.toHaveBeenCalled();
});

View file

@ -56,8 +56,12 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "time", true);
expect(setConfigMock).toHaveBeenCalledWith("time", 60, true);
expect(setConfigMock).toHaveBeenCalledWith("mode", "time", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("time", 60, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets time", () => {
@ -70,8 +74,12 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "time", true);
expect(setConfigMock).toHaveBeenCalledWith("time", 30, true);
expect(setConfigMock).toHaveBeenCalledWith("mode", "time", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("time", 30, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets word count", () => {
@ -84,8 +92,12 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "words", true);
expect(setConfigMock).toHaveBeenCalledWith("words", 50, true);
expect(setConfigMock).toHaveBeenCalledWith("mode", "words", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("words", 50, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets quote length", () => {
@ -98,8 +110,10 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "quote", true);
expect(setConfigMock).toHaveBeenCalledWith("quoteLength", [-2], false);
expect(setConfigMock).toHaveBeenCalledWith("mode", "quote", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("quoteLength", [-2]);
expect(setSelectedQuoteIdMock).toHaveBeenCalledWith(512);
expect(restartTestMock).toHaveBeenCalled();
});
@ -111,7 +125,9 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("punctuation", true, true);
expect(setConfigMock).toHaveBeenCalledWith("punctuation", true, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets numbers", () => {
@ -122,7 +138,9 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("numbers", false, true);
expect(setConfigMock).toHaveBeenCalledWith("numbers", false, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets language", () => {
@ -133,7 +151,9 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("language", "english", true);
expect(setConfigMock).toHaveBeenCalledWith("language", "english", {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets difficulty", () => {
@ -144,7 +164,9 @@ describe("url-handler", () => {
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("difficulty", "master", true);
expect(setConfigMock).toHaveBeenCalledWith("difficulty", "master", {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets funbox", () => {
@ -160,7 +182,9 @@ describe("url-handler", () => {
expect(setConfigMock).toHaveBeenCalledWith(
"funbox",
["crt", "choo_choo"],
true,
{
nosave: true,
},
);
expect(restartTestMock).toHaveBeenCalled();
});
@ -177,7 +201,9 @@ describe("url-handler", () => {
expect(setConfigMock).toHaveBeenCalledWith(
"funbox",
["crt", "choo_choo"],
true,
{
nosave: true,
},
);
expect(restartTestMock).toHaveBeenCalled();
});

View file

@ -91,7 +91,9 @@ function isConfigChangeBlocked(): boolean {
export function setConfig<T extends keyof Config>(
key: T,
value: Config[T],
nosave: boolean = false,
options?: {
nosave?: boolean;
},
): boolean {
const metadata = configMetadata[key] as ConfigMetadataObject[T];
if (metadata === undefined) {
@ -168,7 +170,7 @@ export function setConfig<T extends keyof Config>(
continue; // no need to set if the value is already the same
}
const set = setConfig(targetKey, targetValue, nosave);
const set = setConfig(targetKey, targetValue, options);
if (!set) {
throw new Error(
`Failed to set config key "${targetKey}" with value "${targetValue}" for ${metadata.displayString} config override.`,
@ -178,22 +180,24 @@ export function setConfig<T extends keyof Config>(
}
config[key] = value;
if (!nosave) saveToLocalStorage(key, nosave);
if (!options?.nosave) saveToLocalStorage(key, options?.nosave);
// @ts-expect-error i can't figure this out
ConfigEvent.dispatch({
key: key,
newValue: value,
nosave,
nosave: options?.nosave ?? false,
previousValue: previousValue as Config[T],
});
if (metadata.triggerResize && !nosave) {
if (metadata.triggerResize && !options?.nosave) {
triggerResize();
}
metadata.afterSet?.({ nosave: nosave || false, currentConfig: config });
metadata.afterSet?.({
nosave: options?.nosave ?? false,
currentConfig: config,
});
return true;
}
@ -232,7 +236,9 @@ export function toggleFunbox(funbox: FunboxName, nosave?: boolean): boolean {
}
export function setQuoteLengthAll(nosave?: boolean): boolean {
return setConfig("quoteLength", [0, 1, 2, 3], nosave);
return setConfig("quoteLength", [0, 1, 2, 3], {
nosave,
});
}
const lastConfigsToApply: Set<keyof Config> = new Set([
@ -275,7 +281,7 @@ export async function applyConfig(
for (const configKey of [...firstKeys, ...lastConfigsToApply]) {
const configValue = fullConfig[configKey];
const set = setConfig(configKey, configValue, true);
const set = setConfig(configKey, configValue, { nosave: true });
if (!set) {
configKeysToReset.push(configKey);

View file

@ -241,26 +241,48 @@ export async function setup(challengeName: string): Promise<boolean> {
return false;
}
if (challenge.type === "customTime") {
setConfig("time", challenge.parameters[0] as number, true);
setConfig("mode", "time", true);
setConfig("difficulty", "normal", true);
setConfig("time", challenge.parameters[0] as number, {
nosave: true,
});
setConfig("mode", "time", {
nosave: true,
});
setConfig("difficulty", "normal", {
nosave: true,
});
if (challenge.name === "englishMaster") {
setConfig("language", "english_10k", true);
setConfig("numbers", true, true);
setConfig("punctuation", true, true);
setConfig("language", "english_10k", {
nosave: true,
});
setConfig("numbers", true, {
nosave: true,
});
setConfig("punctuation", true, {
nosave: true,
});
}
} else if (challenge.type === "customWords") {
setConfig("words", challenge.parameters[0] as number, true);
setConfig("mode", "words", true);
setConfig("difficulty", "normal", true);
setConfig("words", challenge.parameters[0] as number, {
nosave: true,
});
setConfig("mode", "words", {
nosave: true,
});
setConfig("difficulty", "normal", {
nosave: true,
});
} else if (challenge.type === "customText") {
CustomText.setText((challenge.parameters[0] as string).split(" "));
CustomText.setMode(challenge.parameters[1] as CustomTextMode);
CustomText.setLimitValue(challenge.parameters[2] as number);
CustomText.setLimitMode(challenge.parameters[3] as CustomTextLimitMode);
CustomText.setPipeDelimiter(challenge.parameters[4] as boolean);
setConfig("mode", "custom", true);
setConfig("difficulty", "normal", true);
setConfig("mode", "custom", {
nosave: true,
});
setConfig("difficulty", "normal", {
nosave: true,
});
} else if (challenge.type === "script") {
Loader.show();
const response = await fetch(
@ -278,8 +300,12 @@ export async function setup(challengeName: string): Promise<boolean> {
CustomText.setMode("repeat");
CustomText.setLimitMode("word");
CustomText.setPipeDelimiter(false);
setConfig("mode", "custom", true);
setConfig("difficulty", "normal", true);
setConfig("mode", "custom", {
nosave: true,
});
setConfig("difficulty", "normal", {
nosave: true,
});
if (challenge.parameters[1] !== null) {
setConfig("theme", challenge.parameters[1] as ThemeName);
}
@ -287,32 +313,66 @@ export async function setup(challengeName: string): Promise<boolean> {
void Funbox.activate(challenge.parameters[2] as FunboxName[]);
}
} else if (challenge.type === "accuracy") {
setConfig("time", 0, true);
setConfig("mode", "time", true);
setConfig("difficulty", "master", true);
setConfig("time", 0, {
nosave: true,
});
setConfig("mode", "time", {
nosave: true,
});
setConfig("difficulty", "master", {
nosave: true,
});
} else if (challenge.type === "funbox") {
setConfig("funbox", challenge.parameters[0] as FunboxName[], true);
setConfig("difficulty", "normal", true);
setConfig("funbox", challenge.parameters[0] as FunboxName[], {
nosave: true,
});
setConfig("difficulty", "normal", {
nosave: true,
});
if (challenge.parameters[1] === "words") {
setConfig("words", challenge.parameters[2] as number, true);
setConfig("words", challenge.parameters[2] as number, {
nosave: true,
});
} else if (challenge.parameters[1] === "time") {
setConfig("time", challenge.parameters[2] as number, true);
setConfig("time", challenge.parameters[2] as number, {
nosave: true,
});
}
setConfig("mode", challenge.parameters[1] as Mode, true);
setConfig("mode", challenge.parameters[1] as Mode, {
nosave: true,
});
if (challenge.parameters[3] !== undefined) {
setConfig("difficulty", challenge.parameters[3] as Difficulty, true);
setConfig("difficulty", challenge.parameters[3] as Difficulty, {
nosave: true,
});
}
} else if (challenge.type === "special") {
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", true);
setConfig("time", 120, true);
setConfig("language", "english_10k", true);
setConfig("punctuation", true, true);
setConfig("stopOnError", "word", true);
setConfig("layout", "semimak", true);
setConfig("keymapLayout", "overrideSync", true);
setConfig("keymapMode", "static", true);
setConfig("mode", "time", {
nosave: true,
});
setConfig("time", 120, {
nosave: true,
});
setConfig("language", "english_10k", {
nosave: true,
});
setConfig("punctuation", true, {
nosave: true,
});
setConfig("stopOnError", "word", {
nosave: true,
});
setConfig("layout", "semimak", {
nosave: true,
});
setConfig("keymapLayout", "overrideSync", {
nosave: true,
});
setConfig("keymapMode", "static", {
nosave: true,
});
}
}
ManualRestart.set();

View file

@ -352,7 +352,9 @@ export async function randomizeTheme(): Promise<void> {
randomTheme = "custom";
}
setConfig("customTheme", false, true);
setConfig("customTheme", false, {
nosave: true,
});
await apply(randomTheme, colorsOverride);
if (randomThemeIndex >= themesList.length) {

View file

@ -130,7 +130,7 @@ const debouncedSave = debounce(2000, async () => {
const arr = Object.keys(filters).map(
(filterKey) => filters[filterKey as keyof typeof filters].value,
) as CustomBackgroundFilter;
setConfig("customBackgroundFilter", arr, false);
setConfig("customBackgroundFilter", arr);
});
ConfigEvent.subscribe(({ key, newValue }) => {

View file

@ -294,7 +294,7 @@ export function handleConfigInput<T extends ConfigKey>({
if (Config[configName] === value) {
return;
}
const didConfigSave = setConfig(configName, value, false);
const didConfigSave = setConfig(configName, value);
if (didConfigSave) {
Notifications.add("Saved", 1, {

View file

@ -46,7 +46,9 @@ export default class SettingsGroup<K extends ConfigKey, T = ConfigType[K]> {
this.configName = configName;
this.mode = mode;
this.configFunction = (param, nosave) =>
setConfig(configName, param as ConfigType[K], nosave);
setConfig(configName, param as ConfigType[K], {
nosave: nosave ?? false,
});
this.setCallback = options?.setCallback;
this.updateCallback = options?.updateCallback;
this.validation = options?.validation;

View file

@ -153,7 +153,7 @@ async function setup(modalEl: HTMLElement): Promise<void> {
arr = [len];
}
if (setConfig("quoteLength", arr, false)) {
if (setConfig("quoteLength", arr)) {
ManualRestart.set();
TestLogic.restart();
}

View file

@ -363,7 +363,7 @@ function apply(val: number): void {
);
}
if (val !== null && !isNaN(val) && val >= 0) {
setConfig("quoteLength", [-2], false);
setConfig("quoteLength", [-2]);
TestState.setSelectedQuoteId(val);
ManualRestart.set();
} else {

View file

@ -207,7 +207,9 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
},
simon_says: {
applyConfig(): void {
setConfig("keymapMode", "next", true);
setConfig("keymapMode", "next", {
nosave: true,
});
},
rememberSettings(): void {
save("keymapMode", Config.keymapMode);
@ -215,7 +217,9 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
},
tts: {
applyConfig(): void {
setConfig("keymapMode", "off", true);
setConfig("keymapMode", "off", {
nosave: true,
});
},
rememberSettings(): void {
save("keymapMode", Config.keymapMode);
@ -368,8 +372,12 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
if (Config.layout === "default") {
layout = "qwerty";
}
setConfig("layout", layout, true);
setConfig("keymapLayout", "overrideSync", true);
setConfig("layout", layout, {
nosave: true,
});
setConfig("keymapLayout", "overrideSync", {
nosave: true,
});
},
rememberSettings(): void {
save("keymapMode", Config.keymapMode);
@ -380,8 +388,12 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
applyConfig(): void {
const layout = Config.customLayoutfluid[0] ?? "qwerty";
setConfig("layout", layout as Layout, true);
setConfig("keymapLayout", layout as KeymapLayout, true);
setConfig("layout", layout as Layout, {
nosave: true,
});
setConfig("keymapLayout", layout as KeymapLayout, {
nosave: true,
});
},
rememberSettings(): void {
save("keymapMode", Config.keymapMode);
@ -485,9 +497,13 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
memory: {
applyConfig(): void {
$("#wordsWrapper").addClass("hidden");
setConfig("showAllLines", true, true);
setConfig("showAllLines", true, {
nosave: true,
});
if (Config.keymapMode === "next") {
setConfig("keymapMode", "react", true);
setConfig("keymapMode", "react", {
nosave: true,
});
}
},
rememberSettings(): void {
@ -684,7 +700,9 @@ const list: Partial<Record<FunboxName, FunboxFunctions>> = {
if (languages.length === 1) {
const lang = languages[0] as LanguageObject;
setConfig("language", lang.name, true);
setConfig("language", lang.name, {
nosave: true,
});
toggleFunbox("polyglot", true);
Notifications.add(
`Disabled polyglot funbox because only one valid language was found. Check your polyglot languages config (${Config.customPolyglot.join(

View file

@ -20,7 +20,9 @@ export function save<T extends ConfigKey>(
settingsMemory[settingName] ??= {
value,
setFunction: (param, noSave?) =>
setConfig(settingName, param as Config[T], noSave),
setConfig(settingName, param as Config[T], {
nosave: noSave ?? false,
}),
};
}

View file

@ -38,7 +38,7 @@ export function setFunbox(funbox: FunboxName[]): boolean {
}
}
FunboxMemory.load();
setConfig("funbox", funbox, false);
setConfig("funbox", funbox);
return true;
}
@ -104,7 +104,9 @@ export async function activate(
),
-1,
);
setConfig("funbox", [], true);
setConfig("funbox", [], {
nosave: true,
});
await clear();
return false;
}
@ -123,7 +125,9 @@ export async function activate(
Misc.createErrorMessage(error, "Failed to activate funbox"),
-1,
);
setConfig("funbox", [], true);
setConfig("funbox", [], {
nosave: true,
});
await clear();
return false;
}
@ -134,7 +138,9 @@ export async function activate(
"Current language does not support this funbox mode",
0,
);
setConfig("funbox", [], true);
setConfig("funbox", [], {
nosave: true,
});
await clear();
return;
}
@ -188,7 +194,9 @@ export async function activate(
-1,
);
}
setConfig("funbox", [], true);
setConfig("funbox", [], {
nosave: true,
});
await clear();
return;
}

View file

@ -148,7 +148,9 @@ export function init(
customText = CustomText.getData();
}
setConfig("mode", "custom", true);
setConfig("mode", "custom", {
nosave: true,
});
CustomText.setPipeDelimiter(true);
CustomText.setText(newCustomText);
CustomText.setLimitMode("section");

View file

@ -497,9 +497,11 @@ async function init(): Promise<boolean> {
important: true,
},
);
setConfig("lazyMode", false, false);
setConfig("lazyMode", false);
} else if (rememberLazyMode && anySupportsLazyMode) {
setConfig("lazyMode", true, true);
setConfig("lazyMode", true, {
nosave: true,
});
}
} else {
// normal mode
@ -510,9 +512,11 @@ async function init(): Promise<boolean> {
important: true,
});
setConfig("lazyMode", false, false);
setConfig("lazyMode", false);
} else if (rememberLazyMode && !language.noLazyMode) {
setConfig("lazyMode", true, true);
setConfig("lazyMode", true, {
nosave: true,
});
}
}
@ -1559,7 +1563,7 @@ $(".pageTest").on("click", "#testConfig .quoteLength .textButton", (e) => {
arr = [len];
}
if (setConfig("quoteLength", arr, false)) {
if (setConfig("quoteLength", arr)) {
ManualRestart.set();
restart();
}
@ -1595,7 +1599,9 @@ ConfigEvent.subscribe(({ key, newValue, nosave }) => {
if (key === "language") {
//automatically enable lazy mode for arabic
if ((newValue as string)?.startsWith("arabic") && ArabicLazyMode.get()) {
setConfig("lazyMode", true, true);
setConfig("lazyMode", true, {
nosave: true,
});
}
restart();
}

View file

@ -127,8 +127,12 @@ function layoutfluid(): void {
if (Config.layout !== layout && layout !== undefined) {
LayoutfluidFunboxTimer.hide();
setConfig("layout", layout as Layout, true);
setConfig("keymapLayout", layout as KeymapLayout, true);
setConfig("layout", layout as Layout, {
nosave: true,
});
setConfig("keymapLayout", layout as KeymapLayout, {
nosave: true,
});
}
}
if (timerDebug) console.timeEnd("layoutfluid");

View file

@ -181,18 +181,24 @@ export function loadTestSettingsFromUrl(getOverride?: string): void {
const applied: Record<string, string> = {};
if (de[0] !== null) {
setConfig("mode", de[0], true);
setConfig("mode", de[0], {
nosave: true,
});
applied["mode"] = de[0];
}
const mode = de[0] ?? Config.mode;
if (de[1] !== null) {
if (mode === "time") {
setConfig("time", parseInt(de[1], 10), true);
setConfig("time", parseInt(de[1], 10), {
nosave: true,
});
} else if (mode === "words") {
setConfig("words", parseInt(de[1], 10), true);
setConfig("words", parseInt(de[1], 10), {
nosave: true,
});
} else if (mode === "quote") {
setConfig("quoteLength", [-2], false);
setConfig("quoteLength", [-2]);
TestState.setSelectedQuoteId(parseInt(de[1], 10));
ManualRestart.set();
}
@ -236,22 +242,30 @@ export function loadTestSettingsFromUrl(getOverride?: string): void {
}
if (de[3] !== null) {
setConfig("punctuation", de[3], true);
setConfig("punctuation", de[3], {
nosave: true,
});
applied["punctuation"] = de[3] ? "on" : "off";
}
if (de[4] !== null) {
setConfig("numbers", de[4], true);
setConfig("numbers", de[4], {
nosave: true,
});
applied["numbers"] = de[4] ? "on" : "off";
}
if (de[5] !== null) {
setConfig("language", de[5] as Language, true);
setConfig("language", de[5] as Language, {
nosave: true,
});
applied["language"] = de[5];
}
if (de[6] !== null) {
setConfig("difficulty", de[6], true);
setConfig("difficulty", de[6], {
nosave: true,
});
applied["difficulty"] = de[6];
}
@ -263,7 +277,9 @@ export function loadTestSettingsFromUrl(getOverride?: string): void {
} else {
val = de[7];
}
setConfig("funbox", val, true);
setConfig("funbox", val, {
nosave: true,
});
applied["funbox"] = val.join(", ");
}