diff --git a/functions/index.js b/functions/index.js index 74524a594..778f4b657 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1170,6 +1170,30 @@ exports.testCompleted = functions } }); +exports.updateEmail = functions.https.onCall(async (request, response) => { + try { + let previousEmail = await admin.auth().getUser(request.uid); + + if (previousEmail.email !== request.previousEmail) { + return { resultCode: -1 }; + } else { + await admin.auth().updateUser(request.uid, { + email: request.newEmail, + emailVerified: false, + }); + return { + resultCode: 1, + }; + } + } catch (e) { + console.error(`error updating email for ${request.uid} - ${e}`); + return { + resultCode: -999, + message: e.message, + }; + } +}); + function updateDiscordRole(discordId, wpm) { db.collection("bot-commands").add({ command: "updateRole", diff --git a/src/js/account.js b/src/js/account.js index 1e9deda3e..79751939c 100644 --- a/src/js/account.js +++ b/src/js/account.js @@ -1504,9 +1504,11 @@ $( config.resultFilters.date.all = true; } else if ($(e.target).hasClass("noFilters")) { Object.keys(config.resultFilters).forEach((group) => { - Object.keys(config.resultFilters[group]).forEach((filter) => { - config.resultFilters[group][filter] = false; - }); + if (group !== "date") { + Object.keys(config.resultFilters[group]).forEach((filter) => { + config.resultFilters[group][filter] = false; + }); + } }); } else { if (e.shiftKey) { diff --git a/src/js/misc.js b/src/js/misc.js index c368243e6..ed45b605d 100644 --- a/src/js/misc.js +++ b/src/js/misc.js @@ -493,8 +493,7 @@ class SimplePopup { id, type, title, - inputPlaceholder = "", - inputVal = "", + inputs = [], text = "", buttonText = "Confirm", execFn @@ -503,8 +502,7 @@ class SimplePopup { this.type = type; this.execFn = execFn; this.title = title; - this.inputPlaceholder = inputPlaceholder; - this.inputVal = inputVal; + this.inputs = inputs; this.text = text; this.wrapper = $("#simplePopupWrapper"); this.element = $("#simplePopup"); @@ -513,7 +511,7 @@ class SimplePopup { reset() { this.element.html(`
- +
`); } @@ -527,21 +525,40 @@ class SimplePopup { el.find(".title").text(this.title); el.find(".text").text(this.text); - if (this.type === "number") { - el.find("input").removeClass("hidden"); - el.find("input").attr("placeholder", this.inputPlaceholder); - el.find("input").attr("min", 1); - el.find("input").val(this.inputVal); - } else { - el.find("input").addClass("hidden"); - } + this.initInputs(); el.find(".button").text(this.buttonText); } } + initInputs() { + let el = this.element; + if (this.inputs.length > 0) { + if (this.type === "number") { + this.inputs.forEach((input) => { + el.find(".inputs").append(` + + `); + }); + } else if (this.type === "text") { + this.inputs.forEach((input) => { + el.find(".inputs").append(` + + `); + }); + } + el.find(".inputs").removeClass("hidden"); + } else { + el.find(".inputs").addClass("hidden"); + } + } + exec() { - this.execFn($("#simplePopup").find("input").val()); + let vals = []; + $.each($("#simplePopup input"), (index, el) => { + vals.push($(el).val()); + }); + this.execFn(...vals); this.hide(); } @@ -551,7 +568,9 @@ class SimplePopup { .stop(true, true) .css("opacity", 0) .removeClass("hidden") - .animate({ opacity: 1 }, 125); + .animate({ opacity: 1 }, 125, () => { + $($("#simplePopup").find("input")[0]).focus(); + }); } hide() { @@ -582,14 +601,54 @@ $(document).on("click", "#simplePopupWrapper .button", (e) => { simplePopups[id].exec(); }); -// simplePopups.testPop = new SimplePopup( -// 'testPop', -// 'number', -// 'This is a test', -// 'Number', -// 1, -// 'Test popup that i made to test the class', -// 'Go', -// (a) => { -// console.log(a); -// }); +$(document).on("keyup", "#simplePopupWrapper input", (e) => { + if (e.key === "Enter") { + let id = $("#simplePopup").attr("popupId"); + simplePopups[id].exec(); + } +}); + +simplePopups.updateEmail = new SimplePopup( + "updateEmail", + "text", + "Update Email", + [ + { + placeholder: "Current email", + initVal: "", + }, + { + placeholder: "New email", + initVal: "", + }, + ], + "Don't mess this one up or you won't be able to login!", + "Update", + (previousEmail, newEmail) => { + try { + showBackgroundLoader(); + updateEmail({ + uid: firebase.auth().currentUser.uid, + previousEmail: previousEmail, + newEmail: newEmail, + }).then((data) => { + hideBackgroundLoader(); + if (data.data.resultCode === 1) { + showNotification("Email updated", 2000); + setTimeout(() => { + signOut(); + }, 1000); + } else if (data.data.resultCode === -1) { + showNotification("Current email doesn't match", 2000); + } else { + showNotification( + "Something went wrong: " + JSON.stringify(data.data), + 7000 + ); + } + }); + } catch (e) { + showNotification("Something went wrong: " + e, 5000); + } + } +); diff --git a/src/js/script.js b/src/js/script.js index 39112f0bc..ff0c21111 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -215,6 +215,7 @@ const saveLbMemory = firebase.functions().httpsCallable("saveLbMemory"); const unlinkDiscord = firebase.functions().httpsCallable("unlinkDiscord"); const verifyUser = firebase.functions().httpsCallable("verifyUser"); const reserveName = firebase.functions().httpsCallable("reserveDisplayName"); +const updateEmail = firebase.functions().httpsCallable("updateEmail"); function refreshThemeColorObject() { let st = getComputedStyle(document.body); @@ -4814,7 +4815,8 @@ $(document).keydown((event) => { config.quickTab && !$(".pageLogin").hasClass("active") && !resultCalculating && - $("#commandLineWrapper").hasClass("hidden") + $("#commandLineWrapper").hasClass("hidden") && + $("#simplePopupWrapper").hasClass("hidden") ) { event.preventDefault(); if ($(".pageTest").hasClass("active")) { @@ -4908,6 +4910,10 @@ $(document).keydown((event) => { if (!config.showAllLines || config.mode == "time") { // let currentTop = Math.floor($($("#words .word")[currentWordIndex]).position().top); // let nextTop = Math.floor($($("#words .word")[currentWordIndex + 1]).position().top); + if (config.stopOnError != "off") { + if (currentWord !== currentInput) return; + } + let currentTop = Math.floor( document.querySelectorAll("#words .word")[currentWordElementIndex] .offsetTop diff --git a/src/js/userconfig.js b/src/js/userconfig.js index d99e6bc66..a7aca7734 100644 --- a/src/js/userconfig.js +++ b/src/js/userconfig.js @@ -96,7 +96,7 @@ async function saveConfigToCookie(noDbCheck = false) { path: "/", }); restartCount = 0; - if (!noDbCheck) saveConfigToDB(); + if (!noDbCheck) await saveConfigToDB(); } async function saveConfigToDB() { @@ -638,7 +638,10 @@ function setEnableAds(val, nosave) { val = "off"; } config.enableAds = val; - if (!nosave) saveConfigToCookie(); + if (!nosave) + saveConfigToCookie().then(() => { + setTimeout(location.reload(), 500); + }); } //flip colors @@ -831,7 +834,7 @@ function changeTimeConfig(time, nosave) { time = 15; } time = parseInt(time); - changeMode("time", nosave); + if (!nosave) changeMode("time", nosave); config.time = time; $("#top .config .time .text-button").removeClass("active"); if (![15, 30, 60, 120].includes(time)) { @@ -865,7 +868,7 @@ function changeWordCount(wordCount, nosave) { wordCount = 10; } wordCount = parseInt(wordCount); - changeMode("words", nosave); + if (!nosave) changeMode("words", nosave); config.words = wordCount; $("#top .config .wordCount .text-button").removeClass("active"); if (![10, 25, 50, 100, 200].includes(wordCount)) { diff --git a/static/css/style.scss b/static/css/style.scss index 167a04ed6..c2889a7f0 100644 --- a/static/css/style.scss +++ b/static/css/style.scss @@ -481,6 +481,11 @@ a:hover { color: var(--sub-color); } + .inputs { + display: grid; + gap: 1rem; + } + .text { font-size: 1rem; color: var(--text-color); diff --git a/static/index.html b/static/index.html index e60fba1de..c160fb8fa 100644 --- a/static/index.html +++ b/static/index.html @@ -2744,7 +2744,10 @@

enable ads

If you wish to support me without directly donating you can - enable ads that will be visible at the bottom of the screen + enable ads that will be visible at the bottom of the screen. + Sellout mode also shows ads on both sides of the screen. +
+
(changes will take effect after a refresh).
@@ -2791,7 +2794,7 @@
-