diff --git a/functions/index.js b/functions/index.js index 367e883b1..3b5b6b8de 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1477,12 +1477,12 @@ exports.addTag = functions.https.onCall((request, response) => { console.error( `error while creating tag for user ${request.uid}: ${e.message}` ); - return { resultCode: -999 }; + return { resultCode: -999, message: e.message }; }); } } catch (e) { console.error(`error adding tag for ${request.uid} - ${e}`); - return { resultCode: -999 }; + return { resultCode: -999, message: e.message }; } }); @@ -1507,12 +1507,12 @@ exports.editTag = functions.https.onCall((request, response) => { console.error( `error while updating tag for user ${request.uid}: ${e.message}` ); - return { resultCode: -999 }; + return { resultCode: -999, message: e.message }; }); } } catch (e) { console.error(`error updating tag for ${request.uid} - ${e}`); - return { resultCode: -999 }; + return { resultCode: -999, message: e.message }; } }); @@ -1573,7 +1573,7 @@ exports.updateResultTags = functions.https.onCall((request, response) => { } } catch (e) { console.error(`error updating tags by ${request.uid} - ${e}`); - return { resultCode: -999 }; + return { resultCode: -999, message: e }; } }); diff --git a/gulpfile.js b/gulpfile.js index e4f1bda03..e73ad8398 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -93,6 +93,7 @@ const refactoredSrc = [ "./src/js/layouts.js", "./src/js/monkey.js", "./src/js/result-filters.js", + "./src/js/notification-center.js", ]; //legacy files diff --git a/src/js/account.js b/src/js/account.js index 73c993957..c646a1ff9 100644 --- a/src/js/account.js +++ b/src/js/account.js @@ -24,7 +24,7 @@ function signIn() { changePage("test"); }) .catch(function (error) { - Misc.showNotification(error.message, 5000); + Notifications.add(error.message, -1); $(".pageLogin .preloader").addClass("hidden"); }); }); @@ -41,7 +41,7 @@ function signIn() { changePage("test"); }) .catch(function (error) { - Misc.showNotification(error.message, 5000); + Notifications.add(error.message, -1); $(".pageLogin .preloader").addClass("hidden"); }); }); @@ -59,7 +59,7 @@ function signUp() { let passwordVerify = $(".pageLogin .register input")[3].value; if (password != passwordVerify) { - Misc.showNotification("Passwords do not match", 3000); + Notifications.add("Passwords do not match", 0, 3); $(".pageLogin .preloader").addClass("hidden"); $(".pageLogin .register .button").removeClass("disabled"); return; @@ -67,14 +67,14 @@ function signUp() { CloudFunctions.namecheck({ name: nname }).then((d) => { if (d.data.resultCode === -1) { - Misc.showNotification("Name unavailable", 3000); + Notifications.add("Name unavailable", -1); $(".pageLogin .preloader").addClass("hidden"); $(".pageLogin .register .button").removeClass("disabled"); return; } else if (d.data.resultCode === -2) { - Misc.showNotification( + Notifications.add( "Name cannot contain special characters or contain more than 14 characters. Can include _ . and -", - 8000 + -1 ); $(".pageLogin .preloader").addClass("hidden"); $(".pageLogin .register .button").removeClass("disabled"); @@ -106,7 +106,7 @@ function signUp() { ); usr.sendEmailVerification(); clearGlobalStats(); - Misc.showNotification("Account created", 2000); + Notifications.add("Account created", 1, 3); $("#menu .icon-button.account .text").text(nname); try { firebase.analytics().logEvent("accountCreated", usr.uid); @@ -144,15 +144,19 @@ function signUp() { .delete() .then(function () { // User deleted. - Misc.showNotification( - "An error occured. Account not created.", - 2000 + Notifications.add( + "Account not created. " + error.message, + -1 ); $(".pageLogin .preloader").addClass("hidden"); }) .catch(function (error) { // An error happened. $(".pageLogin .preloader").addClass("hidden"); + Notifications.add( + "Something went wrong. " + error.message, + -1 + ); console.error(error); }); }); @@ -160,15 +164,13 @@ function signUp() { .catch(function (error) { // Handle Errors here. $(".pageLogin .register .button").removeClass("disabled"); - var errorMessage = error.message; - Misc.showNotification(errorMessage, 5000); + Notifications.add(error.message, -1); $(".pageLogin .preloader").addClass("hidden"); }); } else { - console.error(d.data.message); - Misc.showNotification( + Notifications.add( "Something went wrong when checking name: " + d.data.message, - 5000 + -1 ); } }); @@ -179,7 +181,7 @@ function signOut() { .auth() .signOut() .then(function () { - Misc.showNotification("Signed out", 2000); + Notifications.add("Signed out", 0, 2); clearGlobalStats(); hideAccountSettingsSection(); updateAccountLoginButton(); @@ -187,7 +189,7 @@ function signOut() { db_setSnapshot(null); }) .catch(function (error) { - Misc.showNotification(error.message, 5000); + Notifications.add(error.message, -1); }); } @@ -227,13 +229,15 @@ firebase.auth().onAuthStateChanged(function (user) { $(".pageAccount .group.createdDate").text(text); if (verifyUserWhenLoggedIn !== null) { - Misc.showNotification("Verifying", 1000); + Notifications.add("Verifying", 0, 3); verifyUserWhenLoggedIn.uid = user.uid; CloudFunctions.verifyUser(verifyUserWhenLoggedIn).then((data) => { - Misc.showNotification(data.data.message, 3000); if (data.data.status === 1) { + Notifications.add(data.data.message, 1); db_getSnapshot().discordId = data.data.did; updateDiscordSettingsSection(); + } else { + Notifications.add(data.data.message, -1); } }); } @@ -243,11 +247,11 @@ firebase.auth().onAuthStateChanged(function (user) { try { theme = theme.split(","); config.customThemeColors = theme; - Misc.showNotification("Custom theme applied.", 1000); + Notifications.add("Custom theme applied.", 1); } catch (e) { - Misc.showNotification( + Notifications.add( "Something went wrong. Reverting to default custom colors.", - 3000 + 0 ); config.customThemeColors = defaultConfig.customThemeColors; } @@ -372,9 +376,9 @@ function getAccountDataAndInit() { .catch((e) => { accountIconLoading(false); console.error(e); - Misc.showNotification( - "Error downloading user data. Refresh to try again. If error persists contact Miodec.", - 5000 + Notifications.add( + "Error downloading user data - refresh to try again. Client likely could not connect to the backend, if error persists contact Miodec.", + -1 ); $("#top #menu .account .icon").html(''); $("#top #menu .account").css("opacity", 1); @@ -1010,9 +1014,9 @@ function toggleFilter(group, filter) { ResultFilters.toggleFilter(group, filter); ResultFilters.save(); } catch (e) { - Misc.showNotification( + Notifications.add( "Something went wrong toggling filter. Reverting to defaults", - 3000 + 0 ); console.log("toggling filter error"); console.error(e); @@ -1857,9 +1861,9 @@ function refreshAccountPage() { filteredResults.push(result); } catch (e) { - Misc.showNotification( + Notifications.add( "Something went wrong when filtering. Resetting filters.", - 5000 + 0 ); console.log(result); console.error(e); @@ -2212,7 +2216,7 @@ function refreshAccountPage() { swapElements($(".pageAccount .preloader"), $(".pageAccount .content"), 250); } if (db_getSnapshot() === null) { - Misc.showNotification(`Missing account data. Please refresh.`, 5000); + Notifications.add(`Missing account data. Please refresh.`, -1); $(".pageAccount .preloader").html("Missing account data. Please refresh."); } else if (db_getSnapshot().results === undefined) { db_getUserResults().then((d) => { @@ -2230,7 +2234,7 @@ function refreshAccountPage() { cont(); } catch (e) { console.error(e); - Misc.showNotification(`Something went wrong: ${e}`, 5000); + Notifications.add(`Something went wrong: ${e}`, -1); } } } @@ -2332,7 +2336,7 @@ $("#resultEditTagsPanel .confirmButton").click((f) => { }).then((r) => { hideBackgroundLoader(); if (r.data.resultCode === 1) { - Misc.showNotification("Tags updated.", 3000); + Notifications.add("Tags updated.", 1, 2); db_getSnapshot().results.forEach((result) => { if (result.id === resultid) { result.tags = newtags; @@ -2383,7 +2387,7 @@ $("#resultEditTagsPanel .confirmButton").click((f) => { ); } } else { - Misc.showNotification("Error updating tags", 3000); + Notifications.add("Error updating tags: " + r.data.message, -1); } }); }); @@ -2431,11 +2435,11 @@ $(".pageLogin #forgotPasswordButton").click((e) => { .sendPasswordResetEmail(email) .then(function () { // Email sent. - Misc.showNotification("Email sent", 2000); + Notifications.add("Email sent", 1, 2); }) .catch(function (error) { // An error happened. - Misc.showNotification(error.message, 5000); + Notifications.add(error.message, -1); }); } }); diff --git a/src/js/commandline.js b/src/js/commandline.js index 754729317..e5ecd9a0c 100644 --- a/src/js/commandline.js +++ b/src/js/commandline.js @@ -880,7 +880,7 @@ let commandsEnableAds = { display: "off", exec: () => { setEnableAds("off"); - Misc.showNotification("Don't forget to refresh the page!", 3000); + Notifications.add("Don't forget to refresh the page!", 0); }, }, { @@ -888,7 +888,7 @@ let commandsEnableAds = { display: "on", exec: () => { setEnableAds("on"); - Misc.showNotification("Don't forget to refresh the page!", 3000); + Notifications.add("Don't forget to refresh the page!", 0); }, }, { @@ -896,7 +896,7 @@ let commandsEnableAds = { display: "Sellout", exec: () => { setEnableAds("max"); - Misc.showNotification("Don't forget to refresh the page!", 3000); + Notifications.add("Don't forget to refresh the page!", 0); }, }, ], diff --git a/src/js/exports.js b/src/js/exports.js index 8f8082626..369fd5ce6 100644 --- a/src/js/exports.js +++ b/src/js/exports.js @@ -7,3 +7,4 @@ global.sendVerificationEmail = Misc.sendVerificationEmail; //these exports are just for debugging in the browser global.snapshot = db_getSnapshot; global.config = config; +global.addnotif = Notifications.add; diff --git a/src/js/global-dependencies.js b/src/js/global-dependencies.js index dc414488a..2ce2dfd6a 100644 --- a/src/js/global-dependencies.js +++ b/src/js/global-dependencies.js @@ -25,4 +25,5 @@ import * as Misc from "./misc"; import * as CloudFunctions from "./cloud-functions"; import layouts from "./layouts"; import * as Monkey from "./monkey"; +import * as Notifications from "./notification-center"; import * as ResultFilters from "./result-filters"; diff --git a/src/js/leaderboards.js b/src/js/leaderboards.js index bbfe21874..f260905aa 100644 --- a/src/js/leaderboards.js +++ b/src/js/leaderboards.js @@ -217,7 +217,7 @@ function updateLeaderboards() { } }) .catch((e) => { - Misc.showNotification("Something went wrong", 3000); + Notifications.add("Something went wrong", -1); }); } diff --git a/src/js/notification-center.js b/src/js/notification-center.js new file mode 100644 index 000000000..c0f3be1fe --- /dev/null +++ b/src/js/notification-center.js @@ -0,0 +1,131 @@ +const notificationHistory = []; +let id = 0; +class Notification { + constructor(message, level, duration, customTitle, customIcon) { + this.message = message; + this.level = level; + if (duration == undefined) { + if (level === -1) { + this.duration = 0; + } else { + this.duration = 3000; + } + } else { + this.duration = duration * 1000; + } + this.customTitle = customTitle; + this.customIcon = customIcon; + this.id = id++; + } + //level + //0 - notice + //1 - good + //-1 - bad + show() { + let cls = "notice"; + let icon = ``; + let title = "Notice"; + if (this.level === 1) { + cls = "good"; + icon = ``; + title = "Success"; + } else if (this.level === -1) { + cls = "bad"; + icon = ``; + title = "Error"; + console.error(this.message); + } + + if (this.customTitle != undefined) { + title = this.customTitle; + } + + if (this.customIcon != undefined) { + icon = ``; + } + + // moveCurrentToHistory(); + let oldHeight = $("#notificationCenter .history").height(); + $("#notificationCenter .history").prepend(` + +
+
${icon}
+
${title}
${this.message}
+
+ + `); + let newHeight = $("#notificationCenter .history").height(); + $(`#notificationCenter .notif[id='${this.id}']`).remove(); + $("#notificationCenter .history") + .css("margin-top", 0) + .animate( + { + marginTop: newHeight - oldHeight, + }, + 125, + () => { + $("#notificationCenter .history").css("margin-top", 0); + $("#notificationCenter .history").prepend(` + +
+
${icon}
+
${title}
${this.message}
+
+ + `); + $(`#notificationCenter .notif[id='${this.id}']`) + .css("opacity", 0) + .animate( + { + opacity: 1, + }, + 125, + () => { + $(`#notificationCenter .notif[id='${this.id}']`).css( + "opacity", + "" + ); + } + ); + $(`#notificationCenter .notif[id='${this.id}']`).click((e) => { + this.hide(); + }); + } + ); + if (this.duration > 0) { + setTimeout(() => { + this.hide(); + }, this.duration + 250); + } + $(`#notificationCenter .notif[id='${this.id}']`).hover((e) => { + $(`#notificationCenter .notif[id='${this.id}']`).toggleClass("hover"); + }); + } + hide() { + $(`#notificationCenter .notif[id='${this.id}']`) + .css("opacity", 1) + .animate( + { + opacity: 0, + }, + 125, + () => { + $(`#notificationCenter .notif[id='${this.id}']`).animate( + { + height: 0, + }, + 125, + () => { + $(`#notificationCenter .notif[id='${this.id}']`).remove(); + } + ); + } + ); + } +} + +export function add(message, level, duration, customTitle, customIcon) { + notificationHistory.push( + new Notification(message, level, duration, customTitle, customIcon).show() + ); +} diff --git a/src/js/script.js b/src/js/script.js index 80485b7c0..c32fdb163 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -259,7 +259,7 @@ function copyResultToClipboard() { ]) .then((f) => { $(".notification").removeClass("hidden"); - Misc.showNotification("Copied to clipboard", 1000); + Notifications.add("Copied to clipboard", 1, 2); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -268,7 +268,10 @@ function copyResultToClipboard() { .catch((f) => { open(URL.createObjectURL(blob)); $(".notification").removeClass("hidden"); - Misc.showNotification("Error saving image to clipboard", 2000); + Notifications.add( + "Error saving image to clipboard: " + f.message, + -1 + ); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -277,7 +280,10 @@ function copyResultToClipboard() { } catch (e) { open(URL.createObjectURL(blob)); $(".notification").removeClass("hidden"); - Misc.showNotification("Error saving image to clipboard", 2000); + Notifications.add( + "Error saving image to clipboard: " + e.message, + -1 + ); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -287,7 +293,7 @@ function copyResultToClipboard() { }); } catch (e) { $(".notification").removeClass("hidden"); - Misc.showNotification("Error creating image", 2000); + Notifications.add("Error creating image: " + e.message, -1); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -297,17 +303,17 @@ function copyResultToClipboard() { async function activateFunbox(funbox, mode) { if (testActive || resultVisible) { - Misc.showNotification( + Notifications.add( "You can only change the funbox before starting a test.", - 4000 + 0 ); return false; } if (Misc.getCurrentLanguage().ligatures) { if (funbox == "choo_choo" || funbox == "earthquake") { - Misc.showNotification( + Notifications.add( "Current language does not support this funbox mode", - 3000 + 0 ); activateFunbox("none", null); return; @@ -473,20 +479,20 @@ async function initWords() { quotes.quotes = []; } catch (e) { console.error(e); - Misc.showNotification( + Notifications.add( `No ${config.language.replace(/_\d*k$/g, "")} quotes found`, - 3000 + 0 ); return; } }, error: (e) => { - Misc.showNotification( + Notifications.add( `Error while loading ${config.language.replace( /_\d*k$/g, "" )} quotes: ${e}`, - 5000 + -1 ); return; }, @@ -1000,26 +1006,6 @@ function showWords() { updateCaretPosition(); } -$("#restartTestButton, #startTestButton").on("click", function () { - if (activeFunBox === "memory") { - memoryFunboxInterval = clearInterval(memoryFunboxInterval); - memoryFunboxTimer = Math.round(Math.pow(wordsList.length, 1.2)); - memoryFunboxInterval = setInterval(() => { - memoryFunboxTimer -= 1; - Misc.showNotification(memoryFunboxTimer); - if (memoryFunboxTimer < 0) { - memoryFunboxInterval = clearInterval(memoryFunboxInterval); - memoryFunboxTimer = null; - $("#wordsWrapper").addClass("hidden"); - } - }, 1000); - - if (config.keymapMode === "next") { - setKeymapMode("react"); - } - } -}); - (function (history) { var pushState = history.pushState; history.pushState = function (state) { @@ -2081,11 +2067,11 @@ function showResult(difficultyFailed = false) { if (bailout) afkDetected = false; if (difficultyFailed) { - Misc.showNotification("Test failed", 2000); + Notifications.add("Test failed", 0); } else if (afkDetected) { - Misc.showNotification("Test invalid - AFK detected", 2000); + Notifications.add("Test invalid - AFK detected", 0); } else if (sameWordset) { - Misc.showNotification("Test invalid - repeated", 2000); + Notifications.add("Test invalid - repeated", 0); } else { let activeTags = []; let activeTagsIds = []; @@ -2299,35 +2285,35 @@ function showResult(difficultyFailed = false) { .then((e) => { accountIconLoading(false); if (e.data == null) { - Misc.showNotification( - "Unexpected response from the server.", - 4000 + Notifications.add( + "Unexpected response from the server: " + e.data, + -1 ); return; } if (e.data.resultCode === -1) { - Misc.showNotification("Could not save result", 3000); + Notifications.add("Could not save result", -1); } else if (e.data.resultCode === -2) { - Misc.showNotification( + Notifications.add( "Possible bot detected. Result not saved.", - 4000 + -1 ); } else if (e.data.resultCode === -3) { - Misc.showNotification( + Notifications.add( "Could not verify keypress stats. Result not saved.", - 4000 + -1 ); } else if (e.data.resultCode === -4) { - Misc.showNotification( + Notifications.add( "Result data does not make sense. Result not saved.", - 4000 + -1 ); } else if (e.data.resultCode === -999) { console.error("internal error: " + e.data.message); - Misc.showNotification( + Notifications.add( "Internal error. Result might not be saved. " + e.data.message, - 6000 + -1 ); } else if (e.data.resultCode === 1 || e.data.resultCode === 2) { completedEvent.id = e.data.createdId; @@ -2500,7 +2486,7 @@ function showResult(difficultyFailed = false) { // }).then((d) => { // if (d.data.returnCode === 1) { // } else { - // Misc.showNotification( + // Notifications.add( // `Error saving lb memory ${d.data.message}`, // 4000 // ); @@ -2552,7 +2538,7 @@ function showResult(difficultyFailed = false) { } else if (e.data.resultCode === 1) { hideCrown(); // if (localPb) { - // Misc.showNotification( + // Notifications.add( // "Local PB data is out of sync! Refresh the page to resync it or contact Miodec on Discord.", // 15000 // ); @@ -2562,7 +2548,7 @@ function showResult(difficultyFailed = false) { }) .catch((e) => { console.error(e); - Misc.showNotification("Could not save result. " + e, 5000); + Notifications.add("Could not save result. " + e, -1); }); }); }); @@ -2575,7 +2561,7 @@ function showResult(difficultyFailed = false) { notSignedInLastResult = completedEvent; } } else { - Misc.showNotification("Test invalid", 3000); + Notifications.add("Test invalid", 0); testInvalid = true; try { firebase.analytics().logEvent("testCompletedInvalid", completedEvent); @@ -2776,23 +2762,23 @@ function startTest() { time == Math.floor(config.time / 3) - 3 || time == (config.time / 3) * 2 - 3 ) { - Misc.showNotification("3", 1000); + Notifications.add("3", 0, 1); } if ( time == Math.floor(config.time / 3) - 2 || time == Math.floor(config.time / 3) * 2 - 2 ) { - Misc.showNotification("2", 1000); + Notifications.add("2", 0, 1); } if ( time == Math.floor(config.time / 3) - 1 || time == Math.floor(config.time / 3) * 2 - 1 ) { - Misc.showNotification("1", 1000); + Notifications.add("1", 0, 1); } if (config.layout !== layouts[index] && layouts[index] !== undefined) { - Misc.showNotification(`--- !!! ${layouts[index]} !!! ---`, 3000); + Notifications.add(`--- !!! ${layouts[index]} !!! ---`, 0); } setLayout(layouts[index]); setKeymapLayout(layouts[index]); @@ -2853,9 +2839,10 @@ function restartTest(withSameWordset = false, nosave = false) { ) { } else { if (testActive) { - Misc.showNotification( + Notifications.add( "Restart disabled for long tests. Use your mouse to confirm.", - 4000 + 0, + 4 ); return; } @@ -2863,7 +2850,7 @@ function restartTest(withSameWordset = false, nosave = false) { } if (modeBeforePractise !== null && !withSameWordset) { - Misc.showNotification("Reverting to previous settings.", 1500); + Notifications.add("Reverting to previous settings.", 0); setMode(modeBeforePractise); setPunctuation(punctuationBeforePractise); setNumbers(numbersBeforePractise); @@ -2971,6 +2958,28 @@ function restartTest(withSameWordset = false, nosave = false) { document.querySelector("#liveWpm").innerHTML = "0"; document.querySelector("#liveAcc").innerHTML = "100%"; + if (activeFunBox === "memory") { + memoryFunboxInterval = clearInterval(memoryFunboxInterval); + memoryFunboxTimer = Math.round(Math.pow(wordsList.length, 1.2)); + memoryFunboxInterval = setInterval(() => { + memoryFunboxTimer -= 1; + Notifications.add( + memoryFunboxTimer == 0 ? "Times up" : memoryFunboxTimer, + 0, + 1 + ); + if (memoryFunboxTimer <= 0) { + memoryFunboxInterval = clearInterval(memoryFunboxInterval); + memoryFunboxTimer = null; + $("#wordsWrapper").addClass("hidden"); + } + }, 1000); + + if (config.keymapMode === "next") { + setKeymapMode("react"); + } + } + let mode2 = ""; if (config.mode === "time") { mode2 = config.time; @@ -3037,10 +3046,7 @@ function setCustomText() { customText = customText.replace(/ +/gm, " "); customText = customText.split(" "); if (customText.length >= 10000) { - Misc.showNotification( - "Custom text cannot be longer than 10000 words.", - 4000 - ); + Notifications.add("Custom text cannot be longer than 10000 words.", 0); setMode("time"); customText = "The quick brown fox jumped over the lazy dog".split(" "); } @@ -3122,7 +3128,7 @@ function changePage(page) { function setMode(mode, nosave) { if (mode !== "words" && activeFunBox === "memory") { - Misc.showNotification("Memory funbox can only be used with words mode."); + Notifications.add("Memory funbox can only be used with words mode.", 0); return; } @@ -3817,7 +3823,7 @@ function tagsEdit() { hideBackgroundLoader(); let status = e.data.resultCode; if (status === 1) { - Misc.showNotification("Tag added", 2000); + Notifications.add("Tag added", 1, 2); db_getSnapshot().tags.push({ name: inputVal, id: e.data.id, @@ -3826,9 +3832,9 @@ function tagsEdit() { updateSettingsPage(); updateFilterTags(); } else if (status === -1) { - Misc.showNotification("Invalid tag name", 3000); + Notifications.add("Invalid tag name", 0); } else if (status < -1) { - Misc.showNotification("Unknown error", 3000); + Notifications.add("Unknown error: " + e.data.message, -1); } }); } else if (action === "edit") { @@ -3841,7 +3847,7 @@ function tagsEdit() { hideBackgroundLoader(); let status = e.data.resultCode; if (status === 1) { - Misc.showNotification("Tag updated", 2000); + Notifications.add("Tag updated", 1); db_getSnapshot().tags.forEach((tag) => { if (tag.id === tagid) { tag.name = inputVal; @@ -3851,9 +3857,9 @@ function tagsEdit() { updateSettingsPage(); updateFilterTags(); } else if (status === -1) { - Misc.showNotification("Invalid tag name", 3000); + Notifications.add("Invalid tag name", 0); } else if (status < -1) { - Misc.showNotification("Unknown error", 3000); + Notifications.add("Unknown error: " + e.data.message, -1); } }); } else if (action === "remove") { @@ -3865,7 +3871,7 @@ function tagsEdit() { hideBackgroundLoader(); let status = e.data.resultCode; if (status === 1) { - Misc.showNotification("Tag removed", 2000); + Notifications.add("Tag removed", 1); db_getSnapshot().tags.forEach((tag, index) => { if (tag.id === tagid) { db_getSnapshot().tags.splice(index, 1); @@ -3875,7 +3881,7 @@ function tagsEdit() { updateSettingsPage(); updateFilterTags(); } else if (status < -1) { - Misc.showNotification("Unknown error", 3000); + Notifications.add("Unknown error: " + e.data.message, -1); } }); } @@ -4296,15 +4302,16 @@ function applyMode2Popup() { manualRestart = true; restartTest(); if (val >= 1800) { - Misc.showNotification("Stay safe and take breaks!", 3000); + Notifications.add("Stay safe and take breaks!", 0); } else if (val == 0) { - Misc.showNotification( + Notifications.add( "Infinite time! Make sure to use Bail Out from the command line to save your result.", - 5000 + 0, + 7 ); } } else { - Misc.showNotification("Custom time must be at least 1", 3000); + Notifications.add("Custom time must be at least 1", 0); } } else if (mode == "words") { if (val !== null && !isNaN(val) && val >= 0) { @@ -4312,15 +4319,16 @@ function applyMode2Popup() { manualRestart = true; restartTest(); if (val > 2000) { - Misc.showNotification("Stay safe and take breaks!", 3000); + Notifications.add("Stay safe and take breaks!", 0); } else if (val == 0) { - Misc.showNotification( + Notifications.add( "Infinite words! Make sure to use Bail Out from the command line to save your result.", - 5000 + 0, + 7 ); } } else { - Misc.showNotification("Custom word amount must be at least 1", 3000); + Notifications.add("Custom word amount must be at least 1", 0); } } @@ -4444,7 +4452,7 @@ $(document).on("keypress", "#restartTestButton", (event) => { if (resultCalculating) return; restartTest(); } else { - Misc.showNotification("Quick restart disabled for long tests", 2000); + Notifications.add("Quick restart disabled for long tests", 0); } } }); @@ -4488,7 +4496,7 @@ $(document).on("keypress", "#practiseMissedWordsButton", (event) => { if (Object.keys(missedWords).length > 0) { initPractiseMissedWords(); } else { - Misc.showNotification("You haven't missed any words.", 2000); + Notifications.add("You haven't missed any words.", 0); } } }); @@ -4497,7 +4505,7 @@ $(document.body).on("click", "#practiseMissedWordsButton", () => { if (Object.keys(missedWords).length > 0) { initPractiseMissedWords(); } else { - Misc.showNotification("You haven't missed any words.", 2000); + Notifications.add("You haven't missed any words.", 0); } }); @@ -4818,7 +4826,7 @@ function handleTab(event) { } restartTest(); } else { - Misc.showNotification("Quick restart disabled for long tests", 2000); + Notifications.add("Quick restart disabled for long tests", 0); } } else { changePage("test"); @@ -4915,7 +4923,7 @@ function handleSpace(event, isEnter) { let outof = wordsList.length; index = Math.floor((inputHistory.length + 1) / (outof / 3)); if (config.layout !== layouts[index] && layouts[index] !== undefined) { - Misc.showNotification(`--- !!! ${layouts[index]} !!! ---`, 3000); + Notifications.add(`--- !!! ${layouts[index]} !!! ---`, 0); } setLayout(layouts[index]); setKeymapLayout(layouts[index]); @@ -5394,7 +5402,7 @@ if (firebase.app().options.projectId === "monkey-type-dev-67af4") { if (window.location.hostname === "localhost") { window.onerror = function (error) { - Misc.showNotification(error, 3000); + Notifications.add(error, -1); }; $("#top .logo .top").text("localhost"); $("head title").text($("head title").text() + " (localhost)"); @@ -5496,9 +5504,10 @@ $(".merchBanner a").click((event) => { $(".merchBanner .fas").click((event) => { $(".merchBanner").remove(); Misc.setCookie("merchbannerclosed", true, 365); - Misc.showNotification( - "Won't remind you anymore :) Thanks for continued support <3", - 2500 + Notifications.add( + "Won't remind you anymore. Thanks for continued support <3", + 0, + 5 ); }); @@ -5507,9 +5516,9 @@ $(".pageTest #copyWordsListButton").click(async (event) => { await navigator.clipboard.writeText( wordsList.slice(0, inputHistory.length).join(" ") ); - Misc.showNotification("Copied to clipboard", 1000); + Notifications.add("Copied to clipboard", 0, 2); } catch (e) { - Misc.showNotification("Could not copy to clipboard: " + e, 5000); + Notifications.add("Could not copy to clipboard: " + e, -1); } }); @@ -5585,15 +5594,13 @@ async function setupChallenge(challengeName) { restartTest(false, true); notitext = challenge.message; if (notitext === undefined) { - Misc.showNotification(`Challenge '${challengeName}' loaded.`, 3000); + Notifications.add(`Challenge '${challengeName}' loaded.`, 0); } else { - Misc.showNotification("Challenge loaded. " + notitext, 5000); + Notifications.add("Challenge loaded. " + notitext, 0); } } catch (e) { - Misc.showNotification("Something went wrong: " + e, 5000); - console.log(e); + Notifications.add("Something went wrong: " + e, -1); } - // Misc.showNotification("Challenge loaded", 2000); } let ctx = $("#wpmChart"); diff --git a/src/js/settings.js b/src/js/settings.js index 9252b3dc2..81f6864e0 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -473,9 +473,10 @@ function hideCustomThemeShare() { $("#customThemeShareWrapper input").val() ); } catch (e) { - Misc.showNotification( + Notifications.add( "Something went wrong. Reverting to default custom colors.", - 3000 + 0, + 4 ); config.customThemeColors = defaultConfig.customThemeColors; } @@ -524,12 +525,12 @@ $("#shareCustomThemeButton").click((e) => { Misc.objectToQueryString({ customTheme: share }); navigator.clipboard.writeText(url).then( function () { - Misc.showNotification("URL Copied to clipboard", 2000); + Notifications.add("URL Copied to clipboard", 0); }, function (err) { - Misc.showNotification( + Notifications.add( "Something went wrong when copying the URL: " + err, - 5000 + -1 ); } ); @@ -766,7 +767,7 @@ $( }) .catch((e) => { hideBackgroundLoader(); - Misc.showNotification("Something went wrong. Error: " + e.message, 4000); + Notifications.add("Something went wrong. Error: " + e.message, -1); }); }); @@ -781,13 +782,10 @@ $(".pageSettings .section.discordIntegration #unlinkDiscordButton").click( console.log(ret); if (ret.data.status === 1) { db_getSnapshot().discordId = null; - Misc.showNotification("Accounts unlinked", 2000); + Notifications.add("Accounts unlinked", 0); updateDiscordSettingsSection(); } else { - Misc.showNotification( - "Something went wrong: " + ret.data.message, - 5000 - ); + Notifications.add("Something went wrong: " + ret.data.message, -1); updateDiscordSettingsSection(); } }); @@ -908,7 +906,7 @@ $(".pageSettings .saveCustomThemeButton").click((e) => { } ); setCustomThemeColors(save); - Misc.showNotification("Custom theme colors saved", 1000); + Notifications.add("Custom theme colors saved", 0); }); $(".pageSettings #loadCustomColorsFromPreset").click((e) => { @@ -960,12 +958,12 @@ $("#exportSettingsButton").click((e) => { let configJSON = JSON.stringify(config); navigator.clipboard.writeText(configJSON).then( function () { - Misc.showNotification("JSON Copied to clipboard", 2000); + Notifications.add("JSON Copied to clipboard", 0); }, function (err) { - Misc.showNotification( + Notifications.add( "Something went wrong when copying the settings JSON: " + err, - 5000 + -1 ); } ); @@ -991,9 +989,9 @@ function hideSettingsImport() { try { applyConfig(JSON.parse($("#settingsImportWrapper input").val())); } catch (e) { - Misc.showNotification( + Notifications.add( "An error occured while importing settings: " + e, - 5000 + -1 ); } saveConfigToCookie(); diff --git a/src/js/simple-popups.js b/src/js/simple-popups.js index 2f2d64d3c..c531054b4 100644 --- a/src/js/simple-popups.js +++ b/src/js/simple-popups.js @@ -150,21 +150,21 @@ simplePopups.updateEmail = new SimplePopup( }).then((data) => { hideBackgroundLoader(); if (data.data.resultCode === 1) { - Misc.showNotification("Email updated", 2000); + Notifications.add("Email updated", 0); setTimeout(() => { signOut(); }, 1000); } else if (data.data.resultCode === -1) { - Misc.showNotification("Current email doesn't match", 2000); + Notifications.add("Current email doesn't match", 0); } else { - Misc.showNotification( + Notifications.add( "Something went wrong: " + JSON.stringify(data.data), - 7000 + -1 ); } }); } catch (e) { - Misc.showNotification("Something went wrong: " + e, 5000); + Notifications.add("Something went wrong: " + e, -1); } }, () => {} @@ -192,21 +192,16 @@ simplePopups.clearTagPb = new SimplePopup( $( `.pageSettings .section.tags .tagsList .tag[id="${tagid}"] .clearPbButton` ).attr("aria-label", "No PB found"); - Misc.showNotification("Tag PB cleared.", 1000); + Notifications.add("Tag PB cleared.", 0); } else { - console.error(res.data.message); - Misc.showNotification( - "Something went wrong: " + res.data.message, - 5000 - ); + Notifications.add("Something went wrong: " + res.data.message, -1); } }) .catch((e) => { hideBackgroundLoader(); - console.error(e); - Misc.showNotification( + Notifications.add( "Something went wrong while clearing tag pb " + e, - 5000 + -1 ); }); // console.log(`clearing for ${eval("this.parameters[0]")} ${eval("this.parameters[1]")}`); diff --git a/src/js/userconfig.js b/src/js/userconfig.js index a526767c6..ce45bc8a4 100644 --- a/src/js/userconfig.js +++ b/src/js/userconfig.js @@ -113,7 +113,7 @@ async function saveConfigToDB() { // accountIconLoading(false); // if (d.data.returnCode === 1) { // } else { - // Misc.showNotification( + // Notifications.add( // `Error saving config to DB! ${d.data.message}`, // 4000 // ); @@ -680,7 +680,7 @@ function setHighlightMode(mode, nosave) { mode === "word" && (activeFunBox === "nospace" || activeFunBox === "read_ahead") ) { - Misc.showNotification("Can't use word highlight with this funbox", 3000); + Notifications.add("Can't use word highlight with this funbox", 0); return; } if (mode == null || mode == undefined) { @@ -1145,7 +1145,7 @@ function randomiseTheme() { randomList = config.favThemes; randomTheme = randomList[Math.floor(Math.random() * randomList.length)]; setTheme(randomTheme, true); - Misc.showNotification(randomTheme.replace(/_/g, " "), 1500); + Notifications.add(randomTheme.replace(/_/g, " "), 0); }); } @@ -1482,8 +1482,7 @@ function setFontSize(fontSize, nosave) { function applyConfig(configObj) { if (configObj == null || configObj == undefined) { - Misc.showNotification("Could not apply config", 1000); - console.error("configobj is null or undefined"); + Notifications.add("Could not apply config", -1); return; } Object.keys(defaultConfig).forEach((configKey) => { diff --git a/src/sass/style.scss b/src/sass/style.scss index 0cd6ae106..58a55cd4a 100644 --- a/src/sass/style.scss +++ b/src/sass/style.scss @@ -697,6 +697,82 @@ a:hover { } } +#notificationCenter { + width: 350px; + z-index: 99999999; + display: grid; + gap: 1rem; + position: fixed; + right: 1rem; + top: 1rem; + .history { + display: grid; + gap: 1rem; + } + .notif { + .icon { + color: var(--bg-color); + opacity: 0.5; + padding: 1rem 1rem; + align-items: center; + display: grid; + font-size: 1.25rem; + } + .message { + padding: 1rem 1rem 1rem 0; + .title { + color: var(--bg-color); + font-size: 0.75em; + opacity: 0.5; + line-height: 0.75rem; + } + } + + position: relative; + background: var(--sub-color); + color: var(--bg-color); + display: grid; + grid-template-columns: min-content auto min-content; + border-radius: var(--roundness); + border-width: 0.25rem; + + &.bad { + background-color: var(--error-color); + } + + &.good { + background-color: var(--main-color); + } + + &:hover { + // opacity: .5; + // box-shadow: 0 0 20px rgba(0,0,0,.25); + cursor: pointer; + &::after { + opacity: 1; + } + } + &::after { + transition: 0.125s; + font-family: "Font Awesome 5 Free"; + background: rgba(0, 0, 0, 0.5); + opacity: 0; + font-weight: 900; + content: "\f00d"; + position: absolute; + width: 100%; + height: 100%; + color: var(--bg-color); + font-size: 2.5rem; + display: grid; + /* align-self: center; */ + align-items: center; + text-align: center; + border-radius: var(--roundness); + } + } +} + #supportMeWrapper { width: 100%; height: 100%; diff --git a/static/index.html b/static/index.html index dc3b3a545..ae1414ed8 100644 --- a/static/index.html +++ b/static/index.html @@ -49,6 +49,9 @@ +
+
+