From decba8eaaac9570dcf393b92f978ab9880e15771 Mon Sep 17 00:00:00 2001 From: typer Date: Fri, 27 Nov 2020 23:27:24 -0800 Subject: [PATCH] refactored misc and cloud functions --- gulpfile.js | 9 +- src/js/account.js | 68 ++++--- src/js/cloud-functions.js | 28 +++ src/js/commandline.js | 44 +++-- src/js/dom-util.js | 7 + src/js/exports.js | 4 + src/js/global-dependencies.js | 4 + src/js/leaderboards.js | 6 +- src/js/misc.js | 254 ++++-------------------- src/js/script.js | 353 ++++++++++++++++------------------ src/js/settings.js | 40 ++-- src/js/simple-popups.js | 165 ++++++++++++++++ src/js/userconfig.js | 35 ++-- 13 files changed, 530 insertions(+), 487 deletions(-) create mode 100644 src/js/cloud-functions.js create mode 100644 src/js/dom-util.js create mode 100644 src/js/simple-popups.js diff --git a/gulpfile.js b/gulpfile.js index 5b0b491e2..dbbba2fc8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -85,13 +85,18 @@ let eslintConfig = { //refactored files, which should be es6 modules //once all files are moved here, then can we use a bundler to its full potential -const refactoredSrc = ["./src/js/db.js"]; +const refactoredSrc = [ + "./src/js/db.js", + "./src/js/dom-util.js", + "./src/js/cloud-functions.js", + "./src/js/misc.js", +]; //legacy files //the order of files is important const globalSrc = [ "./src/js/global-dependencies.js", - "./src/js/misc.js", + "./src/js/simple-popups.js", "./src/js/words.js", "./src/js/layouts.js", "./src/js/userconfig.js", diff --git a/src/js/account.js b/src/js/account.js index 1eb1eb939..e84307ed2 100644 --- a/src/js/account.js +++ b/src/js/account.js @@ -38,11 +38,11 @@ $(".pageLogin #forgotPasswordButton").click((e) => { .sendPasswordResetEmail(email) .then(function () { // Email sent. - showNotification("Email sent", 2000); + Misc.showNotification("Email sent", 2000); }) .catch(function (error) { // An error happened. - showNotification(error.message, 5000); + Misc.showNotification(error.message, 5000); }); } }); @@ -73,7 +73,7 @@ function signIn() { changePage("test"); }) .catch(function (error) { - showNotification(error.message, 5000); + Misc.showNotification(error.message, 5000); $(".pageLogin .preloader").addClass("hidden"); }); }); @@ -90,7 +90,7 @@ function signIn() { changePage("test"); }) .catch(function (error) { - showNotification(error.message, 5000); + Misc.showNotification(error.message, 5000); $(".pageLogin .preloader").addClass("hidden"); }); }); @@ -108,22 +108,20 @@ function signUp() { let passwordVerify = $(".pageLogin .register input")[3].value; if (password != passwordVerify) { - showNotification("Passwords do not match", 3000); + Misc.showNotification("Passwords do not match", 3000); $(".pageLogin .preloader").addClass("hidden"); $(".pageLogin .register .button").removeClass("disabled"); return; } - const namecheck = firebase.functions().httpsCallable("checkNameAvailability"); - - namecheck({ name: nname }).then((d) => { + CloudFunctions.namecheck({ name: nname }).then((d) => { if (d.data === -1) { - showNotification("Name unavailable", 3000); + Misc.showNotification("Name unavailable", 3000); $(".pageLogin .preloader").addClass("hidden"); $(".pageLogin .register .button").removeClass("disabled"); return; } else if (d.data === -2) { - showNotification( + Misc.showNotification( "Name cannot contain special characters or contain more than 14 characters. Can include _ . and -", 8000 ); @@ -149,10 +147,10 @@ function signUp() { .collection("users") .doc(usr.uid) .set({ name: nname }, { merge: true }); - reserveName({ name: nname, uid: usr.uid }); + CloudFunctions.reserveName({ name: nname, uid: usr.uid }); usr.sendEmailVerification(); clearGlobalStats(); - showNotification("Account created", 2000); + Misc.showNotification("Account created", 2000); $("#menu .icon-button.account .text").text(nname); try { firebase.analytics().logEvent("accountCreated", usr.uid); @@ -172,7 +170,7 @@ function signUp() { }); if (notSignedInLastResult !== null) { notSignedInLastResult.uid = usr.uid; - testCompleted({ + CloudFunctions.testCompleted({ uid: usr.uid, obj: notSignedInLastResult, }); @@ -191,7 +189,7 @@ function signUp() { .delete() .then(function () { // User deleted. - showNotification( + Misc.showNotification( "An error occured. Account not created.", 2000 ); @@ -208,7 +206,7 @@ function signUp() { // Handle Errors here. $(".pageLogin .register .button").removeClass("disabled"); var errorMessage = error.message; - showNotification(errorMessage, 5000); + Misc.showNotification(errorMessage, 5000); $(".pageLogin .preloader").addClass("hidden"); }); } @@ -220,7 +218,7 @@ function signOut() { .auth() .signOut() .then(function () { - showNotification("Signed out", 2000); + Misc.showNotification("Signed out", 2000); clearGlobalStats(); hideAccountSettingsSection(); updateAccountLoginButton(); @@ -228,7 +226,7 @@ function signOut() { db_setSnapshot(null); }) .catch(function (error) { - showNotification(error.message, 5000); + Misc.showNotification(error.message, 5000); }); } @@ -268,10 +266,10 @@ firebase.auth().onAuthStateChanged(function (user) { $(".pageAccount .group.createdDate").text(text); if (verifyUserWhenLoggedIn !== null) { - showNotification("Verifying", 1000); + Misc.showNotification("Verifying", 1000); verifyUserWhenLoggedIn.uid = user.uid; - verifyUser(verifyUserWhenLoggedIn).then((data) => { - showNotification(data.data.message, 3000); + CloudFunctions.verifyUser(verifyUserWhenLoggedIn).then((data) => { + Misc.showNotification(data.data.message, 3000); if (data.data.status === 1) { db_getSnapshot().discordId = data.data.did; updateDiscordSettingsSection(); @@ -279,14 +277,14 @@ firebase.auth().onAuthStateChanged(function (user) { }); } } - let theme = findGetParameter("customTheme"); + let theme = Misc.findGetParameter("customTheme"); if (theme !== null) { try { theme = theme.split(","); config.customThemeColors = theme; - showNotification("Custom theme applied.", 1000); + Misc.showNotification("Custom theme applied.", 1000); } catch (e) { - showNotification( + Misc.showNotification( "Something went wrong. Reverting to default custom colors.", 3000 ); @@ -393,7 +391,7 @@ function getAccountDataAndInit() { .catch((e) => { accountIconLoading(false); console.error(e); - showNotification( + Misc.showNotification( "Error downloading user data. Refresh to try again. If error persists contact Miodec.", 5000 ); @@ -1003,7 +1001,7 @@ let defaultAccountFilters = { }, }; -getLanguageList().then((languages) => { +Misc.getLanguageList().then((languages) => { languages.forEach((language) => { $( ".pageAccount .content .filterButtons .buttonsAndTitle.languages .buttons" @@ -1020,7 +1018,7 @@ getLanguageList().then((languages) => { $( ".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons" ).append(`
none
`); -getFunboxList().then((funboxModes) => { +Misc.getFunboxList().then((funboxModes) => { funboxModes.forEach((funbox) => { $( ".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons" @@ -1883,7 +1881,7 @@ function refreshAccountPage() { filteredResults.push(result); } catch (e) { - showNotification( + Misc.showNotification( "Something went wrong when filtering. Resetting filters.", 5000 ); @@ -2038,7 +2036,7 @@ function refreshAccountPage() { }); activityChartData_avgWpm.push({ x: parseInt(date), - y: roundTo2( + y: Misc.roundTo2( activityChartData[date].totalWpm / activityChartData[date].amount ), }); @@ -2206,7 +2204,7 @@ function refreshAccountPage() { let wpmPoints = filteredResults.map((r) => r.wpm).reverse(); - let trend = findLineByLeastSquares(wpmPoints); + let trend = Misc.findLineByLeastSquares(wpmPoints); let wpmChange = trend[1][1] - trend[0][1]; @@ -2216,7 +2214,7 @@ function refreshAccountPage() { $(".pageAccount .group.chart .below .text").text( `Speed change per hour spent typing: ${ - plus + roundTo2(wpmChangePerHour) + plus + Misc.roundTo2(wpmChangePerHour) } wpm.` ); @@ -2226,7 +2224,7 @@ function refreshAccountPage() { swapElements($(".pageAccount .preloader"), $(".pageAccount .content"), 250); } if (db_getSnapshot() === null) { - showNotification(`Missing account data. Please refresh.`, 5000); + Misc.showNotification(`Missing account data. Please refresh.`, 5000); $(".pageAccount .preloader").html("Missing account data. Please refresh."); } else if (db_getSnapshot().results === undefined) { db_getUserResults().then((d) => { @@ -2244,7 +2242,7 @@ function refreshAccountPage() { cont(); } catch (e) { console.error(e); - showNotification(`Something went wrong: ${e}`, 5000); + Misc.showNotification(`Something went wrong: ${e}`, 5000); } } } @@ -2339,14 +2337,14 @@ $("#resultEditTagsPanel .confirmButton").click((f) => { }); showBackgroundLoader(); hideResultEditTagsPanel(); - updateResultTags({ + CloudFunctions.updateResultTags({ uid: firebase.auth().currentUser.uid, tags: newtags, resultid: resultid, }).then((r) => { hideBackgroundLoader(); if (r.data.resultCode === 1) { - showNotification("Tags updated.", 3000); + Misc.showNotification("Tags updated.", 3000); db_getSnapshot().results.forEach((result) => { if (result.id === resultid) { result.tags = newtags; @@ -2397,7 +2395,7 @@ $("#resultEditTagsPanel .confirmButton").click((f) => { ); } } else { - showNotification("Error updating tags", 3000); + Misc.showNotification("Error updating tags", 3000); } }); }); diff --git a/src/js/cloud-functions.js b/src/js/cloud-functions.js new file mode 100644 index 000000000..b861d647b --- /dev/null +++ b/src/js/cloud-functions.js @@ -0,0 +1,28 @@ +export const testCompleted = firebase + .functions() + .httpsCallable("testCompleted"); +export const addTag = firebase.functions().httpsCallable("addTag"); +export const editTag = firebase.functions().httpsCallable("editTag"); +export const removeTag = firebase.functions().httpsCallable("removeTag"); +export const updateResultTags = firebase + .functions() + .httpsCallable("updateResultTags"); +export const saveConfig = firebase.functions().httpsCallable("saveConfig"); +export const generatePairingCode = firebase + .functions() + .httpsCallable("generatePairingCode"); +export const saveLbMemory = firebase.functions().httpsCallable("saveLbMemory"); +export const unlinkDiscord = firebase + .functions() + .httpsCallable("unlinkDiscord"); +export const verifyUser = firebase.functions().httpsCallable("verifyUser"); +export const reserveName = firebase + .functions() + .httpsCallable("reserveDisplayName"); +export const updateEmail = firebase.functions().httpsCallable("updateEmail"); +export const namecheck = firebase + .functions() + .httpsCallable("checkNameAvailability"); +export const getLeaderboard = firebase + .functions() + .httpsCallable("getLeaderboard"); diff --git a/src/js/commandline.js b/src/js/commandline.js index d887336d0..0e2a2d968 100644 --- a/src/js/commandline.js +++ b/src/js/commandline.js @@ -1,3 +1,17 @@ +function canBailOut() { + return ( + (config.mode === "custom" && + customTextIsRandom && + customTextWordCount >= 5000) || + (config.mode === "custom" && + !customTextIsRandom && + customText.length >= 5000) || + (config.mode === "words" && config.words >= 5000) || + config.words === 0 || + (config.mode === "time" && (config.time >= 3600 || config.time === 0)) + ); +} + function addChildCommands( unifiedCommands, commandItem, @@ -557,7 +571,7 @@ let commands = { id: "toggleFullscreen", display: "Toggle Fullscreen", exec: () => { - toggleFullscreen(); + Misc.toggleFullscreen(); }, }, { @@ -841,7 +855,7 @@ let commandsEnableAds = { display: "off", exec: () => { setEnableAds("off"); - showNotification("Don't forget to refresh the page!", 3000); + Misc.showNotification("Don't forget to refresh the page!", 3000); }, }, { @@ -849,7 +863,7 @@ let commandsEnableAds = { display: "on", exec: () => { setEnableAds("on"); - showNotification("Don't forget to refresh the page!", 3000); + Misc.showNotification("Don't forget to refresh the page!", 3000); }, }, { @@ -857,7 +871,7 @@ let commandsEnableAds = { display: "Sellout", exec: () => { setEnableAds("max"); - showNotification("Don't forget to refresh the page!", 3000); + Misc.showNotification("Don't forget to refresh the page!", 3000); }, }, ], @@ -1510,10 +1524,10 @@ function updateCommandsTagsList() { } } -getThemesList().then((themes) => { +Misc.getThemesList().then((themes) => { themes.forEach((theme) => { commandsThemes.list.push({ - id: "changeTheme" + capitalizeFirstLetter(theme.name), + id: "changeTheme" + Misc.capitalizeFirstLetter(theme.name), display: theme.name.replace(/_/g, " "), hover: () => { previewTheme(theme.name); @@ -1530,7 +1544,7 @@ function showFavouriteThemesAtTheTop() { commandsThemes.list = []; config.favThemes.forEach((theme) => { commandsThemes.list.push({ - id: "changeTheme" + capitalizeFirstLetter(theme), + id: "changeTheme" + Misc.capitalizeFirstLetter(theme), display: theme.replace(/_/g, " "), hover: () => { previewTheme(theme); @@ -1540,11 +1554,11 @@ function showFavouriteThemesAtTheTop() { }, }); }); - getThemesList().then((themes) => { + Misc.getThemesList().then((themes) => { themes.forEach((theme) => { if (config.favThemes.includes(theme.name)) return; commandsThemes.list.push({ - id: "changeTheme" + capitalizeFirstLetter(theme.name), + id: "changeTheme" + Misc.capitalizeFirstLetter(theme.name), display: theme.name.replace(/_/g, " "), hover: () => { previewTheme(theme.name); @@ -1563,7 +1577,7 @@ let commandsFonts = { list: [], }; -getFontsList().then((fonts) => { +Misc.getFontsList().then((fonts) => { fonts.forEach((font) => { commandsFonts.list.push({ id: "changeFont" + font.name.replace(/ /g, "_"), @@ -1593,7 +1607,7 @@ let commandsFunbox = { ], }; -getFunboxList().then((funboxes) => { +Misc.getFunboxList().then((funboxes) => { funboxes.forEach((funbox) => { commandsFunbox.list.push({ id: "changeFunbox" + funbox.name, @@ -1623,10 +1637,10 @@ let commandsLanguages = { }; commandsLanguages.list = []; -getLanguageList().then((languages) => { +Misc.getLanguageList().then((languages) => { languages.forEach((language) => { commandsLanguages.list.push({ - id: "changeLanguage" + capitalizeFirstLetter(language), + id: "changeLanguage" + Misc.capitalizeFirstLetter(language), display: language.replace(/_/g, " "), exec: () => { setLanguage(language); @@ -1651,7 +1665,7 @@ if (Object.keys(layouts).length > 0) { commandsLayouts.list = []; Object.keys(layouts).forEach((layout) => { commandsLayouts.list.push({ - id: "changeLayout" + capitalizeFirstLetter(layout), + id: "changeLayout" + Misc.capitalizeFirstLetter(layout), display: layout.replace(/_/g, " "), exec: () => { setSavedLayout(layout); @@ -1685,7 +1699,7 @@ if (Object.keys(layouts).length > 0) { Object.keys(layouts).forEach((layout) => { if (layout.toString() != "default") { commandsKeymapLayouts.list.push({ - id: "changeKeymapLayout" + capitalizeFirstLetter(layout), + id: "changeKeymapLayout" + Misc.capitalizeFirstLetter(layout), display: layout.replace(/_/g, " "), exec: () => { setKeymapLayout(layout); diff --git a/src/js/dom-util.js b/src/js/dom-util.js new file mode 100644 index 000000000..86aed3523 --- /dev/null +++ b/src/js/dom-util.js @@ -0,0 +1,7 @@ +export function showBackgroundLoader() { + $("#backgroundLoader").stop(true, true).fadeIn(125); +} + +export function hideBackgroundLoader() { + $("#backgroundLoader").stop(true, true).fadeOut(125); +} diff --git a/src/js/exports.js b/src/js/exports.js index 42848d576..ee348143b 100644 --- a/src/js/exports.js +++ b/src/js/exports.js @@ -1,4 +1,8 @@ //this file should be concatenated with the legacy js files +//try to keep this list short because we need to eliminate it eventually +global.simplePopups = simplePopups; +global.sendVerificationEmail = Misc.sendVerificationEmail; + //these exports are just for debugging in the browser global.snapshot = db_getSnapshot; diff --git a/src/js/global-dependencies.js b/src/js/global-dependencies.js index 1d699615f..38f9239aa 100644 --- a/src/js/global-dependencies.js +++ b/src/js/global-dependencies.js @@ -16,3 +16,7 @@ import { db_getLocalPB, db_saveLocalPB, } from "./db"; + +import { showBackgroundLoader, hideBackgroundLoader } from "./dom-util"; +import * as Misc from "./misc"; +import * as CloudFunctions from "./cloud-functions"; diff --git a/src/js/leaderboards.js b/src/js/leaderboards.js index bab70d73b..bbfe21874 100644 --- a/src/js/leaderboards.js +++ b/src/js/leaderboards.js @@ -49,13 +49,13 @@ function updateLeaderboards() { showBackgroundLoader(); Promise.all([ - firebase.functions().httpsCallable("getLeaderboard")({ + CloudFunctions.getLeaderboard({ mode: boardinfo[0], mode2: boardinfo[1], type: "daily", uid: uid, }), - firebase.functions().httpsCallable("getLeaderboard")({ + CloudFunctions.getLeaderboard({ mode: boardinfo[0], mode2: boardinfo[1], type: "global", @@ -217,7 +217,7 @@ function updateLeaderboards() { } }) .catch((e) => { - showNotification("Something went wrong", 3000); + Misc.showNotification("Something went wrong", 3000); }); } diff --git a/src/js/misc.js b/src/js/misc.js index 72f5326dc..ddbea1b67 100644 --- a/src/js/misc.js +++ b/src/js/misc.js @@ -1,5 +1,7 @@ +import { showBackgroundLoader, hideBackgroundLoader } from "./dom-util"; + let themesList = null; -async function getThemesList() { +export async function getThemesList() { if (themesList == null) { return $.getJSON("themes/list.json", function (data) { const list = data.sort(function (a, b) { @@ -18,7 +20,7 @@ async function getThemesList() { } let sortedThemesList = null; -async function getSortedThemesList() { +export async function getSortedThemesList() { if (sortedThemesList == null) { if (themesList == null) { await getThemesList(); @@ -36,7 +38,7 @@ async function getSortedThemesList() { } let funboxList = null; -async function getFunboxList() { +export async function getFunboxList() { if (funboxList == null) { return $.getJSON("funbox/list.json", function (data) { funboxList = data.sort(function (a, b) { @@ -54,7 +56,7 @@ async function getFunboxList() { } let fontsList = null; -async function getFontsList() { +export async function getFontsList() { if (fontsList == null) { return $.getJSON("js/fonts.json", function (data) { fontsList = data.sort(function (a, b) { @@ -72,7 +74,7 @@ async function getFontsList() { } let languageList = null; -async function getLanguageList() { +export async function getLanguageList() { if (languageList == null) { return $.getJSON("languages/list.json", function (data) { languageList = data; @@ -84,7 +86,12 @@ async function getLanguageList() { } let currentLanguage = null; -async function getLanguage(lang) { + +export function getCurrentLanguage() { + return currentLanguage; +} + +export async function getLanguage(lang) { try { if (currentLanguage == null || currentLanguage.name !== lang) { console.log("getting language json"); @@ -96,7 +103,8 @@ async function getLanguage(lang) { } catch (e) { console.error(`error getting language`); console.error(e); - config.language = "english"; + //TODO: set config language to english + //config.language = "english"; showNotification(`Error getting language: ${e.message}`, 4000); await $.getJSON(`languages/english.json`, function (data) { currentLanguage = data; @@ -105,14 +113,14 @@ async function getLanguage(lang) { } } -function setCookie(cname, cvalue, exdays) { +export function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000); var expires = "expires=" + d.toUTCString(); document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; } -function getCookie(cname) { +export function getCookie(cname) { var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(";"); @@ -128,7 +136,7 @@ function getCookie(cname) { return ""; } -function sendVerificationEmail() { +export function sendVerificationEmail() { showBackgroundLoader(); let cu = firebase.auth().currentUser; cu.sendEmailVerification() @@ -142,9 +150,8 @@ function sendVerificationEmail() { console.error(e.message); }); } -window.sendVerificationEmail = sendVerificationEmail; -function smooth(arr, windowSize, getter = (value) => value, setter) { +export function smooth(arr, windowSize, getter = (value) => value, setter) { const get = getter; const result = []; @@ -166,7 +173,7 @@ function smooth(arr, windowSize, getter = (value) => value, setter) { return result; } -function stdDev(array) { +export function stdDev(array) { try { const n = array.length; const mean = array.reduce((a, b) => a + b) / n; @@ -178,7 +185,7 @@ function stdDev(array) { } } -function mean(array) { +export function mean(array) { try { return ( array.reduce((previous, current) => (current += previous)) / array.length @@ -188,7 +195,7 @@ function mean(array) { } } -function showNotification(text, time) { +export function showNotification(text, time) { let noti = $(".notification"); noti.text(text); noti.css("top", `-${noti.outerHeight()}px`); @@ -221,7 +228,7 @@ function showNotification(text, time) { ); } -function getReleasesFromGitHub() { +export function getReleasesFromGitHub() { $.getJSON( "https://api.github.com/repos/Miodec/monkeytype/releases", (data) => { @@ -257,19 +264,19 @@ function getReleasesFromGitHub() { // }); // } -function getLastChar(word) { +export function getLastChar(word) { return word.charAt(word.length - 1); } -function capitalizeFirstLetter(str) { +export function capitalizeFirstLetter(str) { return str.charAt(0).toUpperCase() + str.slice(1); } -function isASCIILetter(c) { +export function isASCIILetter(c) { return c.length === 1 && /[a-z]/i.test(c); } -function kogasa(cov) { +export function kogasa(cov) { return ( 100 * (1 - Math.tanh(cov + Math.pow(cov, 3) / 3 + Math.pow(cov, 5) / 5)) ); @@ -322,11 +329,11 @@ function hexToHSL(H) { }; } -function roundTo2(num) { +export function roundTo2(num) { return Math.round((num + Number.EPSILON) * 100) / 100; } -function findLineByLeastSquares(values_y) { +export function findLineByLeastSquares(values_y) { var sum_x = 0; var sum_y = 0; var sum_xy = 0; @@ -372,11 +379,7 @@ function findLineByLeastSquares(values_y) { return [returnpoint1, returnpoint2]; } -function calculateSlope([[x1, y1], [x2, y2]]) { - return (y1 - y2) / (x1 - x2); -} - -function getGibberish() { +export function getGibberish() { let randLen = Math.floor(Math.random() * 7) + 1; let ret = ""; for (let i = 0; i < randLen; i++) { @@ -385,7 +388,7 @@ function getGibberish() { return ret; } -function secondsToString(sec) { +export function secondsToString(sec) { const hours = Math.floor(sec / 3600); const minutes = Math.floor((sec % 3600) / 60); const seconds = roundTo2((sec % 3600) % 60); @@ -405,7 +408,7 @@ function secondsToString(sec) { return ret; } -function getNumbers(len) { +export function getNumbers(len) { let randLen = Math.floor(Math.random() * len) + 1; let ret = ""; for (let i = 0; i < randLen; i++) { @@ -415,7 +418,7 @@ function getNumbers(len) { return ret; } -function getSpecials() { +export function getSpecials() { let randLen = Math.floor(Math.random() * 7) + 1; let ret = ""; let specials = [ @@ -449,7 +452,7 @@ function getSpecials() { return ret; } -function getASCII() { +export function getASCII() { let randLen = Math.floor(Math.random() * 10) + 1; let ret = ""; for (let i = 0; i < randLen; i++) { @@ -458,7 +461,7 @@ function getASCII() { return ret; } -function getPositionString(number) { +export function getPositionString(number) { let numend = "th"; let t = number % 10; let h = number % 100; @@ -474,7 +477,7 @@ function getPositionString(number) { return number + numend; } -function findGetParameter(parameterName) { +export function findGetParameter(parameterName) { var result = null, tmp = []; location.search @@ -487,7 +490,7 @@ function findGetParameter(parameterName) { return result; } -function objectToQueryString(obj) { +export function objectToQueryString(obj) { var str = []; for (var p in obj) if (Object.prototype.hasOwnProperty.call(obj, p)) { @@ -496,7 +499,7 @@ function objectToQueryString(obj) { return str.join("&"); } -function toggleFullscreen(elem) { +export function toggleFullscreen(elem) { elem = elem || document.documentElement; if ( @@ -526,184 +529,3 @@ function toggleFullscreen(elem) { } } } - -function canBailOut() { - return ( - (config.mode === "custom" && - customTextIsRandom && - customTextWordCount >= 5000) || - (config.mode === "custom" && - !customTextIsRandom && - customText.length >= 5000) || - (config.mode === "words" && config.words >= 5000) || - config.words === 0 || - (config.mode === "time" && (config.time >= 3600 || config.time === 0)) - ); -} - -let simplePopups = {}; -window.simplePopups = simplePopups; -class SimplePopup { - constructor( - id, - type, - title, - inputs = [], - text = "", - buttonText = "Confirm", - execFn - ) { - this.id = id; - this.type = type; - this.execFn = execFn; - this.title = title; - this.inputs = inputs; - this.text = text; - this.wrapper = $("#simplePopupWrapper"); - this.element = $("#simplePopup"); - this.buttonText = buttonText; - } - reset() { - this.element.html(` -
-
-
-
`); - } - - init() { - let el = this.element; - el.find("input").val(""); - if (el.attr("popupId") !== this.id) { - this.reset(); - el.attr("popupId", this.id); - el.find(".title").text(this.title); - el.find(".text").text(this.text); - - this.initInputs(); - - el.find(".button").text(this.buttonText); - } - } - - initInputs() { - let el = this.element; - if (this.inputs.length > 0) { - if (this.type === "number") { - this.inputs.forEach((input) => { - el.find(".inputs").append(` - - `); - }); - } else if (this.type === "text") { - this.inputs.forEach((input) => { - el.find(".inputs").append(` - - `); - }); - } - el.find(".inputs").removeClass("hidden"); - } else { - el.find(".inputs").addClass("hidden"); - } - } - - exec() { - let vals = []; - $.each($("#simplePopup input"), (index, el) => { - vals.push($(el).val()); - }); - this.execFn(...vals); - this.hide(); - } - - show() { - this.init(); - this.wrapper - .stop(true, true) - .css("opacity", 0) - .removeClass("hidden") - .animate({ opacity: 1 }, 125, () => { - $($("#simplePopup").find("input")[0]).focus(); - }); - } - - hide() { - this.wrapper - .stop(true, true) - .css("opacity", 1) - .removeClass("hidden") - .animate({ opacity: 0 }, 125, () => { - this.wrapper.addClass("hidden"); - }); - } -} - -$("#simplePopupWrapper").click((e) => { - if ($(e.target).attr("id") === "simplePopupWrapper") { - $("#simplePopupWrapper") - .stop(true, true) - .css("opacity", 1) - .removeClass("hidden") - .animate({ opacity: 0 }, 125, () => { - $("#simplePopupWrapper").addClass("hidden"); - }); - } -}); - -$(document).on("click", "#simplePopupWrapper .button", (e) => { - let id = $("#simplePopup").attr("popupId"); - simplePopups[id].exec(); -}); - -$(document).on("keyup", "#simplePopupWrapper input", (e) => { - if (e.key === "Enter") { - let id = $("#simplePopup").attr("popupId"); - simplePopups[id].exec(); - } -}); - -simplePopups.updateEmail = new SimplePopup( - "updateEmail", - "text", - "Update Email", - [ - { - placeholder: "Current email", - initVal: "", - }, - { - placeholder: "New email", - initVal: "", - }, - ], - "Don't mess this one up or you won't be able to login!", - "Update", - (previousEmail, newEmail) => { - try { - showBackgroundLoader(); - updateEmail({ - uid: firebase.auth().currentUser.uid, - previousEmail: previousEmail, - newEmail: newEmail, - }).then((data) => { - hideBackgroundLoader(); - if (data.data.resultCode === 1) { - showNotification("Email updated", 2000); - setTimeout(() => { - signOut(); - }, 1000); - } else if (data.data.resultCode === -1) { - showNotification("Current email doesn't match", 2000); - } else { - showNotification( - "Something went wrong: " + JSON.stringify(data.data), - 7000 - ); - } - }); - } catch (e) { - showNotification("Something went wrong: " + e, 5000); - } - } -); diff --git a/src/js/script.js b/src/js/script.js index 3ae1a8b29..29fcc608e 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -203,21 +203,6 @@ let customTextIsRandom = false; let customTextWordCount = 1; let randomQuote = null; -const testCompleted = firebase.functions().httpsCallable("testCompleted"); -const addTag = firebase.functions().httpsCallable("addTag"); -const editTag = firebase.functions().httpsCallable("editTag"); -const removeTag = firebase.functions().httpsCallable("removeTag"); -const updateResultTags = firebase.functions().httpsCallable("updateResultTags"); -const saveConfig = firebase.functions().httpsCallable("saveConfig"); -const generatePairingCode = firebase - .functions() - .httpsCallable("generatePairingCode"); -const saveLbMemory = firebase.functions().httpsCallable("saveLbMemory"); -const unlinkDiscord = firebase.functions().httpsCallable("unlinkDiscord"); -const verifyUser = firebase.functions().httpsCallable("verifyUser"); -const reserveName = firebase.functions().httpsCallable("reserveDisplayName"); -const updateEmail = firebase.functions().httpsCallable("updateEmail"); - function refreshThemeColorObject() { let st = getComputedStyle(document.body); @@ -240,7 +225,10 @@ function refreshThemeColorObject() { function copyResultToClipboard() { if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) { - showNotification("Sorry, this feature is not supported in Firefox", 4000); + Misc.showNotification( + "Sorry, this feature is not supported in Firefox", + 4000 + ); } else { $(".pageTest .ssWatermark").removeClass("hidden"); $(".pageTest .buttons").addClass("hidden"); @@ -271,7 +259,7 @@ function copyResultToClipboard() { ]) .then((f) => { $(".notification").removeClass("hidden"); - showNotification("Copied to clipboard", 1000); + Misc.showNotification("Copied to clipboard", 1000); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -279,7 +267,7 @@ function copyResultToClipboard() { }) .catch((f) => { $(".notification").removeClass("hidden"); - showNotification("Error saving image to clipboard", 2000); + Misc.showNotification("Error saving image to clipboard", 2000); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -289,7 +277,7 @@ function copyResultToClipboard() { }); } catch (e) { $(".notification").removeClass("hidden"); - showNotification("Error creating image", 2000); + Misc.showNotification("Error creating image", 2000); $(".pageTest .ssWatermark").addClass("hidden"); $(".pageTest .buttons").removeClass("hidden"); if (firebase.auth().currentUser == null) @@ -300,15 +288,15 @@ function copyResultToClipboard() { function activateFunbox(funbox, mode) { if (testActive || resultVisible) { - showNotification( + Misc.showNotification( "You can only change the funbox before starting a test.", 4000 ); return false; } - if (currentLanguage.ligatures) { + if (Misc.getCurrentLanguage().ligatures) { if (funbox == "choo_choo" || funbox == "earthquake") { - showNotification( + Misc.showNotification( "Current language does not support this funbox mode", 3000 ); @@ -424,7 +412,7 @@ async function initWords() { currentCorrected = ""; currentInput = ""; - let language = await getLanguage(config.language); + let language = await Misc.getLanguage(config.language); if (config.mode === "quote" && quotes === null) { showBackgroundLoader(); @@ -526,16 +514,16 @@ async function initWords() { } randomWord = randomcaseword; } else if (activeFunBox === "gibberish") { - randomWord = getGibberish(); + randomWord = Misc.getGibberish(); } else if (activeFunBox === "58008") { setToggleSettings(false, true); - randomWord = getNumbers(7); + randomWord = Misc.getNumbers(7); } else if (activeFunBox === "specials") { setToggleSettings(false, true); - randomWord = getSpecials(); + randomWord = Misc.getSpecials(); } else if (activeFunBox === "ascii") { setToggleSettings(false, true); - randomWord = getASCII(); + randomWord = Misc.getASCII(); } if (config.punctuation && config.mode != "custom") { @@ -543,7 +531,7 @@ async function initWords() { } if (config.numbers && config.mode != "custom") { if (Math.random() < 0.1) { - randomWord = getNumbers(4); + randomWord = Misc.getNumbers(4); } } @@ -603,7 +591,8 @@ function emulateLayout(event) { function emulatedLayoutShouldShiftKey(event, newKeyPreview) { if (config.capsLockBackspace) return event.shiftKey; const isCapsLockHeld = event.originalEvent.getModifierState("CapsLock"); - if (isCapsLockHeld) return isASCIILetter(newKeyPreview) !== event.shiftKey; + if (isCapsLockHeld) + return Misc.isASCIILetter(newKeyPreview) !== event.shiftKey; return event.shiftKey; } @@ -617,7 +606,7 @@ function emulateLayout(event) { } if (config.layout === "default") { //override the caps lock modifier for the default layout if needed - if (config.capsLockBackspace && isASCIILetter(event.key)) { + if (config.capsLockBackspace && Misc.isASCIILetter(event.key)) { replaceEventKey( event, event.shiftKey @@ -698,16 +687,16 @@ function punctuateWord(previousWord, currentWord, index, maxindex) { if ( index == 0 || - getLastChar(previousWord) == "." || - getLastChar(previousWord) == "?" || - getLastChar(previousWord) == "!" + Misc.getLastChar(previousWord) == "." || + Misc.getLastChar(previousWord) == "?" || + Misc.getLastChar(previousWord) == "!" ) { //always capitalise the first word or if there was a dot - word = capitalizeFirstLetter(word); + word = Misc.capitalizeFirstLetter(word); } else if ( //10% chance to end a sentence (Math.random() < 0.1 && - getLastChar(previousWord) != "." && + Misc.getLastChar(previousWord) != "." && index != maxindex - 2) || index == maxindex - 1 ) { @@ -721,8 +710,8 @@ function punctuateWord(previousWord, currentWord, index, maxindex) { } } else if ( Math.random() < 0.01 && - getLastChar(previousWord) != "," && - getLastChar(previousWord) != "." + Misc.getLastChar(previousWord) != "," && + Misc.getLastChar(previousWord) != "." ) { //1% chance to add quotes word = `"${word}"`; @@ -731,21 +720,21 @@ function punctuateWord(previousWord, currentWord, index, maxindex) { word = word + ":"; } else if ( Math.random() < 0.01 && - getLastChar(previousWord) != "," && - getLastChar(previousWord) != "." && + Misc.getLastChar(previousWord) != "," && + Misc.getLastChar(previousWord) != "." && previousWord != "-" ) { //1% chance to add a dash word = "-"; } else if ( Math.random() < 0.01 && - getLastChar(previousWord) != "," && - getLastChar(previousWord) != "." && - getLastChar(previousWord) != ";" + Misc.getLastChar(previousWord) != "," && + Misc.getLastChar(previousWord) != "." && + Misc.getLastChar(previousWord) != ";" ) { //1% chance to add semicolon word = word + ";"; - } else if (Math.random() < 0.2 && getLastChar(previousWord) != ",") { + } else if (Math.random() < 0.2 && Misc.getLastChar(previousWord) != ",") { //2% chance to add a comma word += ","; } @@ -770,10 +759,10 @@ function addWord() { return; const language = config.mode !== "custom" - ? currentLanguage + ? Misc.getCurrentLanguage() : { //borrow the direction of the current language - leftToRight: currentLanguage.leftToRight, + leftToRight: Misc.getCurrentLanguage().leftToRight, words: customText, }; const wordset = language.words; @@ -812,13 +801,13 @@ function addWord() { } randomWord = randomcaseword; } else if (activeFunBox === "gibberish") { - randomWord = getGibberish(); + randomWord = Misc.getGibberish(); } else if (activeFunBox === "58008") { - randomWord = getNumbers(7); + randomWord = Misc.getNumbers(7); } else if (activeFunBox === "specials") { - randomWord = getSpecials(); + randomWord = Misc.getSpecials(); } else if (activeFunBox === "ascii") { - randomWord = getASCII(); + randomWord = Misc.getASCII(); } if (config.punctuation && config.mode != "custom") { @@ -826,7 +815,7 @@ function addWord() { } if (config.numbers && config.mode != "custom") { if (Math.random() < 0.1) { - randomWord = getNumbers(4); + randomWord = Misc.getNumbers(4); } } @@ -888,7 +877,7 @@ $("#restartTestButton, #startTestButton").on("click", function () { memoryFunboxTimer = Math.round(Math.pow(wordsList.length, 1.2)); memoryFunboxInterval = setInterval(() => { memoryFunboxTimer -= 1; - showNotification(memoryFunboxTimer); + Misc.showNotification(memoryFunboxTimer); if (memoryFunboxTimer < 0) { memoryFunboxInterval = clearInterval(memoryFunboxInterval); memoryFunboxTimer = null; @@ -965,7 +954,7 @@ function compareInput(showError) { showResult(true); } let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; } @@ -1013,7 +1002,7 @@ function compareInput(showError) { showResult(true); } let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; } @@ -1166,15 +1155,15 @@ function updateTimer() { "linear" ); } else if (config.timerStyle === "text") { - let displayTime = secondsToString(config.time - time); + let displayTime = Misc.secondsToString(config.time - time); if (config.time === 0) { - displayTime = secondsToString(time); + displayTime = Misc.secondsToString(time); } $("#timerNumber").html("
" + displayTime + "
"); } else if (config.timerStyle === "mini") { - let displayTime = secondsToString(config.time - time); + let displayTime = Misc.secondsToString(config.time - time); if (config.time === 0) { - displayTime = secondsToString(time); + displayTime = Misc.secondsToString(time); } $("#miniTimerAndLiveWpm .time").html(displayTime); } @@ -1449,7 +1438,7 @@ function updateCaretPosition() { } if ($(currentLetter).length == 0) return; - const isLanguageLeftToRight = currentLanguage.leftToRight; + const isLanguageLeftToRight = Misc.getCurrentLanguage().leftToRight; let currentLetterPosLeft = isLanguageLeftToRight ? currentLetter.offsetLeft : currentLetter.offsetLeft + $(currentLetter).width(); @@ -1590,10 +1579,10 @@ function countChars() { function calculateStats() { let testSeconds = (testEnd - testStart) / 1000; let chars = countChars(); - let wpm = roundTo2( + let wpm = Misc.roundTo2( ((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5 ); - let wpmraw = roundTo2( + let wpmraw = Misc.roundTo2( ((chars.allCorrectChars + chars.spaces + chars.incorrectChars + @@ -1601,7 +1590,7 @@ function calculateStats() { (60 / testSeconds)) / 5 ); - let acc = roundTo2( + let acc = Misc.roundTo2( (accuracyStats.correct / (accuracyStats.correct + accuracyStats.incorrect)) * 100 @@ -1672,33 +1661,33 @@ function showResult(difficultyFailed = false) { clearTimeout(timer); let testtime = stats.time; let afkseconds = keypressPerSecond.filter((x) => x.count == 0).length; - let afkSecondsPercent = roundTo2((afkseconds / testtime) * 100); + let afkSecondsPercent = Misc.roundTo2((afkseconds / testtime) * 100); $("#result #resultWordsHistory").addClass("hidden"); if (config.alwaysShowDecimalPlaces) { if (config.alwaysShowCPM == false) { $("#result .stats .wpm .top .text").text("wpm"); - $("#result .stats .wpm .bottom").text(roundTo2(stats.wpm)); - $("#result .stats .raw .bottom").text(roundTo2(stats.wpmRaw)); + $("#result .stats .wpm .bottom").text(Misc.roundTo2(stats.wpm)); + $("#result .stats .raw .bottom").text(Misc.roundTo2(stats.wpmRaw)); $("#result .stats .wpm .bottom").attr( "aria-label", - roundTo2(stats.wpm * 5) + " cpm" + Misc.roundTo2(stats.wpm * 5) + " cpm" ); } else { $("#result .stats .wpm .top .text").text("cpm"); - $("#result .stats .wpm .bottom").text(roundTo2(stats.wpm * 5)); - $("#result .stats .raw .bottom").text(roundTo2(stats.wpmRaw * 5)); + $("#result .stats .wpm .bottom").text(Misc.roundTo2(stats.wpm * 5)); + $("#result .stats .raw .bottom").text(Misc.roundTo2(stats.wpmRaw * 5)); $("#result .stats .wpm .bottom").attr( "aria-label", - roundTo2(stats.wpm) + " wpm" + Misc.roundTo2(stats.wpm) + " wpm" ); } - $("#result .stats .acc .bottom").text(roundTo2(stats.acc) + "%"); - let time = roundTo2(testtime) + "s"; + $("#result .stats .acc .bottom").text(Misc.roundTo2(stats.acc) + "%"); + let time = Misc.roundTo2(testtime) + "s"; if (testtime > 61) { - time = secondsToString(roundTo2(testtime)); + time = Misc.secondsToString(Misc.roundTo2(testtime)); } $("#result .stats .time .bottom .text").text(time); $("#result .stats .raw .bottom").removeAttr("aria-label"); @@ -1713,7 +1702,7 @@ function showResult(difficultyFailed = false) { $("#result .stats .wpm .top .text").text("wpm"); $("#result .stats .wpm .bottom").attr( "aria-label", - stats.wpm + ` (${roundTo2(stats.wpm * 5)} cpm)` + stats.wpm + ` (${Misc.roundTo2(stats.wpm * 5)} cpm)` ); $("#result .stats .wpm .bottom").text(Math.round(stats.wpm)); $("#result .stats .raw .bottom").text(Math.round(stats.wpmRaw)); @@ -1722,7 +1711,7 @@ function showResult(difficultyFailed = false) { $("#result .stats .wpm .top .text").text("cpm"); $("#result .stats .wpm .bottom").attr( "aria-label", - stats.wpm * 5 + ` (${roundTo2(stats.wpm)} wpm)` + stats.wpm * 5 + ` (${Misc.roundTo2(stats.wpm)} wpm)` ); $("#result .stats .wpm .bottom").text(Math.round(stats.wpm * 5)); $("#result .stats .raw .bottom").text(Math.round(stats.wpmRaw * 5)); @@ -1733,12 +1722,12 @@ function showResult(difficultyFailed = false) { $("#result .stats .acc .bottom").attr("aria-label", stats.acc + "%"); let time = Math.round(testtime) + "s"; if (testtime > 61) { - time = secondsToString(Math.round(testtime)); + time = Misc.secondsToString(Math.round(testtime)); } $("#result .stats .time .bottom .text").text(time); $("#result .stats .time .bottom").attr( "aria-label", - `${roundTo2(testtime)}s (${afkseconds}s afk ${afkSecondsPercent}%)` + `${Misc.roundTo2(testtime)}s (${afkseconds}s afk ${afkSecondsPercent}%)` ); } $("#result .stats .time .bottom .afk").text(""); @@ -1803,7 +1792,7 @@ function showResult(difficultyFailed = false) { let labels = []; for (let i = 1; i <= wpmHistory.length; i++) { if (lastSecondNotRound && i === wpmHistory.length) { - labels.push(roundTo2(testtime).toString()); + labels.push(Misc.roundTo2(testtime).toString()); } else { labels.push(i.toString()); } @@ -1832,15 +1821,16 @@ function showResult(difficultyFailed = false) { Math.round((f.count / 5) * 60) ); - let rawWpmPerSecond = smooth(rawWpmPerSecondRaw, 1); + let rawWpmPerSecond = Misc.smooth(rawWpmPerSecondRaw, 1); - let stddev = stdDev(rawWpmPerSecondRaw); - let avg = mean(rawWpmPerSecondRaw); + let stddev = Misc.stdDev(rawWpmPerSecondRaw); + let avg = Misc.mean(rawWpmPerSecondRaw); - let consistency = roundTo2(kogasa(stddev / avg)); - let keyConsistency = roundTo2( - kogasa( - stdDev(keypressStats.spacing.array) / mean(keypressStats.spacing.array) + let consistency = Misc.roundTo2(Misc.kogasa(stddev / avg)); + let keyConsistency = Misc.roundTo2( + Misc.kogasa( + Misc.stdDev(keypressStats.spacing.array) / + Misc.mean(keypressStats.spacing.array) ) ); @@ -1849,7 +1839,9 @@ function showResult(difficultyFailed = false) { } if (config.alwaysShowDecimalPlaces) { - $("#result .stats .consistency .bottom").text(roundTo2(consistency) + "%"); + $("#result .stats .consistency .bottom").text( + Misc.roundTo2(consistency) + "%" + ); $("#result .stats .consistency .bottom").attr( "aria-label", `${keyConsistency}% key` @@ -1925,11 +1917,11 @@ function showResult(difficultyFailed = false) { if (bailout) afkDetected = false; if (difficultyFailed) { - showNotification("Test failed", 2000); + Misc.showNotification("Test failed", 2000); } else if (afkDetected) { - showNotification("Test invalid - AFK detected", 2000); + Misc.showNotification("Test invalid - AFK detected", 2000); } else if (sameWordset) { - showNotification("Test invalid - repeated", 2000); + Misc.showNotification("Test invalid - repeated", 2000); } else { let activeTags = []; try { @@ -2035,7 +2027,7 @@ function showResult(difficultyFailed = false) { showCrown(); $("#result .stats .wpm .crown").attr( "aria-label", - "+" + roundTo2(pbDiff) + "+" + Misc.roundTo2(pbDiff) ); } localPb = true; @@ -2057,39 +2049,39 @@ function showResult(difficultyFailed = false) { } $("#result .stats .leaderboards").removeClass("hidden"); $("#result .stats .leaderboards .bottom").html("checking..."); - testCompleted({ + CloudFunctions.testCompleted({ uid: firebase.auth().currentUser.uid, obj: completedEvent, }) .then((e) => { accountIconLoading(false); if (e.data == null) { - showNotification( + Misc.showNotification( "Unexpected response from the server.", 4000 ); return; } if (e.data.resultCode === -1) { - showNotification("Could not save result", 3000); + Misc.showNotification("Could not save result", 3000); } else if (e.data.resultCode === -2) { - showNotification( + Misc.showNotification( "Possible bot detected. Result not saved.", 4000 ); } else if (e.data.resultCode === -3) { - showNotification( + Misc.showNotification( "Could not verify keypress stats. Result not saved.", 4000 ); } else if (e.data.resultCode === -4) { - showNotification( + Misc.showNotification( "Result data does not make sense. Result not saved.", 4000 ); } else if (e.data.resultCode === -999) { console.error("internal error: " + e.data.message); - showNotification( + Misc.showNotification( "Internal error. Result might not be saved. " + e.data.message, 6000 @@ -2170,7 +2162,7 @@ function showResult(difficultyFailed = false) { "global", glb.insertedAt ); - let str = getPositionString(glb.insertedAt + 1); + let str = Misc.getPositionString(glb.insertedAt + 1); globalLbString = `global: ${str}`; } else { globalLbDiff = glbMemory - glb.foundAt; @@ -2180,7 +2172,7 @@ function showResult(difficultyFailed = false) { "global", glb.foundAt ); - let str = getPositionString(glb.foundAt + 1); + let str = Misc.getPositionString(glb.foundAt + 1); globalLbString = `global: ${str}`; } } @@ -2226,7 +2218,7 @@ function showResult(difficultyFailed = false) { "daily", dlb.insertedAt ); - let str = getPositionString(dlb.insertedAt + 1); + let str = Misc.getPositionString(dlb.insertedAt + 1); dailyLbString = `daily: ${str}`; } else { dailyLbDiff = dlbMemory - dlb.foundAt; @@ -2236,7 +2228,7 @@ function showResult(difficultyFailed = false) { "daily", dlb.foundAt ); - let str = getPositionString(dlb.foundAt + 1); + let str = Misc.getPositionString(dlb.foundAt + 1); dailyLbString = `daily: ${str}`; } } @@ -2255,13 +2247,13 @@ function showResult(difficultyFailed = false) { globalLbString + "
" + dailyLbString ); - saveLbMemory({ + CloudFunctions.saveLbMemory({ uid: firebase.auth().currentUser.uid, obj: db_getSnapshot().lbMemory, }).then((d) => { if (d.data.returnCode === 1) { } else { - showNotification( + Misc.showNotification( `Error saving lb memory ${d.data.message}`, 4000 ); @@ -2311,7 +2303,7 @@ function showResult(difficultyFailed = false) { ); } else if (e.data.resultCode === 1) { if (localPb) { - showNotification( + Misc.showNotification( "Local PB data is out of sync! Refresh the page to resync it or contact Miodec on Discord.", 15000 ); @@ -2321,7 +2313,7 @@ function showResult(difficultyFailed = false) { }) .catch((e) => { console.error(e); - showNotification("Could not save result. " + e, 5000); + Misc.showNotification("Could not save result. " + e, 5000); }); }); }); @@ -2334,7 +2326,7 @@ function showResult(difficultyFailed = false) { notSignedInLastResult = completedEvent; } } else { - showNotification("Test invalid", 3000); + Misc.showNotification("Test invalid", 3000); testInvalid = true; try { firebase.analytics().logEvent("testCompletedInvalid", completedEvent); @@ -2541,23 +2533,23 @@ function startTest() { time == Math.floor(config.time / 3) - 3 || time == (config.time / 3) * 2 - 3 ) { - showNotification("3", 1000); + Misc.showNotification("3", 1000); } if ( time == Math.floor(config.time / 3) - 2 || time == Math.floor(config.time / 3) * 2 - 2 ) { - showNotification("2", 1000); + Misc.showNotification("2", 1000); } if ( time == Math.floor(config.time / 3) - 1 || time == Math.floor(config.time / 3) * 2 - 1 ) { - showNotification("1", 1000); + Misc.showNotification("1", 1000); } if (config.layout !== layouts[index] && layouts[index] !== undefined) { - showNotification(`--- !!! ${layouts[index]} !!! ---`, 3000); + Misc.showNotification(`--- !!! ${layouts[index]} !!! ---`, 3000); } setLayout(layouts[index]); setKeymapLayout(layouts[index]); @@ -2618,7 +2610,7 @@ function restartTest(withSameWordset = false, nosave = false) { customText.length < 1000) ) { } else { - showNotification( + Misc.showNotification( "Restart disabled for long tests. Use your mouse to confirm.", 4000 ); @@ -2627,7 +2619,7 @@ function restartTest(withSameWordset = false, nosave = false) { } if (modeBeforePractise !== null && !withSameWordset) { - showNotification("Reverting to previous settings.", 1500); + Misc.showNotification("Reverting to previous settings.", 1500); setMode(modeBeforePractise); modeBeforePractise = null; } @@ -2688,7 +2680,7 @@ function restartTest(withSameWordset = false, nosave = false) { !config.customTheme ) { randomiseTheme(); - showNotification(config.theme.replace(/_/g, " "), 1500); + Misc.showNotification(config.theme.replace(/_/g, " "), 1500); } } resultVisible = false; @@ -2774,7 +2766,10 @@ function setCustomText() { customText = customText.replace(/ +/gm, " "); customText = customText.split(" "); if (customText.length >= 10000) { - showNotification("Custom text cannot be longer than 10000 words.", 4000); + Misc.showNotification( + "Custom text cannot be longer than 10000 words.", + 4000 + ); setMode("time"); customText = "The quick brown fox jumped over the lazy dog".split(" "); } @@ -2872,7 +2867,7 @@ function changePage(page) { function setMode(mode, nosave) { if (mode !== "words" && activeFunBox === "memory") { - showNotification("Memory funbox can only be used with words mode."); + Misc.showNotification("Memory funbox can only be used with words mode."); return; } @@ -3289,14 +3284,6 @@ function hideEditTags() { } } -function showBackgroundLoader() { - $("#backgroundLoader").stop(true, true).fadeIn(125); -} - -function hideBackgroundLoader() { - $("#backgroundLoader").stop(true, true).fadeOut(125); -} - function updateTestModesNotice() { let anim = false; if ($(".pageTest #testModesNotice").text() === "") anim = true; @@ -3437,29 +3424,30 @@ function tagsEdit() { hideEditTags(); if (action === "add") { showBackgroundLoader(); - addTag({ uid: firebase.auth().currentUser.uid, name: inputVal }).then( - (e) => { - hideBackgroundLoader(); - let status = e.data.resultCode; - if (status === 1) { - showNotification("Tag added", 2000); - db_getSnapshot().tags.push({ - name: inputVal, - id: e.data.id, - }); - updateResultEditTagsPanelButtons(); - updateSettingsPage(); - updateFilterTags(); - } else if (status === -1) { - showNotification("Invalid tag name", 3000); - } else if (status < -1) { - showNotification("Unknown error", 3000); - } + CloudFunctions.addTag({ + uid: firebase.auth().currentUser.uid, + name: inputVal, + }).then((e) => { + hideBackgroundLoader(); + let status = e.data.resultCode; + if (status === 1) { + Misc.showNotification("Tag added", 2000); + db_getSnapshot().tags.push({ + name: inputVal, + id: e.data.id, + }); + updateResultEditTagsPanelButtons(); + updateSettingsPage(); + updateFilterTags(); + } else if (status === -1) { + Misc.showNotification("Invalid tag name", 3000); + } else if (status < -1) { + Misc.showNotification("Unknown error", 3000); } - ); + }); } else if (action === "edit") { showBackgroundLoader(); - editTag({ + CloudFunctions.editTag({ uid: firebase.auth().currentUser.uid, name: inputVal, tagid: tagid, @@ -3467,7 +3455,7 @@ function tagsEdit() { hideBackgroundLoader(); let status = e.data.resultCode; if (status === 1) { - showNotification("Tag updated", 2000); + Misc.showNotification("Tag updated", 2000); db_getSnapshot().tags.forEach((tag) => { if (tag.id === tagid) { tag.name = inputVal; @@ -3477,32 +3465,33 @@ function tagsEdit() { updateSettingsPage(); updateFilterTags(); } else if (status === -1) { - showNotification("Invalid tag name", 3000); + Misc.showNotification("Invalid tag name", 3000); } else if (status < -1) { - showNotification("Unknown error", 3000); + Misc.showNotification("Unknown error", 3000); } }); } else if (action === "remove") { showBackgroundLoader(); - removeTag({ uid: firebase.auth().currentUser.uid, tagid: tagid }).then( - (e) => { - hideBackgroundLoader(); - let status = e.data.resultCode; - if (status === 1) { - showNotification("Tag removed", 2000); - db_getSnapshot().tags.forEach((tag, index) => { - if (tag.id === tagid) { - db_getSnapshot().tags.splice(index, 1); - } - }); - updateResultEditTagsPanelButtons(); - updateSettingsPage(); - updateFilterTags(); - } else if (status < -1) { - showNotification("Unknown error", 3000); - } + CloudFunctions.removeTag({ + uid: firebase.auth().currentUser.uid, + tagid: tagid, + }).then((e) => { + hideBackgroundLoader(); + let status = e.data.resultCode; + if (status === 1) { + Misc.showNotification("Tag removed", 2000); + db_getSnapshot().tags.forEach((tag, index) => { + if (tag.id === tagid) { + db_getSnapshot().tags.splice(index, 1); + } + }); + updateResultEditTagsPanelButtons(); + updateSettingsPage(); + updateFilterTags(); + } else if (status < -1) { + Misc.showNotification("Unknown error", 3000); } - ); + }); } } @@ -3891,15 +3880,15 @@ function applyMode2Popup() { manualRestart = true; restartTest(); if (val >= 1800) { - showNotification("Stay safe and take breaks!", 3000); + Misc.showNotification("Stay safe and take breaks!", 3000); } else if (val == 0) { - showNotification( + Misc.showNotification( "Infinite time! Make sure to use Bail Out from the command line to save your result.", 5000 ); } } else { - showNotification("Custom time must be at least 1", 3000); + Misc.showNotification("Custom time must be at least 1", 3000); } } else if (mode == "words") { if (val !== null && !isNaN(val) && val >= 0) { @@ -3907,15 +3896,15 @@ function applyMode2Popup() { manualRestart = true; restartTest(); if (val > 2000) { - showNotification("Stay safe and take breaks!", 3000); + Misc.showNotification("Stay safe and take breaks!", 3000); } else if (val == 0) { - showNotification( + Misc.showNotification( "Infinite words! Make sure to use Bail Out from the command line to save your result.", 5000 ); } } else { - showNotification("Custom word amount must be at least 1", 3000); + Misc.showNotification("Custom word amount must be at least 1", 3000); } } @@ -4029,13 +4018,13 @@ $(document).on("keypress", "#restartTestButton", (event) => { ) { if (testActive) { let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; } restartTest(); } else { - showNotification("Quick restart disabled for long tests", 2000); + Misc.showNotification("Quick restart disabled for long tests", 2000); } } }); @@ -4068,7 +4057,7 @@ $(document).on("keypress", "#practiseMissedWordsButton", (event) => { if (Object.keys(missedWords).length > 0) { initPractiseMissedWords(); } else { - showNotification("You haven't missed any words.", 2000); + Misc.showNotification("You haven't missed any words.", 2000); } } }); @@ -4077,7 +4066,7 @@ $(document.body).on("click", "#practiseMissedWordsButton", (event) => { if (Object.keys(missedWords).length > 0) { initPractiseMissedWords(); } else { - showNotification("You haven't missed any words.", 2000); + Misc.showNotification("You haven't missed any words.", 2000); } }); @@ -4229,13 +4218,13 @@ $(document).keydown((event) => { ) { if (testActive) { let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; } restartTest(); } else { - showNotification("Quick restart disabled for long tests", 2000); + Misc.showNotification("Quick restart disabled for long tests", 2000); } } else { changePage("test"); @@ -4393,7 +4382,7 @@ $(document).keydown((event) => { let outof = wordsList.length; index = Math.floor((inputHistory.length + 1) / (outof / 3)); if (config.layout !== layouts[index] && layouts[index] !== undefined) { - showNotification(`--- !!! ${layouts[index]} !!! ---`, 3000); + Misc.showNotification(`--- !!! ${layouts[index]} !!! ---`, 3000); } setLayout(layouts[index]); setKeymapLayout(layouts[index]); @@ -4457,7 +4446,7 @@ $(document).keydown((event) => { lastSecondNotRound = true; showResult(true); let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; return; @@ -4476,7 +4465,7 @@ $(document).keydown((event) => { lastSecondNotRound = true; showResult(true); let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; return; @@ -4667,7 +4656,7 @@ $(document).keydown(function (event) { lastSecondNotRound = true; showResult(true); let testNow = performance.now(); - let testSeconds = roundTo2((testNow - testStart) / 1000); + let testSeconds = Misc.roundTo2((testNow - testStart) / 1000); incompleteTestSeconds += testSeconds; restartCount++; return; @@ -4764,7 +4753,7 @@ if (firebase.app().options.projectId === "monkey-type-dev-67af4") { if (window.location.hostname === "localhost") { window.onerror = function (error) { - this.showNotification(error, 3000); + Misc.showNotification(error, 3000); }; $("#top .logo .top").text("localhost"); $("head title").text($("head title").text() + " (localhost)"); @@ -4776,7 +4765,7 @@ if (window.location.hostname === "localhost") { manualRestart = true; loadConfigFromCookie(); -getReleasesFromGitHub(); +Misc.getReleasesFromGitHub(); // getPatreonNames(); $(document).on("mouseenter", "#resultWordsHistory .words .word", (e) => { @@ -4848,9 +4837,9 @@ $(".pageTest #copyWordsListButton").click(async (event) => { await navigator.clipboard.writeText( wordsList.slice(0, inputHistory.length).join(" ") ); - showNotification("Copied to clipboard", 1000); + Misc.showNotification("Copied to clipboard", 1000); } catch (e) { - showNotification("Could not copy to clipboard: " + e, 5000); + Misc.showNotification("Could not copy to clipboard: " + e, 5000); } }); diff --git a/src/js/settings.js b/src/js/settings.js index ba25156eb..094386d13 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -261,7 +261,7 @@ async function fillSettingsPage() { refreshThemeButtons(); let langEl = $(".pageSettings .section.language .buttons").empty(); - getLanguageList().then((languages) => { + Misc.getLanguageList().then((languages) => { languages.forEach((language) => { langEl.append( `
${language.replace( @@ -299,7 +299,7 @@ async function fillSettingsPage() { let funboxEl = $(".pageSettings .section.funbox .buttons").empty(); funboxEl.append(`
none
`); - getFunboxList().then((funboxModes) => { + Misc.getFunboxList().then((funboxModes) => { funboxModes.forEach((funbox) => { if (funbox.name === "mirror") { funboxEl.append( @@ -325,7 +325,7 @@ async function fillSettingsPage() { }); let fontsEl = $(".pageSettings .section.fontFamily .buttons").empty(); - getFontsList().then((fonts) => { + Misc.getFontsList().then((fonts) => { fonts.forEach((font) => { fontsEl.append( `
{ ); let url = - "https://monkeytype.com?" + objectToQueryString({ customTheme: share }); + "https://monkeytype.com?" + + Misc.objectToQueryString({ customTheme: share }); navigator.clipboard.writeText(url).then( function () { - showNotification("URL Copied to clipboard", 2000); + Misc.showNotification("URL Copied to clipboard", 2000); }, function (err) { - showNotification( + Misc.showNotification( "Something went wrong when copying the URL: " + err, 5000 ); @@ -715,7 +716,7 @@ $( ".pageSettings .section.discordIntegration .buttons .generateCodeButton" ).click((e) => { showBackgroundLoader(); - generatePairingCode({ uid: firebase.auth().currentUser.uid }) + CloudFunctions.generatePairingCode({ uid: firebase.auth().currentUser.uid }) .then((ret) => { hideBackgroundLoader(); if (ret.data.status === 1 || ret.data.status === 2) { @@ -731,7 +732,7 @@ $( }) .catch((e) => { hideBackgroundLoader(); - showNotification("Something went wrong. Error: " + e.message, 4000); + Misc.showNotification("Something went wrong. Error: " + e.message, 4000); }); }); @@ -739,15 +740,20 @@ $(".pageSettings .section.discordIntegration #unlinkDiscordButton").click( (e) => { if (confirm("Are you sure?")) { showBackgroundLoader(); - unlinkDiscord({ uid: firebase.auth().currentUser.uid }).then((ret) => { + CloudFunctions.unlinkDiscord({ + uid: firebase.auth().currentUser.uid, + }).then((ret) => { hideBackgroundLoader(); console.log(ret); if (ret.data.status === 1) { db_getSnapshot().discordId = null; - showNotification("Accounts unlinked", 2000); + Misc.showNotification("Accounts unlinked", 2000); updateDiscordSettingsSection(); } else { - showNotification("Something went wrong: " + ret.data.message, 5000); + Misc.showNotification( + "Something went wrong: " + ret.data.message, + 5000 + ); updateDiscordSettingsSection(); } }); @@ -857,7 +863,7 @@ $(".pageSettings .saveCustomThemeButton").click((e) => { } ); setCustomThemeColors(save); - showNotification("Custom theme colors saved", 1000); + Misc.showNotification("Custom theme colors saved", 1000); }); $(".pageSettings #loadCustomColorsFromPreset").click((e) => { @@ -909,10 +915,10 @@ $("#exportSettingsButton").click((e) => { let configJSON = JSON.stringify(config); navigator.clipboard.writeText(configJSON).then( function () { - showNotification("JSON Copied to clipboard", 2000); + Misc.showNotification("JSON Copied to clipboard", 2000); }, function (err) { - showNotification( + Misc.showNotification( "Something went wrong when copying the settings JSON: " + err, 5000 ); @@ -940,7 +946,7 @@ function hideSettingsImport() { try { applyConfig(JSON.parse($("#settingsImportWrapper input").val())); } catch (e) { - showNotification( + Misc.showNotification( "An error occured while importing settings: " + e, 5000 ); diff --git a/src/js/simple-popups.js b/src/js/simple-popups.js new file mode 100644 index 000000000..ef4d0b6d1 --- /dev/null +++ b/src/js/simple-popups.js @@ -0,0 +1,165 @@ +let simplePopups = {}; +class SimplePopup { + constructor( + id, + type, + title, + inputs = [], + text = "", + buttonText = "Confirm", + execFn + ) { + this.id = id; + this.type = type; + this.execFn = execFn; + this.title = title; + this.inputs = inputs; + this.text = text; + this.wrapper = $("#simplePopupWrapper"); + this.element = $("#simplePopup"); + this.buttonText = buttonText; + } + reset() { + this.element.html(` +
+
+
+
`); + } + + init() { + let el = this.element; + el.find("input").val(""); + if (el.attr("popupId") !== this.id) { + this.reset(); + el.attr("popupId", this.id); + el.find(".title").text(this.title); + el.find(".text").text(this.text); + + this.initInputs(); + + el.find(".button").text(this.buttonText); + } + } + + initInputs() { + let el = this.element; + if (this.inputs.length > 0) { + if (this.type === "number") { + this.inputs.forEach((input) => { + el.find(".inputs").append(` + + `); + }); + } else if (this.type === "text") { + this.inputs.forEach((input) => { + el.find(".inputs").append(` + + `); + }); + } + el.find(".inputs").removeClass("hidden"); + } else { + el.find(".inputs").addClass("hidden"); + } + } + + exec() { + let vals = []; + $.each($("#simplePopup input"), (index, el) => { + vals.push($(el).val()); + }); + this.execFn(...vals); + this.hide(); + } + + show() { + this.init(); + this.wrapper + .stop(true, true) + .css("opacity", 0) + .removeClass("hidden") + .animate({ opacity: 1 }, 125, () => { + $($("#simplePopup").find("input")[0]).focus(); + }); + } + + hide() { + this.wrapper + .stop(true, true) + .css("opacity", 1) + .removeClass("hidden") + .animate({ opacity: 0 }, 125, () => { + this.wrapper.addClass("hidden"); + }); + } +} + +$("#simplePopupWrapper").click((e) => { + if ($(e.target).attr("id") === "simplePopupWrapper") { + $("#simplePopupWrapper") + .stop(true, true) + .css("opacity", 1) + .removeClass("hidden") + .animate({ opacity: 0 }, 125, () => { + $("#simplePopupWrapper").addClass("hidden"); + }); + } +}); + +$(document).on("click", "#simplePopupWrapper .button", (e) => { + let id = $("#simplePopup").attr("popupId"); + simplePopups[id].exec(); +}); + +$(document).on("keyup", "#simplePopupWrapper input", (e) => { + if (e.key === "Enter") { + let id = $("#simplePopup").attr("popupId"); + simplePopups[id].exec(); + } +}); + +simplePopups.updateEmail = new SimplePopup( + "updateEmail", + "text", + "Update Email", + [ + { + placeholder: "Current email", + initVal: "", + }, + { + placeholder: "New email", + initVal: "", + }, + ], + "Don't mess this one up or you won't be able to login!", + "Update", + (previousEmail, newEmail) => { + try { + showBackgroundLoader(); + CloudFunctions.updateEmail({ + uid: firebase.auth().currentUser.uid, + previousEmail: previousEmail, + newEmail: newEmail, + }).then((data) => { + hideBackgroundLoader(); + if (data.data.resultCode === 1) { + Misc.showNotification("Email updated", 2000); + setTimeout(() => { + signOut(); + }, 1000); + } else if (data.data.resultCode === -1) { + Misc.showNotification("Current email doesn't match", 2000); + } else { + Misc.showNotification( + "Something went wrong: " + JSON.stringify(data.data), + 7000 + ); + } + }); + } catch (e) { + Misc.showNotification("Something went wrong: " + e, 5000); + } + } +); diff --git a/src/js/userconfig.js b/src/js/userconfig.js index 96a3dca73..d3744cd5f 100644 --- a/src/js/userconfig.js +++ b/src/js/userconfig.js @@ -93,7 +93,7 @@ async function saveConfigToCookie(noDbCheck = false) { // expires: d, // path: "/", // }); - setCookie("config", JSON.stringify(config), 365); + Misc.setCookie("config", JSON.stringify(config), 365); restartCount = 0; if (!noDbCheck) await saveConfigToDB(); } @@ -101,19 +101,20 @@ async function saveConfigToCookie(noDbCheck = false) { async function saveConfigToDB() { if (firebase.auth().currentUser !== null) { accountIconLoading(true); - saveConfig({ uid: firebase.auth().currentUser.uid, obj: config }).then( - (d) => { - accountIconLoading(false); - if (d.data.returnCode === 1) { - } else { - showNotification( - `Error saving config to DB! ${d.data.message}`, - 4000 - ); - } - return; + CloudFunctions.saveConfig({ + uid: firebase.auth().currentUser.uid, + obj: config, + }).then((d) => { + accountIconLoading(false); + if (d.data.returnCode === 1) { + } else { + Misc.showNotification( + `Error saving config to DB! ${d.data.message}`, + 4000 + ); } - ); + return; + }); } } @@ -141,14 +142,14 @@ function saveActiveTagsToCookie() { // expires: d, // path: "/", // }); - setCookie("activeTags", JSON.stringify(tags), 365); + Misc.setCookie("activeTags", JSON.stringify(tags), 365); } catch (e) {} } function loadConfigFromCookie() { console.log("loading cookie config"); // let newConfig = $.cookie("config"); - let newConfig = getCookie("config"); + let newConfig = Misc.getCookie("config"); if (newConfig !== undefined && newConfig !== "") { try { newConfig = JSON.parse(newConfig); @@ -294,7 +295,7 @@ function applyConfig(configObj) { function loadActiveTagsFromCookie() { // let newTags = $.cookie("activeTags"); - let newTags = getCookie("activeTags"); + let newTags = Misc.getCookie("activeTags"); if (newTags !== undefined && newTags !== "") { try { newTags = JSON.parse(newTags); @@ -1144,7 +1145,7 @@ function setTheme(name, nosave) { let randomTheme = null; function randomiseTheme() { - var randomList = themesList.map((t) => { + var randomList = Misc.getThemesList().map((t) => { return t.name; }); if (config.randomTheme === "fav" && config.favThemes.length > 0)