From 71cdce20e3ced9ba154adf7cf196da39e784fbd1 Mon Sep 17 00:00:00 2001 From: Ferotiq <64989416+Ferotiq@users.noreply.github.com> Date: Sat, 19 Feb 2022 10:44:27 -0600 Subject: [PATCH] TypeScript FrontEnd: Add Account Files (#2494) * add account files, config, and db, fix other files, and make lint script work on cmd * fuck operating systems * remove project from eslint * Merging and fixing some bugs * fixed result ordering * fixed quote filter stopping all results * fixed words filter not working * corrected type * Update commandline-lists.ts * Update types.d.ts * removing explicit tag types * mfing prettier * small changes * stuff * fixes * fix cannot read properties of undefined * another check just to be safe * okay that works Co-authored-by: Miodec --- .github/ISSUE_TEMPLATE/bug_report.yaml | 19 +- .prettierrc | 11 +- .../{all-time-stats.js => all-time-stats.ts} | 20 +- ...i-result-chart.js => mini-result-chart.ts} | 36 +- .../account/{pb-tables.js => pb-tables.ts} | 5 +- .../{result-filters.js => result-filters.ts} | 174 +++-- ...{sign-out-button.js => sign-out-button.ts} | 4 +- frontend/src/scripts/{config.js => config.ts} | 458 ++++++++----- .../scripts/controllers/account-controller.js | 45 +- .../scripts/controllers/input-controller.js | 5 +- .../src/scripts/controllers/tag-controller.js | 16 +- .../controllers/verification-controller.js | 6 +- frontend/src/scripts/{db.js => db.ts} | 453 ++++++++----- .../src/scripts/elements/commandline-lists.ts | 46 +- frontend/src/scripts/elements/commandline.ts | 2 +- .../elements/custom-background-filter.ts | 9 +- frontend/src/scripts/elements/leaderboards.ts | 6 +- frontend/src/scripts/elements/modes-notice.ts | 2 +- frontend/src/scripts/elements/monkey-power.ts | 2 +- frontend/src/scripts/misc.ts | 21 +- .../src/scripts/observables/config-event.ts | 8 +- frontend/src/scripts/pages/account.ts | 620 +++++++++--------- frontend/src/scripts/pages/settings.ts | 14 +- .../popups/custom-test-duration-popup.ts | 2 +- .../popups/custom-word-amount-popup.ts | 2 +- .../src/scripts/popups/edit-preset-popup.ts | 21 +- .../src/scripts/popups/edit-tags-popup.ts | 18 +- .../popups/mobile-test-config-popup.ts | 24 +- .../src/scripts/popups/pb-tables-popup.ts | 67 +- .../src/scripts/popups/quote-rate-popup.ts | 23 +- .../src/scripts/popups/quote-search-popup.ts | 2 +- .../src/scripts/popups/result-tags-popup.ts | 16 +- frontend/src/scripts/popups/simple-popups.ts | 22 +- .../src/scripts/settings/settings-group.ts | 2 +- frontend/src/scripts/settings/theme-picker.ts | 2 +- frontend/src/scripts/test/live-burst.ts | 10 +- frontend/src/scripts/test/result.js | 20 +- frontend/src/scripts/test/test-words.ts | 2 +- frontend/src/scripts/types/types.d.ts | 97 ++- package-lock.json | 16 +- package.json | 4 +- 41 files changed, 1377 insertions(+), 955 deletions(-) rename frontend/src/scripts/account/{all-time-stats.js => all-time-stats.ts} (64%) rename frontend/src/scripts/account/{mini-result-chart.js => mini-result-chart.ts} (71%) rename frontend/src/scripts/account/{pb-tables.js => pb-tables.ts} (98%) rename frontend/src/scripts/account/{result-filters.js => result-filters.ts} (67%) rename frontend/src/scripts/account/{sign-out-button.js => sign-out-button.ts} (92%) rename frontend/src/scripts/{config.js => config.ts} (78%) rename frontend/src/scripts/{db.js => db.ts} (57%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 7c82d19d5..044d0eeba 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -2,7 +2,6 @@ name: Bug report description: Create a report to help us improve labels: [bug] body: - - type: markdown attributes: value: | @@ -10,8 +9,7 @@ body: ``` Thanks for taking the time to fill out this bug! If you need real-time help, join us on Discord: discord.gg/monkeytype ``` - - + - type: checkboxes attributes: label: Did you clear cache before opening an issue? @@ -19,7 +17,7 @@ body: options: - label: I have cleared my cache required: true - + - type: checkboxes attributes: label: Is there an existing issue for this? @@ -27,7 +25,7 @@ body: options: - label: I have searched the existing issues required: true - + - type: markdown attributes: value: | @@ -35,35 +33,35 @@ body: ``` Below fields are very important to quickly track down the issue, so please take the time to carefully check when the issue happens and when it does not. ``` - + - type: dropdown attributes: label: Does the issue happen when logged in? options: ["Yes", "No", "N/A"] validations: required: true - + - type: dropdown attributes: label: Does the issue happen when logged out? options: ["Yes", "No"] validations: required: true - + - type: dropdown attributes: label: Does the issue happen in incognito mode when logged in? options: ["Yes", "No", "N/A"] validations: required: true - + - type: dropdown attributes: label: Does the issue happen in incognito mode when logged out? options: ["Yes", "No"] validations: required: true - + - type: textarea attributes: label: Account information @@ -128,4 +126,3 @@ body: Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. validations: required: false - diff --git a/.prettierrc b/.prettierrc index 9ecd5a034..61dfe5298 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,14 @@ { "tabWidth": 2, "useTabs": false, - "htmlWhitespaceSensitivity": "ignore" + "htmlWhitespaceSensitivity": "ignore", + "endOfLine": "lf", + "overrides": [ + { + "files": ["*.ts"], + "options": { + "parser": "typescript" + } + } + ] } diff --git a/frontend/src/scripts/account/all-time-stats.js b/frontend/src/scripts/account/all-time-stats.ts similarity index 64% rename from frontend/src/scripts/account/all-time-stats.js rename to frontend/src/scripts/account/all-time-stats.ts index 9d222795f..cce9700c1 100644 --- a/frontend/src/scripts/account/all-time-stats.js +++ b/frontend/src/scripts/account/all-time-stats.ts @@ -1,33 +1,37 @@ import * as DB from "../db"; import * as Misc from "../misc"; -export function clear() { +export function clear(): void { $(".pageAccount .globalTimeTyping .val").text(`-`); $(".pageAccount .globalTestsStarted .val").text(`-`); $(".pageAccount .globalTestsCompleted .val").text(`-`); } -export function update() { - if (DB.getSnapshot().globalStats.time != undefined) { +export function update(): void { + const snapshot = DB.getSnapshot(); + + if (snapshot.globalStats !== undefined) { // let th = Math.floor(DB.getSnapshot().globalStats.time / 3600); // let tm = Math.floor((DB.getSnapshot().globalStats.time % 3600) / 60); // let ts = Math.floor((DB.getSnapshot().globalStats.time % 3600) % 60); $(".pageAccount .globalTimeTyping .val").text( Misc.secondsToString( - Math.round(DB.getSnapshot().globalStats.time), + Math.round(snapshot.globalStats.time as number), true, true ) ); } - if (DB.getSnapshot().globalStats.started != undefined) { + + if (snapshot.globalStats !== undefined) { $(".pageAccount .globalTestsStarted .val").text( - DB.getSnapshot().globalStats.started + snapshot.globalStats.started as number ); } - if (DB.getSnapshot().globalStats.completed != undefined) { + + if (snapshot.globalStats !== undefined) { $(".pageAccount .globalTestsCompleted .val").text( - DB.getSnapshot().globalStats.completed + snapshot.globalStats.completed as number ); } } diff --git a/frontend/src/scripts/account/mini-result-chart.js b/frontend/src/scripts/account/mini-result-chart.ts similarity index 71% rename from frontend/src/scripts/account/mini-result-chart.js rename to frontend/src/scripts/account/mini-result-chart.ts index 4168eccf6..8f33dfb5c 100644 --- a/frontend/src/scripts/account/mini-result-chart.js +++ b/frontend/src/scripts/account/mini-result-chart.ts @@ -1,23 +1,23 @@ import * as ChartController from "../controllers/chart-controller"; import Config from "../config"; -export function updatePosition(x, y) { +export function updatePosition(x: number, y: number): void { $(".pageAccount .miniResultChartWrapper").css({ top: y, left: x }); } -export function show() { +export function show(): void { $(".pageAccount .miniResultChartWrapper").stop(true, true).fadeIn(125); $(".pageAccount .miniResultChartBg").stop(true, true).fadeIn(125); } -function hide() { +function hide(): void { $(".pageAccount .miniResultChartWrapper").stop(true, true).fadeOut(125); $(".pageAccount .miniResultChartBg").stop(true, true).fadeOut(125); } -export function updateData(data) { +export function updateData(data: MonkeyTypes.ChartData): void { // let data = filteredResults[filteredId].chartData; - let labels = []; + const labels = []; for (let i = 1; i <= data.wpm.length; i++) { labels.push(i.toString()); } @@ -28,22 +28,22 @@ export function updateData(data) { ChartController.miniResult.updateColors(); - let maxChartVal = Math.max(...[Math.max(...data.wpm), Math.max(...data.raw)]); - let minChartVal = Math.min(...[Math.min(...data.wpm), Math.min(...data.raw)]); - ChartController.miniResult.options.scales.yAxes[0].ticks.max = Math.round( - maxChartVal + const maxChartVal = Math.max( + ...[Math.max(...data.wpm), Math.max(...data.raw)] ); - ChartController.miniResult.options.scales.yAxes[1].ticks.max = Math.round( - maxChartVal + const minChartVal = Math.min( + ...[Math.min(...data.wpm), Math.min(...data.raw)] ); + ChartController.miniResult.options.scales.yAxes[0].ticks.max = + Math.round(maxChartVal); + ChartController.miniResult.options.scales.yAxes[1].ticks.max = + Math.round(maxChartVal); if (!Config.startGraphsAtZero) { - ChartController.miniResult.options.scales.yAxes[0].ticks.min = Math.round( - minChartVal - ); - ChartController.miniResult.options.scales.yAxes[1].ticks.min = Math.round( - minChartVal - ); + ChartController.miniResult.options.scales.yAxes[0].ticks.min = + Math.round(minChartVal); + ChartController.miniResult.options.scales.yAxes[1].ticks.min = + Math.round(minChartVal); } else { ChartController.miniResult.options.scales.yAxes[0].ticks.min = 0; ChartController.miniResult.options.scales.yAxes[1].ticks.min = 0; @@ -52,6 +52,6 @@ export function updateData(data) { ChartController.miniResult.update({ duration: 0 }); } -$(document).on("click", ".pageAccount .miniResultChartBg", (event) => { +$(document).on("click", ".pageAccount .miniResultChartBg", () => { hide(); }); diff --git a/frontend/src/scripts/account/pb-tables.js b/frontend/src/scripts/account/pb-tables.ts similarity index 98% rename from frontend/src/scripts/account/pb-tables.js rename to frontend/src/scripts/account/pb-tables.ts index 031f45877..3669c7c81 100644 --- a/frontend/src/scripts/account/pb-tables.js +++ b/frontend/src/scripts/account/pb-tables.ts @@ -2,7 +2,7 @@ import * as DB from "../db"; import Config from "../config"; import * as Misc from "../misc"; -export function update() { +export function update(): void { $(".pageAccount .timePbTable tbody").html(` 15 @@ -75,10 +75,11 @@ export function update() { } const pb = DB.getSnapshot().personalBests; + if (pb === undefined) return; let pbData; let text; let dateText = `-
-`; - let multiplier = Config.alwaysShowCPM ? 5 : 1; + const multiplier = Config.alwaysShowCPM ? 5 : 1; text = ""; try { diff --git a/frontend/src/scripts/account/result-filters.js b/frontend/src/scripts/account/result-filters.ts similarity index 67% rename from frontend/src/scripts/account/result-filters.js rename to frontend/src/scripts/account/result-filters.ts index 5f4129841..8f125c7b9 100644 --- a/frontend/src/scripts/account/result-filters.js +++ b/frontend/src/scripts/account/result-filters.ts @@ -3,7 +3,7 @@ import * as DB from "../db"; import Config from "../config"; import * as Notifications from "../elements/notifications"; -export let defaultResultFilters = { +export const defaultResultFilters: MonkeyTypes.ResultFilters = { difficulty: { normal: true, expert: true, @@ -62,15 +62,15 @@ export let defaultResultFilters = { export let filters = defaultResultFilters; -function save() { +function save(): void { window.localStorage.setItem("resultFilters", JSON.stringify(filters)); } -export function load() { +export function load(): void { // let newTags = $.cookie("activeTags"); console.log("loading filters"); try { - let newResultFilters = window.localStorage.getItem("resultFilters"); + const newResultFilters = window.localStorage.getItem("resultFilters"); if ( newResultFilters != undefined && newResultFilters !== "" && @@ -84,7 +84,9 @@ export function load() { // save(); } - let newTags = {}; + const newTags: { + [tag: string]: boolean; + } = { none: false }; Object.keys(defaultResultFilters.tags).forEach((tag) => { if (filters.tags[tag] !== undefined) { @@ -104,11 +106,13 @@ export function load() { } } -export function getFilters() { +export function getFilters(): MonkeyTypes.ResultFilters { return filters; } -export function getGroup(group) { +export function getGroup( + group: G +): MonkeyTypes.ResultFilters[G] { return filters[group]; } @@ -116,7 +120,10 @@ export function getGroup(group) { // filters[group][filter] = value; // } -export function getFilter(group, filter) { +export function getFilter( + group: G, + filter: MonkeyTypes.Filter +): MonkeyTypes.ResultFilters[G][MonkeyTypes.Filter] { return filters[group][filter]; } @@ -124,30 +131,42 @@ export function getFilter(group, filter) { // filters[group][filter] = !filters[group][filter]; // } -export function loadTags(tags) { +export function loadTags(tags: MonkeyTypes.Tag[]): void { console.log("loading tags"); tags.forEach((tag) => { defaultResultFilters.tags[tag._id] = true; }); } -export function reset() { +export function reset(): void { filters = defaultResultFilters; save(); } -export function updateActive() { - let aboveChartDisplay = {}; - Object.keys(getFilters()).forEach((group) => { +type AboveChartDisplay = MonkeyTypes.PartialRecord< + MonkeyTypes.Group, + { all: boolean; array?: string[] } +>; + +export function updateActive(): void { + const aboveChartDisplay: AboveChartDisplay = {}; + (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => { aboveChartDisplay[group] = { all: true, array: [], }; - Object.keys(getGroup(group)).forEach((filter) => { + ( + Object.keys(getGroup(group)) as MonkeyTypes.Filter[] + ).forEach((filter) => { + const groupAboveChartDisplay = aboveChartDisplay[group]; + + if (groupAboveChartDisplay === undefined) return; + if (getFilter(group, filter)) { - aboveChartDisplay[group].array.push(filter); + groupAboveChartDisplay["array"]?.push(filter); } else { - aboveChartDisplay[group].all = false; + if (groupAboveChartDisplay["all"] !== undefined) + groupAboveChartDisplay["all"] = false; } let buttonEl; if (group === "date") { @@ -167,7 +186,7 @@ export function updateActive() { }); }); - function addText(group) { + function addText(group: MonkeyTypes.Group): string { let ret = ""; ret += "
"; if (group == "difficulty") { @@ -200,21 +219,23 @@ export function updateActive() { } else if (group == "funbox") { ret += ``; } - if (aboveChartDisplay[group].all) { + if (aboveChartDisplay[group]?.all) { ret += "all"; } else { if (group === "tags") { - ret += aboveChartDisplay.tags.array - .map((id) => { + ret += aboveChartDisplay.tags?.array + ?.map((id) => { if (id == "none") return id; - let name = DB.getSnapshot().tags.filter((t) => t._id == id)[0]; + const snapshot = DB.getSnapshot(); + const name = snapshot.tags?.filter((t) => t._id == id)[0]; if (name !== undefined) { - return DB.getSnapshot().tags.filter((t) => t._id == id)[0].name; + return snapshot.tags?.filter((t) => t._id == id)[0].name; } + return name; }) .join(", "); } else { - ret += aboveChartDisplay[group].array.join(", ").replace(/_/g, " "); + ret += aboveChartDisplay[group]?.array?.join(", ").replace(/_/g, " "); } } ret += "
"; @@ -232,13 +253,13 @@ export function updateActive() { chartString += `
`; //time - if (aboveChartDisplay.mode.array.includes("time")) { + if (aboveChartDisplay.mode?.array?.includes("time")) { chartString += addText("time"); chartString += `
`; } //words - if (aboveChartDisplay.mode.array.includes("words")) { + if (aboveChartDisplay.mode?.array?.includes("words")) { chartString += addText("words"); chartString += `
`; } @@ -271,14 +292,21 @@ export function updateActive() { }, 0); } -export function toggle(group, filter) { +export function toggle( + group: G, + filter: MonkeyTypes.Filter +): void { try { if (group === "date") { - Object.keys(getGroup("date")).forEach((date) => { - filters["date"][date] = false; - }); + (Object.keys(getGroup("date")) as MonkeyTypes.Filter<"date">[]).forEach( + (date) => { + filters["date"][date] = false; + } + ); } - filters[group][filter] = !filters[group][filter]; + filters[group][filter] = !filters[group][ + filter + ] as unknown as MonkeyTypes.ResultFilters[G][keyof MonkeyTypes.ResultFilters[G]]; save(); } catch (e) { Notifications.add( @@ -292,18 +320,21 @@ export function toggle(group, filter) { } } -export function updateTags() { +export function updateTags(): void { $( ".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons" ).empty(); - if (DB.getSnapshot().tags.length > 0) { + + const snapshot = DB.getSnapshot(); + + if (snapshot.tags?.length || 0 > 0) { $(".pageAccount .content .filterButtons .buttonsAndTitle.tags").removeClass( "hidden" ); $( ".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons" ).append(`
no tag
`); - DB.getSnapshot().tags.forEach((tag) => { + snapshot.tags?.forEach((tag) => { $( ".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons" ).append(`
${tag.name}
`); @@ -318,32 +349,49 @@ export function updateTags() { $( ".pageAccount .filterButtons .buttonsAndTitle .buttons, .pageAccount .group.topFilters .buttonsAndTitle.testDate .buttons" ).click(".button", (e) => { - const filter = $(e.target).attr("filter"); - const group = $(e.target).parents(".buttons").attr("group"); + const group = $(e.target) + .parents(".buttons") + .attr("group") as MonkeyTypes.Group; + const filter = $(e.target).attr("filter") as MonkeyTypes.Filter; if ($(e.target).hasClass("allFilters")) { - Object.keys(getFilters()).forEach((group) => { - Object.keys(getGroup(group)).forEach((filter) => { + (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => { + ( + Object.keys(getGroup(group)) as MonkeyTypes.Filter[] + ).forEach((filter) => { if (group === "date") { + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = false; - } else { + } else if (filters[group] !== undefined) { + // @ts-ignore filters[group][filter] = true; } }); }); filters["date"]["all"] = true; } else if ($(e.target).hasClass("noFilters")) { - Object.keys(getFilters()).forEach((group) => { + (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => { if (group !== "date") { - Object.keys(getGroup(group)).forEach((filter) => { + ( + Object.keys(getGroup(group)) as MonkeyTypes.Filter[] + ).forEach((filter) => { + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = false; }); } }); } else if ($(e.target).hasClass("button")) { if (e.shiftKey) { - Object.keys(getGroup(group)).forEach((filter) => { + ( + Object.keys(getGroup(group)) as MonkeyTypes.Filter[] + ).forEach((filter) => { + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = false; }); + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = true; } else { toggle(group, filter); @@ -354,12 +402,18 @@ $( save(); }); -$(".pageAccount .topFilters .button.allFilters").click((e) => { - Object.keys(getFilters()).forEach((group) => { - Object.keys(getGroup(group)).forEach((filter) => { +$(".pageAccount .topFilters .button.allFilters").click(() => { + (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => { + ( + Object.keys(getGroup(group)) as MonkeyTypes.Filter[] + ).forEach((filter) => { if (group === "date") { + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = false; } else { + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = true; } }); @@ -369,9 +423,13 @@ $(".pageAccount .topFilters .button.allFilters").click((e) => { save(); }); -$(".pageAccount .topFilters .button.currentConfigFilter").click((e) => { - Object.keys(getFilters()).forEach((group) => { - Object.keys(getGroup(group)).forEach((filter) => { +$(".pageAccount .topFilters .button.currentConfigFilter").click(() => { + (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => { + ( + Object.keys(getGroup(group)) as MonkeyTypes.Filter[] + ).forEach((filter) => { + // TODO figure out why "filter" is never + // @ts-ignore filters[group][filter] = false; }); }); @@ -379,11 +437,22 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => { filters["difficulty"][Config.difficulty] = true; filters["mode"][Config.mode] = true; if (Config.mode === "time") { - filters["time"][Config.time] = true; + if ([15, 30, 60, 120].includes(Config.time)) { + const configTime = Config.time as MonkeyTypes.DefaultTimeModes; + filters["time"][configTime] = true; + } } else if (Config.mode === "words") { - filters["words"][Config.words] = true; + if ([10, 25, 50, 100, 200].includes(Config.words)) { + const configWords = Config.words as MonkeyTypes.DefaultWordsModes; + filters["words"][configWords] = true; + } } else if (Config.mode === "quote") { - Object.keys(getGroup("quoteLength")).forEach((ql) => { + ( + Object.keys( + getGroup("quoteLength") + ) as MonkeyTypes.Filter<"quoteLength">[] + ).forEach((ql) => { + // TODO figure out how to fix this filters["quoteLength"][ql] = true; }); } @@ -410,7 +479,8 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => { } filters["tags"]["none"] = true; - DB.getSnapshot().tags.forEach((tag) => { + + DB.getSnapshot().tags?.forEach((tag) => { if (tag.active === true) { filters["tags"]["none"] = false; filters["tags"][tag._id] = true; @@ -422,7 +492,7 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => { save(); }); -$(".pageAccount .topFilters .button.toggleAdvancedFilters").click((e) => { +$(".pageAccount .topFilters .button.toggleAdvancedFilters").click(() => { $(".pageAccount .filterButtons").slideToggle(250); $(".pageAccount .topFilters .button.toggleAdvancedFilters").toggleClass( "active" diff --git a/frontend/src/scripts/account/sign-out-button.js b/frontend/src/scripts/account/sign-out-button.ts similarity index 92% rename from frontend/src/scripts/account/sign-out-button.js rename to frontend/src/scripts/account/sign-out-button.ts index 0fe149942..4c85d266e 100644 --- a/frontend/src/scripts/account/sign-out-button.js +++ b/frontend/src/scripts/account/sign-out-button.ts @@ -1,4 +1,4 @@ -export function show() { +export function show(): void { // $(".signOut").removeClass("hidden").css("opacity", 1); $(".signOut") .stop(true, true) @@ -18,7 +18,7 @@ export function show() { ); } -export function hide() { +export function hide(): void { $(".signOut") .stop(true, true) .css({ diff --git a/frontend/src/scripts/config.js b/frontend/src/scripts/config.ts similarity index 78% rename from frontend/src/scripts/config.js rename to frontend/src/scripts/config.ts index 830784006..9ed4a1290 100644 --- a/frontend/src/scripts/config.js +++ b/frontend/src/scripts/config.ts @@ -4,25 +4,25 @@ import * as Notifications from "./elements/notifications"; import * as Misc from "./misc"; import * as ConfigEvent from "./observables/config-event"; -export let localStorageConfig = null; +export let localStorageConfig: MonkeyTypes.Config; export let dbConfigLoaded = false; export let changedBeforeDb = false; -export function setLocalStorageConfig(val) { +export function setLocalStorageConfig(val: MonkeyTypes.Config): void { localStorageConfig = val; } -export function setDbConfigLoaded(val) { +export function setDbConfigLoaded(val: boolean): void { dbConfigLoaded = val; } -export function setChangedBeforeDb(val) { +export function setChangedBeforeDb(val: boolean): void { changedBeforeDb = val; } -let loadDone; +let loadDone: (...stuff: any[]) => any; -let defaultConfig = { +const defaultConfig: MonkeyTypes.Config = { theme: "serika_dark", customTheme: false, customThemeColors: [ @@ -73,7 +73,7 @@ let defaultConfig = { keymapStyle: "staggered", keymapLegendStyle: "lowercase", keymapLayout: "overrideSync", - fontFamily: "Roboto_Mono", + fontFamily: "roboto_mono", smoothLineScroll: false, alwaysShowDecimalPlaces: false, alwaysShowWordsHistory: false, @@ -117,7 +117,7 @@ let defaultConfig = { lazyMode: false, }; -function isConfigKeyValid(name) { +function isConfigKeyValid(name: string): boolean { if (name === null || name === undefined || name === "") return false; if (name.length > 30) return false; return /^[0-9a-zA-Z_.\-#+]+$/.test(name); @@ -127,7 +127,7 @@ let config = { ...defaultConfig, }; -export async function saveToLocalStorage(noDbCheck = false) { +export async function saveToLocalStorage(noDbCheck = false): Promise { if (!dbConfigLoaded && !noDbCheck) { setChangedBeforeDb(true); } @@ -137,9 +137,9 @@ export async function saveToLocalStorage(noDbCheck = false) { // expires: d, // path: "/", // }); - let save = config; + const save = config; delete save.resultFilters; - let stringified = JSON.stringify(save); + const stringified = JSON.stringify(save); window.localStorage.setItem("config", stringified); // restartCount = 0; if (!noDbCheck) await DB.saveConfig(save); @@ -147,7 +147,7 @@ export async function saveToLocalStorage(noDbCheck = false) { } //numbers -export function setNumbers(numb, nosave) { +export function setNumbers(numb: boolean, nosave?: boolean): void { if (config.mode === "quote") { numb = false; } @@ -162,7 +162,7 @@ export function setNumbers(numb, nosave) { } //punctuation -export function setPunctuation(punc, nosave) { +export function setPunctuation(punc: boolean, nosave?: boolean): void { if (config.mode === "quote") { punc = false; } @@ -176,12 +176,12 @@ export function setPunctuation(punc, nosave) { ConfigEvent.dispatch("punctuation", config.punctuation); } -export function setMode(mode, nosave) { +export function setMode(mode: MonkeyTypes.Mode, nosave?: boolean): void { if (mode !== "words" && config.funbox === "memory") { Notifications.add("Memory funbox can only be used with words mode.", 0); return; } - let previous = config.mode; + const previous = config.mode; config.mode = mode; if (config.mode == "custom") { setPunctuation(false, true); @@ -198,7 +198,7 @@ export function setMode(mode, nosave) { ConfigEvent.dispatch("mode", previous, config.mode); } -export function setPlaySoundOnError(val, nosave) { +export function setPlaySoundOnError(val: boolean, nosave?: boolean): void { if (val == undefined) { val = false; } @@ -207,7 +207,10 @@ export function setPlaySoundOnError(val, nosave) { ConfigEvent.dispatch("playSoundOnError", config.playSoundOnError); } -export function setPlaySoundOnClick(val, nosave) { +export function setPlaySoundOnClick( + val: MonkeyTypes.PlaySoundOnClick, + nosave?: boolean +): void { if (val == undefined) { val = "off"; } @@ -216,7 +219,10 @@ export function setPlaySoundOnClick(val, nosave) { ConfigEvent.dispatch("playSoundOnClick", config.playSoundOnClick); } -export function setSoundVolume(val, nosave) { +export function setSoundVolume( + val: MonkeyTypes.SoundVolume, + nosave?: boolean +): void { if (val == undefined) { val = "1.0"; } @@ -226,7 +232,10 @@ export function setSoundVolume(val, nosave) { } //difficulty -export function setDifficulty(diff, nosave) { +export function setDifficulty( + diff: MonkeyTypes.Difficulty, + nosave?: boolean +): void { if ( (diff !== "normal" && diff !== "expert" && diff !== "master") || diff == undefined @@ -239,20 +248,20 @@ export function setDifficulty(diff, nosave) { } //set fav themes -export function setFavThemes(themes, nosave) { +export function setFavThemes(themes: string[], nosave?: boolean): void { config.favThemes = themes; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("favThemes", config.favThemes); } -export function setFunbox(funbox, nosave) { - let val = funbox ? funbox : "none"; +export function setFunbox(funbox: string, nosave?: boolean): void { + const val = funbox ? funbox : "none"; config.funbox = val; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("funbox", config.funbox); } -export function setBlindMode(blind, nosave) { +export function setBlindMode(blind: boolean, nosave?: boolean): void { if (blind == undefined) { blind = false; } @@ -261,7 +270,10 @@ export function setBlindMode(blind, nosave) { ConfigEvent.dispatch("blindMode", config.blindMode); } -export function setChartAccuracy(chartAccuracy, nosave) { +export function setChartAccuracy( + chartAccuracy: boolean, + nosave?: boolean +): void { if (chartAccuracy == undefined) { chartAccuracy = true; } @@ -270,7 +282,10 @@ export function setChartAccuracy(chartAccuracy, nosave) { ConfigEvent.dispatch("chartAccuracy", config.chartAccuracy); } -export function setChartStyle(chartStyle, nosave) { +export function setChartStyle( + chartStyle: MonkeyTypes.ChartStyle, + nosave?: boolean +): void { if (chartStyle == undefined) { chartStyle = "line"; } @@ -279,7 +294,10 @@ export function setChartStyle(chartStyle, nosave) { ConfigEvent.dispatch("chartStyle", config.chartStyle); } -export function setStopOnError(soe, nosave) { +export function setStopOnError( + soe: MonkeyTypes.StopOnError | boolean, + nosave?: boolean +): void { if (soe == undefined || soe === true || soe === false) { soe = "off"; } @@ -291,7 +309,10 @@ export function setStopOnError(soe, nosave) { ConfigEvent.dispatch("stopOnError", config.stopOnError); } -export function setAlwaysShowDecimalPlaces(val, nosave) { +export function setAlwaysShowDecimalPlaces( + val: boolean, + nosave?: boolean +): void { if (val == undefined) { val = false; } @@ -303,7 +324,7 @@ export function setAlwaysShowDecimalPlaces(val, nosave) { ); } -export function setAlwaysShowCPM(val, nosave) { +export function setAlwaysShowCPM(val: boolean, nosave?: boolean): void { if (val == undefined) { val = false; } @@ -312,7 +333,7 @@ export function setAlwaysShowCPM(val, nosave) { ConfigEvent.dispatch("alwaysShowCPM", config.alwaysShowCPM); } -export function setShowOutOfFocusWarning(val, nosave) { +export function setShowOutOfFocusWarning(val: boolean, nosave?: boolean): void { if (val == undefined) { val = true; } @@ -324,7 +345,7 @@ export function setShowOutOfFocusWarning(val, nosave) { ConfigEvent.dispatch("showOutOfFocusWarning", config.showOutOfFocusWarning); } -export function setSwapEscAndTab(val, nosave) { +export function setSwapEscAndTab(val: boolean, nosave?: boolean): void { if (val == undefined) { val = false; } @@ -334,7 +355,10 @@ export function setSwapEscAndTab(val, nosave) { } //pace caret -export function setPaceCaret(val, nosave) { +export function setPaceCaret( + val: MonkeyTypes.PaceCaret, + nosave?: boolean +): void { if (val == undefined) { val = "off"; } @@ -353,9 +377,8 @@ export function setPaceCaret(val, nosave) { ConfigEvent.dispatch("paceCaret", config.paceCaret); } -export function setPaceCaretCustomSpeed(val, nosave) { - val = parseInt(val); - if (val == undefined || Number.isNaN(val)) { +export function setPaceCaretCustomSpeed(val: number, nosave?: boolean): void { + if (val == undefined) { val = 100; } config.paceCaretCustomSpeed = val; @@ -363,7 +386,7 @@ export function setPaceCaretCustomSpeed(val, nosave) { ConfigEvent.dispatch("paceCaretCustomSpeed", config.paceCaretCustomSpeed); } -export function setRepeatedPace(pace, nosave) { +export function setRepeatedPace(pace: boolean, nosave?: boolean): void { if (pace == undefined) { pace = true; } @@ -373,7 +396,10 @@ export function setRepeatedPace(pace, nosave) { } //min wpm -export function setMinWpm(minwpm, nosave) { +export function setMinWpm( + minwpm: MonkeyTypes.MinimumWordsPerMinute, + nosave?: boolean +): void { if (minwpm == undefined) { minwpm = "off"; } @@ -382,9 +408,8 @@ export function setMinWpm(minwpm, nosave) { ConfigEvent.dispatch("minWpm", config.minWpm); } -export function setMinWpmCustomSpeed(val, nosave) { - val = parseInt(val); - if (val == undefined || Number.isNaN(val)) { +export function setMinWpmCustomSpeed(val: number, nosave?: boolean): void { + if (val == undefined) { val = 100; } config.minWpmCustomSpeed = val; @@ -393,7 +418,10 @@ export function setMinWpmCustomSpeed(val, nosave) { } //min acc -export function setMinAcc(min, nosave) { +export function setMinAcc( + min: MonkeyTypes.MinimumAccuracy, + nosave?: boolean +): void { if (min == undefined) { min = "off"; } @@ -402,8 +430,8 @@ export function setMinAcc(min, nosave) { ConfigEvent.dispatch("minAcc", config.minAcc); } -export function setMinAccCustom(val, nosave) { - if (val == undefined || Number.isNaN(parseInt(val))) { +export function setMinAccCustom(val: number, nosave?: boolean): void { + if (val === undefined) { val = 90; } config.minAccCustom = val; @@ -412,7 +440,10 @@ export function setMinAccCustom(val, nosave) { } //min burst -export function setMinBurst(min, nosave) { +export function setMinBurst( + min: MonkeyTypes.MinimumBurst, + nosave?: boolean +): void { if (min == undefined) { min = "off"; } @@ -421,9 +452,8 @@ export function setMinBurst(min, nosave) { ConfigEvent.dispatch("minBurst", config.minBurst); } -export function setMinBurstCustomSpeed(val, nosave) { - val = parseInt(val); - if (val == undefined || Number.isNaN(val)) { +export function setMinBurstCustomSpeed(val: number, nosave?: boolean): void { + if (val == undefined) { val = 100; } config.minBurstCustomSpeed = val; @@ -432,7 +462,10 @@ export function setMinBurstCustomSpeed(val, nosave) { } //always show words history -export function setAlwaysShowWordsHistory(val, nosave) { +export function setAlwaysShowWordsHistory( + val: boolean, + nosave?: boolean +): void { if (val == undefined) { val = false; } @@ -442,7 +475,10 @@ export function setAlwaysShowWordsHistory(val, nosave) { } //single list command line -export function setSingleListCommandLine(option, nosave) { +export function setSingleListCommandLine( + option: MonkeyTypes.SingleListCommandLine, + nosave?: boolean +): void { if (!option) option = "manual"; config.singleListCommandLine = option; if (!nosave) saveToLocalStorage(); @@ -450,7 +486,7 @@ export function setSingleListCommandLine(option, nosave) { } //caps lock warning -export function setCapsLockWarning(val, nosave) { +export function setCapsLockWarning(val: boolean, nosave?: boolean): void { if (val == undefined) { val = false; } @@ -459,7 +495,7 @@ export function setCapsLockWarning(val, nosave) { ConfigEvent.dispatch("capsLockWarning", config.capsLockWarning); } -export function setShowAllLines(sal, nosave) { +export function setShowAllLines(sal: boolean, nosave?: boolean): void { if (sal == undefined) { sal = false; } @@ -470,7 +506,7 @@ export function setShowAllLines(sal, nosave) { ConfigEvent.dispatch("showAllLines", config.showAllLines); } -export function setQuickEnd(qe, nosave) { +export function setQuickEnd(qe: boolean, nosave?: boolean): void { if (qe == undefined) { qe = false; } @@ -479,7 +515,10 @@ export function setQuickEnd(qe, nosave) { ConfigEvent.dispatch("quickEnd", config.quickEnd); } -export function setEnableAds(val, nosave) { +export function setEnableAds( + val: MonkeyTypes.EnableAds | boolean, + nosave?: boolean +): void { if (val == undefined || val === true || val === false) { val = "off"; } @@ -493,7 +532,10 @@ export function setEnableAds(val, nosave) { } } -export function setRepeatQuotes(val, nosave) { +export function setRepeatQuotes( + val: MonkeyTypes.RepeatQuotes | boolean, + nosave?: boolean +): void { if (val == undefined || val === true || val === false) { val = "off"; } @@ -503,7 +545,7 @@ export function setRepeatQuotes(val, nosave) { } //flip colors -export function setFlipTestColors(flip, nosave) { +export function setFlipTestColors(flip: boolean, nosave?: boolean): void { if (flip == undefined) { flip = false; } @@ -513,7 +555,7 @@ export function setFlipTestColors(flip, nosave) { } //extra color -export function setColorfulMode(extra, nosave) { +export function setColorfulMode(extra: boolean, nosave?: boolean): void { if (extra == undefined) { extra = false; } @@ -523,7 +565,7 @@ export function setColorfulMode(extra, nosave) { } //strict space -export function setStrictSpace(val, nosave) { +export function setStrictSpace(val: boolean, nosave?: boolean): void { if (val == undefined) { val = false; } @@ -533,7 +575,10 @@ export function setStrictSpace(val, nosave) { } //opposite shift space -export function setOppositeShiftMode(val, nosave) { +export function setOppositeShiftMode( + val: MonkeyTypes.OppositeShiftMode, + nosave?: boolean +): void { if (val == undefined) { val = "off"; } @@ -542,7 +587,10 @@ export function setOppositeShiftMode(val, nosave) { ConfigEvent.dispatch("oppositeShiftMode", config.oppositeShiftMode); } -export function setPageWidth(val, nosave) { +export function setPageWidth( + val: MonkeyTypes.PageWidth, + nosave?: boolean +): void { if (val == null || val == undefined) { val = "100"; } @@ -559,7 +607,10 @@ export function setPageWidth(val, nosave) { ConfigEvent.dispatch("pageWidth", config.pageWidth); } -export function setCaretStyle(caretStyle, nosave) { +export function setCaretStyle( + caretStyle: MonkeyTypes.CaretStyle, + nosave?: boolean +): void { if (caretStyle == null || caretStyle == undefined) { caretStyle = "default"; } @@ -591,7 +642,10 @@ export function setCaretStyle(caretStyle, nosave) { ConfigEvent.dispatch("caretStyle", config.caretStyle); } -export function setPaceCaretStyle(caretStyle, nosave) { +export function setPaceCaretStyle( + caretStyle: MonkeyTypes.CaretStyle, + nosave?: boolean +): void { if (caretStyle == null || caretStyle == undefined) { caretStyle = "default"; } @@ -621,7 +675,7 @@ export function setPaceCaretStyle(caretStyle, nosave) { ConfigEvent.dispatch("paceCaretStyle", config.paceCaretStyle); } -export function setShowTimerProgress(timer, nosave) { +export function setShowTimerProgress(timer: boolean, nosave?: boolean): void { if (timer == null || timer == undefined) { timer = false; } @@ -630,7 +684,7 @@ export function setShowTimerProgress(timer, nosave) { ConfigEvent.dispatch("showTimerProgress", config.showTimerProgress); } -export function setShowLiveWpm(live, nosave) { +export function setShowLiveWpm(live: boolean, nosave?: boolean): void { if (live == null || live == undefined) { live = false; } @@ -639,7 +693,7 @@ export function setShowLiveWpm(live, nosave) { ConfigEvent.dispatch("showLiveWpm", config.showLiveWpm); } -export function setShowLiveAcc(live, nosave) { +export function setShowLiveAcc(live: boolean, nosave?: boolean): void { if (live == null || live == undefined) { live = false; } @@ -648,7 +702,7 @@ export function setShowLiveAcc(live, nosave) { ConfigEvent.dispatch("showLiveAcc", config.showLiveAcc); } -export function setShowLiveBurst(live, nosave) { +export function setShowLiveBurst(live: boolean, nosave?: boolean): void { if (live == null || live == undefined) { live = false; } @@ -657,7 +711,10 @@ export function setShowLiveBurst(live, nosave) { ConfigEvent.dispatch("showLiveBurst", config.showLiveBurst); } -export function setHighlightMode(mode, nosave) { +export function setHighlightMode( + mode: MonkeyTypes.HighlightMode, + nosave?: boolean +): void { if ( mode === "word" && (config.funbox === "nospace" || @@ -678,7 +735,7 @@ export function setHighlightMode(mode, nosave) { ConfigEvent.dispatch("highlightMode", config.highlightMode); } -export function setHideExtraLetters(val, nosave) { +export function setHideExtraLetters(val: boolean, nosave?: boolean): void { if (val == null || val == undefined) { val = false; } @@ -687,7 +744,10 @@ export function setHideExtraLetters(val, nosave) { ConfigEvent.dispatch("hideExtraLetters", config.hideExtraLetters); } -export function setTimerStyle(style, nosave) { +export function setTimerStyle( + style: MonkeyTypes.TimerStyle, + nosave?: boolean +): void { if (style == null || style == undefined) { style = "mini"; } @@ -696,7 +756,10 @@ export function setTimerStyle(style, nosave) { ConfigEvent.dispatch("timerStyle", config.timerStyle); } -export function setTimerColor(color, nosave) { +export function setTimerColor( + color: MonkeyTypes.TimerColor, + nosave?: boolean +): void { if (!color || !["black", "sub", "text", "main"].includes(color)) { color = "black"; } @@ -738,9 +801,12 @@ export function setTimerColor(color, nosave) { if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("timerColor", config.timerColor); } -export function setTimerOpacity(opacity, nosave) { +export function setTimerOpacity( + opacity: MonkeyTypes.TimerOpacity, + nosave?: boolean +): void { if (opacity == null || opacity == undefined) { - opacity = 0.25; + opacity = "0.25"; } config.timerOpacity = opacity; if (!nosave) saveToLocalStorage(); @@ -748,7 +814,7 @@ export function setTimerOpacity(opacity, nosave) { } //key tips -export function setKeyTips(keyTips, nosave) { +export function setKeyTips(keyTips: boolean, nosave?: boolean): void { config.showKeyTips = keyTips; if (config.showKeyTips) { $("#bottom .keyTips").removeClass("hidden"); @@ -760,26 +826,34 @@ export function setKeyTips(keyTips, nosave) { } //mode -export function setTimeConfig(time, nosave) { - if (time === null || isNaN(time) || time < 0) { - time = 15; - } - time = parseInt(time); - // if (!nosave) setMode("time", nosave); - config.time = time; +export function setTimeConfig( + time: MonkeyTypes.TimeModes, + nosave?: boolean +): void { + const newTime = + time === null || time === undefined || isNaN(time) || time < 0 + ? defaultConfig.time + : time; + $("#top .config .time .text-button").removeClass("active"); - if (![15, 30, 60, 120].includes(time)) { - time = "custom"; - } - $("#top .config .time .text-button[timeConfig='" + time + "']").addClass( - "active" - ); + + const timeCustom = ![15, 30, 60, 120].includes(newTime) ? "custom" : newTime; + + config.time = newTime; + + $( + "#top .config .time .text-button[timeConfig='" + timeCustom + "']" + ).addClass("active"); if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("time", config.time); } //quote length -export function setQuoteLength(len, nosave, multipleMode) { +export function setQuoteLength( + len: MonkeyTypes.QuoteLengthArray | MonkeyTypes.QuoteLength, + nosave?: boolean, + multipleMode?: boolean +): void { if (Array.isArray(len)) { //config load if (len.length === 1 && len[0] === -1) len = [1]; @@ -789,7 +863,7 @@ export function setQuoteLength(len, nosave, multipleMode) { if (len === null || isNaN(len) || len < -2 || len > 3) { len = 1; } - len = parseInt(len); + len = parseInt(len.toString()) as MonkeyTypes.QuoteLength; if (multipleMode) { if (!config.quoteLength.includes(len)) { config.quoteLength.push(len); @@ -812,31 +886,35 @@ export function setQuoteLength(len, nosave, multipleMode) { ConfigEvent.dispatch("quoteLength", config.quoteLength); } -export function setWordCount(wordCount, nosave) { - wordCount = parseInt(wordCount); - if ( +export function setWordCount( + wordCount: MonkeyTypes.WordsModes, + nosave?: boolean +): void { + const newWordCount = wordCount === null || - isNaN(wordCount) || + wordCount === undefined || wordCount < 0 || wordCount > 100000 - ) { - wordCount = defaultConfig.words; - } - // if (!nosave) setMode("words", nosave); - config.words = wordCount; + ? defaultConfig.words + : wordCount; + $("#top .config .wordCount .text-button").removeClass("active"); - if (![10, 25, 50, 100, 200].includes(wordCount)) { - wordCount = "custom"; - } - $(`#top .config .wordCount .text-button[wordCount='${wordCount}']`).addClass( - "active" - ); + + const wordCustom = ![10, 25, 50, 100, 200].includes(newWordCount) + ? "custom" + : newWordCount; + + config.words = newWordCount; + + $( + "#top .config .wordCount .text-button[wordCount='" + wordCustom + "']" + ).addClass("active"); if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("words", config.words); } //caret -export function setSmoothCaret(mode, nosave) { +export function setSmoothCaret(mode: boolean, nosave?: boolean): void { config.smoothCaret = mode; if (mode) { $("#caret").css("animation-name", "caretFlashSmooth"); @@ -847,21 +925,21 @@ export function setSmoothCaret(mode, nosave) { ConfigEvent.dispatch("smoothCaret", config.smoothCaret); } -export function setStartGraphsAtZero(mode, nosave) { +export function setStartGraphsAtZero(mode: boolean, nosave?: boolean): void { config.startGraphsAtZero = mode; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("startGraphsAtZero", config.startGraphsAtZero); } //linescroll -export function setSmoothLineScroll(mode, nosave) { +export function setSmoothLineScroll(mode: boolean, nosave?: boolean): void { config.smoothLineScroll = mode; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("smoothLineScroll", config.smoothLineScroll); } //quick tab -export function setQuickTabMode(mode, nosave) { +export function setQuickTabMode(mode: boolean, nosave?: boolean): void { config.quickTab = mode; if (!config.quickTab) { $("#restartTestButton").removeClass("hidden"); @@ -878,9 +956,9 @@ export function setQuickTabMode(mode, nosave) { ConfigEvent.dispatch("quickTab", config.quickTab); } -export function previewFontFamily(font) { +export function previewFontFamily(font: string): void { if (font == undefined) { - font = "Roboto_Mono"; + font = "roboto_mono"; } document.documentElement.style.setProperty( "--font", @@ -889,9 +967,9 @@ export function previewFontFamily(font) { } //font family -export function setFontFamily(font, nosave) { +export function setFontFamily(font: string, nosave?: boolean): void { if (font == undefined || font === "") { - font = "Roboto_Mono"; + font = "roboto_mono"; Notifications.add( "Empty input received, reverted to the default font.", 0, @@ -918,7 +996,7 @@ export function setFontFamily(font, nosave) { } //freedom -export function setFreedomMode(freedom, nosave) { +export function setFreedomMode(freedom: boolean, nosave?: boolean): void { if (freedom == null) { freedom = false; } @@ -930,7 +1008,10 @@ export function setFreedomMode(freedom, nosave) { ConfigEvent.dispatch("freedomMode", config.freedomMode); } -export function setConfidenceMode(cm, nosave) { +export function setConfidenceMode( + cm: MonkeyTypes.ConfidenceMode, + nosave?: boolean +): void { if (cm == undefined || !["off", "on", "max"].includes(cm)) { cm = defaultConfig.confidenceMode; } @@ -943,7 +1024,10 @@ export function setConfidenceMode(cm, nosave) { ConfigEvent.dispatch("confidenceMode", config.confidenceMode); } -export function setIndicateTypos(value, nosave) { +export function setIndicateTypos( + value: MonkeyTypes.IndicateTypos, + nosave?: boolean +): void { if (!["off", "below", "replace"].includes(value)) { value = defaultConfig.indicateTypos; } @@ -952,27 +1036,34 @@ export function setIndicateTypos(value, nosave) { ConfigEvent.dispatch("indicateTypos", config.indicateTypos); } -export function setCustomTheme(boolean, nosave) { +export function setCustomTheme(boolean: boolean, nosave?: boolean): void { if (boolean !== undefined) config.customTheme = boolean; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("customTheme", config.customTheme); } -export function setTheme(name, nosave) { +export function setTheme(name: string, nosave?: boolean): void { config.theme = name; - setCustomTheme(false, true, true); + setCustomTheme(false, true); if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("theme", config.theme); } -function setThemes(theme, customState, nosave) { +function setThemes( + theme: string, + customState: boolean, + nosave?: boolean +): void { config.theme = theme; config.customTheme = customState; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("setThemes", customState); } -export function setRandomTheme(val, nosave) { +export function setRandomTheme( + val: MonkeyTypes.RandomTheme | boolean, + nosave?: boolean +): void { if (val === undefined || val === true || val === false) { val = "off"; } @@ -981,7 +1072,7 @@ export function setRandomTheme(val, nosave) { ConfigEvent.dispatch("randomTheme", config.randomTheme); } -export function setBritishEnglish(val, nosave) { +export function setBritishEnglish(val: boolean, nosave?: boolean): void { if (!val) { val = false; } @@ -990,7 +1081,7 @@ export function setBritishEnglish(val, nosave) { ConfigEvent.dispatch("britishEnglish", config.britishEnglish); } -export function setLazyMode(val, nosave) { +export function setLazyMode(val: boolean, nosave?: boolean): void { if (!val) { val = false; } @@ -999,7 +1090,7 @@ export function setLazyMode(val, nosave) { ConfigEvent.dispatch("lazyMode", config.lazyMode, nosave); } -export function setCustomThemeColors(colors, nosave) { +export function setCustomThemeColors(colors: string[], nosave?: boolean): void { if (colors !== undefined) { config.customThemeColors = colors; // ThemeController.set("custom"); @@ -1009,7 +1100,7 @@ export function setCustomThemeColors(colors, nosave) { ConfigEvent.dispatch("customThemeColors", config.customThemeColors); } -export function setLanguage(language, nosave) { +export function setLanguage(language: string, nosave?: boolean): void { if (language == null || language == undefined) { language = "english"; } @@ -1025,7 +1116,7 @@ export function setLanguage(language, nosave) { ConfigEvent.dispatch("language", config.language); } -export function setMonkey(monkey, nosave) { +export function setMonkey(monkey: boolean, nosave?: boolean): void { if (monkey === null || monkey === undefined) { monkey = false; } @@ -1039,7 +1130,10 @@ export function setMonkey(monkey, nosave) { ConfigEvent.dispatch("monkey", config.monkey); } -export function setKeymapMode(mode, nosave) { +export function setKeymapMode( + mode: MonkeyTypes.KeymapMode, + nosave?: boolean +): void { if (mode == null || mode == undefined) { mode = "off"; } @@ -1050,7 +1144,10 @@ export function setKeymapMode(mode, nosave) { ConfigEvent.dispatch("keymapMode", config.keymapMode); } -export function setKeymapLegendStyle(style, nosave) { +export function setKeymapLegendStyle( + style: MonkeyTypes.KeymapLegendStyle, + nosave?: boolean +): void { // Remove existing styles const keymapLegendStyles = ["lowercase", "uppercase", "blank"]; keymapLegendStyles.forEach((name) => { @@ -1079,14 +1176,17 @@ export function setKeymapLegendStyle(style, nosave) { ConfigEvent.dispatch("keymapLegendStyle", config.keymapLegendStyle); } -export function setKeymapStyle(style, nosave) { +export function setKeymapStyle( + style: MonkeyTypes.KeymapStyle, + nosave?: boolean +): void { style = style || "staggered"; config.keymapStyle = style; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("keymapStyle", config.keymapStyle); } -export function setKeymapLayout(layout, nosave) { +export function setKeymapLayout(layout: string, nosave?: boolean): void { if (layout == null || layout == undefined) { layout = "qwerty"; } @@ -1095,7 +1195,7 @@ export function setKeymapLayout(layout, nosave) { ConfigEvent.dispatch("keymapLayout", config.keymapLayout); } -export function setLayout(layout, nosave) { +export function setLayout(layout: string, nosave?: boolean): void { if (layout == null || layout == undefined) { layout = "qwerty"; } @@ -1104,7 +1204,7 @@ export function setLayout(layout, nosave) { ConfigEvent.dispatch("layout", config.layout); } -// export function setSavedLayout(layout, nosave) { +// export function setSavedLayout(layout, nosave?: boolean): void { // if (layout == null || layout == undefined) { // layout = "qwerty"; // } @@ -1112,7 +1212,10 @@ export function setLayout(layout, nosave) { // setLayout(layout, nosave); // } -export function setFontSize(fontSize, nosave) { +export function setFontSize( + fontSize: MonkeyTypes.FontSize, + nosave?: boolean +): void { if (fontSize == null || fontSize == undefined) { fontSize = 1; } @@ -1162,7 +1265,7 @@ export function setFontSize(fontSize, nosave) { ConfigEvent.dispatch("fontSize", config.fontSize); } -export function setCustomBackground(value, nosave) { +export function setCustomBackground(value: string, nosave?: boolean): void { if (value == null || value == undefined) { value = ""; } @@ -1182,36 +1285,46 @@ export function setCustomBackground(value, nosave) { } } -export async function setCustomLayoutfluid(value, nosave) { +export async function setCustomLayoutfluid( + value: MonkeyTypes.CustomLayoutFluidSpaces, + nosave?: boolean +): Promise { if (value == null || value == undefined) { value = "qwerty#dvorak#colemak"; } - value = value.replace(/ /g, "#"); + let customLayoutfluid = value.replace( + / /g, + "#" + ) as MonkeyTypes.CustomLayoutFluid; //validate the layouts - let allGood = true; - await value.split("#").forEach(async (customLayout) => { - const lay = await Misc.getLayout(customLayout); - if (!lay) allGood = false; - }); + const allGood = ( + await Promise.all( + value.split("#").map((customLayout) => Misc.getLayout(customLayout)) + ) + ).every((customLayout) => customLayout); + if (!allGood) { Notifications.add( "One of the layouts was not found. Make sure the name matches exactly. Reverting to default", 0, 4 ); - value = "qwerty#dvorak#colemak"; + customLayoutfluid = "qwerty#dvorak#colemak"; nosave = false; } - config.customLayoutfluid = value; + config.customLayoutfluid = customLayoutfluid; $(".pageSettings .section.customLayoutfluid input").val( - value.replace(/#/g, " ") + customLayoutfluid.replace(/#/g, " ") ); if (!nosave) saveToLocalStorage(); - ConfigEvent.dispatch("customLayoutFluid", config.customLayoutFluid); + ConfigEvent.dispatch("customLayoutFluid", config.customLayoutfluid); } -export function setCustomBackgroundSize(value, nosave) { +export function setCustomBackgroundSize( + value: MonkeyTypes.CustomBackgroundSize, + nosave?: boolean +): void { if (value != "cover" && value != "contain" && value != "max") { value = "cover"; } @@ -1220,20 +1333,26 @@ export function setCustomBackgroundSize(value, nosave) { ConfigEvent.dispatch("customBackgroundSize", config.customBackgroundSize); } -export function setCustomBackgroundFilter(array, nosave) { +export function setCustomBackgroundFilter( + array: MonkeyTypes.CustomBackgroundFilter, + nosave?: boolean +): void { config.customBackgroundFilter = array; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("customBackgroundFilter", config.customBackgroundFilter); } -export function setMonkeyPowerLevel(level, nosave) { +export function setMonkeyPowerLevel( + level: MonkeyTypes.MonkeyPowerLevel, + nosave?: boolean +): void { if (!["off", "1", "2", "3", "4"].includes(level)) level = "off"; config.monkeyPowerLevel = level; if (!nosave) saveToLocalStorage(); ConfigEvent.dispatch("monkeyPowerLevel", config.monkeyPowerLevel); } -export function setBurstHeatmap(value, nosave) { +export function setBurstHeatmap(value: boolean, nosave?: boolean): void { if (!value) { value = false; } @@ -1244,17 +1363,21 @@ export function setBurstHeatmap(value, nosave) { ConfigEvent.dispatch("burstHeatmap", config.burstHeatmap); } -export function apply(configObj) { - if (configObj == null || configObj == undefined) { +export function apply(configObj: MonkeyTypes.Config | null | "null"): void { + if (configObj == null || configObj == undefined || configObj === "null") { Notifications.add("Could not apply config", -1, 3); return; } - Object.keys(defaultConfig).forEach((configKey) => { - if (configObj[configKey] === undefined) { - configObj[configKey] = defaultConfig[configKey]; + (Object.keys(defaultConfig) as (keyof MonkeyTypes.Config)[]).forEach( + (configKey) => { + if (configObj[configKey] === undefined) { + const newValue = defaultConfig[configKey]; + + (configObj[configKey] as typeof newValue) = newValue; + } } - }); - if (configObj && configObj != null && configObj != "null") { + ); + if (configObj && configObj !== null) { setCustomThemeColors(configObj.customThemeColors, true); setThemes(configObj.theme, configObj.customTheme, true); // setTheme(configObj.theme, true); @@ -1432,7 +1555,7 @@ export function apply(configObj) { $("#ad_about1").remove(); $("#ad_about2").remove(); } - } catch (e) { + } catch (e: any) { Notifications.add("Error initialising ads: " + e.message); console.log("error initialising ads " + e.message); $(".footerads").remove(); @@ -1454,20 +1577,25 @@ export function apply(configObj) { } } -export function reset() { +export function reset(): void { apply(defaultConfig); saveToLocalStorage(); } -export function loadFromLocalStorage() { +export function loadFromLocalStorage(): void { console.log("loading localStorage config"); // let newConfig = $.cookie("config"); - let newConfig = window.localStorage.getItem("config"); - if (newConfig !== undefined && newConfig !== null && newConfig !== "") { + const newConfigString = window.localStorage.getItem("config"); + let newConfig: MonkeyTypes.Config; + if ( + newConfigString !== undefined && + newConfigString !== null && + newConfigString !== "" + ) { try { - newConfig = JSON.parse(newConfig); + newConfig = JSON.parse(newConfigString); } catch (e) { - newConfig = {}; + newConfig = {} as MonkeyTypes.Config; } apply(newConfig); console.log("applying localStorage config"); @@ -1479,23 +1607,23 @@ export function loadFromLocalStorage() { loadDone(); } -export function getConfigChanges() { - let configChanges = {}; - Object.keys(config) +export function getConfigChanges(): MonkeyTypes.Config { + const configChanges = {} as MonkeyTypes.Config; + (Object.keys(config) as (keyof MonkeyTypes.Config)[]) .filter((key) => { return config[key] != defaultConfig[key]; }) .forEach((key) => { - configChanges[key] = config[key]; + (configChanges[key] as typeof config[typeof key]) = config[key]; }); return configChanges; } -export function setConfig(newConfig) { +export function setConfig(newConfig: MonkeyTypes.Config): void { config = newConfig; } -export let loadPromise = new Promise((v) => { +export const loadPromise = new Promise((v) => { loadDone = v; }); diff --git a/frontend/src/scripts/controllers/account-controller.js b/frontend/src/scripts/controllers/account-controller.js index 490f111aa..c2c95f352 100644 --- a/frontend/src/scripts/controllers/account-controller.js +++ b/frontend/src/scripts/controllers/account-controller.js @@ -79,10 +79,10 @@ export async function getDataAndInit() { LoadingPage.updateBar(45); } LoadingPage.updateText("Applying settings..."); - let snap = DB.getSnapshot(); - $("#menu .icon-button.account .text").text(snap.name); + const snapshot = DB.getSnapshot(); + $("#menu .icon-button.account .text").text(snapshot.name); - ResultFilters.loadTags(DB.getSnapshot().tags); + ResultFilters.loadTags(snapshot.tags); Promise.all([Misc.getLanguageList(), Misc.getFunboxList()]).then((values) => { let languages = values[0]; @@ -98,12 +98,12 @@ export async function getDataAndInit() { }); let user = firebase.auth().currentUser; - if (snap.name == undefined) { + if (snapshot.name == undefined) { //verify username if (Misc.isUsernameValid(user.name)) { //valid, just update - snap.name = user.name; - DB.setSnapshot(snap); + snapshot.name = user.name; + DB.setSnapshot(snapshot); DB.updateName(user.uid, user.name); } else { //invalid, get new @@ -134,7 +134,8 @@ export async function getDataAndInit() { if (response?.status == 200) { nameGood = true; Notifications.add("Name updated", 1); - DB.getSnapshot().name = name; + snapshot.name = name; + DB.setSnapshot(snapshot); $("#menu .icon-button.account .text").text(name); } } @@ -145,11 +146,11 @@ export async function getDataAndInit() { if (Config.localStorageConfig === null) { console.log("no local config, applying db"); AccountButton.loading(false); - UpdateConfig.apply(DB.getSnapshot().config); + UpdateConfig.apply(snapshot.config); Settings.update(); UpdateConfig.saveToLocalStorage(true); TestLogic.restart(false, true); - } else if (DB.getSnapshot().config !== undefined) { + } else if (snapshot.config !== undefined) { //loading db config, keep for now let configsDifferent = false; Object.keys(Config).forEach((key) => { @@ -158,22 +159,18 @@ export async function getDataAndInit() { if (key !== "resultFilters") { if (Array.isArray(Config[key])) { Config[key].forEach((arrval, index) => { - if (arrval != DB.getSnapshot().config[key][index]) { + if (arrval != snapshot.config[key][index]) { configsDifferent = true; console.log( - `.config is different: ${arrval} != ${ - DB.getSnapshot().config[key][index] - }` + `.config is different: ${arrval} != ${snapshot.config[key][index]}` ); } }); } else { - if (Config[key] != DB.getSnapshot().config[key]) { + if (Config[key] != snapshot.config[key]) { configsDifferent = true; console.log( - `..config is different ${key}: ${Config[key]} != ${ - DB.getSnapshot().config[key] - }` + `..config is different ${key}: ${Config[key]} != ${snapshot.config[key]}` ); } } @@ -188,7 +185,7 @@ export async function getDataAndInit() { if (configsDifferent) { console.log("configs are different, applying config from db"); AccountButton.loading(false); - UpdateConfig.apply(DB.getSnapshot().config); + UpdateConfig.apply(snapshot.config); Settings.update(); UpdateConfig.saveToLocalStorage(true); if (ActivePage.get() == "test") { @@ -444,7 +441,11 @@ export async function signInWithGoogle() { }) .then((result) => { if (result.status === 200) { - DB.getSnapshot().results.push(TestLogic.notSignedInLastResult); + const snapshot = DB.getSnapshot(); + + snapshot.results.push(TestLogic.notSignedInLastResult); + + DB.setSnapshot(snapshot); } }); // PageController.change("account"); @@ -659,7 +660,11 @@ async function signUp() { }) .then((result) => { if (result.status === 200) { - DB.getSnapshot().results.push(TestLogic.notSignedInLastResult); + const snapshot = DB.getSnapshot(); + + snapshot.results.push(TestLogic.notSignedInLastResult); + + DB.setSnapshot(snapshot); } }); PageController.change("account"); diff --git a/frontend/src/scripts/controllers/input-controller.js b/frontend/src/scripts/controllers/input-controller.js index 9d81e7bda..10418c5ab 100644 --- a/frontend/src/scripts/controllers/input-controller.js +++ b/frontend/src/scripts/controllers/input-controller.js @@ -523,8 +523,9 @@ function handleChar(char, charIndex) { } } - let activeWordTopBeforeJump = document.querySelector("#words .word.active") - .offsetTop; + let activeWordTopBeforeJump = document.querySelector( + "#words .word.active" + ).offsetTop; TestUI.updateWordElement(); if (!Config.hideExtraLetters) { diff --git a/frontend/src/scripts/controllers/tag-controller.js b/frontend/src/scripts/controllers/tag-controller.js index 5fdf0b6a8..11de721e0 100644 --- a/frontend/src/scripts/controllers/tag-controller.js +++ b/frontend/src/scripts/controllers/tag-controller.js @@ -22,19 +22,31 @@ export function saveActiveToLocalStorage() { } export function clear(nosave = false) { - DB.getSnapshot().tags.forEach((tag) => { + const snapshot = DB.getSnapshot(); + + snapshot.tags = snapshot.tags.map((tag) => { tag.active = false; + + return tag; }); + + DB.setSnapshot(snapshot); ModesNotice.update(); if (!nosave) saveActiveToLocalStorage(); } export function set(tagid, state, nosave = false) { - DB.getSnapshot().tags.forEach((tag) => { + const snapshot = DB.getSnapshot(); + + snapshot.tags = snapshot.tags.map((tag) => { if (tag._id === tagid) { tag.active = state; } + + return tag; }); + + DB.setSnapshot(snapshot); ModesNotice.update(); if (!nosave) saveActiveToLocalStorage(); } diff --git a/frontend/src/scripts/controllers/verification-controller.js b/frontend/src/scripts/controllers/verification-controller.js index 548b9df35..353b3589a 100644 --- a/frontend/src/scripts/controllers/verification-controller.js +++ b/frontend/src/scripts/controllers/verification-controller.js @@ -27,7 +27,11 @@ export async function verify(user) { Notifications.add(response.data.message); } else { Notifications.add("Accounts linked", 1); - DB.getSnapshot().discordId = response.data.did; + const snapshot = DB.getSnapshot(); + + snapshot.discordId = response.data.did; + + DB.setSnapshot(snapshot); Settings.updateDiscordSection(); } } diff --git a/frontend/src/scripts/db.js b/frontend/src/scripts/db.ts similarity index 57% rename from frontend/src/scripts/db.js rename to frontend/src/scripts/db.ts index 4f97987e0..07b89e041 100644 --- a/frontend/src/scripts/db.js +++ b/frontend/src/scripts/db.ts @@ -3,20 +3,22 @@ import * as Notifications from "./elements/notifications"; import axiosInstance from "./axios-instance"; import * as LoadingPage from "./pages/loading"; -let dbSnapshot = null; +let dbSnapshot: MonkeyTypes.Snapshot; -export function updateName(uid, name) { +export function updateName(uid: string, name: string): void { //TODO update axiosInstance.patch("/user/name", { name, }); + + name = uid; // this is just so that typescript is happy; Remove once this function is updated. } -export function getSnapshot() { +export function getSnapshot(): MonkeyTypes.Snapshot { return dbSnapshot; } -export function setSnapshot(newSnapshot) { +export function setSnapshot(newSnapshot: MonkeyTypes.Snapshot): void { try { delete newSnapshot.banned; } catch {} @@ -26,11 +28,19 @@ export function setSnapshot(newSnapshot) { dbSnapshot = newSnapshot; } -export async function initSnapshot() { +export async function initSnapshot(): Promise< + MonkeyTypes.Snapshot | number | boolean +> { //send api request with token that returns tags, presets, and data needed for snap - let defaultSnap = { + const defaultSnap: MonkeyTypes.Snapshot = { results: undefined, - personalBests: {}, + personalBests: { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }, name: undefined, presets: [], tags: [], @@ -38,7 +48,7 @@ export async function initSnapshot() { banned: undefined, verified: undefined, emailVerified: undefined, - lbMemory: {}, + lbMemory: { time: { 15: { english: 0 }, 60: { english: 0 } } }, globalStats: { time: 0, started: 0, @@ -47,7 +57,7 @@ export async function initSnapshot() { quoteRatings: undefined, quoteMod: false, }; - let snap = defaultSnap; + const snap = defaultSnap; try { if (firebase.auth().currentUser == null) return false; // if (ActivePage.get() == "loading") { @@ -56,16 +66,16 @@ export async function initSnapshot() { // LoadingPage.updateBar(16); // } // LoadingPage.updateText("Downloading user..."); - let promises = await Promise.all([ + const promises = await Promise.all([ axiosInstance.get("/user"), axiosInstance.get("/config"), axiosInstance.get("/user/tags"), axiosInstance.get("/presets"), ]); - let userData = promises[0].data; - let configData = promises[1].data; - let tagsData = promises[2].data; - let presetsData = promises[3].data; + const userData = promises[0].data; + const configData = promises[1].data; + const tagsData = promises[2].data; + const presetsData = promises[3].data; snap.name = userData.name; snap.personalBests = userData.personalBests; @@ -84,7 +94,7 @@ export async function initSnapshot() { if (userData.lbMemory?.time15 || userData.lbMemory?.time60) { //old memory format - snap.lbMemory = {}; + snap.lbMemory = {} as MonkeyTypes.LeaderboardMemory; } else if (userData.lbMemory) { snap.lbMemory = userData.lbMemory; } @@ -104,7 +114,7 @@ export async function initSnapshot() { // } // LoadingPage.updateText("Downloading tags..."); snap.tags = tagsData; - snap.tags = snap.tags.sort((a, b) => { + snap.tags = snap.tags?.sort((a, b) => { if (a.name > b.name) { return 1; } else if (a.name < b.name) { @@ -120,7 +130,7 @@ export async function initSnapshot() { // } // LoadingPage.updateText("Downloading presets..."); snap.presets = presetsData; - snap.presets = snap.presets.sort((a, b) => { + snap.presets = snap.presets?.sort((a, b) => { if (a.name > b.name) { return 1; } else if (a.name < b.name) { @@ -138,8 +148,8 @@ export async function initSnapshot() { } } -export async function getUserResults() { - let user = firebase.auth().currentUser; +export async function getUserResults(): Promise { + const user = firebase.auth().currentUser; if (user == null) return false; if (dbSnapshot === null) return false; if (dbSnapshot.results !== undefined) { @@ -148,8 +158,11 @@ export async function getUserResults() { try { LoadingPage.updateText("Downloading results..."); LoadingPage.updateBar(90); - let results = await axiosInstance.get("/results"); - results.data.forEach((result) => { + const resultsData = await axiosInstance.get("/results"); + + let results = resultsData.data as MonkeyTypes.Result[]; + + results.forEach((result) => { if (result.bailedOut === undefined) result.bailedOut = false; if (result.blindMode === undefined) result.blindMode = false; if (result.lazyMode === undefined) result.lazyMode = false; @@ -160,12 +173,10 @@ export async function getUserResults() { if (result.numbers === undefined) result.numbers = false; if (result.punctuation === undefined) result.punctuation = false; }); - results.data = results.data.sort((a, b) => { - return a.timestamp < b.timestamp; - }); - dbSnapshot.results = results.data; + results = results.sort((a, b) => b.timestamp - a.timestamp); + dbSnapshot.results = results; return true; - } catch (e) { + } catch (e: any) { Notifications.add("Error getting results: " + e.message, -1); return false; } @@ -208,17 +219,18 @@ export async function getUserResults() { */ } -export async function getUserHighestWpm( - mode, - mode2, - punctuation, - language, - difficulty, - lazyMode -) { - function cont() { +export async function getUserHighestWpm( + mode: M, + mode2: MonkeyTypes.Mode2, + punctuation: boolean, + language: string, + difficulty: MonkeyTypes.Difficulty, + lazyMode: boolean +): Promise { + function cont(): number { let topWpm = 0; - dbSnapshot.results.forEach((result) => { + + dbSnapshot.results?.forEach((result) => { if ( result.mode == mode && result.mode2 == mode2 && @@ -236,25 +248,22 @@ export async function getUserHighestWpm( return topWpm; } - let retval; - if (dbSnapshot == null || dbSnapshot.results === undefined) { - retval = 0; - } else { - retval = cont(); - } + const retval = + dbSnapshot === null || dbSnapshot.results === undefined ? 0 : cont(); + return retval; } -export async function getUserAverageWpm10( - mode, - mode2, - punctuation, - language, - difficulty, - lazyMode -) { - function cont() { - let activeTagIds = []; +export async function getUserAverageWpm10( + mode: M, + mode2: MonkeyTypes.Mode2, + punctuation: boolean, + language: string, + difficulty: MonkeyTypes.Difficulty, + lazyMode: boolean +): Promise { + function cont(): number { + const activeTagIds: string[] = []; getSnapshot()?.tags?.forEach((tag) => { if (tag.active === true) { activeTagIds.push(tag._id); @@ -266,7 +275,7 @@ export async function getUserAverageWpm10( let last10Wpm = 0; let last10Count = 0; // You have to use every so you can break out of the loop - dbSnapshot.results.every((result) => { + dbSnapshot.results?.every((result) => { if ( result.mode == mode && result.punctuation == punctuation && @@ -311,34 +320,35 @@ export async function getUserAverageWpm10( return Math.round(wpmSum / count); } - let retval = 0; + const retval = + dbSnapshot === null || (await getUserResults()) === false ? 0 : cont(); - if (dbSnapshot == null) return retval; - let dbSnapshotValid = await getUserResults(); - if (dbSnapshotValid === false) { - return retval; - } - retval = cont(); return retval; } -export async function getLocalPB( - mode, - mode2, - punctuation, - language, - difficulty, - lazyMode, - funbox -) { +export async function getLocalPB( + mode: M, + mode2: MonkeyTypes.Mode2, + punctuation: boolean, + language: string, + difficulty: MonkeyTypes.Difficulty, + lazyMode: boolean, + funbox: string +): Promise { if (funbox !== "none" && funbox !== "plus_one" && funbox !== "plus_two") { return 0; } - function cont() { + function cont(): number { let ret = 0; try { - dbSnapshot.personalBests[mode][mode2].forEach((pb) => { + if (!dbSnapshot.personalBests) return ret; + + ( + dbSnapshot.personalBests[mode][ + mode2 + ] as unknown as MonkeyTypes.PersonalBest[] + ).forEach((pb) => { if ( pb.punctuation == punctuation && pb.difficulty == difficulty && @@ -349,43 +359,61 @@ export async function getLocalPB( ret = pb.wpm; } }); + return ret; } catch (e) { return ret; } } - let retval; - if (dbSnapshot == null) { - retval = 0; - } else { - retval = cont(); - } + const retval = dbSnapshot === null ? 0 : cont(); + return retval; } -export async function saveLocalPB( - mode, - mode2, - punctuation, - language, - difficulty, - lazyMode, - wpm, - acc, - raw, - consistency -) { +export async function saveLocalPB( + mode: M, + mode2: MonkeyTypes.Mode2, + punctuation: boolean, + language: string, + difficulty: MonkeyTypes.Difficulty, + lazyMode: boolean, + wpm: number, + acc: number, + raw: number, + consistency: number +): Promise { if (mode == "quote") return; - function cont() { + function cont(): void { let found = false; - if (dbSnapshot.personalBests === undefined) dbSnapshot.personalBests = {}; - if (dbSnapshot.personalBests[mode] === undefined) - dbSnapshot.personalBests[mode] = {}; - if (dbSnapshot.personalBests[mode][mode2] === undefined) - dbSnapshot.personalBests[mode][mode2] = []; + if (dbSnapshot.personalBests === undefined) + dbSnapshot.personalBests = { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }; - dbSnapshot.personalBests[mode][mode2].forEach((pb) => { + if (dbSnapshot.personalBests[mode] === undefined) { + if (mode === "zen") { + dbSnapshot.personalBests["zen"] = { zen: [] }; + } else { + dbSnapshot.personalBests[mode as Exclude] = { + custom: [], + }; + } + } + + if (dbSnapshot.personalBests[mode][mode2] === undefined) + dbSnapshot.personalBests[mode][mode2] = + [] as unknown as MonkeyTypes.PersonalBests[M][keyof MonkeyTypes.PersonalBests[M]]; + + ( + dbSnapshot.personalBests[mode][ + mode2 + ] as unknown as MonkeyTypes.PersonalBest[] + ).forEach((pb) => { if ( pb.punctuation == punctuation && pb.difficulty == difficulty && @@ -404,7 +432,11 @@ export async function saveLocalPB( }); if (!found) { //nothing found - dbSnapshot.personalBests[mode][mode2].push({ + ( + dbSnapshot.personalBests[mode][ + mode2 + ] as unknown as MonkeyTypes.PersonalBest[] + ).push({ language: language, difficulty: difficulty, lazyMode: lazyMode, @@ -423,20 +455,39 @@ export async function saveLocalPB( } } -export async function getLocalTagPB( - tagId, - mode, - mode2, - punctuation, - language, - difficulty, - lazyMode -) { - function cont() { +export async function getLocalTagPB( + tagId: string, + mode: M, + mode2: MonkeyTypes.Mode2, + punctuation: boolean, + language: string, + difficulty: MonkeyTypes.Difficulty, + lazyMode: boolean +): Promise { + function cont(): number { let ret = 0; - let filteredtag = dbSnapshot.tags.filter((t) => t._id === tagId)[0]; + + const filteredtag = (getSnapshot().tags ?? []).filter( + (t) => t._id === tagId + )[0]; + + if (filteredtag === undefined) return ret; + + if (filteredtag.personalBests === undefined) { + filteredtag.personalBests = { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }; + } + try { - filteredtag.personalBests[mode][mode2].forEach((pb) => { + const personalBests = (filteredtag.personalBests[mode][mode2] ?? + []) as MonkeyTypes.PersonalBest[]; + + personalBests.forEach((pb) => { if ( pb.punctuation == punctuation && pb.difficulty == difficulty && @@ -453,37 +504,51 @@ export async function getLocalTagPB( return ret; } - let retval; - if (dbSnapshot == null) { - retval = 0; - } else { - retval = cont(); - } + const retval = dbSnapshot === null ? 0 : cont(); + return retval; } -export async function saveLocalTagPB( - tagId, - mode, - mode2, - punctuation, - language, - difficulty, - lazyMode, - wpm, - acc, - raw, - consistency -) { +export async function saveLocalTagPB( + tagId: string, + mode: M, + mode2: MonkeyTypes.Mode2, + punctuation: boolean, + language: string, + difficulty: MonkeyTypes.Difficulty, + lazyMode: boolean, + wpm: number, + acc: number, + raw: number, + consistency: number +): Promise { if (mode == "quote") return; - function cont() { - let filteredtag = dbSnapshot.tags.filter((t) => t._id === tagId)[0]; + function cont(): void { + const filteredtag = dbSnapshot.tags?.filter( + (t) => t._id === tagId + )[0] as MonkeyTypes.Tag; + + if (!filteredtag.personalBests) { + filteredtag.personalBests = { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }; + } + try { let found = false; if (filteredtag.personalBests[mode][mode2] === undefined) { - filteredtag.personalBests[mode][mode2] = []; + filteredtag.personalBests[mode][mode2] = + [] as unknown as MonkeyTypes.PersonalBests[M][keyof MonkeyTypes.PersonalBests[M]]; } - filteredtag.personalBests[mode][mode2].forEach((pb) => { + ( + filteredtag.personalBests[mode][ + mode2 + ] as unknown as MonkeyTypes.PersonalBest[] + ).forEach((pb) => { if ( pb.punctuation == punctuation && pb.difficulty == difficulty && @@ -502,7 +567,11 @@ export async function saveLocalTagPB( }); if (!found) { //nothing found - filteredtag.personalBests[mode][mode2].push({ + ( + filteredtag.personalBests[mode][ + mode2 + ] as unknown as MonkeyTypes.PersonalBest[] + ).push({ language: language, difficulty: difficulty, lazyMode: lazyMode, @@ -516,8 +585,20 @@ export async function saveLocalTagPB( } } catch (e) { //that mode or mode2 is not found - filteredtag.personalBests = {}; - filteredtag.personalBests[mode] = {}; + filteredtag.personalBests = { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }; + if (mode === "zen") { + filteredtag.personalBests["zen"] = { zen: [] }; + } else { + filteredtag.personalBests[mode as Exclude] = { + custom: [], + }; + } filteredtag.personalBests[mode][mode2] = [ { language: language, @@ -530,42 +611,63 @@ export async function saveLocalTagPB( timestamp: Date.now(), consistency: consistency, }, - ]; + ] as unknown as MonkeyTypes.PersonalBests[M][keyof MonkeyTypes.PersonalBests[M]]; } } if (dbSnapshot != null) { cont(); } + + return; } -export function updateLbMemory(mode, mode2, language, rank, api = false) { +export function updateLbMemory( + mode: M, + mode2: MonkeyTypes.Mode2, + language: string, + rank: number, + api = false +): void { //could dbSnapshot just be used here instead of getSnapshot() - if (dbSnapshot.lbMemory === undefined) dbSnapshot.lbMemory = {}; - if (dbSnapshot.lbMemory[mode] === undefined) dbSnapshot.lbMemory[mode] = {}; - if (dbSnapshot.lbMemory[mode][mode2] === undefined) - dbSnapshot.lbMemory[mode][mode2] = {}; - let current = dbSnapshot.lbMemory[mode][mode2][language]; - dbSnapshot.lbMemory[mode][mode2][language] = rank; - if (api && current != rank) { - axiosInstance.patch("/user/leaderboardMemory", { - mode, - mode2, - language, - rank, - }); + + if (mode === "time") { + const timeMode = mode as "time", + timeMode2 = mode2 as 15 | 60; + + const snapshot = getSnapshot(); + if (snapshot.lbMemory === undefined) + snapshot.lbMemory = { time: { 15: { english: 0 }, 60: { english: 0 } } }; + if (snapshot.lbMemory[timeMode] === undefined) + snapshot.lbMemory[timeMode] = { + 15: { english: 0 }, + 60: { english: 0 }, + }; + if (snapshot.lbMemory[timeMode][timeMode2] === undefined) + snapshot.lbMemory[timeMode][timeMode2] = {}; + const current = snapshot.lbMemory[timeMode][timeMode2][language]; + snapshot.lbMemory[timeMode][timeMode2][language] = rank; + if (api && current != rank) { + axiosInstance.patch("/user/leaderboardMemory", { + mode, + mode2, + language, + rank, + }); + } + setSnapshot(snapshot); } } -export async function saveConfig(config) { +export async function saveConfig(config: MonkeyTypes.Config): Promise { if (firebase.auth().currentUser !== null) { AccountButton.loading(true); try { await axiosInstance.post("/config/save", { config }); - } catch (e) { + } catch (e: any) { AccountButton.loading(false); - let msg = e?.response?.data?.message ?? e.message; + const msg = e?.response?.data?.message ?? e.message; Notifications.add("Failed to save config: " + msg, -1); return; } @@ -573,30 +675,41 @@ export async function saveConfig(config) { } } -export function saveLocalResult(result) { - if (getSnapshot() !== null && getSnapshot().results !== undefined) { - getSnapshot().results.unshift(result); +export function saveLocalResult( + result: MonkeyTypes.Result +): void { + const snapshot = getSnapshot(); + + if (snapshot !== null && snapshot.results !== undefined) { + snapshot.results.unshift(result); + + setSnapshot(snapshot); } } -export function updateLocalStats(stats) { - if (getSnapshot() !== null) { - if (getSnapshot().globalStats.time == undefined) { - getSnapshot().globalStats.time = stats.time; +export function updateLocalStats(stats: MonkeyTypes.Stats): void { + const snapshot = getSnapshot(); + if (snapshot.globalStats === undefined) + snapshot.globalStats = {} as MonkeyTypes.Stats; + if (snapshot !== null && snapshot.globalStats !== undefined) { + if (snapshot.globalStats.time == undefined) { + snapshot.globalStats.time = stats.time; } else { - getSnapshot().globalStats.time += stats.time; + snapshot.globalStats.time += stats.time; } - if (getSnapshot().globalStats.started == undefined) { - getSnapshot().globalStats.started = stats.started; + if (snapshot.globalStats.started == undefined) { + snapshot.globalStats.started = stats.started; } else { - getSnapshot().globalStats.started += stats.started; + snapshot.globalStats.started += stats.started; } - if (getSnapshot().globalStats.completed == undefined) { - getSnapshot().globalStats.completed = 1; + if (snapshot.globalStats.completed == undefined) { + snapshot.globalStats.completed = 1; } else { - getSnapshot().globalStats.completed += 1; + snapshot.globalStats.completed += 1; } } + + setSnapshot(snapshot); } // export async function DB.getLocalTagPB(tagId) { @@ -613,10 +726,8 @@ export function updateLocalStats(stats) { // } // } -// let retval; -// if (dbSnapshot != null) { -// retval = cont(); -// } +// const retval = dbSnapshot !== null ? cont() : undefined; + // return retval; // } diff --git a/frontend/src/scripts/elements/commandline-lists.ts b/frontend/src/scripts/elements/commandline-lists.ts index 90b937a7b..691a4e2f1 100644 --- a/frontend/src/scripts/elements/commandline-lists.ts +++ b/frontend/src/scripts/elements/commandline-lists.ts @@ -212,7 +212,7 @@ const commandsTags: MonkeyTypes.CommandsGroup = { }; export function updateTagCommands(): void { - if (DB.getSnapshot()?.tags?.length > 0) { + if (DB.getSnapshot()?.tags?.length ?? 0 > 0) { commandsTags.list = []; commandsTags.list.push({ @@ -220,15 +220,21 @@ export function updateTagCommands(): void { display: `Clear tags`, icon: "fa-times", exec: (): void => { - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + const snapshot = DB.getSnapshot(); + + snapshot.tags = snapshot.tags?.map((tag) => { tag.active = false; + + return tag; }); + + DB.setSnapshot(snapshot); ModesNotice.update(); TagController.saveActiveToLocalStorage(); }, }); - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { let dis = tag.name; if (tag.active === true) { @@ -283,10 +289,12 @@ const commandsPresets: MonkeyTypes.CommandsGroup = { }; export function updatePresetCommands(): void { - if (DB.getSnapshot()?.presets?.length > 0) { + const snapshot = DB.getSnapshot(); + + if (snapshot.presets !== undefined && snapshot.presets.length > 0) { commandsPresets.list = []; - DB.getSnapshot().presets.forEach((preset: MonkeyTypes.Preset) => { + snapshot.presets.forEach((preset: MonkeyTypes.Preset) => { const dis = preset.name; commandsPresets.list.push({ @@ -1655,7 +1663,7 @@ const commandsTimerColor: MonkeyTypes.CommandsGroup = { display: "black", configValue: "black", exec: (): void => { - UpdateConfig.setTimerColor("bar"); + UpdateConfig.setTimerColor("black"); }, }, { @@ -1740,7 +1748,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = { display: ".25", configValue: 0.25, exec: (): void => { - UpdateConfig.setTimerOpacity(0.25); + UpdateConfig.setTimerOpacity("0.25"); }, }, { @@ -1748,7 +1756,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = { display: ".5", configValue: 0.5, exec: (): void => { - UpdateConfig.setTimerOpacity(0.5); + UpdateConfig.setTimerOpacity("0.5"); }, }, { @@ -1756,7 +1764,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = { display: ".75", configValue: 0.75, exec: (): void => { - UpdateConfig.setTimerOpacity(0.75); + UpdateConfig.setTimerOpacity("0.75"); }, }, { @@ -1764,7 +1772,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = { display: "1", configValue: 1, exec: (): void => { - UpdateConfig.setTimerOpacity(1); + UpdateConfig.setTimerOpacity("1"); }, }, ], @@ -1780,7 +1788,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = { configValue: 10, exec: (): void => { UpdateConfig.setMode("words"); - UpdateConfig.setWordCount("10"); + UpdateConfig.setWordCount(10); TestLogic.restart(); }, }, @@ -1790,7 +1798,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = { configValue: 25, exec: (): void => { UpdateConfig.setMode("words"); - UpdateConfig.setWordCount("25"); + UpdateConfig.setWordCount(25); TestLogic.restart(); }, }, @@ -1800,7 +1808,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = { configValue: 50, exec: (): void => { UpdateConfig.setMode("words"); - UpdateConfig.setWordCount("50"); + UpdateConfig.setWordCount(50); TestLogic.restart(); }, }, @@ -1810,7 +1818,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = { configValue: 100, exec: (): void => { UpdateConfig.setMode("words"); - UpdateConfig.setWordCount("100"); + UpdateConfig.setWordCount(100); TestLogic.restart(); }, }, @@ -1820,7 +1828,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = { configValue: 200, exec: (): void => { UpdateConfig.setMode("words"); - UpdateConfig.setWordCount("200"); + UpdateConfig.setWordCount(200); TestLogic.restart(); }, }, @@ -2057,7 +2065,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = { configValue: 15, exec: (): void => { UpdateConfig.setMode("time"); - UpdateConfig.setTimeConfig("15"); + UpdateConfig.setTimeConfig(15); TestLogic.restart(); }, }, @@ -2067,7 +2075,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = { configValue: 30, exec: (): void => { UpdateConfig.setMode("time"); - UpdateConfig.setTimeConfig("30"); + UpdateConfig.setTimeConfig(30); TestLogic.restart(); }, }, @@ -2077,7 +2085,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = { configValue: 60, exec: (): void => { UpdateConfig.setMode("time"); - UpdateConfig.setTimeConfig("60"); + UpdateConfig.setTimeConfig(60); TestLogic.restart(); }, }, @@ -2087,7 +2095,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = { configValue: 120, exec: (): void => { UpdateConfig.setMode("time"); - UpdateConfig.setTimeConfig("120"); + UpdateConfig.setTimeConfig(120); TestLogic.restart(); }, }, diff --git a/frontend/src/scripts/elements/commandline.ts b/frontend/src/scripts/elements/commandline.ts index 5c97f8ce6..dcca80fd5 100644 --- a/frontend/src/scripts/elements/commandline.ts +++ b/frontend/src/scripts/elements/commandline.ts @@ -320,7 +320,7 @@ function useSingleListCommandLine(sshow = true): void { // } else if (Config.singleListCommandLine == "on") { CommandlineLists.setCurrent([allCommands]); // } - if (Config.singleListCommandLine != "off") + if (Config.singleListCommandLine != "manual") $("#commandLine").addClass("allCommands"); if (sshow) show(); } diff --git a/frontend/src/scripts/elements/custom-background-filter.ts b/frontend/src/scripts/elements/custom-background-filter.ts index 5bebb1791..b396a9089 100644 --- a/frontend/src/scripts/elements/custom-background-filter.ts +++ b/frontend/src/scripts/elements/custom-background-filter.ts @@ -117,17 +117,16 @@ $(".section.customBackgroundFilter .opacity input").on("input", () => { }); $(".section.customBackgroundFilter .save.button").click(() => { - const arr: number[] = []; - Object.keys(filters).forEach((filterKey) => { - arr.push(filters[filterKey as keyof typeof filters].value); - }); + const arr = Object.keys(filters).map( + (filterKey) => filters[filterKey as keyof typeof filters].value + ) as MonkeyTypes.CustomBackgroundFilter; UpdateConfig.setCustomBackgroundFilter(arr, false); Notifications.add("Custom background filters saved", 1); }); ConfigEvent.subscribe((eventKey, eventValue) => { if (eventKey === "customBackgroundFilter") { - loadConfig(((eventValue as unknown) as any[]).map((ev) => parseFloat(ev))); + loadConfig((eventValue as unknown as any[]).map((ev) => parseFloat(ev))); apply(); } }); diff --git a/frontend/src/scripts/elements/leaderboards.ts b/frontend/src/scripts/elements/leaderboards.ts index c7a9d9633..01131ccea 100644 --- a/frontend/src/scripts/elements/leaderboards.ts +++ b/frontend/src/scripts/elements/leaderboards.ts @@ -70,9 +70,9 @@ function updateTimerElement(): void { function startTimer(): void { updateTimerElement(); - updateTimer = (setInterval(() => { + updateTimer = setInterval(() => { updateTimerElement(); - }, 1000) as unknown) as number; + }, 1000) as unknown as number; } function showLoader(lb: number): void { @@ -152,7 +152,7 @@ function checkLbMemory(lb: LbKey): void { side = "right"; } - const memory = DB.getSnapshot()?.lbMemory?.time?.[lb]?.english; + const memory = DB.getSnapshot()?.lbMemory?.time?.[lb]?.["english"]; if (memory && currentRank[lb]) { const difference = memory - currentRank[lb].rank; diff --git a/frontend/src/scripts/elements/modes-notice.ts b/frontend/src/scripts/elements/modes-notice.ts index 385e30a6b..cc8b48117 100644 --- a/frontend/src/scripts/elements/modes-notice.ts +++ b/frontend/src/scripts/elements/modes-notice.ts @@ -169,7 +169,7 @@ export function update(): void { let tagsString = ""; try { - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { if (tag.active === true) { tagsString += tag.name + ", "; } diff --git a/frontend/src/scripts/elements/monkey-power.ts b/frontend/src/scripts/elements/monkey-power.ts index 58f9f0830..0efabaa80 100644 --- a/frontend/src/scripts/elements/monkey-power.ts +++ b/frontend/src/scripts/elements/monkey-power.ts @@ -212,7 +212,7 @@ export async function addPower(good = true, extra = false): Promise { `translate(${shake[0]}px, ${shake[1]}px)` ); if (ctx.resetTimeOut) clearTimeout(ctx.resetTimeOut); - ctx.resetTimeOut = (setTimeout(reset, 2000) as unknown) as number; + ctx.resetTimeOut = setTimeout(reset, 2000) as unknown as number; } // Sparks diff --git a/frontend/src/scripts/misc.ts b/frontend/src/scripts/misc.ts index c1d43edda..600bd7a39 100644 --- a/frontend/src/scripts/misc.ts +++ b/frontend/src/scripts/misc.ts @@ -6,21 +6,24 @@ export function getuid(): void { console.error("Only share this uid with Miodec and nobody else!"); } -function hexToHSL( - hex: string -): { hue: number; sat: number; lgt: number; string: string } { +function hexToHSL(hex: string): { + hue: number; + sat: number; + lgt: number; + string: string; +} { // Convert hex to RGB first let r: number; let g: number; let b: number; if (hex.length == 4) { - r = (("0x" + hex[1] + hex[1]) as unknown) as number; - g = (("0x" + hex[2] + hex[2]) as unknown) as number; - b = (("0x" + hex[3] + hex[3]) as unknown) as number; + r = ("0x" + hex[1] + hex[1]) as unknown as number; + g = ("0x" + hex[2] + hex[2]) as unknown as number; + b = ("0x" + hex[3] + hex[3]) as unknown as number; } else if (hex.length == 7) { - r = (("0x" + hex[1] + hex[2]) as unknown) as number; - g = (("0x" + hex[3] + hex[4]) as unknown) as number; - b = (("0x" + hex[5] + hex[6]) as unknown) as number; + r = ("0x" + hex[1] + hex[2]) as unknown as number; + g = ("0x" + hex[3] + hex[4]) as unknown as number; + b = ("0x" + hex[5] + hex[6]) as unknown as number; } else { r = 0x00; g = 0x00; diff --git a/frontend/src/scripts/observables/config-event.ts b/frontend/src/scripts/observables/config-event.ts index c3a86c3a5..424e8d9a8 100644 --- a/frontend/src/scripts/observables/config-event.ts +++ b/frontend/src/scripts/observables/config-event.ts @@ -1,12 +1,12 @@ -type SubscribeFunction = (key: string, value?: string, value2?: string) => void; +type SubscribeFunction = (key: string, value?: V, value2?: V2) => void; -const subscribers: SubscribeFunction[] = []; +const subscribers: SubscribeFunction[] = []; -export function subscribe(fn: SubscribeFunction): void { +export function subscribe(fn: SubscribeFunction): void { subscribers.push(fn); } -export function dispatch(key: string, value: string, value2: string): void { +export function dispatch(key: string, value?: V, value2?: V2): void { subscribers.forEach((fn) => { try { fn(key, value, value2); diff --git a/frontend/src/scripts/pages/account.ts b/frontend/src/scripts/pages/account.ts index 983f1ab53..1f13014ee 100644 --- a/frontend/src/scripts/pages/account.ts +++ b/frontend/src/scripts/pages/account.ts @@ -23,7 +23,7 @@ export function toggleFilterDebug(): void { } } -let filteredResults: MonkeyTypes.Result[] = []; +let filteredResults: MonkeyTypes.Result[] = []; let visibleTableLines = 0; function loadMoreLines(lineIndex?: number): void { @@ -102,7 +102,7 @@ function loadMoreLines(lineIndex?: number): void { if (result.tags !== undefined && result.tags.length > 0) { result.tags.forEach((tag) => { - DB.getSnapshot().tags.forEach((snaptag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((snaptag) => { if (tag === snaptag._id) { tagNames += snaptag.name + ", "; } @@ -258,323 +258,332 @@ export function update(): void { filteredResults = []; $(".pageAccount .history table tbody").empty(); - DB.getSnapshot().results.forEach((result: MonkeyTypes.Result) => { - // totalSeconds += tt; + DB.getSnapshot().results?.forEach( + (result: MonkeyTypes.Result) => { + // totalSeconds += tt; - //apply filters - try { - let resdiff = result.difficulty; - if (resdiff == undefined) { - resdiff = "normal"; - } - if (!ResultFilters.getFilter("difficulty", resdiff)) { - if (filterDebug) - console.log(`skipping result due to difficulty filter`, result); - return; - } - if (!ResultFilters.getFilter("mode", result.mode)) { - if (filterDebug) - console.log(`skipping result due to mode filter`, result); - return; - } - - if (result.mode == "time") { - let timefilter = "custom"; - if ([15, 30, 60, 120].includes(parseInt(result.mode2 as string))) { - timefilter = result.mode2.toString(); + //apply filters + try { + let resdiff = result.difficulty; + if (resdiff == undefined) { + resdiff = "normal"; } - if (!ResultFilters.getFilter("time", timefilter)) { + if (!ResultFilters.getFilter("difficulty", resdiff)) { if (filterDebug) - console.log(`skipping result due to time filter`, result); + console.log(`skipping result due to difficulty filter`, result); return; } - } else if (result.mode == "words") { - let wordfilter = "custom"; - if ( - [10, 25, 50, 100, 200].includes(parseInt(result.mode2 as string)) - ) { - wordfilter = result.mode2.toString(); - } - if (!ResultFilters.getFilter("words", wordfilter)) { + if (!ResultFilters.getFilter("mode", result.mode)) { if (filterDebug) - console.log(`skipping result due to word filter`, result); + console.log(`skipping result due to mode filter`, result); return; } - } - if (result.quoteLength != null) { - let filter = null; - if (result.quoteLength === 0) { - filter = "short"; - } else if (result.quoteLength === 1) { - filter = "medium"; - } else if (result.quoteLength === 2) { - filter = "long"; - } else if (result.quoteLength === 3) { - filter = "thicc"; - } - if ( - filter !== null && - !ResultFilters.getFilter("quoteLength", filter) - ) { - if (filterDebug) - console.log(`skipping result due to quoteLength filter`, result); - return; - } - } - - let langFilter = ResultFilters.getFilter( - "language", - result.language ?? "english" - ); - - if ( - result.language === "english_expanded" && - ResultFilters.getFilter("language", "english_1k") - ) { - langFilter = true; - } - if (!langFilter) { - if (filterDebug) - console.log(`skipping result due to language filter`, result); - return; - } - - let puncfilter = "off"; - if (result.punctuation) { - puncfilter = "on"; - } - if (!ResultFilters.getFilter("punctuation", puncfilter)) { - if (filterDebug) - console.log(`skipping result due to punctuation filter`, result); - return; - } - - let numfilter = "off"; - if (result.numbers) { - numfilter = "on"; - } - if (!ResultFilters.getFilter("numbers", numfilter)) { - if (filterDebug) - console.log(`skipping result due to numbers filter`, result); - return; - } - - if (result.funbox === "none" || result.funbox === undefined) { - if (!ResultFilters.getFilter("funbox", "none")) { - if (filterDebug) - console.log(`skipping result due to funbox filter`, result); - return; - } - } else { - if (!ResultFilters.getFilter("funbox", result.funbox)) { - if (filterDebug) - console.log(`skipping result due to funbox filter`, result); - return; - } - } - - let tagHide = true; - if (result.tags === undefined || result.tags.length === 0) { - //no tags, show when no tag is enabled - if (DB.getSnapshot().tags.length > 0) { - if (ResultFilters.getFilter("tags", "none")) tagHide = false; - } else { - tagHide = false; - } - } else { - //tags exist - const validTags: string[] = DB.getSnapshot().tags.map( - (t: MonkeyTypes.Tag) => t._id - ); - result.tags.forEach((tag) => { - //check if i even need to check tags anymore - if (!tagHide) return; - //check if tag is valid - if (validTags.includes(tag)) { - //tag valid, check if filter is on - if (ResultFilters.getFilter("tags", tag)) tagHide = false; - } else { - //tag not found in valid tags, meaning probably deleted - if (ResultFilters.getFilter("tags", "none")) tagHide = false; + if (result.mode == "time") { + let timefilter: MonkeyTypes.Mode2Custom<"time"> = "custom"; + if ([15, 30, 60, 120].includes(parseInt(result.mode2 as string))) { + timefilter = result.mode2; } - }); + if (!ResultFilters.getFilter("time", timefilter)) { + if (filterDebug) + console.log(`skipping result due to time filter`, result); + return; + } + } else if (result.mode == "words") { + let wordfilter: MonkeyTypes.Mode2Custom<"words"> = "custom"; + if ( + [10, 25, 50, 100, 200].includes(parseInt(result.mode2 as string)) + ) { + wordfilter = result.mode2; + } + if (!ResultFilters.getFilter("words", wordfilter)) { + if (filterDebug) + console.log(`skipping result due to word filter`, result); + return; + } + } + + if (result.quoteLength != null) { + let filter: MonkeyTypes.QuoteModes | undefined = undefined; + if (result.quoteLength === 0) { + filter = "short"; + } else if (result.quoteLength === 1) { + filter = "medium"; + } else if (result.quoteLength === 2) { + filter = "long"; + } else if (result.quoteLength === 3) { + filter = "thicc"; + } + if ( + filter !== undefined && + !ResultFilters.getFilter("quoteLength", filter) + ) { + if (filterDebug) + console.log( + `skipping result due to quoteLength filter`, + result + ); + return; + } + } + + let langFilter = ResultFilters.getFilter( + "language", + result.language ?? "english" + ); + + if ( + result.language === "english_expanded" && + ResultFilters.getFilter("language", "english_1k") + ) { + langFilter = true; + } + if (!langFilter) { + if (filterDebug) + console.log(`skipping result due to language filter`, result); + return; + } + + let puncfilter: MonkeyTypes.Filter<"punctuation"> = "off"; + if (result.punctuation) { + puncfilter = "on"; + } + if (!ResultFilters.getFilter("punctuation", puncfilter)) { + if (filterDebug) + console.log(`skipping result due to punctuation filter`, result); + return; + } + + let numfilter: MonkeyTypes.Filter<"numbers"> = "off"; + if (result.numbers) { + numfilter = "on"; + } + if (!ResultFilters.getFilter("numbers", numfilter)) { + if (filterDebug) + console.log(`skipping result due to numbers filter`, result); + return; + } + + if (result.funbox === "none" || result.funbox === undefined) { + if (!ResultFilters.getFilter("funbox", "none")) { + if (filterDebug) + console.log(`skipping result due to funbox filter`, result); + return; + } + } else { + if (!ResultFilters.getFilter("funbox", result.funbox)) { + if (filterDebug) + console.log(`skipping result due to funbox filter`, result); + return; + } + } + + let tagHide = true; + if (result.tags === undefined || result.tags.length === 0) { + //no tags, show when no tag is enabled + if (DB.getSnapshot().tags?.length || 0 > 0) { + if (ResultFilters.getFilter("tags", "none")) tagHide = false; + } else { + tagHide = false; + } + } else { + //tags exist + const validTags = DB.getSnapshot().tags?.map((t) => t._id); + + if (validTags === undefined) return; + + result.tags.forEach((tag) => { + //check if i even need to check tags anymore + if (!tagHide) return; + //check if tag is valid + if (validTags?.includes(tag)) { + //tag valid, check if filter is on + if (ResultFilters.getFilter("tags", tag)) tagHide = false; + } else { + //tag not found in valid tags, meaning probably deleted + if (ResultFilters.getFilter("tags", "none")) tagHide = false; + } + }); + } + + if (tagHide) { + if (filterDebug) + console.log(`skipping result due to tag filter`, result); + return; + } + + const timeSinceTest = Math.abs(result.timestamp - Date.now()) / 1000; + + let datehide = true; + + if ( + ResultFilters.getFilter("date", "all") || + (ResultFilters.getFilter("date", "last_day") && + timeSinceTest <= 86400) || + (ResultFilters.getFilter("date", "last_week") && + timeSinceTest <= 604800) || + (ResultFilters.getFilter("date", "last_month") && + timeSinceTest <= 2592000) || + (ResultFilters.getFilter("date", "last_3months") && + timeSinceTest <= 7776000) + ) { + datehide = false; + } + + if (datehide) { + if (filterDebug) + console.log(`skipping result due to date filter`, result); + return; + } + + filteredResults.push(result); + } catch (e) { + Notifications.add( + "Something went wrong when filtering. Resetting filters.", + 0 + ); + console.log(result); + console.error(e); + ResultFilters.reset(); + ResultFilters.updateActive(); + update(); } + //filters done + //======================================= - if (tagHide) { - if (filterDebug) - console.log(`skipping result due to tag filter`, result); - return; - } + const resultDate = new Date(result.timestamp); + resultDate.setSeconds(0); + resultDate.setMinutes(0); + resultDate.setHours(0); + resultDate.setMilliseconds(0); + const resultTimestamp = resultDate.getTime(); - const timeSinceTest = Math.abs(result.timestamp - Date.now()) / 1000; - - let datehide = true; - - if ( - ResultFilters.getFilter("date", "all") || - (ResultFilters.getFilter("date", "last_day") && - timeSinceTest <= 86400) || - (ResultFilters.getFilter("date", "last_week") && - timeSinceTest <= 604800) || - (ResultFilters.getFilter("date", "last_month") && - timeSinceTest <= 2592000) || - (ResultFilters.getFilter("date", "last_3months") && - timeSinceTest <= 7776000) - ) { - datehide = false; - } - - if (datehide) { - if (filterDebug) - console.log(`skipping result due to date filter`, result); - return; - } - - filteredResults.push(result); - } catch (e) { - Notifications.add( - "Something went wrong when filtering. Resetting filters.", - 0 - ); - console.log(result); - console.error(e); - ResultFilters.reset(); - ResultFilters.updateActive(); - update(); - } - //filters done - //======================================= - - const resultDate = new Date(result.timestamp); - resultDate.setSeconds(0); - resultDate.setMinutes(0); - resultDate.setHours(0); - resultDate.setMilliseconds(0); - const resultTimestamp = resultDate.getTime(); - - if (Object.keys(activityChartData).includes(String(resultTimestamp))) { - activityChartData[resultTimestamp].amount++; - activityChartData[resultTimestamp].time += - result.testDuration + - result.incompleteTestSeconds - - (result.afkDuration ?? 0); - activityChartData[resultTimestamp].totalWpm += result.wpm; - } else { - activityChartData[resultTimestamp] = { - amount: 1, - time: + if (Object.keys(activityChartData).includes(String(resultTimestamp))) { + activityChartData[resultTimestamp].amount++; + activityChartData[resultTimestamp].time += result.testDuration + result.incompleteTestSeconds - - (result.afkDuration ?? 0), - totalWpm: result.wpm, - }; - } - - let tt = 0; - if ( - result.testDuration == undefined && - result.mode2 !== "custom" && - result.mode2 !== "zen" - ) { - //test finished before testDuration field was introduced - estimate - if (result.mode == "time") { - tt = result.mode2; - } else if (result.mode == "words") { - tt = (result.mode2 / result.wpm) * 60; + (result.afkDuration ?? 0); + activityChartData[resultTimestamp].totalWpm += result.wpm; + } else { + activityChartData[resultTimestamp] = { + amount: 1, + time: + result.testDuration + + result.incompleteTestSeconds - + (result.afkDuration ?? 0), + totalWpm: result.wpm, + }; } - } else { - tt = result.testDuration; - } - if (result.incompleteTestSeconds != undefined) { - tt += result.incompleteTestSeconds; - } else if (result.restartCount != undefined && result.restartCount > 0) { - tt += (tt / 4) * result.restartCount; - } - // if (result.incompleteTestSeconds != undefined) { - // tt += result.incompleteTestSeconds; - // } else if (result.restartCount != undefined && result.restartCount > 0) { - // tt += (tt / 4) * result.restartCount; - // } - totalSecondsFiltered += tt; - - if (last10 < 10) { - last10++; - wpmLast10total += result.wpm; - totalAcc10 += result.acc; - result.consistency !== undefined - ? (totalCons10 += result.consistency) - : 0; - } - testCount++; - - if (result.consistency !== undefined) { - consCount++; - totalCons += result.consistency; - if (result.consistency > topCons) { - topCons = result.consistency; + let tt = 0; + if ( + result.testDuration == undefined && + result.mode2 !== "custom" && + result.mode2 !== "zen" + ) { + //test finished before testDuration field was introduced - estimate + if (result.mode == "time") { + tt = result.mode2; + } else if (result.mode == "words") { + tt = (result.mode2 / result.wpm) * 60; + } + } else { + tt = result.testDuration; } - } - - if (result.rawWpm != null) { - if (rawWpm.last10Count < 10) { - rawWpm.last10Count++; - rawWpm.last10Total += result.rawWpm; + if (result.incompleteTestSeconds != undefined) { + tt += result.incompleteTestSeconds; + } else if ( + result.restartCount != undefined && + result.restartCount > 0 + ) { + tt += (tt / 4) * result.restartCount; } - rawWpm.total += result.rawWpm; - rawWpm.count++; - if (result.rawWpm > rawWpm.max) { - rawWpm.max = result.rawWpm; + + // if (result.incompleteTestSeconds != undefined) { + // tt += result.incompleteTestSeconds; + // } else if (result.restartCount != undefined && result.restartCount > 0) { + // tt += (tt / 4) * result.restartCount; + // } + totalSecondsFiltered += tt; + + if (last10 < 10) { + last10++; + wpmLast10total += result.wpm; + totalAcc10 += result.acc; + result.consistency !== undefined + ? (totalCons10 += result.consistency) + : 0; } + testCount++; + + if (result.consistency !== undefined) { + consCount++; + totalCons += result.consistency; + if (result.consistency > topCons) { + topCons = result.consistency; + } + } + + if (result.rawWpm != null) { + if (rawWpm.last10Count < 10) { + rawWpm.last10Count++; + rawWpm.last10Total += result.rawWpm; + } + rawWpm.total += result.rawWpm; + rawWpm.count++; + if (result.rawWpm > rawWpm.max) { + rawWpm.max = result.rawWpm; + } + } + + if (result.acc > topAcc) { + topAcc = result.acc; + } + + totalAcc += result.acc; + + if (result.restartCount != undefined) { + testRestarts += result.restartCount; + } + + chartData.push({ + x: result.timestamp, + y: Config.alwaysShowCPM ? Misc.roundTo2(result.wpm * 5) : result.wpm, + acc: result.acc, + mode: result.mode, + mode2: result.mode2, + punctuation: result.punctuation as boolean, + language: result.language, + timestamp: result.timestamp, + difficulty: result.difficulty, + raw: Config.alwaysShowCPM + ? Misc.roundTo2(result.rawWpm * 5) + : result.rawWpm, + }); + + wpmChartData.push(result.wpm); + + accChartData.push({ + x: result.timestamp, + y: 100 - result.acc, + }); + + if (result.wpm > topWpm) { + const puncsctring = result.punctuation ? ",
with punctuation" : ""; + const numbsctring = result.numbers + ? ",
" + (result.punctuation ? "&" : "") + "with numbers" + : ""; + topWpm = result.wpm; + if (result.mode == "custom") topMode = result.mode; + else + topMode = + result.mode + " " + result.mode2 + puncsctring + numbsctring; + } + + totalWpm += result.wpm; } - - if (result.acc > topAcc) { - topAcc = result.acc; - } - - totalAcc += result.acc; - - if (result.restartCount != undefined) { - testRestarts += result.restartCount; - } - - chartData.push({ - x: result.timestamp, - y: Config.alwaysShowCPM ? Misc.roundTo2(result.wpm * 5) : result.wpm, - acc: result.acc, - mode: result.mode, - mode2: result.mode2, - punctuation: result.punctuation as boolean, - language: result.language, - timestamp: result.timestamp, - difficulty: result.difficulty, - raw: Config.alwaysShowCPM - ? Misc.roundTo2(result.rawWpm * 5) - : result.rawWpm, - }); - - wpmChartData.push(result.wpm); - - accChartData.push({ - x: result.timestamp, - y: 100 - result.acc, - }); - - if (result.wpm > topWpm) { - const puncsctring = result.punctuation ? ",
with punctuation" : ""; - const numbsctring = result.numbers - ? ",
" + (result.punctuation ? "&" : "") + "with numbers" - : ""; - topWpm = result.wpm; - if (result.mode == "custom") topMode = result.mode; - else - topMode = - result.mode + " " + result.mode2 + puncsctring + numbsctring; - } - - totalWpm += result.wpm; - }); + ); if (Config.alwaysShowCPM) { $(".pageAccount .group.history table thead tr td:nth-child(2)").text( @@ -630,8 +639,10 @@ export function update(): void { "Average Wpm"; } - ChartController.accountActivity.data.datasets[0].data = activityChartData_time; - ChartController.accountActivity.data.datasets[1].data = activityChartData_avgWpm; + ChartController.accountActivity.data.datasets[0].data = + activityChartData_time; + ChartController.accountActivity.data.datasets[1].data = + activityChartData_avgWpm; if (Config.alwaysShowCPM) { ChartController.accountHistory.options.scales.yAxes[0].scaleLabel.labelString = @@ -653,9 +664,8 @@ export function update(): void { Math.floor(maxWpmChartVal) + (10 - (Math.floor(maxWpmChartVal) % 10)); if (!Config.startGraphsAtZero) { - ChartController.accountHistory.options.scales.yAxes[0].ticks.min = Math.floor( - minWpmChartVal - ); + ChartController.accountHistory.options.scales.yAxes[0].ticks.min = + Math.floor(minWpmChartVal); } else { ChartController.accountHistory.options.scales.yAxes[0].ticks.min = 0; } @@ -963,7 +973,9 @@ $(document).on("click", ".pageAccount .miniResultChartButton", (event) => { console.log("updating"); const filteredId = $(event.currentTarget).attr("filteredResultsId"); if (filteredId === undefined) return; - MiniResultChart.updateData(filteredResults[parseInt(filteredId)].chartData); + MiniResultChart.updateData( + filteredResults[parseInt(filteredId)].chartData as MonkeyTypes.ChartData + ); MiniResultChart.show(); MiniResultChart.updatePosition( event.pageX - ($(".pageAccount .miniResultChartWrapper").outerWidth() ?? 0), diff --git a/frontend/src/scripts/pages/settings.ts b/frontend/src/scripts/pages/settings.ts index 5c724ae6a..460aef147 100644 --- a/frontend/src/scripts/pages/settings.ts +++ b/frontend/src/scripts/pages/settings.ts @@ -587,7 +587,7 @@ function setActiveFunboxButton(): void { function refreshTagsSettingsSection(): void { if (firebase.auth().currentUser !== null && DB.getSnapshot() !== null) { const tagsEl = $(".pageSettings .section.tags .tagsList").empty(); - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { // let tagPbString = "No PB found"; // if (tag.pb != undefined && tag.pb > 0) { // tagPbString = `PB: ${tag.pb}`; @@ -622,7 +622,7 @@ function refreshTagsSettingsSection(): void { function refreshPresetsSettingsSection(): void { if (firebase.auth().currentUser !== null && DB.getSnapshot() !== null) { const presetsEl = $(".pageSettings .section.presets .presetsList").empty(); - DB.getSnapshot().presets.forEach((preset: MonkeyTypes.Preset) => { + DB.getSnapshot().presets?.forEach((preset: MonkeyTypes.Preset) => { presetsEl.append(`
@@ -904,7 +904,7 @@ $(".pageSettings .section.customBackgroundSize .inputAndButton .save").on( UpdateConfig.setCustomBackground( $( ".pageSettings .section.customBackgroundSize .inputAndButton input" - ).val() + ).val() as string ); } ); @@ -915,7 +915,7 @@ $(".pageSettings .section.customBackgroundSize .inputAndButton input").keypress( UpdateConfig.setCustomBackground( $( ".pageSettings .section.customBackgroundSize .inputAndButton input" - ).val() + ).val() as string ); } } @@ -925,7 +925,9 @@ $(".pageSettings .section.customLayoutfluid .inputAndButton .save").on( "click", () => { UpdateConfig.setCustomLayoutfluid( - $(".pageSettings .section.customLayoutfluid .inputAndButton input").val() + $( + ".pageSettings .section.customLayoutfluid .inputAndButton input" + ).val() as MonkeyTypes.CustomLayoutFluidSpaces ); Notifications.add("Custom layoutfluid saved", 1); } @@ -937,7 +939,7 @@ $(".pageSettings .section.customLayoutfluid .inputAndButton .input").keypress( UpdateConfig.setCustomLayoutfluid( $( ".pageSettings .section.customLayoutfluid .inputAndButton input" - ).val() + ).val() as MonkeyTypes.CustomLayoutFluidSpaces ); Notifications.add("Custom layoutfluid saved", 1); } diff --git a/frontend/src/scripts/popups/custom-test-duration-popup.ts b/frontend/src/scripts/popups/custom-test-duration-popup.ts index 05dcc46cc..d617e41d2 100644 --- a/frontend/src/scripts/popups/custom-test-duration-popup.ts +++ b/frontend/src/scripts/popups/custom-test-duration-popup.ts @@ -102,7 +102,7 @@ function apply(): void { const val = parseInput($("#customTestDurationPopup input").val() as string); if (val !== null && !isNaN(val) && val >= 0) { - UpdateConfig.setTimeConfig(val); + UpdateConfig.setTimeConfig(val as MonkeyTypes.TimeModes); ManualRestart.set(); TestLogic.restart(); if (val >= 1800) { diff --git a/frontend/src/scripts/popups/custom-word-amount-popup.ts b/frontend/src/scripts/popups/custom-word-amount-popup.ts index f0656bd90..916bd451b 100644 --- a/frontend/src/scripts/popups/custom-word-amount-popup.ts +++ b/frontend/src/scripts/popups/custom-word-amount-popup.ts @@ -36,7 +36,7 @@ function apply(): void { const val = parseInt($("#customWordAmountPopup input").val() as string); if (val !== null && !isNaN(val) && val >= 0) { - UpdateConfig.setWordCount(val); + UpdateConfig.setWordCount(val as MonkeyTypes.WordsModes); ManualRestart.set(); TestLogic.restart(); if (val > 2000) { diff --git a/frontend/src/scripts/popups/edit-preset-popup.ts b/frontend/src/scripts/popups/edit-preset-popup.ts index 532928392..62a672960 100644 --- a/frontend/src/scripts/popups/edit-preset-popup.ts +++ b/frontend/src/scripts/popups/edit-preset-popup.ts @@ -79,11 +79,11 @@ async function apply(): Promise { ); // TODO fix this sometime - let configChanges: ConfigChanges = (null as unknown) as ConfigChanges; + let configChanges: ConfigChanges = null as unknown as ConfigChanges; if ((updateConfig && action === "edit") || action === "add") { configChanges = Config.getConfigChanges() as ConfigChanges; const activeTagIds: string[] = []; - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { if (tag.active) { activeTagIds.push(tag._id); } @@ -112,7 +112,7 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Preset added", 1, 2); - DB.getSnapshot().presets.push({ + DB.getSnapshot().presets?.push({ name: inputVal, config: configChanges, _id: response.data.insertedId, @@ -140,12 +140,15 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Preset updated", 1); - const preset: MonkeyTypes.Snapshot = DB.getSnapshot().presets.filter( + const preset = DB.getSnapshot().presets?.filter( (preset: MonkeyTypes.Preset) => preset._id == presetid )[0]; - preset.name = inputVal; - if (updateConfig === true) preset.config = configChanges; - Settings.update(); + + if (preset !== undefined) { + preset.name = inputVal; + if (updateConfig === true) preset.config = configChanges; + Settings.update(); + } } } else if (action === "remove") { Loader.show(); @@ -166,10 +169,10 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Preset removed", 1); - DB.getSnapshot().presets.forEach( + DB.getSnapshot().presets?.forEach( (preset: MonkeyTypes.Preset, index: number) => { if (preset._id === presetid) { - DB.getSnapshot().presets.splice(index, 1); + DB.getSnapshot().presets?.splice(index, 1); } } ); diff --git a/frontend/src/scripts/popups/edit-tags-popup.ts b/frontend/src/scripts/popups/edit-tags-popup.ts index 4a4089d6e..5a3144f4a 100644 --- a/frontend/src/scripts/popups/edit-tags-popup.ts +++ b/frontend/src/scripts/popups/edit-tags-popup.ts @@ -91,7 +91,7 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Tag added", 1); - DB.getSnapshot().tags.push({ + DB.getSnapshot().tags?.push({ name: response.data.name, _id: response.data._id, }); @@ -119,7 +119,7 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Tag updated", 1); - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { if (tag._id === tagid) { tag.name = inputVal; } @@ -145,9 +145,9 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Tag removed", 1); - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag, index: number) => { + DB.getSnapshot().tags?.forEach((tag, index: number) => { if (tag._id === tagid) { - DB.getSnapshot().tags.splice(index, 1); + DB.getSnapshot().tags?.splice(index, 1); } }); ResultTagsPopup.updateButtons(); @@ -171,9 +171,15 @@ async function apply(): Promise { Notifications.add(response.data.message); } else { Notifications.add("Tag PB cleared", 1); - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { if (tag._id === tagid) { - tag.personalBests = {}; + tag.personalBests = { + time: {}, + words: {}, + custom: { custom: [] }, + zen: { zen: [] }, + quote: { custom: [] }, + }; } }); ResultTagsPopup.updateButtons(); diff --git a/frontend/src/scripts/popups/mobile-test-config-popup.ts b/frontend/src/scripts/popups/mobile-test-config-popup.ts index d589c8e70..f958e8acc 100644 --- a/frontend/src/scripts/popups/mobile-test-config-popup.ts +++ b/frontend/src/scripts/popups/mobile-test-config-popup.ts @@ -95,23 +95,27 @@ $("#top .mobileConfig").click(() => { el.find(".wordsGroup .button").on("click", (e) => { const wrd = $(e.currentTarget).attr("words"); + if (wrd == "custom") { hidePopup(); CustomWordAmountPopup.show(); - } else { - UpdateConfig.setWordCount(wrd); + } else if (wrd !== undefined) { + const wrdNum = parseInt(wrd); + UpdateConfig.setWordCount(wrdNum); ManualRestart.set(); TestLogic.restart(); } }); el.find(".timeGroup .button").on("click", (e) => { - const mode = $(e.currentTarget).attr("time"); - if (mode == "custom") { + const time = $(e.currentTarget).attr("time"); + + if (time == "custom") { hidePopup(); CustomTestDurationPopup.show(); - } else { - UpdateConfig.setTimeConfig(mode); + } else if (time !== undefined) { + const timeNum = parseInt(time); + UpdateConfig.setTimeConfig(timeNum); ManualRestart.set(); TestLogic.restart(); } @@ -128,7 +132,11 @@ el.find(".quoteGroup .button").on("click", (e) => { if (len == -1) { len = [0, 1, 2, 3]; } - UpdateConfig.setQuoteLength(len, false, e.shiftKey); + UpdateConfig.setQuoteLength( + len as MonkeyTypes.QuoteLength | MonkeyTypes.QuoteLengthArray, + false, + e.shiftKey + ); ManualRestart.set(); TestLogic.restart(); } @@ -154,7 +162,7 @@ el.find(".numbers").on("click", () => { el.find(".modeGroup .button").on("click", (e) => { if ($(e.currentTarget).hasClass("active")) return; const mode = $(e.currentTarget).attr("mode"); - UpdateConfig.setMode(mode); + UpdateConfig.setMode(mode as MonkeyTypes.Mode); ManualRestart.set(); TestLogic.restart(); }); diff --git a/frontend/src/scripts/popups/pb-tables-popup.ts b/frontend/src/scripts/popups/pb-tables-popup.ts index e24dc8a96..f4c4d2b72 100644 --- a/frontend/src/scripts/popups/pb-tables-popup.ts +++ b/frontend/src/scripts/popups/pb-tables-popup.ts @@ -1,47 +1,42 @@ import * as DB from "../db"; -function update(mode: string): void { +interface PersonalBest extends MonkeyTypes.PersonalBest { + mode2: MonkeyTypes.Mode2; +} + +function update(mode: MonkeyTypes.Mode): void { $("#pbTablesPopup table tbody").empty(); $($("#pbTablesPopup table thead tr td")[0]).text(mode); - type PersonalBests = { - [key: string]: PersonalBest[]; - }; + const snapshot = DB.getSnapshot(); - type PersonalBest = { - acc: number; - consistency: number; - difficulty: MonkeyTypes.Difficulty; - lazyMode: boolean; - language: string; - punctuation: boolean; - raw: number; - wpm: number; - timestamp: number; - mode2?: string; - }; + const allmode2 = ( + snapshot.personalBests === undefined + ? undefined + : snapshot.personalBests[mode] + ) as { [quote: string]: PersonalBest[] } | undefined; - const allmode2: PersonalBests = DB.getSnapshot().personalBests[mode]; - - if (!allmode2) return; + if (allmode2 === undefined) return; const list: PersonalBest[] = []; - Object.keys(allmode2).forEach(function (key) { - let pbs = allmode2[key]; - pbs = pbs.sort(function (a, b) { - return b.wpm - a.wpm; - // if (a.difficulty === b.difficulty) { - // return (a.language < b.language ? -1 : 1); - // } - // return (a.difficulty < b.difficulty ? -1 : 1) - }); - pbs.forEach(function (pb) { - pb.mode2 = key; - list.push(pb); - }); - }); + (Object.keys(allmode2) as MonkeyTypes.Mode2[]).forEach( + function (key) { + let pbs = allmode2[key]; + pbs = pbs.sort(function (a, b) { + return b.wpm - a.wpm; + // if (a.difficulty === b.difficulty) { + // return (a.language < b.language ? -1 : 1); + // } + // return (a.difficulty < b.difficulty ? -1 : 1) + }); + pbs.forEach(function (pb) { + pb.mode2 = key; + list.push(pb); + }); + } + ); - let mode2memory: string; + let mode2memory: MonkeyTypes.Mode2; list.forEach((pb) => { let dateText = `-
-`; @@ -74,11 +69,11 @@ function update(mode: string): void { ${dateText} `); - mode2memory = pb.mode2 as string; + mode2memory = pb.mode2 as never; }); } -function show(mode: string): void { +function show(mode: MonkeyTypes.Mode): void { if ($("#pbTablesPopupWrapper").hasClass("hidden")) { update(mode); diff --git a/frontend/src/scripts/popups/quote-rate-popup.ts b/frontend/src/scripts/popups/quote-rate-popup.ts index 2a457c5e2..09d2c9cca 100644 --- a/frontend/src/scripts/popups/quote-rate-popup.ts +++ b/frontend/src/scripts/popups/quote-rate-popup.ts @@ -15,12 +15,6 @@ type QuoteStats = { language: string; }; -type QuoteRatings = { - [language: string]: { - [id: string]: number; - }; -}; - let quoteStats: QuoteStats | null | Record = null; let currentQuote: MonkeyTypes.Quote | null = null; @@ -111,9 +105,13 @@ export function show(quote: MonkeyTypes.Quote, shouldReset = true): void { currentQuote = quote; rating = 0; - const alreadyRated = DB.getSnapshot().quoteRatings?.[ - currentQuote.language - ]?.[currentQuote.id]; + + const snapshot = DB.getSnapshot(); + + if (snapshot.quoteRatings === undefined) return; + + const alreadyRated = + snapshot.quoteRatings[currentQuote.language][currentQuote.id]; if (alreadyRated) { rating = alreadyRated; } @@ -174,7 +172,10 @@ async function submit(): Promise { if (response.status !== 200) { Notifications.add(response.data.message); } else { - let quoteRatings: QuoteRatings = DB.getSnapshot().quoteRatings; + let quoteRatings = DB.getSnapshot().quoteRatings; + + if (quoteRatings === undefined) return; + if (quoteRatings?.[currentQuote.language]?.[currentQuote.id]) { const oldRating = quoteRatings[currentQuote.language][currentQuote.id]; const diff = rating - oldRating; @@ -243,5 +244,5 @@ $("#quoteRatePopup .submitButton").click(() => { $(".pageTest #rateQuoteButton").click(async () => { // TODO remove this when done with TestWords - show((TestWords.randomQuote as unknown) as MonkeyTypes.Quote); + show(TestWords.randomQuote as unknown as MonkeyTypes.Quote); }); diff --git a/frontend/src/scripts/popups/quote-search-popup.ts b/frontend/src/scripts/popups/quote-search-popup.ts index ff2cbd3f8..830f77fdb 100644 --- a/frontend/src/scripts/popups/quote-search-popup.ts +++ b/frontend/src/scripts/popups/quote-search-popup.ts @@ -146,7 +146,7 @@ export function apply(val: number): boolean { } let ret; if (val !== null && !isNaN(val) && val >= 0) { - UpdateConfig.setQuoteLength(-2, false); + UpdateConfig.setQuoteLength(-2 as MonkeyTypes.QuoteLength, false); selectedId = val; ManualRestart.set(); ret = true; diff --git a/frontend/src/scripts/popups/result-tags-popup.ts b/frontend/src/scripts/popups/result-tags-popup.ts index d339da2b6..53ab97a35 100644 --- a/frontend/src/scripts/popups/result-tags-popup.ts +++ b/frontend/src/scripts/popups/result-tags-popup.ts @@ -32,7 +32,7 @@ function hide(): void { export function updateButtons(): void { $("#resultEditTagsPanel .buttons").empty(); - DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((tag) => { $("#resultEditTagsPanel .buttons").append( `
${tag.name}
` ); @@ -52,7 +52,7 @@ function updateActiveButtons(active: string[]): void { } $(document).on("click", ".pageAccount .group.history #resultEditTags", (f) => { - if (DB.getSnapshot().tags.length > 0) { + if (DB.getSnapshot().tags?.length || 0 > 0) { const resultid = $(f.target).parents("span").attr("resultid") as string; const tags = $(f.target).parents("span").attr("tags") as string; $("#resultEditTagsPanel").attr("resultid", resultid); @@ -97,17 +97,19 @@ $("#resultEditTagsPanel .confirmButton").click(() => { Notifications.add(response.data.message); } else { Notifications.add("Tags updated.", 1, 2); - DB.getSnapshot().results.forEach((result: MonkeyTypes.Result) => { - if (result._id === resultid) { - result.tags = newtags; + DB.getSnapshot().results?.forEach( + (result: MonkeyTypes.Result) => { + if (result._id === resultid) { + result.tags = newtags; + } } - }); + ); let tagNames = ""; if (newtags.length > 0) { newtags.forEach((tag) => { - DB.getSnapshot().tags.forEach((snaptag: MonkeyTypes.Tag) => { + DB.getSnapshot().tags?.forEach((snaptag) => { if (tag === snaptag._id) { tagNames += snaptag.name + ", "; } diff --git a/frontend/src/scripts/popups/simple-popups.ts b/frontend/src/scripts/popups/simple-popups.ts index 8d7587801..004dc619a 100644 --- a/frontend/src/scripts/popups/simple-popups.ts +++ b/frontend/src/scripts/popups/simple-popups.ts @@ -578,10 +578,16 @@ list["clearTagPb"] = new SimplePopup( .then((res) => { Loader.hide(); if (res.data.resultCode === 1) { - const tag = DB.getSnapshot().tags.filter( - (t: MonkeyTypes.Tag) => t._id === tagid - )[0]; - tag.pb = 0; + const tag = DB.getSnapshot().tags?.filter((t) => t._id === tagid)[0]; + + if (tag === undefined) return; + tag.personalBests = { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }; $( `.pageSettings .section.tags .tagsList .tag[id="${tagid}"] .clearPbButton` ).attr("aria-label", "No PB found"); @@ -665,7 +671,13 @@ list["resetPersonalBests"] = new SimplePopup( Notifications.add(response.data.message); } else { Notifications.add("Personal bests have been reset", 1); - DB.getSnapshot().personalBests = {}; + DB.getSnapshot().personalBests = { + time: {}, + words: {}, + zen: { zen: [] }, + quote: { custom: [] }, + custom: { custom: [] }, + }; } } catch (e) { Loader.hide(); diff --git a/frontend/src/scripts/settings/settings-group.ts b/frontend/src/scripts/settings/settings-group.ts index 1126544c5..3c3e16fec 100644 --- a/frontend/src/scripts/settings/settings-group.ts +++ b/frontend/src/scripts/settings/settings-group.ts @@ -9,7 +9,7 @@ export default class SettingsGroup { public updateCallback?: () => any; constructor( configName: string, - configFunction: () => any, + configFunction: (...values: any[]) => any, mode: string, setCallback?: () => any, updateCallback?: () => any diff --git a/frontend/src/scripts/settings/theme-picker.ts b/frontend/src/scripts/settings/theme-picker.ts index ac7fc87be..174b3486e 100644 --- a/frontend/src/scripts/settings/theme-picker.ts +++ b/frontend/src/scripts/settings/theme-picker.ts @@ -212,7 +212,7 @@ $(document).on( $(document).on("click", ".pageSettings .section.themes .theme.button", (e) => { const theme = $(e.currentTarget).attr("theme"); - if (!$(e.target).hasClass("favButton")) { + if (!$(e.target).hasClass("favButton") && theme !== undefined) { UpdateConfig.setTheme(theme); updateActiveButton(); } diff --git a/frontend/src/scripts/test/live-burst.ts b/frontend/src/scripts/test/live-burst.ts index 6b33c033a..9d23d8ca3 100644 --- a/frontend/src/scripts/test/live-burst.ts +++ b/frontend/src/scripts/test/live-burst.ts @@ -7,12 +7,10 @@ export function update(burst: number): void { if (Config.blindMode) { number = 0; } - (document.querySelector( - "#miniTimerAndLiveWpm .burst" - ) as Element).innerHTML = number.toString(); - (document.querySelector( - "#liveBurst" - ) as Element).innerHTML = number.toString(); + (document.querySelector("#miniTimerAndLiveWpm .burst") as Element).innerHTML = + number.toString(); + (document.querySelector("#liveBurst") as Element).innerHTML = + number.toString(); } export function show(): void { diff --git a/frontend/src/scripts/test/result.js b/frontend/src/scripts/test/result.js index f203e9bd8..00dd49ff9 100644 --- a/frontend/src/scripts/test/result.js +++ b/frontend/src/scripts/test/result.js @@ -35,9 +35,8 @@ async function updateGraph() { } ChartController.result.updateColors(); ChartController.result.data.labels = labels; - ChartController.result.options.scales.yAxes[0].scaleLabel.labelString = Config.alwaysShowCPM - ? "Character per Minute" - : "Words per Minute"; + ChartController.result.options.scales.yAxes[0].scaleLabel.labelString = + Config.alwaysShowCPM ? "Character per Minute" : "Words per Minute"; let chartData1 = Config.alwaysShowCPM ? TestInput.wpmHistory.map((a) => a * 5) : TestInput.wpmHistory; @@ -156,12 +155,10 @@ export async function updateGraphPBLine() { ) { maxChartVal = parseFloat(chartlpb) + 20; } - ChartController.result.options.scales.yAxes[0].ticks.max = Math.round( - maxChartVal - ); - ChartController.result.options.scales.yAxes[1].ticks.max = Math.round( - maxChartVal - ); + ChartController.result.options.scales.yAxes[0].ticks.max = + Math.round(maxChartVal); + ChartController.result.options.scales.yAxes[1].ticks.max = + Math.round(maxChartVal); ChartController.result.update({ duration: 0 }); } @@ -548,9 +545,8 @@ function updateOther( export function updateRateQuote(randomQuote) { if (Config.mode === "quote") { - let userqr = DB.getSnapshot().quoteRatings?.[randomQuote.language]?.[ - randomQuote.id - ]; + let userqr = + DB.getSnapshot().quoteRatings?.[randomQuote.language]?.[randomQuote.id]; if (userqr) { $(".pageTest #result #rateQuoteButton .icon") .removeClass("far") diff --git a/frontend/src/scripts/test/test-words.ts b/frontend/src/scripts/test/test-words.ts index 206e29a56..85d378623 100644 --- a/frontend/src/scripts/test/test-words.ts +++ b/frontend/src/scripts/test/test-words.ts @@ -57,7 +57,7 @@ class Words { } export const words = new Words(); export let hasTab = false; -export let randomQuote = (null as unknown) as MonkeyTypes.Quote; +export let randomQuote = null as unknown as MonkeyTypes.Quote; export function setRandomQuote(rq: MonkeyTypes.Quote): void { randomQuote = rq; diff --git a/frontend/src/scripts/types/types.d.ts b/frontend/src/scripts/types/types.d.ts index 641d2b2eb..fbeb4b97f 100644 --- a/frontend/src/scripts/types/types.d.ts +++ b/frontend/src/scripts/types/types.d.ts @@ -7,17 +7,17 @@ declare namespace MonkeyTypes { type Mode2 = keyof PersonalBests[M]; + type Mode2Custom = Mode2 | "custom"; + type LanguageGroup = { name: string; languages: string[] }; - // type Mode2 = 10 | 15 | 25 | 30 | 50 | 60 | 100 | 120 | 200 | "zen" | "custom"; + type WordsModes = number; - type NoncustomWordsModes = 10 | 25 | 50 | 100 | 200; + type TimeModes = number; - type WordsModes = NoncustomWordsModes | CustomModes; + type DefaultWordsModes = 10 | 25 | 50 | 100; - type NoncustomTimeModes = 15 | 30 | 60 | 120; - - type TimeModes = NoncustomTimeModes | CustomModes; + type DefaultTimeModes = 15 | 30 | 60 | 120; type QuoteModes = "short" | "medium" | "long" | "thicc"; @@ -40,7 +40,7 @@ declare namespace MonkeyTypes { type TimerStyle = "bar" | "text" | "mini"; - type RandomTheme = "off" | "on" | "favorite" | "light" | "dark"; + type RandomTheme = "off" | "on" | "fav" | "light" | "dark"; type TimerColor = "black" | "sub" | "text" | "main"; @@ -61,15 +61,17 @@ declare namespace MonkeyTypes { type SingleListCommandLine = "manual" | "on"; - type PlaySoundOnClick = - | "off" - | "click" - | "beep" - | "pop" - | "nk_creams" - | "typewriter" - | "osu" - | "hitmarker"; + /* + off = off + 1 = click + 2 = beep + 3 = pop + 4 = nk creams + 5 = typewriter + 6 = osu + 7 = hitmarker + */ + type PlaySoundOnClick = "off" | "1" | "2" | "3" | "4" | "5" | "6" | "7"; type SoundVolume = "0.1" | "0.5" | "1.0"; @@ -83,7 +85,7 @@ declare namespace MonkeyTypes { type HighlightMode = "off" | "letter" | "word"; - type EnableAds = "off" | "on" | "sellout"; + type EnableAds = "off" | "on" | "max"; type MinimumAccuracy = "off" | "custom"; @@ -95,12 +97,27 @@ declare namespace MonkeyTypes { type CustomBackgroundFilter = [0 | 1, 0 | 1, 0 | 1, 0 | 1, 0 | 1]; - type MonkeyPowerLevel = "off" | "mellow" | "high" | "ultra" | "over_9000"; + /* + off = off + 1 = mellow + 2 = high + 3 = ultra + 4 = over 9000 + */ + type MonkeyPowerLevel = "off" | "1" | "2" | "3" | "4"; type MinimumBurst = "off" | "fixed" | "flex"; type FunboxObjectType = "script" | "style"; + type IndicateTypos = "off" | "below" | "replace"; + + type CustomLayoutFluid = `${string}#${string}#${string}`; + + type CustomLayoutFluidSpaces = + | CustomLayoutFluid + | `${string} ${string} ${string}`; + interface FunboxObject { name: string; type: FunboxObjectType; @@ -137,22 +154,22 @@ declare namespace MonkeyTypes { interface PersonalBests { time: { [key: number]: PersonalBest[]; - custom: PersonalBest[]; }; words: { [key: number]: PersonalBest[]; - custom: PersonalBest[]; }; quote: { [quote: string]: PersonalBest[] }; custom: { custom: PersonalBest[] }; - zen: PersonalBest[]; + zen: { + zen: PersonalBest[]; + }; } interface Tag { _id: string; name: string; - personalBests: PersonalBests | Record; - active: boolean; + personalBests?: PersonalBests; + active?: boolean; } interface Stats { @@ -172,7 +189,7 @@ declare namespace MonkeyTypes { sd: number; } - interface Result { + interface Result { _id: string; wpm: number; rawWpm: number; @@ -180,8 +197,8 @@ declare namespace MonkeyTypes { correctChars?: number; // -------------- incorrectChars?: number; // legacy results acc: number; - mode: Mode; - mode2: number | "custom" | "zen"; + mode: M; + mode2: Mode2; quoteLength: number; timestamp: number; restartCount: number; @@ -235,7 +252,7 @@ declare namespace MonkeyTypes { layout: string; funbox: string; confidenceMode: ConfidenceMode; - indicateTypos: boolean; + indicateTypos: IndicateTypos; timerStyle: TimerStyle; colorfulMode: boolean; randomTheme: RandomTheme; @@ -282,7 +299,7 @@ declare namespace MonkeyTypes { customBackground: string; customBackgroundSize: CustomBackgroundSize; customBackgroundFilter: CustomBackgroundFilter; - customLayoutfluid: string; + customLayoutfluid: CustomLayoutFluid; monkeyPowerLevel: MonkeyPowerLevel; minBurst: MinimumBurst; minBurstCustomSpeed: number; @@ -295,6 +312,14 @@ declare namespace MonkeyTypes { wordCount: WordsModes; } + interface LeaderboardMemory { + time: { + [key in 15 | 60]: { + [language: string]: number; + }; + }; + } + interface Leaderboards { time: { [key in 15 | 60]: LeaderboardEntry[]; @@ -319,24 +344,34 @@ declare namespace MonkeyTypes { hidden?: boolean; } + interface QuoteRatings { + [language: string]: { + [id: string | number]: any; // TODO find this + }; + } + interface Snapshot { banned?: boolean; emailVerified?: boolean; - quoteRatings?: object; // TODO find structure of quoteRatings - results?: Result[]; + quoteRatings?: QuoteRatings; + results?: Result[]; verified?: boolean; personalBests?: PersonalBests; name?: string; presets?: Preset[]; tags?: Tag[]; favouriteThemes?: string[]; - lbMemory?: Leaderboards; + lbMemory?: LeaderboardMemory; globalStats?: Stats; quoteMod?: boolean; discordId?: string; config?: Config; } + type PartialRecord = { + [P in K]?: T; + }; + interface ResultFilters { difficulty: { normal: boolean; diff --git a/package-lock.json b/package-lock.json index d44a306da..c94bbdcbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,8 @@ "eslint-plugin-promise": "5.1.0", "eslint-plugin-require-path-exists": "1.1.9", "husky": "4.3.0", - "jsonschema": "^1.4.0", - "prettier": "2.1.2", + "jsonschema": "1.4.0", + "prettier": "2.5.1", "pretty-quick": "3.1.0" }, "engines": { @@ -4515,9 +4515,9 @@ } }, "node_modules/prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -9301,9 +9301,9 @@ "dev": true }, "prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true }, "pretty-quick": { diff --git a/package.json b/package.json index 890e4e283..7ef69a370 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "eslint-plugin-promise": "5.1.0", "eslint-plugin-require-path-exists": "1.1.9", "husky": "4.3.0", - "jsonschema": "^1.4.0", - "prettier": "2.1.2", + "jsonschema": "1.4.0", + "prettier": "2.5.1", "pretty-quick": "3.1.0" }, "husky": {