diff --git a/functions/index.js b/functions/index.js index 711bf6299..8dd718551 100644 --- a/functions/index.js +++ b/functions/index.js @@ -2385,77 +2385,86 @@ async function checkLeaderboards( ["15", "60"].includes(String(resultObj.mode2)) && resultObj.language === "english" ) { - return await db.runTransaction(async (t) => { - const lbdoc = await t.get( - db - .collection("leaderboards") - .where("mode", "==", String(resultObj.mode)) - .where("mode2", "==", String(resultObj.mode2)) - .where("type", "==", type) - ); - let lbData; - let docid = `${String(resultObj.mode)}_${String( - resultObj.mode2 - )}_${type}`; - if (lbdoc.docs.length === 0) { - console.log( - `no ${resultObj.mode} ${resultObj.mode2} ${type} leaderboard found - creating` - ); - let toAdd = { - size: 20, - mode: String(resultObj.mode), - mode2: String(resultObj.mode2), - type: type, - }; - t.set( + return db + .runTransaction(async (t) => { + const lbdoc = await t.get( db .collection("leaderboards") - .doc( - `${String(resultObj.mode)}_${String(resultObj.mode2)}_${type}` - ), - toAdd + .where("mode", "==", String(resultObj.mode)) + .where("mode2", "==", String(resultObj.mode2)) + .where("type", "==", type) ); - lbData = toAdd; - } else { - lbData = lbdoc.docs[0].data(); - } - let boardInfo = lbData; - if ( - boardInfo.minWpm === undefined || - boardInfo.board.length !== boardInfo.size || - (boardInfo.minWpm !== undefined && - resultObj.wpm > boardInfo.minWpm && - boardInfo.board.length === boardInfo.size) - ) { - let boardData = lbData.board; - let lb = new Leaderboard( - boardInfo.size, - resultObj.mode, - resultObj.mode2, - boardInfo.type, - boardData - ); - let insertResult = lb.insert(resultObj); - - if (insertResult.insertedAt >= 0) { - t.update(db.collection("leaderboards").doc(docid), { - size: lb.size, - type: lb.type, - board: lb.board, - minWpm: lb.getMinWpm(), - }); + let lbData; + let docid = `${String(resultObj.mode)}_${String( + resultObj.mode2 + )}_${type}`; + if (lbdoc.docs.length === 0) { + console.log( + `no ${resultObj.mode} ${resultObj.mode2} ${type} leaderboard found - creating` + ); + let toAdd = { + size: 20, + mode: String(resultObj.mode), + mode2: String(resultObj.mode2), + type: type, + }; + t.set( + db + .collection("leaderboards") + .doc( + `${String(resultObj.mode)}_${String(resultObj.mode2)}_${type}` + ), + toAdd + ); + lbData = toAdd; + } else { + lbData = lbdoc.docs[0].data(); } + let boardInfo = lbData; + if ( + boardInfo.minWpm === undefined || + boardInfo.board.length !== boardInfo.size || + (boardInfo.minWpm !== undefined && + resultObj.wpm > boardInfo.minWpm && + boardInfo.board.length === boardInfo.size) + ) { + let boardData = lbData.board; + let lb = new Leaderboard( + boardInfo.size, + resultObj.mode, + resultObj.mode2, + boardInfo.type, + boardData + ); + let insertResult = lb.insert(resultObj); + if (insertResult.insertedAt >= 0) { + t.update(db.collection("leaderboards").doc(docid), { + size: lb.size, + type: lb.type, + board: lb.board, + minWpm: lb.getMinWpm(), + }); + } + + return { + insertedAt: insertResult, + }; + } else { + //not above leaderboard minwpm + return { + insertedAt: -999, + }; + } + }) + .catch((error) => { + console.error( + `error in transaction checking leaderboards - ${error}` + ); return { - insertedAt: insertResult, + insertedAt: null, }; - } else { - //not above leaderboard minwpm - return { - insertedAt: -999, - }; - } - }); + }); } else { return { insertedAt: null, diff --git a/gulpfile.js b/gulpfile.js index 236b4e43b..b9abd269c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -112,6 +112,7 @@ const refactoredSrc = [ "./src/js/account-icon.js", "./src/js/test/practise-missed.js", "./src/js/test/test-ui.js", + "./src/js/test/keymap.js", ]; //legacy files diff --git a/src/js/global-dependencies.js b/src/js/global-dependencies.js index 731f6695b..72de2f27d 100644 --- a/src/js/global-dependencies.js +++ b/src/js/global-dependencies.js @@ -40,3 +40,4 @@ import * as Focus from "./focus"; import * as AccountIcon from "./account-icon"; import * as PractiseMissed from "./practise-missed"; import * as TestUI from "./test-ui"; +import * as Keymap from "./keymap"; diff --git a/src/js/script.js b/src/js/script.js index a58ebf68e..8b9ac1b4f 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -371,9 +371,9 @@ async function initWords() { } //handle right-to-left languages if (language.leftToRight) { - arrangeCharactersLeftToRight(); + TestUI.arrangeCharactersLeftToRight(); } else { - arrangeCharactersRightToLeft(); + TestUI.arrangeCharactersRightToLeft(); } if (language.ligatures) { $("#words").addClass("withLigatures"); @@ -390,14 +390,6 @@ async function initWords() { // } } -function arrangeCharactersRightToLeft() { - $("#words").addClass("rightToLeftTest"); -} - -function arrangeCharactersLeftToRight() { - $("#words").removeClass("rightToLeftTest"); -} - function setToggleSettings(state, nosave) { setPunctuation(state, nosave); setNumbers(state, nosave); @@ -761,7 +753,12 @@ function showWords() { } if (Config.keymapMode === "next") { - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); } TestUI.updateActiveElement(); @@ -1097,162 +1094,6 @@ function updateTimer() { } } -function hideKeymap() { - $(".keymap").addClass("hidden"); - // $("#liveWpm").removeClass("lower"); -} - -function showKeymap() { - $(".keymap").removeClass("hidden"); - // $("#liveWpm").addClass("lower"); -} - -function flashPressedKeymapKey(key, correct) { - if (key == undefined) return; - switch (key) { - case "\\": - case "|": - key = "#KeyBackslash"; - break; - case "}": - case "]": - key = "#KeyRightBracket"; - break; - case "{": - case "[": - key = "#KeyLeftBracket"; - break; - case '"': - case "'": - key = "#KeyQuote"; - break; - case ":": - case ";": - key = "#KeySemicolon"; - break; - case "<": - case ",": - key = "#KeyComma"; - break; - case ">": - case ".": - key = "#KeyPeriod"; - break; - case "?": - case "/": - key = "#KeySlash"; - break; - case "" || "Space": - key = "#KeySpace"; - break; - default: - key = `#Key${key.toUpperCase()}`; - } - - if (key == "#KeySpace") { - key = ".key-split-space"; - } - - try { - if (correct || Config.blindMode) { - $(key) - .stop(true, true) - .css({ - color: ThemeColors.bg, - backgroundColor: ThemeColors.main, - borderColor: ThemeColors.main, - }) - .animate( - { - color: ThemeColors.sub, - backgroundColor: "transparent", - borderColor: ThemeColors.sub, - }, - 500, - "easeOutExpo" - ); - } else { - $(key) - .stop(true, true) - .css({ - color: ThemeColors.bg, - backgroundColor: ThemeColors.error, - borderColor: ThemeColors.error, - }) - .animate( - { - color: ThemeColors.sub, - backgroundColor: "transparent", - borderColor: ThemeColors.sub, - }, - 500, - "easeOutExpo" - ); - } - } catch (e) {} -} - -function updateHighlightedKeymapKey() { - try { - if ($(".active-key") != undefined) { - $(".active-key").removeClass("active-key"); - } - - var currentKey = wordsList[currentWordIndex] - .substring(currentInput.length, currentInput.length + 1) - .toString() - .toUpperCase(); - - let highlightKey; - switch (currentKey) { - case "\\": - case "|": - highlightKey = "#KeyBackslash"; - break; - case "}": - case "]": - highlightKey = "#KeyRightBracket"; - break; - case "{": - case "[": - highlightKey = "#KeyLeftBracket"; - break; - case '"': - case "'": - highlightKey = "#KeyQuote"; - break; - case ":": - case ";": - highlightKey = "#KeySemicolon"; - break; - case "<": - case ",": - highlightKey = "#KeyComma"; - break; - case ">": - case ".": - highlightKey = "#KeyPeriod"; - break; - case "?": - case "/": - highlightKey = "#KeySlash"; - break; - case "": - highlightKey = "#KeySpace"; - break; - default: - highlightKey = `#Key${currentKey}`; - } - - $(highlightKey).addClass("active-key"); - if (highlightKey === "#KeySpace") { - $("#KeySpace2").addClass("active-key"); - } - } catch (e) { - console.log("could not update highlighted keymap key: " + e.message); - } -} - function countChars() { let correctWordChars = 0; let correctChars = 0; @@ -1423,7 +1264,7 @@ function showResult(difficultyFailed = false) { hideLiveWpm(); hideLiveAcc(); hideTimer(); - hideKeymap(); + Keymap.hide(); let stats = calculateStats(); if (stats === undefined) { stats = { @@ -2476,7 +2317,12 @@ function startTest() { } setLayout(layouts[index]); setKeymapLayout(layouts[index]); - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); settingsGroups.layout.updateButton(); } @@ -2675,9 +2521,9 @@ function restartTest(withSameWordset = false, nosave = false, event) { sameWordset = false; } if (Config.keymapMode !== "off") { - showKeymap(); + Keymap.show(); } else { - hideKeymap(); + Keymap.hide(); } document.querySelector("#miniTimerAndLiveWpm .wpm").innerHTML = "0"; document.querySelector("#miniTimerAndLiveWpm .acc").innerHTML = "100%"; @@ -2730,7 +2576,12 @@ function restartTest(withSameWordset = false, nosave = false, event) { settingsGroups.layout.updateButton(); setKeymapLayout("qwerty"); settingsGroups.keymapLayout.updateButton(); - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); } $("#result").addClass("hidden"); @@ -4477,9 +4328,14 @@ function handleBackspace(event) { } Sound.playClick(Config.playSoundOnClick); if (Config.keymapMode === "react") { - flashPressedKeymapKey(event.code, true); + Keymap.flashKey(event.code, true); } else if (Config.keymapMode === "next") { - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); } Caret.updatePosition(currentInput); } @@ -4508,7 +4364,12 @@ function handleSpace(event, isEnter) { } setLayout(layouts[index]); setKeymapLayout(layouts[index]); - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); settingsGroups.layout.updateButton(); } dontInsertSpace = true; @@ -4637,9 +4498,14 @@ function handleSpace(event, isEnter) { Caret.updatePosition(currentInput); if (Config.keymapMode === "react") { - flashPressedKeymapKey(event.code, true); + Keymap.flashKey(event.code, true); } else if (Config.keymapMode === "next") { - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); } if ( Config.mode === "words" || @@ -4925,9 +4791,14 @@ function handleAlpha(event) { //keymap if (Config.keymapMode === "react") { - flashPressedKeymapKey(event.key, thisCharCorrect); + Keymap.flashKey(event.key, thisCharCorrect); } else if (Config.keymapMode === "next") { - updateHighlightedKeymapKey(); + Keymap.highlightKey( + wordsList[currentWordIndex] + .substring(currentInput.length, currentInput.length + 1) + .toString() + .toUpperCase() + ); } let activeWordTopBeforeJump = TestUI.activeWordTop; diff --git a/src/js/test/keymap.js b/src/js/test/keymap.js new file mode 100644 index 000000000..9a43b6776 --- /dev/null +++ b/src/js/test/keymap.js @@ -0,0 +1,250 @@ +import Config from "./config"; +import * as ThemeColors from "./theme-colors"; +import layouts from "./layouts"; + +//TODO remove after wordslist and currentinput and current word index are in a module +export function highlightKey(currentKey) { + try { + if ($(".active-key") != undefined) { + $(".active-key").removeClass("active-key"); + } + + // var currentKey = wordsList[currentWordIndex] + // .substring(currentInput.length, currentInput.length + 1) + // .toString() + // .toUpperCase(); + + let highlightKey; + switch (currentKey) { + case "\\": + case "|": + highlightKey = "#KeyBackslash"; + break; + case "}": + case "]": + highlightKey = "#KeyRightBracket"; + break; + case "{": + case "[": + highlightKey = "#KeyLeftBracket"; + break; + case '"': + case "'": + highlightKey = "#KeyQuote"; + break; + case ":": + case ";": + highlightKey = "#KeySemicolon"; + break; + case "<": + case ",": + highlightKey = "#KeyComma"; + break; + case ">": + case ".": + highlightKey = "#KeyPeriod"; + break; + case "?": + case "/": + highlightKey = "#KeySlash"; + break; + case "": + highlightKey = "#KeySpace"; + break; + default: + highlightKey = `#Key${currentKey}`; + } + + $(highlightKey).addClass("active-key"); + if (highlightKey === "#KeySpace") { + $("#KeySpace2").addClass("active-key"); + } + } catch (e) { + console.log("could not update highlighted keymap key: " + e.message); + } +} + +export function flashKey(key, correct) { + if (key == undefined) return; + switch (key) { + case "\\": + case "|": + key = "#KeyBackslash"; + break; + case "}": + case "]": + key = "#KeyRightBracket"; + break; + case "{": + case "[": + key = "#KeyLeftBracket"; + break; + case '"': + case "'": + key = "#KeyQuote"; + break; + case ":": + case ";": + key = "#KeySemicolon"; + break; + case "<": + case ",": + key = "#KeyComma"; + break; + case ">": + case ".": + key = "#KeyPeriod"; + break; + case "?": + case "/": + key = "#KeySlash"; + break; + case "" || "Space": + key = "#KeySpace"; + break; + default: + key = `#Key${key.toUpperCase()}`; + } + + if (key == "#KeySpace") { + key = ".key-split-space"; + } + + try { + if (correct || Config.blindMode) { + $(key) + .stop(true, true) + .css({ + color: ThemeColors.bg, + backgroundColor: ThemeColors.main, + borderColor: ThemeColors.main, + }) + .animate( + { + color: ThemeColors.sub, + backgroundColor: "transparent", + borderColor: ThemeColors.sub, + }, + 500, + "easeOutExpo" + ); + } else { + $(key) + .stop(true, true) + .css({ + color: ThemeColors.bg, + backgroundColor: ThemeColors.error, + borderColor: ThemeColors.error, + }) + .animate( + { + color: ThemeColors.sub, + backgroundColor: "transparent", + borderColor: ThemeColors.sub, + }, + 500, + "easeOutExpo" + ); + } + } catch (e) {} +} + +export function hide() { + $(".keymap").addClass("hidden"); +} + +export function show() { + $(".keymap").removeClass("hidden"); +} + +//TODO remove setkeymaplayout after userconfig is a module +export function refreshKeys(layout, setKeymapLayout) { + try { + let lts = layouts[layout]; //layout to show + let layoutString = layout; + if (Config.keymapLayout === "overrideSync") { + if (Config.layout === "default") { + lts = layouts["qwerty"]; + layoutString = "default"; + } else { + lts = layouts[Config.layout]; + layoutString = Config.layout; + } + } + + if (lts.keymapShowTopRow) { + $(".keymap .r1").removeClass("hidden"); + } else { + $(".keymap .r1").addClass("hidden"); + } + + $($(".keymap .r5 .keymap-key .letter")[0]).text( + layoutString.replace(/_/g, " ") + ); + + if (lts.iso) { + $(".keymap .r4 .keymap-key.first").removeClass("hidden-key"); + } else { + $(".keymap .r4 .keymap-key.first").addClass("hidden-key"); + } + + var toReplace = lts.keys.slice(1, 48); + var count = 0; + + $(".keymap .letter") + .map(function () { + if (count < toReplace.length) { + var key = toReplace[count].charAt(0); + this.innerHTML = key; + + switch (key) { + case "\\": + case "|": + this.parentElement.id = "KeyBackslash"; + break; + case "}": + case "]": + this.parentElement.id = "KeyRightBracket"; + break; + case "{": + case "[": + this.parentElement.id = "KeyLeftBracket"; + break; + case '"': + case "'": + this.parentElement.id = "KeyQuote"; + break; + case ":": + case ";": + this.parentElement.id = "KeySemicolon"; + break; + case "<": + case ",": + this.parentElement.id = "KeyComma"; + break; + case ">": + case ".": + this.parentElement.id = "KeyPeriod"; + break; + case "?": + case "/": + this.parentElement.id = "KeySlash"; + break; + case "": + this.parentElement.id = "KeySpace"; + break; + default: + this.parentElement.id = `Key${key.toUpperCase()}`; + } + } + count++; + // } + }) + .get(); + } catch (e) { + console.log( + "something went wrong when changing layout, resettings: " + e.message + ); + setKeymapLayout("qwerty", true); + } +} diff --git a/src/js/test/test-ui.js b/src/js/test/test-ui.js index 6f5489cc6..1f3d2a4cd 100644 --- a/src/js/test/test-ui.js +++ b/src/js/test/test-ui.js @@ -348,6 +348,14 @@ export function updateModesNotice( } } +export function arrangeCharactersRightToLeft() { + $("#words").addClass("rightToLeftTest"); +} + +export function arrangeCharactersLeftToRight() { + $("#words").removeClass("rightToLeftTest"); +} + $(document.body).on("click", "#copyResultToClipboardButton", () => { screenshot(); }); diff --git a/src/js/userconfig.js b/src/js/userconfig.js index 51925b334..d8070c3c3 100644 --- a/src/js/userconfig.js +++ b/src/js/userconfig.js @@ -1087,7 +1087,7 @@ function setLayout(layout, nosave) { ConfigSet.layout(layout); TestUI.updateModesNotice(sameWordset, textHasTab, paceCaret, activeFunbox); if (Config.keymapLayout === "overrideSync") { - refreshKeymapKeys(Config.keymapLayout); + Keymap.refreshKeys(Config.keymapLayout, setKeymapLayout); } if (!nosave) saveConfigToCookie(); } @@ -1131,109 +1131,15 @@ function setKeymapStyle(style, nosave) { if (!nosave) saveConfigToCookie(); } -function keymapShowIsoKey(tf) { - if (tf) { - $(".keymap .r4 .keymap-key.first").removeClass("hidden-key"); - } else { - $(".keymap .r4 .keymap-key.first").addClass("hidden-key"); - } -} - function setKeymapLayout(layout, nosave) { if (layout == null || layout == undefined) { layout = "qwerty"; } ConfigSet.keymapLayout(layout); - refreshKeymapKeys(layout); + Keymap.refreshKeys(layout, setKeymapLayout); if (!nosave) saveConfigToCookie(); } -function refreshKeymapKeys(layout) { - try { - let lts = layouts[layout]; //layout to show - let layoutString = layout; - if (Config.keymapLayout === "overrideSync") { - if (Config.layout === "default") { - lts = layouts["qwerty"]; - layoutString = "default"; - } else { - lts = layouts[Config.layout]; - layoutString = Config.layout; - } - } - - if (lts.keymapShowTopRow) { - $(".keymap .r1").removeClass("hidden"); - } else { - $(".keymap .r1").addClass("hidden"); - } - - $($(".keymap .r5 .keymap-key .letter")[0]).text( - layoutString.replace(/_/g, " ") - ); - keymapShowIsoKey(lts.iso); - - var toReplace = lts.keys.slice(1, 48); - var count = 0; - - $(".keymap .letter") - .map(function () { - if (count < toReplace.length) { - var key = toReplace[count].charAt(0); - this.innerHTML = key; - - switch (key) { - case "\\": - case "|": - this.parentElement.id = "KeyBackslash"; - break; - case "}": - case "]": - this.parentElement.id = "KeyRightBracket"; - break; - case "{": - case "[": - this.parentElement.id = "KeyLeftBracket"; - break; - case '"': - case "'": - this.parentElement.id = "KeyQuote"; - break; - case ":": - case ";": - this.parentElement.id = "KeySemicolon"; - break; - case "<": - case ",": - this.parentElement.id = "KeyComma"; - break; - case ">": - case ".": - this.parentElement.id = "KeyPeriod"; - break; - case "?": - case "/": - this.parentElement.id = "KeySlash"; - break; - case "": - this.parentElement.id = "KeySpace"; - break; - default: - this.parentElement.id = `Key${key.toUpperCase()}`; - } - } - count++; - // } - }) - .get(); - } catch (e) { - console.log( - "something went wrong when changing layout, resettings: " + e.message - ); - setKeymapLayout("qwerty", true); - } -} - function setFontSize(fontSize, nosave) { if (fontSize == null || fontSize == undefined) { fontSize = 1;