diff --git a/.prettierignore b/.prettierignore
index ff265a8f5..44e1ccc46 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,10 +1,10 @@
*.min.js
layouts.js
-english_quotes.json
+quotes/english.json
chartjs-plugin-*.js
sound/*
node_modules
css/balloon.css
css/fa.css
css/style.min.css
-_list.json
\ No newline at end of file
+_list.json
diff --git a/functions/index.js b/functions/index.js
index a037df129..3b5b6b8de 100644
--- a/functions/index.js
+++ b/functions/index.js
@@ -1,9 +1,11 @@
const functions = require("firebase-functions");
const admin = require("firebase-admin");
let key = "./serviceAccountKey.json";
+let origin = "http://localhost:5000";
if (process.env.GCLOUD_PROJECT === "monkey-type") {
key = "./serviceAccountKey_live.json";
+ origin = "https://monkeytype.com";
}
var serviceAccount = require(key);
@@ -133,14 +135,36 @@ exports.clearName = functions.auth.user().onDelete((user) => {
db.collection("users").doc(user.uid).delete();
});
-exports.checkNameAvailability = functions.https.onCall(
+exports.checkNameAvailability = functions.https.onRequest(
async (request, response) => {
+ response.set("Access-Control-Allow-Origin", origin);
+ if (request.method === "OPTIONS") {
+ // Send response to OPTIONS requests
+ response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
+ response.set(
+ "Access-Control-Allow-Headers",
+ "Authorization,Content-Type"
+ );
+ response.set("Access-Control-Max-Age", "3600");
+ response.status(204).send("");
+ return;
+ }
+ request = request.body.data;
+
// 1 - available
// -1 - unavailable (taken)
// -2 - not valid name
// -999 - unknown error
try {
- if (!isUsernameValid(request.name)) return -2;
+ if (!isUsernameValid(request.name)) {
+ response.status(200).send({
+ data: {
+ resultCode: -2,
+ message: "Username is not valid",
+ },
+ });
+ return;
+ }
let takendata = await db
.collection("takenNames")
@@ -150,9 +174,21 @@ exports.checkNameAvailability = functions.https.onCall(
takendata = takendata.data();
if (takendata !== undefined && takendata.taken) {
- return -1;
+ response.status(200).send({
+ data: {
+ resultCode: -1,
+ message: "Username is taken",
+ },
+ });
+ return;
} else {
- return 1;
+ response.status(200).send({
+ data: {
+ resultCode: 1,
+ message: "Username is available",
+ },
+ });
+ return;
}
// return getAllNames().then((data) => {
@@ -167,8 +203,17 @@ exports.checkNameAvailability = functions.https.onCall(
// return available;
// });
} catch (e) {
- console.log(e.message);
- return -999;
+ console.error(
+ `Error while checking name availability for ${request.name}:` +
+ e.message
+ );
+ response.status(200).send({
+ data: {
+ resultCode: -999,
+ message: "Unexpected error: " + e,
+ },
+ });
+ return;
}
}
);
@@ -588,14 +633,14 @@ function validateResult(result) {
}
exports.requestTest = functions.https.onRequest((request, response) => {
- response.set("Access-Control-Allow-Origin", "*");
+ response.set("Access-Control-Allow-Origin", origin);
response.set("Access-Control-Allow-Headers", "*");
response.set("Access-Control-Allow-Credentials", "true");
response.status(200).send({ data: "test" });
});
exports.getPatreons = functions.https.onRequest(async (request, response) => {
- response.set("Access-Control-Allow-Origin", "*");
+ response.set("Access-Control-Allow-Origin", origin);
response.set("Access-Control-Allow-Headers", "*");
response.set("Access-Control-Allow-Credentials", "true");
if (request.method === "OPTIONS") {
@@ -629,7 +674,7 @@ exports.getPatreons = functions.https.onRequest(async (request, response) => {
});
exports.verifyUser = functions.https.onRequest(async (request, response) => {
- response.set("Access-Control-Allow-Origin", "*");
+ response.set("Access-Control-Allow-Origin", origin);
response.set("Access-Control-Allow-Headers", "*");
response.set("Access-Control-Allow-Credentials", "true");
if (request.method === "OPTIONS") {
@@ -1002,7 +1047,7 @@ async function incrementTimeSpentTyping(uid, res, userData) {
}
exports.testCompleted = functions.https.onRequest(async (request, response) => {
- response.set("Access-Control-Allow-Origin", "*");
+ response.set("Access-Control-Allow-Origin", origin);
if (request.method === "OPTIONS") {
// Send response to OPTIONS requests
response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
@@ -1055,7 +1100,13 @@ exports.testCompleted = functions.https.onRequest(async (request, response) => {
return;
}
- if (obj.wpm <= 0 || obj.wpm > 350 || obj.acc < 50 || obj.acc > 100) {
+ if (
+ obj.wpm <= 0 ||
+ obj.wpm > 350 ||
+ obj.acc < 50 ||
+ obj.acc > 100 ||
+ obj.consistency > 100
+ ) {
response.status(200).send({ data: { resultCode: -1 } });
return;
}
@@ -1426,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 };
}
});
@@ -1456,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 };
}
});
@@ -1522,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 };
}
});
@@ -1984,7 +2035,7 @@ class Leaderboard {
// });
exports.unlinkDiscord = functions.https.onRequest((request, response) => {
- response.set("Access-Control-Allow-Origin", "*");
+ response.set("Access-Control-Allow-Origin", origin);
if (request.method === "OPTIONS") {
// Send response to OPTIONS requests
response.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
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 997d40c89..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,27 +59,27 @@ 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;
}
CloudFunctions.namecheck({ name: nname }).then((d) => {
- if (d.data === -1) {
- Misc.showNotification("Name unavailable", 3000);
+ if (d.data.resultCode === -1) {
+ Notifications.add("Name unavailable", -1);
$(".pageLogin .preloader").addClass("hidden");
$(".pageLogin .register .button").removeClass("disabled");
return;
- } else if (d.data === -2) {
- Misc.showNotification(
+ } else if (d.data.resultCode === -2) {
+ 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");
return;
- } else if (d.data === 1) {
+ } else if (d.data.resultCode === 1) {
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
@@ -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,10 +164,14 @@ 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 {
+ Notifications.add(
+ "Something went wrong when checking name: " + d.data.message,
+ -1
+ );
}
});
}
@@ -173,7 +181,7 @@ function signOut() {
.auth()
.signOut()
.then(function () {
- Misc.showNotification("Signed out", 2000);
+ Notifications.add("Signed out", 0, 2);
clearGlobalStats();
hideAccountSettingsSection();
updateAccountLoginButton();
@@ -181,7 +189,7 @@ function signOut() {
db_setSnapshot(null);
})
.catch(function (error) {
- Misc.showNotification(error.message, 5000);
+ Notifications.add(error.message, -1);
});
}
@@ -221,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);
}
});
}
@@ -237,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;
}
@@ -366,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);
@@ -1004,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);
@@ -1851,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);
@@ -2206,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) => {
@@ -2224,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);
}
}
}
@@ -2326,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;
@@ -2377,7 +2387,7 @@ $("#resultEditTagsPanel .confirmButton").click((f) => {
);
}
} else {
- Misc.showNotification("Error updating tags", 3000);
+ Notifications.add("Error updating tags: " + r.data.message, -1);
}
});
});
@@ -2425,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..e2c2a640a 100644
--- a/src/js/commandline.js
+++ b/src/js/commandline.js
@@ -1,11 +1,15 @@
function canBailOut() {
return (
(config.mode === "custom" &&
- customTextIsRandom &&
- customTextWordCount >= 5000) ||
+ customText.isWordRandom &&
+ customText.word >= 5000) ||
(config.mode === "custom" &&
- !customTextIsRandom &&
- customText.length >= 5000) ||
+ !customText.isWordRandom &&
+ !customText.isTimeRandom &&
+ customText.text.length >= 5000) ||
+ (config.mode === "custom" &&
+ customText.isTimeRandom &&
+ customText.time >= 3600) ||
(config.mode === "words" && config.words >= 5000) ||
config.words === 0 ||
(config.mode === "time" && (config.time >= 3600 || config.time === 0))
@@ -880,7 +884,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 +892,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 +900,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(`
+
+
+
+ `);
+ 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(`
+
+
+
+ `);
+ $(`#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 3e9f2aa84..96b2742d9 100644
--- a/src/js/script.js
+++ b/src/js/script.js
@@ -202,9 +202,17 @@ function initClickSounds() {
};
}
-let customText = "The quick brown fox jumps over the lazy dog".split(" ");
-let customTextIsRandom = false;
-let customTextWordCount = 1;
+let customText = {
+ text: "The quick brown fox jumps over the lazy dog".split(" "),
+ isWordRandom: false,
+ isTimeRandom: false,
+ word: "",
+ time: "",
+};
+
+// let customText = "The quick brown fox jumps over the lazy dog".split(" ");
+// let customText.isWordRandom = false;
+// let customText.word = 1;
let randomQuote = null;
function refreshThemeColorObject() {
@@ -259,7 +267,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 +276,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 +288,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 +301,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 +311,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 +487,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;
},
@@ -506,10 +520,12 @@ async function initWords() {
let wordsBound = 100;
if (config.showAllLines) {
if (config.mode === "custom") {
- if (customTextIsRandom) {
- wordsBound = customTextWordCount;
+ if (customText.isWordRandom) {
+ wordsBound = customText.word;
+ } else if (customText.isTimeRandom) {
+ wordsBound = 100;
} else {
- wordsBound = customText.length;
+ wordsBound = customText.text.length;
}
} else if (config.mode != "time") {
wordsBound = config.words;
@@ -520,19 +536,38 @@ async function initWords() {
}
if (
config.mode == "custom" &&
- customTextIsRandom &&
- customTextWordCount < wordsBound
+ customText.isWordRandom &&
+ customText.word < wordsBound
) {
- wordsBound = customTextWordCount;
+ wordsBound = customText.word;
}
if (
config.mode == "custom" &&
- !customTextIsRandom &&
- customText.length < wordsBound
+ customText.isTimeRandom &&
+ customText.time < wordsBound
) {
- wordsBound = customText.length;
+ wordsBound = 100;
+ }
+ if (
+ config.mode == "custom" &&
+ !customText.isWordRandom &&
+ customText.text.length < wordsBound
+ ) {
+ wordsBound = customText.text.length;
}
}
+
+ if (
+ (config.mode === "custom" &&
+ customText.isWordRandom &&
+ customText.word == 0) ||
+ (config.mode === "custom" &&
+ customText.isTimeRandom &&
+ customText.time == 0)
+ ) {
+ wordsBound = 100;
+ }
+
if (config.mode === "words" && config.words === 0) {
wordsBound = 100;
}
@@ -541,16 +576,19 @@ async function initWords() {
}
let wordset = language.words;
if (config.mode == "custom") {
- wordset = customText;
+ wordset = customText.text;
}
for (let i = 0; i < wordsBound; i++) {
let randomWord = wordset[Math.floor(Math.random() * wordset.length)];
const previousWord = wordsList[i - 1];
const previousWord2 = wordsList[i - 2];
- if (config.mode == "custom" && customTextIsRandom) {
+ if (
+ config.mode == "custom" &&
+ (customText.isWordRandom || customText.isTimeRandom)
+ ) {
randomWord = wordset[Math.floor(Math.random() * wordset.length)];
- } else if (config.mode == "custom" && !customTextIsRandom) {
- randomWord = customText[i];
+ } else if (config.mode == "custom" && !customText.isWordRandom) {
+ randomWord = customText.text[i];
} else {
while (
randomWord == previousWord ||
@@ -585,10 +623,10 @@ async function initWords() {
randomWord = Misc.getASCII();
}
- if (config.punctuation && config.mode != "custom") {
+ if (config.punctuation) {
randomWord = punctuateWord(previousWord, randomWord, i, wordsBound);
}
- if (config.numbers && config.mode != "custom") {
+ if (config.numbers) {
if (Math.random() < 0.1) {
randomWord = Misc.getNumbers(4);
}
@@ -868,11 +906,12 @@ function addWord() {
wordsList.length >= config.words &&
config.words > 0) ||
(config.mode === "custom" &&
- customTextIsRandom &&
- wordsList.length >= customTextWordCount) ||
+ customText.isWordRandom &&
+ wordsList.length >= customText.word &&
+ customText.word != 0) ||
(config.mode === "custom" &&
- !customTextIsRandom &&
- wordsList.length >= customText.length)
+ !customText.isWordRandom &&
+ wordsList.length >= customText.text.length)
)
return;
const language =
@@ -881,7 +920,7 @@ function addWord() {
: {
//borrow the direction of the current language
leftToRight: Misc.getCurrentLanguage().leftToRight,
- words: customText,
+ words: customText.text,
};
const wordset = language.words;
let randomWord = wordset[Math.floor(Math.random() * wordset.length)];
@@ -893,10 +932,14 @@ function addWord() {
.replace(/[.?!":\-,]/g, "")
.toLowerCase();
- if (config.mode === "custom" && customTextIsRandom && wordset.length < 3) {
+ if (
+ config.mode === "custom" &&
+ customText.isWordRandom &&
+ wordset.length < 3
+ ) {
randomWord = wordset[Math.floor(Math.random() * wordset.length)];
- } else if (config.mode == "custom" && !customTextIsRandom) {
- randomWord = customText[wordsList.length];
+ } else if (config.mode == "custom" && !customText.isWordRandom) {
+ randomWord = customText.text[wordsList.length];
} else {
while (
previousWordStripped == randomWord ||
@@ -973,7 +1016,12 @@ function showWords() {
$("#wordsWrapper").removeClass("hidden");
const wordHeight = $(document.querySelector(".word")).outerHeight(true);
const wordsHeight = $(document.querySelector("#words")).outerHeight(true);
- if (config.showAllLines && config.mode != "time") {
+ if (
+ config.showAllLines &&
+ config.mode != "time" &&
+ !(customText.isWordRandom && customText.word == 0) &&
+ !customText.isTimeRandom
+ ) {
$("#words").css("height", "auto");
$("#wordsWrapper").css("height", "auto");
let nh = wordHeight * 3;
@@ -1000,26 +1048,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) {
@@ -1262,9 +1290,16 @@ function restartTimer() {
function updateTimer() {
if (!config.showTimerProgress) return;
- if (config.mode === "time") {
+ if (
+ config.mode === "time" ||
+ (config.mode === "custom" && customText.isTimeRandom)
+ ) {
+ let maxtime = config.time;
+ if (config.mode === "custom" && customText.isTimeRandom) {
+ maxtime = customText.time;
+ }
if (config.timerStyle === "bar") {
- let percent = 100 - ((time + 1) / config.time) * 100;
+ let percent = 100 - ((time + 1) / maxtime) * 100;
$("#timer")
.stop(true, true)
.animate(
@@ -1275,14 +1310,14 @@ function updateTimer() {
"linear"
);
} else if (config.timerStyle === "text") {
- let displayTime = Misc.secondsToString(config.time - time);
- if (config.time === 0) {
+ let displayTime = Misc.secondsToString(maxtime - time);
+ if (maxtime === 0) {
displayTime = Misc.secondsToString(time);
}
$("#timerNumber").html("" + displayTime + "
");
} else if (config.timerStyle === "mini") {
- let displayTime = Misc.secondsToString(config.time - time);
- if (config.time === 0) {
+ let displayTime = Misc.secondsToString(maxtime - time);
+ if (maxtime === 0) {
displayTime = Misc.secondsToString(time);
}
$("#miniTimerAndLiveWpm .time").html(displayTime);
@@ -1298,10 +1333,10 @@ function updateTimer() {
outof = config.words;
}
if (config.mode === "custom") {
- if (customTextIsRandom) {
- outof = customTextWordCount;
+ if (customText.isWordRandom) {
+ outof = customText.word;
} else {
- outof = customText.length;
+ outof = customText.text.length;
}
}
let percent = Math.floor(((currentWordIndex + 1) / outof) * 100);
@@ -1319,13 +1354,13 @@ function updateTimer() {
outof = config.words;
}
if (config.mode === "custom") {
- if (customTextIsRandom) {
- outof = customTextWordCount;
+ if (customText.isWordRandom) {
+ outof = customText.word;
} else {
- outof = customText.length;
+ outof = customText.text.length;
}
}
- if (config.words === 0) {
+ if (outof === 0) {
$("#timerNumber").html("" + `${inputHistory.length}` + "
");
} else {
$("#timerNumber").html(
@@ -1338,10 +1373,10 @@ function updateTimer() {
outof = config.words;
}
if (config.mode === "custom") {
- if (customTextIsRandom) {
- outof = customTextWordCount;
+ if (customText.isWordRandom) {
+ outof = customText.word;
} else {
- outof = customText.length;
+ outof = customText.text.length;
}
}
if (config.words === 0) {
@@ -2081,11 +2116,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 +2334,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 +2535,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 +2587,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 +2597,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 +2610,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);
@@ -2753,7 +2788,10 @@ function startTest() {
timer = setTimeout(function () {
time++;
$(".pageTest #premidSecondsLeft").text(config.time - time);
- if (config.mode === "time") {
+ if (
+ config.mode === "time" ||
+ (config.mode === "custom" && customText.isTimeRandom)
+ ) {
updateTimer();
}
let wpmAndRaw = liveWpmAndRaw();
@@ -2776,23 +2814,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]);
@@ -2821,8 +2859,18 @@ function startTest() {
failTest();
return;
}
- if (config.mode == "time") {
- if (time >= config.time && config.time !== 0) {
+ if (
+ config.mode == "time" ||
+ (config.mode === "custom" && customText.isTimeRandom)
+ ) {
+ if (
+ (time >= config.time &&
+ config.time !== 0 &&
+ config.mode === "time") ||
+ (time >= customText.time &&
+ customText.time !== 0 &&
+ config.mode === "custom")
+ ) {
//times up
clearTimeout(timer);
hideCaret();
@@ -2845,17 +2893,22 @@ function restartTest(withSameWordset = false, nosave = false) {
(config.mode === "time" && config.time < 3600 && config.time > 0) ||
config.mode === "quote" ||
(config.mode === "custom" &&
- customTextIsRandom &&
- customTextWordCount < 1000) ||
+ customText.isWordRandom &&
+ customText.word < 1000 &&
+ customText.word != 0) ||
(config.mode === "custom" &&
- !customTextIsRandom &&
- customText.length < 1000)
+ customText.isTimeRandom &&
+ customText.time < 3600 &&
+ customText.time != 0) ||
+ (config.mode === "custom" &&
+ !customText.isWordRandom &&
+ customText.text.length < 1000)
) {
} else {
if (testActive) {
- Misc.showNotification(
+ Notifications.add(
"Restart disabled for long tests. Use your mouse to confirm.",
- 4000
+ 0
);
return;
}
@@ -2863,7 +2916,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 +3024,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;
@@ -3032,17 +3107,14 @@ function focusWords() {
}
function setCustomText() {
- customText = prompt("Custom text").trim();
- customText = customText.replace(/[\n\r\t ]/gm, " ");
- customText = customText.replace(/ +/gm, " ");
- customText = customText.split(" ");
- if (customText.length >= 10000) {
- Misc.showNotification(
- "Custom text cannot be longer than 10000 words.",
- 4000
- );
+ customText.text = prompt("Custom text").trim();
+ customText.text = customText.text.replace(/[\n\r\t ]/gm, " ");
+ customText.text = customText.text.replace(/ +/gm, " ");
+ customText.text = customText.text.split(" ");
+ if (customText.text.text.length >= 10000) {
+ Notifications.add("Custom text cannot be longer than 10000 words.", 0);
setMode("time");
- customText = "The quick brown fox jumped over the lazy dog".split(" ");
+ customText.text = "The quick brown fox jumped over the lazy dog".split(" ");
}
}
@@ -3122,7 +3194,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;
}
@@ -3155,8 +3227,8 @@ function setMode(mode, nosave) {
$("#top .config .wordCount").addClass("hidden");
$("#top .config .time").addClass("hidden");
$("#top .config .customText").removeClass("hidden");
- $("#top .config .punctuationMode").addClass("hidden");
- $("#top .config .numbersMode").addClass("hidden");
+ $("#top .config .punctuationMode").removeClass("hidden");
+ $("#top .config .numbersMode").removeClass("hidden");
$("#top .config .quoteLength").addClass("hidden");
setPunctuation(false, true);
setNumbers(false, true);
@@ -3817,7 +3889,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 +3898,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 +3913,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 +3923,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 +3937,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 +3947,7 @@ function tagsEdit() {
updateSettingsPage();
updateFilterTags();
} else if (status < -1) {
- Misc.showNotification("Unknown error", 3000);
+ Notifications.add("Unknown error: " + e.data.message, -1);
}
});
}
@@ -3896,19 +3968,20 @@ function hideCapsWarning() {
function showCustomTextPopup() {
if ($("#customTextPopupWrapper").hasClass("hidden")) {
if ($("#customTextPopup .check input").prop("checked")) {
- $("#customTextPopup .inputs .wordcount").removeClass("hidden");
+ $("#customTextPopup .inputs .randomInputFields").removeClass("hidden");
} else {
- $("#customTextPopup .inputs .wordcount").addClass("hidden");
+ $("#customTextPopup .inputs .randomInputFields").addClass("hidden");
}
$("#customTextPopupWrapper")
.stop(true, true)
.css("opacity", 0)
.removeClass("hidden")
.animate({ opacity: 1 }, 100, () => {
- let newtext = customText.join(" ");
+ let newtext = customText.text.join(" ");
newtext = newtext.replace(/\n /g, "\n");
$("#customTextPopup textarea").val(newtext);
- $("#customTextPopup .wordcount input").val(customTextWordCount);
+ $("#customTextPopup .wordcount input").val(customText.word);
+ $("#customTextPopup .time input").val(customText.time);
$("#customTextPopup textarea").focus();
});
}
@@ -3939,9 +4012,9 @@ $("#customTextPopupWrapper").mousedown((e) => {
$("#customTextPopup .inputs .check input").change(() => {
if ($("#customTextPopup .check input").prop("checked")) {
- $("#customTextPopup .inputs .wordcount").removeClass("hidden");
+ $("#customTextPopup .inputs .randomInputFields").removeClass("hidden");
} else {
- $("#customTextPopup .inputs .wordcount").addClass("hidden");
+ $("#customTextPopup .inputs .randomInputFields").addClass("hidden");
}
});
@@ -3951,11 +4024,20 @@ $("#customTextPopup textarea").keypress((e) => {
}
});
+$("#customTextPopup .randomInputFields .wordcount input").keypress((e) => {
+ $("#customTextPopup .randomInputFields .time input").val("");
+});
+
+$("#customTextPopup .randomInputFields .time input").keypress((e) => {
+ $("#customTextPopup .randomInputFields .wordcount input").val("");
+});
+
$("#customTextPopup .button").click(() => {
let text = $("#customTextPopup textarea").val();
text = text.trim();
// text = text.replace(/[\r]/gm, " ");
- text = text.replace(/\t/gm, "\t");
+ text = text.replace(/\\\\t/gm, "\t");
+ text = text.replace(/\\\\n/gm, "\n");
text = text.replace(/ +/gm, " ");
// text = text.replace(/(\r\n)+/g, "\r\n");
// text = text.replace(/(\n)+/g, "\n");
@@ -3967,9 +4049,46 @@ $("#customTextPopup .button").click(() => {
// text = Misc.remove_non_ascii(text);
text = text.replace(/[\u2060]/g, "");
text = text.split(" ");
- customText = text;
- customTextIsRandom = $("#customTextPopup .check input").prop("checked");
- customTextWordCount = $("#customTextPopup .wordcount input").val();
+ customText.text = text;
+ customText.word = parseInt($("#customTextPopup .wordcount input").val());
+ customText.time = parseInt($("#customTextPopup .time input").val());
+
+ customText.isWordRandom =
+ $("#customTextPopup .check input").prop("checked") &&
+ !isNaN(customText.word);
+ customText.isTimeRandom =
+ $("#customTextPopup .check input").prop("checked") &&
+ !isNaN(customText.time);
+
+ if (isNaN(customText.word) && isNaN(customText.time)) {
+ Notifications.add(
+ "You need to specify word count or time in seconds to start a random custom test.",
+ 0,
+ 5
+ );
+ return;
+ }
+
+ if (!isNaN(customText.word) && !isNaN(customText.time)) {
+ Notifications.add(
+ "You need to pick between word count or time in seconds to start a random custom test.",
+ 0,
+ 5
+ );
+ return;
+ }
+
+ if (
+ (customText.isWordRandom && parseInt(customText.word) === 0) ||
+ (customText.isTimeRandom && parseInt(customText.time) === 0)
+ ) {
+ Notifications.add(
+ "Infinite words! Make sure to use Bail Out from the command line to save your result.",
+ 0,
+ 7
+ );
+ }
+
manualRestart = true;
restartTest();
hideCustomTextPopup();
@@ -4295,15 +4414,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) {
@@ -4311,15 +4431,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);
}
}
@@ -4425,11 +4546,14 @@ $(document).on("keypress", "#restartTestButton", (event) => {
(config.mode === "time" && config.time < 3600) ||
config.mode === "quote" ||
(config.mode === "custom" &&
- customTextIsRandom &&
- customTextWordCount < 1000) ||
+ customText.isWordRandom &&
+ customText.word < 1000) ||
(config.mode === "custom" &&
- !customTextIsRandom &&
- customText.length < 1000)
+ customText.isTimeRandom &&
+ customText.time < 3600) ||
+ (config.mode === "custom" &&
+ !customText.isWordRandom &&
+ customText.text.length < 1000)
) {
if (testActive) {
let testNow = performance.now();
@@ -4443,7 +4567,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);
}
}
});
@@ -4469,9 +4593,9 @@ function initPractiseMissedWords() {
newCustomText.push(missedWord);
}
});
- customText = newCustomText;
- customTextIsRandom = true;
- customTextWordCount = 50;
+ customText.text = newCustomText;
+ customText.isWordRandom = true;
+ customText.word = 50;
modeBeforePractise = null;
punctuationBeforePractise = null;
@@ -4487,7 +4611,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);
}
}
});
@@ -4496,7 +4620,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);
}
});
@@ -4800,11 +4924,14 @@ function handleTab(event) {
(config.mode === "time" && config.time < 3600) ||
config.mode === "quote" ||
(config.mode === "custom" &&
- customTextIsRandom &&
- customTextWordCount < 1000) ||
+ customText.isWordRandom &&
+ customText.word < 1000) ||
(config.mode === "custom" &&
- !customTextIsRandom &&
- customText.length < 1000)
+ customText.isTimeRandom &&
+ customText.time < 3600) ||
+ (config.mode === "custom" &&
+ !customText.isWordRandom &&
+ customText.text.length < 1000)
) {
if (testActive) {
let testNow = performance.now();
@@ -4817,7 +4944,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");
@@ -4914,7 +5041,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]);
@@ -5010,7 +5137,12 @@ function handleSpace(event, isEnter) {
correctedHistory.push(currentCorrected);
currentCorrected = "";
- if (!config.showAllLines || config.mode == "time") {
+ if (
+ !config.showAllLines ||
+ config.mode == "time" ||
+ (customText.isWordRandom && customText.word == 0) ||
+ customText.isTimeRandom
+ ) {
let currentTop = Math.floor(
document.querySelectorAll("#words .word")[currentWordElementIndex - 1]
.offsetTop
@@ -5368,11 +5500,14 @@ window.addEventListener("beforeunload", (event) => {
(config.mode === "time" && config.time < 3600) ||
config.mode === "quote" ||
(config.mode === "custom" &&
- customTextIsRandom &&
- customTextWordCount < 1000) ||
+ customText.isWordRandom &&
+ customText.word < 1000) ||
(config.mode === "custom" &&
- !customTextIsRandom &&
- customText.length < 1000)
+ customText.isTimeRandom &&
+ customText.time < 1000) ||
+ (config.mode === "custom" &&
+ !customText.isWordRandom &&
+ customText.text.length < 1000)
) {
} else {
if (testActive) {
@@ -5393,7 +5528,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)");
@@ -5495,9 +5630,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
);
});
@@ -5506,9 +5642,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);
}
});
@@ -5542,9 +5678,9 @@ async function setupChallenge(challengeName) {
setMode("words", true);
setDifficulty("normal", true);
} else if (challenge.type === "customText") {
- customText = challenge.parameters[0].split(" ");
- customTextIsRandom = challenge.parameters[1];
- customTextWordCount = challenge.parameters[2];
+ customText.text = challenge.parameters[0].split(" ");
+ customText.isWordRandom = challenge.parameters[1];
+ customText.word = parseInt(challenge.parameters[2]);
setMode("custom", true);
setDifficulty("normal", true);
} else if (challenge.type === "script") {
@@ -5553,8 +5689,8 @@ async function setupChallenge(challengeName) {
let text = scriptdata.trim();
text = text.replace(/[\n\r\t ]/gm, " ");
text = text.replace(/ +/gm, " ");
- customText = text.split(" ");
- customTextIsRandom = false;
+ customText.text = text.split(" ");
+ customText.isWordRandom = false;
setMode("custom", true);
setDifficulty("normal", true);
if (challenge.parameters[1] != null) {
@@ -5584,15 +5720,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..e5a812fba 100644
--- a/src/sass/style.scss
+++ b/src/sass/style.scss
@@ -415,6 +415,13 @@ a:hover {
justify-items: left;
}
+ .randomInputFields {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ text-align: center;
+ align-items: center;
+ }
+
.check {
span {
display: block;
@@ -697,6 +704,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..544576a33 100644
--- a/static/index.html
+++ b/static/index.html
@@ -49,6 +49,9 @@
+
- Word count
-
-
+