$(".pageLogin .register input").keyup((e) => { if (e.key == "Enter") { signUp(); } }); $(".pageLogin .register .button").click((e) => { signUp(); }); $(".pageLogin .login input").keyup((e) => { if (e.key == "Enter") { signIn(); } }); $(".pageLogin .login .button").click((e) => { signIn(); }); $(".signOut").click((e) => { signOut(); }); $(".pageAccount .loadMoreButton").click((e) => { loadMoreLines(); }); $(".pageLogin #forgotPasswordButton").click((e) => { let email = prompt("Email address"); if (email) { firebase .auth() .sendPasswordResetEmail(email) .then(function () { // Email sent. showNotification("Email sent", 2000); }) .catch(function (error) { // An error happened. showNotification(error.message, 5000); }); } }); function showSignOutButton() { $(".signOut").removeClass("hidden").css("opacity", 1); } function hideSignOutButton() { $(".signOut").css("opacity", 0).addClass("hidden"); } function signIn() { $(".pageLogin .preloader").removeClass("hidden"); let email = $(".pageLogin .login input")[0].value; let password = $(".pageLogin .login input")[1].value; if ($(".pageLogin .login #rememberMe input").prop("checked")) { //remember me firebase .auth() .setPersistence(firebase.auth.Auth.Persistence.LOCAL) .then(function () { return firebase .auth() .signInWithEmailAndPassword(email, password) .then((e) => { changePage("test"); }) .catch(function (error) { showNotification(error.message, 5000); $(".pageLogin .preloader").addClass("hidden"); }); }); } else { //dont remember firebase .auth() .setPersistence(firebase.auth.Auth.Persistence.SESSION) .then(function () { return firebase .auth() .signInWithEmailAndPassword(email, password) .then((e) => { changePage("test"); }) .catch(function (error) { showNotification(error.message, 5000); $(".pageLogin .preloader").addClass("hidden"); }); }); } } let dontCheckUserName = false; function signUp() { $(".pageLogin .preloader").removeClass("hidden"); let nname = $(".pageLogin .register input")[0].value; let email = $(".pageLogin .register input")[1].value; let password = $(".pageLogin .register input")[2].value; let passwordVerify = $(".pageLogin .register input")[3].value; const namecheck = firebase.functions().httpsCallable("checkNameAvailability"); namecheck({ name: nname }).then((d) => { if (d.data === -1) { showNotification("Name unavailable", 3000); $(".pageLogin .preloader").addClass("hidden"); return; } else if (d.data === -2) { showNotification( "Name cannot contain special characters or contain more than 14 characters. Can include _ . and -", 8000 ); $(".pageLogin .preloader").addClass("hidden"); return; } else if (d.data === 1) { if (password != passwordVerify) { showNotification("Passwords do not match", 3000); $(".pageLogin .preloader").addClass("hidden"); return; } firebase .auth() .createUserWithEmailAndPassword(email, password) .then((user) => { // Account has been created here. dontCheckUserName = true; let usr = user.user; usr .updateProfile({ displayName: nname, }) .then(function () { // Update successful. firebase .firestore() .collection("users") .doc(usr.uid) .set({ name: nname }, { merge: true }); usr.sendEmailVerification(); showNotification("Account created", 2000); $("#menu .icon-button.account .text").text(nname); try { firebase.analytics().logEvent("accountCreated", usr.uid); } catch (e) { console.log("Analytics unavailable"); } $(".pageLogin .preloader").addClass("hidden"); dbSnapshot = { results: [], personalBests: {}, tags: [], }; changePage("account"); }) .catch(function (error) { // An error happened. console.error(error); usr .delete() .then(function () { // User deleted. showNotification( "An error occured. Account not created.", 2000 ); $(".pageLogin .preloader").addClass("hidden"); }) .catch(function (error) { // An error happened. $(".pageLogin .preloader").addClass("hidden"); }); }); }) .catch(function (error) { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; showNotification(errorMessage, 5000); $(".pageLogin .preloader").addClass("hidden"); }); } }); } function signOut() { firebase .auth() .signOut() .then(function () { showNotification("Signed out", 2000); updateAccountLoginButton(); changePage("login"); dbSnapshot = null; }) .catch(function (error) { showNotification(error.message, 5000); }); } function sendVerificationEmail() { let cu = firebase.auth().currentUser; cu.sendEmailVerification() .then((e) => { showNotification("Email sent to " + cu.email, 4000); }) .catch((e) => { showNotification("Error: " + e.message, 3000); console.error(e.message); }); } firebase.auth().onAuthStateChanged(function (user) { if (user) { // User is signed in. if (user.emailVerified === false) { $(".pageAccount .content").prepend( `
Your account is not verified. Click here to resend the verification email.` ); } updateAccountLoginButton(); accountIconLoading(true); db_getUserSnapshot() .then((e) => { if (!configChangedBeforeDb) { if (cookieConfig === null) { accountIconLoading(false); applyConfig(dbSnapshot.config); // showNotification('Applying db config',3000); updateSettingsPage(); saveConfigToCookie(true); } else if (dbSnapshot.config !== undefined) { let configsDifferent = false; Object.keys(config).forEach((key) => { if (!configsDifferent) { try { if (key !== "resultFilters") { if (Array.isArray(config[key])) { config[key].forEach((arrval, index) => { if (arrval != dbSnapshot.config[key][index]) configsDifferent = true; }); } else { if (config[key] != dbSnapshot.config[key]) configsDifferent = true; } } } catch (e) { console.log(e); configsDifferent = true; } } }); if (configsDifferent) { accountIconLoading(false); applyConfig(dbSnapshot.config); updateSettingsPage(); saveConfigToCookie(true); } } dbConfigLoaded = true; } else { accountIconLoading(false); } try { if ( config.resultFilters === undefined || config.resultFilters === null || config.resultFilters.difficulty === undefined ) { if ( dbSnapshot.config.resultFilters == null || dbSnapshot.config.resultFilters.difficulty === undefined ) { config.resultFilters = defaultAccountFilters; } else { config.resultFilters = dbSnapshot.config.resultFilters; } } } catch (e) { config.resultFilters = defaultAccountFilters; } if ($(".pageLogin").hasClass("active")) { changePage("account"); } refreshThemeButtons(); accountIconLoading(false); updateFilterTags(); updateCommandsTagsList(); loadActiveTagsFromCookie(); updateResultEditTagsPanelButtons(); refreshTagsSettingsSection(); updateDiscordSettingsSection(); }) .catch((e) => { accountIconLoading(false); showNotification("Error downloading user data: " + e, 5000); }); var displayName = user.displayName; var email = user.email; var emailVerified = user.emailVerified; var photoURL = user.photoURL; var isAnonymous = user.isAnonymous; var uid = user.uid; var providerData = user.providerData; // showNotification('Signed in', 1000); $(".pageLogin .preloader").addClass("hidden"); if (!dontCheckUserName) verifyUsername(); $("#menu .icon-button.account .text").text(displayName); } }); var resultHistoryChart = new Chart($(".pageAccount #resultHistoryChart"), { animationSteps: 60, type: "line", data: { datasets: [ { label: "wpm", fill: false, data: [], borderColor: "#f44336", borderWidth: 2, // trendlineLinear: { // style: "rgba(244,67,54,.25)", // lineStyle: "solid", // width: 1 // } trendlineLinear: { style: "rgba(255,105,180, .8)", lineStyle: "dotted", width: 4, }, }, ], }, options: { tooltips: { // Disable the on-canvas tooltip enabled: true, titleFontFamily: "Roboto Mono", bodyFontFamily: "Roboto Mono", intersect: false, custom: function (tooltip) { if (!tooltip) return; // disable displaying the color box; tooltip.displayColors = false; }, callbacks: { // HERE YOU CUSTOMIZE THE LABELS title: function () { return; }, beforeLabel: function (tooltipItem, data) { let resultData = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; let label = `${data.datasets[tooltipItem.datasetIndex].label}: ${ tooltipItem.yLabel }` + "\n" + `acc: ${resultData.acc}` + "\n\n" + `mode: ${resultData.mode} `; if (resultData.mode == "time") { label += resultData.mode2; } else if (resultData.mode == "words") { label += resultData.mode2; } let diff = resultData.difficulty; if (diff == undefined) { diff = "normal"; } label += "\n" + `difficulty: ${diff}`; label += "\n" + `punctuation: ${resultData.punctuation}` + "\n" + `language: ${resultData.language}` + "\n\n" + `date: ${moment(resultData.timestamp).format("DD MMM YYYY HH:mm")}`; return label; }, label: function (tooltipItem, data) { return; }, afterLabel: function (tooltipItem, data) { return; }, }, }, animation: { duration: 250, }, legend: { display: false, labels: { fontFamily: "Roboto Mono", fontColor: "#ffffff", }, }, responsive: true, // maintainAspectRatio: false, // tooltips: { // mode: 'index', // intersect: false, // }, hover: { mode: "nearest", intersect: true, }, scales: { xAxes: [ { ticks: { fontFamily: "Roboto Mono", }, type: "time", bounds: "ticks", distribution: "series", display: false, scaleLabel: { display: true, labelString: "Date", }, }, ], yAxes: [ { ticks: { fontFamily: "Roboto Mono", beginAtZero: true, }, display: true, scaleLabel: { display: false, labelString: "Words per Minute", }, }, ], }, }, }); let hoverChart = new Chart($(".pageAccount #hoverChart"), { type: "line", data: { labels: [], datasets: [ { label: "wpm", data: [], // backgroundColor: 'rgba(255, 255, 255, 0.25)', borderColor: "rgba(125, 125, 125, 1)", borderWidth: 2, yAxisID: "wpm", order: 2, radius: 2, }, { label: "raw", data: [], // backgroundColor: 'rgba(255, 255, 255, 0.25)', borderColor: "rgba(125, 125, 125, 1)", borderWidth: 2, yAxisID: "raw", order: 3, radius: 2, }, { label: "errors", data: [], // backgroundColor: 'rgba(255, 255, 255, 0.25)', borderColor: "rgba(255, 125, 125, 1)", pointBackgroundColor: "rgba(255, 125, 125, 1)", borderWidth: 2, order: 1, yAxisID: "error", // barPercentage: 0.1, maxBarThickness: 10, type: "scatter", pointStyle: "crossRot", radius: function (context) { var index = context.dataIndex; var value = context.dataset.data[index]; return value.y <= 0 ? 0 : 3; }, pointHoverRadius: function (context) { var index = context.dataIndex; var value = context.dataset.data[index]; return value.y <= 0 ? 0 : 5; }, }, ], }, options: { tooltips: { titleFontFamily: "Roboto Mono", bodyFontFamily: "Roboto Mono", mode: "index", intersect: false, }, legend: { display: false, labels: { defaultFontFamily: "Roboto Mono", }, }, responsive: true, maintainAspectRatio: false, // hover: { // mode: 'x', // intersect: false // }, scales: { xAxes: [ { ticks: { fontFamily: "Roboto Mono", autoSkip: true, autoSkipPadding: 40, }, display: true, scaleLabel: { display: false, labelString: "Seconds", fontFamily: "Roboto Mono", }, }, ], yAxes: [ { id: "wpm", display: true, scaleLabel: { display: true, labelString: "Words per Minute", fontFamily: "Roboto Mono", }, ticks: { fontFamily: "Roboto Mono", beginAtZero: true, min: 0, autoSkip: true, autoSkipPadding: 40, }, gridLines: { display: true, }, }, { id: "raw", display: false, scaleLabel: { display: true, labelString: "Raw Words per Minute", fontFamily: "Roboto Mono", }, ticks: { fontFamily: "Roboto Mono", beginAtZero: true, min: 0, autoSkip: true, autoSkipPadding: 40, }, gridLines: { display: false, }, }, { id: "error", display: true, position: "right", scaleLabel: { display: true, labelString: "Errors", fontFamily: "Roboto Mono", }, ticks: { precision: 0, fontFamily: "Roboto Mono", beginAtZero: true, autoSkip: true, autoSkipPadding: 40, }, gridLines: { display: false, }, }, ], }, annotation: { annotations: [ { enabled: false, type: "line", mode: "horizontal", scaleID: "wpm", value: "-30", borderColor: "red", borderWidth: 1, borderDash: [2, 2], label: { // Background color of label, default below backgroundColor: "blue", fontFamily: "Roboto Mono", // Font size of text, inherits from global fontSize: 11, // Font style of text, default below fontStyle: "normal", // Font color of text, default below fontColor: "#fff", // Padding of label to add left/right, default below xPadding: 6, // Padding of label to add top/bottom, default below yPadding: 6, // Radius of label rectangle, default below cornerRadius: 3, // Anchor position of label on line, can be one of: top, bottom, left, right, center. Default below. position: "center", // Whether the label is enabled and should be displayed enabled: true, // Text to display in label - default is null. Provide an array to display values on a new line content: "PB", }, }, ], }, }, }); function updateHoverChart(filteredId) { let data = filteredResults[filteredId].chartData; let labels = []; for (let i = 1; i <= data.wpm.length; i++) { labels.push(i.toString()); } hoverChart.data.labels = labels; hoverChart.data.datasets[0].data = data.wpm; hoverChart.data.datasets[1].data = data.raw; hoverChart.data.datasets[2].data = data.err; hoverChart.options.scales.xAxes[0].ticks.minor.fontColor = themeColors.sub; hoverChart.options.scales.xAxes[0].scaleLabel.fontColor = themeColors.sub; hoverChart.options.scales.yAxes[0].ticks.minor.fontColor = themeColors.sub; hoverChart.options.scales.yAxes[2].ticks.minor.fontColor = themeColors.sub; hoverChart.options.scales.yAxes[0].scaleLabel.fontColor = themeColors.sub; hoverChart.options.scales.yAxes[2].scaleLabel.fontColor = themeColors.sub; hoverChart.data.datasets[0].borderColor = themeColors.main; hoverChart.data.datasets[0].pointBackgroundColor = themeColors.main; hoverChart.data.datasets[1].borderColor = themeColors.sub; hoverChart.data.datasets[1].pointBackgroundColor = themeColors.sub; hoverChart.options.annotation.annotations[0].borderColor = themeColors.sub; hoverChart.options.annotation.annotations[0].label.backgroundColor = themeColors.sub; hoverChart.options.annotation.annotations[0].label.fontColor = themeColors.bg; let maxChartVal = Math.max(...[Math.max(...data.wpm), Math.max(...data.raw)]); hoverChart.options.scales.yAxes[0].ticks.max = Math.round(maxChartVal); hoverChart.options.scales.yAxes[1].ticks.max = Math.round(maxChartVal); hoverChart.update({ duration: 0 }); } function showHoverChart() { $(".pageAccount .hoverChartWrapper").stop(true, true).fadeIn(125); $(".pageAccount .hoverChartBg").stop(true, true).fadeIn(125); } function hideHoverChart() { $(".pageAccount .hoverChartWrapper").stop(true, true).fadeOut(125); $(".pageAccount .hoverChartBg").stop(true, true).fadeOut(125); } function updateHoverChartPosition(x, y) { $(".pageAccount .hoverChartWrapper").css({ top: y, left: x }); } $(document).on("click", ".pageAccount .hoverChartButton", (event) => { console.log("updating"); let filterid = $(event.currentTarget).attr("filteredResultsId"); if (filterid === undefined) return; updateHoverChart(filterid); showHoverChart(); updateHoverChartPosition( event.pageX - $(".pageAccount .hoverChartWrapper").outerWidth(), event.pageY + 30 ); }); $(document).on("click", ".pageAccount .hoverChartBg", (event) => { hideHoverChart(); }); // $(document).on("mouseleave", ".pageAccount .hoverChartButton", (event) => { // hideHoverChart(); // }); let defaultAccountFilters = { difficulty: { normal: true, expert: true, master: true, }, mode: { words: true, time: true, quote: true, custom: true, }, words: { 10: true, 25: true, 50: true, 100: true, 200: true, custom: true, }, time: { 15: true, 30: true, 60: true, 120: true, custom: true, }, punctuation: { on: true, off: true, }, date: { last_day: false, last_week: false, last_month: false, all: true, }, tags: { none: true, }, language: {}, funbox: { none: true, }, }; Object.keys(words).forEach((language) => { $( ".pageAccount .content .filterButtons .buttonsAndTitle.languages .buttons" ).append( `
` ); defaultAccountFilters.language[language] = true; if (language === "english_expanded") { $( ".pageAccount .content .filterButtons .buttonsAndTitle.languages .buttons" ).append(` `); defaultAccountFilters.language["english_10k"] = true; } }); $( ".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons" ).append(` `); getFunboxList().then((funboxModes) => { funboxModes.forEach((funbox) => { $( ".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons" ).append( ` ` ); defaultAccountFilters.funbox[funbox.name] = true; }); }); function updateFilterTags() { $( ".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons" ).empty(); if (dbSnapshot.tags.length > 0) { $(".pageAccount .content .filterButtons .buttonsAndTitle.tags").removeClass( "hidden" ); $( ".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons" ).append(` `); dbSnapshot.tags.forEach((tag) => { defaultAccountFilters.tags[tag.id] = true; $( ".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons" ).append(` `); }); } else { $(".pageAccount .content .filterButtons .buttonsAndTitle.tags").addClass( "hidden" ); } // showActiveFilters(); } function toggleFilter(group, filter) { if (group === "date") { Object.keys(config.resultFilters.date).forEach((date) => { setFilter("date", date, false); }); } config.resultFilters[group][filter] = !config.resultFilters[group][filter]; } function setFilter(group, filter, set) { config.resultFilters[group][filter] = set; } // function toggleFilterButton(filter) { // const element = $( // `.pageAccount .content .filterButtons .button[filter=${filter}]` // ); // if (element.hasClass("active")) { // //disable that filter // if (filter == "all" || filter == "none") { // return; // } else if (filter == "mode_words") { // // $.each($(`.pageAccount .content .filterButtons .buttons.wordsFilter .button`),(index,obj)=>{ // // let f = $(obj).attr('filter') // // disableFilterButton(f) // // }) // } else if (filter == "mode_time") { // // $.each($(`.pageAccount .content .filterButtons .buttons.timeFilter .button`),(index,obj)=>{ // // let f = $(obj).attr('filter') // // disableFilterButton(f) // // }) // } else if (filter == "punc_off") { // enableFilterButton("punc_on"); // } else if (filter == "punc_on") { // enableFilterButton("punc_off"); // } // disableFilterButton(filter); // disableFilterButton("all"); // } else { // //enable that filter // disableFilterButton("none"); // if (filter == "all") { // $.each( // $(`.pageAccount .content .filterButtons .button`), // (index, obj) => { // let f = $(obj).attr("filter"); // if ( // f != "none" && // f != "date_month" && // f != "date_week" && // f != "date_day" // ) { // enableFilterButton(f); // } // } // ); // } else if (filter == "none") { // disableFilterButton("all"); // $.each( // $(`.pageAccount .content .filterButtons .button`), // (index, obj) => { // let f = $(obj).attr("filter"); // if (f != "none") { // disableFilterButton(f); // } // } // ); // } else if ( // filter == "date_all" || // filter == "date_month" || // filter == "date_week" || // filter == "date_day" // ) { // disableFilterButton("date_all"); // disableFilterButton("date_month"); // disableFilterButton("date_week"); // disableFilterButton("date_day"); // enableFilterButton(filter); // } // // else if(filter == "mode_words"){ // // $.each($(`.pageAccount .content .filterButtons .buttons.wordsFilter .button`),(index,obj)=>{ // // let f = $(obj).attr('filter'); // // enableFilterButton(f); // // }) // // }else if(filter == "mode_time"){ // // $.each($(`.pageAccount .content .filterButtons .buttons.timeFilter .button`),(index,obj)=>{ // // let f = $(obj).attr('filter'); // // enableFilterButton(f); // // }) // // }else if(['10','25','50','100','200'].includes(filter)){ // // enableFilterButton('words'); // // }else if(['15','30','60','120'].includes(filter)){ // // enableFilterButton('time'); // // } // enableFilterButton(filter); // } // showActiveFilters(); // } // function disableFilterButton(filter) { // const element = $( // `.pageAccount .content .filterButtons .button[filter=${filter}]` // ); // element.removeClass("active"); // } // function enableFilterButton(filter) { // const element = $( // `.pageAccount .content .filterButtons .button[filter=${filter}]` // ); // element.addClass("active"); // } function showActiveFilters() { // activeFilters = []; // $.each($(".pageAccount .filterButtons .button"), (i, obj) => { // if ($(obj).hasClass("active")) { // activeFilters.push($(obj).attr("filter")); // } // }); let aboveChartDisplay = {}; Object.keys(config.resultFilters).forEach((group) => { aboveChartDisplay[group] = { all: true, array: [], }; Object.keys(config.resultFilters[group]).forEach((filter) => { if (config.resultFilters[group][filter]) { aboveChartDisplay[group].array.push(filter); } else { aboveChartDisplay[group].all = false; } let buttonEl = $( `.pageAccount .group.filterButtons .filterGroup[group="${group}"] .button[filter="${filter}"]` ); if (config.resultFilters[group][filter]) { buttonEl.addClass("active"); } else { buttonEl.removeClass("active"); } }); }); let chartString = ""; let allall = true; let count = 0; Object.keys(aboveChartDisplay).forEach((group) => { count++; if (group === "time" && !aboveChartDisplay.mode.array.includes("time")) return; if (group === "words" && !aboveChartDisplay.mode.array.includes("words")) return; if (aboveChartDisplay[group].array.length > 0) { chartString += "