Merge branch 'newnav'

This commit is contained in:
Miodec 2022-09-05 13:55:09 +02:00
commit 85dc20e8cd
38 changed files with 1437 additions and 396 deletions

View file

@ -1,4 +1,4 @@
import _ from "lodash";
import _, { eq } from "lodash";
import * as UserDAL from "../../dal/user";
import MonkeyError from "../../utils/error";
import Logger from "../../utils/logger";
@ -160,9 +160,14 @@ export async function getUser(
const agentLog = buildAgentLog(req);
Logger.logToDb("user_data_requested", agentLog, uid);
let inboxUnreadSize = 0;
if (req.ctx.configuration.users.inbox.enabled) {
inboxUnreadSize = _.filter(userInfo.inbox, { read: false }).length;
}
const userData = {
...getRelevantUserInfo(userInfo),
inboxUnreadSize: _.filter(userInfo.inbox, { read: false }).length,
inboxUnreadSize: inboxUnreadSize,
};
return new MonkeyResponse("User data retrieved", userData);
@ -520,7 +525,10 @@ export async function getInbox(
const inbox = await UserDAL.getInbox(uid);
return new MonkeyResponse("Inbox retrieved", inbox);
return new MonkeyResponse("Inbox retrieved", {
inbox,
maxMail: req.ctx.configuration.users.inbox.maxMail,
});
}
export async function updateInbox(

View file

@ -818,7 +818,8 @@ function buildRewardUpdates(
if (reward.type === "xp") {
totalXp += isNaN(reward.item) ? 0 : reward.item;
} else if (reward.type === "badge") {
newBadges.push(reward.item);
const item = _.omit(reward.item, "selected");
newBadges.push(item);
}
});

View file

@ -213,8 +213,9 @@ key {
}
.pageLoading {
height: 100%;
display: grid;
justify-content: center;
align-items: center;
}
.pageLoading,
@ -356,7 +357,7 @@ key {
color: var(--sub-color);
cursor: pointer;
transition: background 0.125s, color 0.125s;
padding: 0.5rem;
padding: 0.5em;
border-radius: var(--roundness);
text-align: center;
user-select: none;
@ -364,16 +365,16 @@ key {
align-content: center;
height: min-content;
height: -moz-min-content;
line-height: 1.25rem;
line-height: 1.25em;
appearance: none;
border: none;
font-family: inherit;
font-size: 1rem;
font-size: 1em;
width: max-content;
width: -moz-max-content;
display: grid;
grid-auto-flow: column;
gap: 0.25rem;
gap: 0.25em;
text-decoration: none;
.fas,

View file

@ -4,6 +4,7 @@
gap: 1rem;
justify-content: space-around;
align-items: center;
height: 100%;
.side {
display: grid;

View file

@ -46,6 +46,7 @@
}
.level {
transition: 0.125s;
width: max-content;
font-size: 0.65rem;
line-height: 1rem;
@ -78,7 +79,7 @@
position: absolute;
left: 100%;
margin-left: 0.5rem;
top: 0;
top: 0.2rem;
transform: translateY(-50%);
font-size: 0.75rem;
color: var(--main-color);
@ -97,6 +98,9 @@
}
}
}
&:hover .level {
background-color: var(--text-color);
}
}
}
@ -128,7 +132,7 @@
}
#top {
grid-template-areas: "logo menu config";
grid-template-areas: "logo menu";
line-height: 2.3rem;
font-size: 2.3rem;
/* text-align: center; */
@ -136,7 +140,7 @@
padding: 0 5px;
display: grid;
grid-auto-flow: column;
grid-template-columns: auto 1fr auto;
grid-template-columns: auto 1fr;
z-index: 2;
align-items: center;
gap: 0.5rem;
@ -168,13 +172,13 @@
font-size: 0.65rem;
line-height: 0.65rem;
color: var(--sub-color);
transition: 0.25s;
transition: color 0.25s;
}
position: relative;
font-size: 2rem;
margin-bottom: 0.4rem;
margin-top: -0.4rem;
font-family: "Lexend Deca";
transition: 0.25s;
transition: color 0.25s;
}
white-space: nowrap;
user-select: none;

View file

@ -1324,3 +1324,164 @@
overflow-y: scroll;
}
}
#alertsPopupWrapper {
padding: 0;
justify-content: end;
z-index: 99999999;
// padding: 2rem;
#alertsPopup {
background: var(--bg-color);
width: calc(350px + 2rem);
right: 0;
// height: calc(100vh - 4rem);
height: 100%;
top: 0;
padding: 2rem calc(1rem - 7px) 2rem 1rem; // -7px for the scrollbar
// padding: 1rem;
// border-radius: var(--roundness);
overflow: hidden;
margin-right: -10rem;
border-radius: var(--roundness) 0 0 var(--roundness);
.separator {
background-color: var(--sub-alt-color);
height: 0.25rem;
width: 100%;
border-radius: calc(var(--roundness) / 2);
}
.scrollWrapper {
padding: 0 1rem 0 1rem;
overflow-y: scroll;
display: grid;
gap: 2rem;
align-content: baseline;
height: 100%;
}
.accountAlerts > .title,
.notificationHistory > .title,
.psas > .title {
font-size: 1.25rem;
margin-bottom: 1rem;
color: var(--sub-color);
user-select: none;
}
.list {
display: grid;
gap: 1rem;
.nothing {
width: 100%;
color: var(--text-color);
font-size: 0.75rem;
text-align: center;
margin: 2rem 0;
}
.preloader {
width: 100%;
color: var(--main-color);
text-align: center;
font-size: 1rem;
margin: 2rem 0;
}
.item {
display: grid;
grid-template-areas: "indicator title buttons" "indicator body buttons";
grid-template-columns: 0.25rem auto 1rem;
gap: 0.25rem 0.5rem;
.indicator {
grid-area: indicator;
background-color: var(--sub-alt-color);
width: 0.25rem;
height: 100%;
border-radius: calc(var(--roundness) / 2);
transition: 0.125s;
&.main {
background-color: var(--main-color);
}
&.error {
background-color: var(--error-color);
}
&.sub {
background-color: var(--sub-color);
}
}
.title {
grid-area: title;
font-size: 0.75rem;
color: var(--sub-color);
}
.body {
grid-area: body;
font-size: 0.75rem;
color: var(--text-color);
transition: 0.125s;
opacity: 1;
}
.buttons {
grid-area: buttons;
width: 100%;
display: grid;
grid-auto-flow: row;
gap: 0.5rem;
opacity: 0;
transition: 0.125s;
align-items: center;
align-content: center;
.button {
font-size: 0.75rem;
padding: 0.5em;
line-height: 1.25em;
height: 100%;
display: grid;
}
}
&:hover {
.buttons {
opacity: 1;
}
.body {
opacity: 1;
}
}
}
}
.psas .list .item {
grid-template-areas: "indicator body";
grid-template-columns: 0.25rem auto;
.body {
opacity: 1;
}
}
.notificationHistory .list .item {
grid-template-areas: "indicator title" "indicator body";
grid-template-columns: 0.25rem auto;
.title {
font-size: 0.75rem;
color: var(--sub-color);
}
.body {
opacity: 1;
}
}
.accountAlerts {
.title {
display: grid;
grid-template-columns: 1fr auto;
}
.list .item {
grid-template-areas: "indicator timestamp buttons" "indicator title buttons" "indicator body buttons";
.timestamp {
grid-area: timestamp;
font-size: 0.6rem;
color: var(--sub-color);
opacity: 0.5;
}
.rewards {
overflow: hidden;
margin-top: 0.35rem;
}
}
}
}
}

View file

@ -916,6 +916,117 @@
}
}
#mobileTestConfig {
font-size: 0.75rem;
padding: 0.25rem 1rem;
background: var(--sub-alt-color);
border-radius: var(--roundness);
width: max-content;
justify-self: center;
display: none;
height: max-content;
}
#testConfig {
display: grid;
font-size: 0.75rem;
gap: 0.5rem;
grid-auto-flow: column;
height: max-content;
width: 100%;
justify-content: space-around;
transition: 0.125s;
margin-bottom: 1rem;
.puncAndNum {
// transition: 0.25s cubic-bezier(0.37, 0, 0.63, 1);
overflow: hidden;
max-width: 15rem;
opacity: 1;
}
.row {
display: flex;
// padding: 0 0.5rem;
background: var(--sub-alt-color);
border-radius: var(--roundness);
// width: max-content;
}
.spacer {
height: auto;
width: 0.25rem;
border-radius: calc(var(--roundness) / 2);
background: var(--bg-color);
margin: 0.5rem 0;
transition: 0.25s;
&.scrolled {
width: 0;
margin: auto 0;
}
}
.wordCount,
.time {
.textButton {
line-height: 1rem;
span {
height: 1.1em;
}
}
}
.mode,
.time,
.wordCount,
.puncAndNum,
.quoteLength,
.customText,
.zen {
display: grid;
grid-auto-flow: column;
.textButton {
transition: 0.125s;
padding: 0.75rem 0.5rem 0.7rem 0.5rem;
&:first-child {
padding: 0.75rem 0.5rem 0.7rem 1rem;
}
&:last-child {
padding: 0.75rem 1rem 0.7rem 0.5rem;
}
&:only-child {
padding: 0.75rem 1rem 0.7rem 1rem;
}
}
}
.time,
.wordCount,
.customText,
.zen,
.quoteLength,
.puncAndNum {
// width: 100%;
justify-content: center;
overflow: hidden;
}
.customText {
display: grid;
}
&.focus {
opacity: 0;
}
}
.pageTest {
height: 100%;
display: grid;
grid-template-rows: 1fr auto 1fr;
}
#menu {
width: 100%;
grid-template-columns: auto auto auto 1fr auto;
}
.pageTest {
#wordsWrapper {
position: relative;

View file

@ -159,6 +159,29 @@
}
@media only screen and (max-width: 900px) {
#testConfig {
.mode,
.time,
.wordCount,
.puncAndNum,
.customText,
.zen,
.quoteLength {
.textButton {
padding: 0.75rem 0.3rem 0.7rem 0.3rem;
&:first-child {
padding: 0.75rem 0.3rem 0.7rem 0.6rem;
}
&:last-child {
padding: 0.75rem 0.6rem 0.7rem 0.3rem;
}
&:only-child {
padding: 0.75rem 0.6rem 0.7rem 0.6rem;
}
}
}
}
.ad.ad-h {
display: none;
}
@ -280,32 +303,97 @@
}
@media only screen and (max-width: 800px) {
#testConfig {
.spacer {
display: none;
}
.row {
display: grid;
justify-items: center;
padding: 0.25rem 1rem;
}
.mode,
.time,
.wordCount,
.puncAndNum,
.customText,
.zen,
.quoteLength {
.textButton {
padding: 0.5rem 0.75rem 0.45rem 0.75rem;
&:first-child {
padding: 0.5rem 0.75rem 0.45rem 0.75rem;
}
&:last-child {
padding: 0.5rem 0.75rem 0.45rem 0.75rem;
}
&:only-child {
padding: 0.5rem 0.75rem 0.45rem 0.75rem;
}
}
}
}
#top {
.logo {
.text {
font-size: 1.9rem !important;
}
.bottom {
font-size: 1.9rem;
line-height: 1.9rem;
margin-top: 0;
}
}
#menu {
gap: 0.1rem;
.textButton {
padding: 0.25rem;
font-size: 0.8rem;
line-height: 0.8rem;
&.account {
margin-top: 0.05rem;
.text {
display: none;
}
.avatar {
width: 1rem;
height: 1rem;
}
.level {
line-height: 0.8rem;
}
}
}
}
}
.pageSettings .settingsGroup.quickNav .links {
grid-auto-flow: unset;
grid-template-columns: 1fr 1fr 1fr;
justify-items: center;
}
#centerContent {
#top {
grid-template-areas:
"logo config"
"menu config";
grid-template-columns: auto auto;
.logo {
margin-bottom: 0;
}
}
// #top {
// grid-template-areas:
// "logo config"
// "menu config";
// grid-template-columns: auto auto;
// .logo {
// margin-bottom: 0;
// }
// }
#menu {
gap: 0.5rem;
font-size: 0.8rem;
line-height: 0.8rem;
margin-top: -0.5rem;
// #menu {
// gap: 0.5rem;
// font-size: 0.8rem;
// line-height: 0.8rem;
// margin-top: -0.5rem;
.textButton {
padding: 0.25rem;
}
}
// .textButton {
// padding: 0.25rem;
// }
// }
}
#contactPopupWrapper #contactPopup .buttons {
@ -640,6 +728,9 @@
}
}
}
#testModesNotice {
font-size: 0.75rem;
}
#cookiePopupWrapper {
#cookiePopup,
.extensionMessage {
@ -728,27 +819,15 @@
}
#top {
align-items: self-end;
.logo {
.icon {
width: 1.5rem !important;
}
grid-template-columns: auto;
.text {
font-size: 1.5rem !important;
margin-bottom: 0.3rem !important;
}
.bottom {
font-size: 1.75rem;
line-height: 1.75rem;
margin-top: 0;
}
.top {
display: none;
}
}
#menu {
.textButton {
padding: 0;
// padding: 0;
}
}
}
@ -770,7 +849,7 @@
}
#centerContent {
#top {
grid-template-columns: 1fr auto;
// grid-template-columns: 1fr auto;
.desktopConfig {
display: none;
}
@ -778,6 +857,7 @@
display: block;
}
}
gap: 1rem;
padding: 1rem;
}
#middle {
@ -806,6 +886,16 @@
}
}
@media only screen and (max-width: 450px) {
#testConfig {
display: none;
}
#mobileTestConfig {
display: block;
}
}
@media only screen and (max-width: 400px) {
#top .config {
grid-gap: 0.25rem;
@ -888,6 +978,16 @@
}
}
@media (pointer: coarse) and (max-width: 800px) {
#testConfig {
display: none;
}
#mobileTestConfig {
display: block;
}
}
@media (hover: none) and (pointer: coarse) {
#commandLineMobileButton {
display: block !important;

View file

@ -1,46 +0,0 @@
export function show(): void {
// $(".signOut").removeClass("hidden").css("opacity", 1);
$(".signOut")
.stop(true, true)
.removeClass("hidden")
.css({
opacity: 0,
transition: "0s",
})
.animate(
{
opacity: 1,
},
125,
() => {
$(".signOut").css({ transition: "0.25s" });
}
);
}
export function hide(): void {
$(".signOut")
.stop(true, true)
.css({
opacity: 1,
transition: "0s",
})
.animate(
{
opacity: 0,
},
125,
() => {
$(".signOut").css({ transition: "0.25s" });
$(".signOut").addClass("hidden");
}
);
// $(".signOut").css("opacity", 0).addClass("hidden");
}
// $("#liveWpm").removeClass("hidden").css("opacity", 0).animate(
// {
// opacity: Config.timerOpacity,
// },
// 125
// );

View file

@ -192,4 +192,19 @@ export default class Users {
},
});
}
async getInbox(): Promise<Ape.EndpointData> {
return await this.httpClient.get(`${BASE_PATH}/inbox`);
}
async updateInbox(options: {
mailIdsToDelete?: string[];
mailIdsToMarkRead?: string[];
}): Promise<Ape.EndpointData> {
const payload = {
mailIdsToDelete: options.mailIdsToDelete,
mailIdsToMarkRead: options.mailIdsToMarkRead,
};
return await this.httpClient.patch(`${BASE_PATH}/inbox`, { payload });
}
}

View file

@ -96,11 +96,6 @@ export function setNumbers(numb: boolean, nosave?: boolean): boolean {
numb = false;
}
config.numbers = numb;
if (!config.numbers) {
$("#top .config .numbersMode .textButton").removeClass("active");
} else {
$("#top .config .numbersMode .textButton").addClass("active");
}
saveToLocalStorage("numbers", nosave);
ConfigEvent.dispatch("numbers", config.numbers);
@ -115,11 +110,6 @@ export function setPunctuation(punc: boolean, nosave?: boolean): boolean {
punc = false;
}
config.punctuation = punc;
if (!config.punctuation) {
$("#top .config .punctuationMode .textButton").removeClass("active");
} else {
$("#top .config .punctuationMode .textButton").addClass("active");
}
saveToLocalStorage("punctuation", nosave);
ConfigEvent.dispatch("punctuation", config.punctuation);
@ -982,15 +972,8 @@ export function setTimeConfig(
const newTime = isNaN(time) || time < 0 ? DefaultConfig.time : time;
$("#top .config .time .textButton").removeClass("active");
const timeCustom = ![15, 30, 60, 120].includes(newTime) ? "custom" : newTime;
config.time = newTime;
$("#top .config .time .textButton[timeConfig='" + timeCustom + "']").addClass(
"active"
);
saveToLocalStorage("time", nosave);
ConfigEvent.dispatch("time", config.time);
@ -1035,12 +1018,6 @@ export function setQuoteLength(
}
}
// if (!nosave) setMode("quote", nosave);
$("#top .config .quoteLength .textButton").removeClass("active");
config.quoteLength.forEach((ql) => {
$(
"#top .config .quoteLength .textButton[quoteLength='" + ql + "']"
).addClass("active");
});
saveToLocalStorage("quoteLength", nosave);
ConfigEvent.dispatch("quoteLength", config.quoteLength);
@ -1056,17 +1033,8 @@ export function setWordCount(
const newWordCount =
wordCount < 0 || wordCount > 100000 ? DefaultConfig.words : wordCount;
$("#top .config .wordCount .textButton").removeClass("active");
const wordCustom = ![10, 25, 50, 100, 200].includes(newWordCount)
? "custom"
: newWordCount;
config.words = newWordCount;
$(
"#top .config .wordCount .textButton[wordCount='" + wordCustom + "']"
).addClass("active");
saveToLocalStorage("words", nosave);
ConfigEvent.dispatch("words", config.words);

View file

@ -27,5 +27,6 @@ export const defaultSnap: MonkeyTypes.Snapshot = {
addedAt: 0,
filterPresets: [],
xp: 0,
inboxUnreadSize: 0,
streak: 0,
};

View file

@ -20,6 +20,7 @@ import * as TagController from "./tag-controller";
import * as ResultTagsPopup from "../popups/result-tags-popup";
import * as URLHandler from "../utils/url-handler";
import * as Account from "../pages/account";
import * as Alerts from "../elements/alerts";
import {
EmailAuthProvider,
GoogleAuthProvider,
@ -238,8 +239,9 @@ export async function loadUser(user: UserType): Promise<void> {
if ((await getDataAndInit()) === false) {
signOut();
}
const { discordId, discordAvatar, xp } = DB.getSnapshot();
const { discordId, discordAvatar, xp, inboxUnreadSize } = DB.getSnapshot();
AccountButton.update(xp, discordId, discordAvatar);
Alerts.setBellButtonColored(inboxUnreadSize > 0);
// var displayName = user.displayName;
// var email = user.email;
// var emailVerified = user.emailVerified;
@ -249,6 +251,8 @@ export async function loadUser(user: UserType): Promise<void> {
// var providerData = user.providerData;
LoginPage.hidePreloader();
$("#top .signInOut .icon").html(`<i class="fas fa-fw fa-sign-out-alt"></i>`);
// showFavouriteThemesAtTheTop();
if (TestLogic.notSignedInLastResult !== null) {
@ -274,8 +278,12 @@ const authListener = Auth.onAuthStateChanged(async function (user) {
const hash = window.location.hash;
console.log(`auth state changed, user ${user ? true : false}`);
if (user) {
$("#top .signInOut .icon").html(
`<i class="fas fa-fw fa-sign-out-alt"></i>`
);
await loadUser(user);
} else {
$("#top .signInOut .icon").html(`<i class="fas fa-fw fa-sign-in-alt"></i>`);
if (window.location.pathname == "/account") {
window.history.replaceState("", "", "/login");
}
@ -472,6 +480,9 @@ export function signOut(): void {
DB.setSnapshot(defaultSnap);
$(".pageLogin .button").removeClass("disabled");
$(".pageLogin input").prop("disabled", false);
$("#top .signInOut .icon").html(
`<i class="fas fa-fw fa-sign-in-alt"></i>`
);
hideFavoriteQuoteLength();
})
.catch(function (error) {
@ -643,8 +654,12 @@ $(".pageLogin .login .button.signInWithGoogle").on("click", () => {
// signInWithGitHub();
// });
$(".signOut").on("click", () => {
signOut();
$("#top .signInOut").on("click", () => {
if (Auth.currentUser) {
signOut();
} else {
navigate("/login");
}
});
$(".pageLogin .register input").keyup((e) => {

View file

@ -120,3 +120,7 @@ export function getHTMLById(
badge.icon ? `<i class="fas ${badge.icon}"></i>` : ""
}${noText ? "" : `<div class="text">${badge.name}</div>`}</div>`;
}
export function getById(id: number): MonkeyTypes.UserBadge {
return badges[id];
}

View file

@ -96,6 +96,7 @@ export async function initSnapshot(): Promise<
snap.addedAt = userData.addedAt;
snap.inventory = userData.inventory;
snap.xp = userData.xp ?? 0;
snap.inboxUnreadSize = userData.inboxUnreadSize ?? 0;
snap.streak = userData?.streak?.length ?? 0;
if (userData.lbMemory?.time15 || userData.lbMemory?.time60) {
@ -815,6 +816,17 @@ export function addXp(xp: number): void {
setSnapshot(snapshot);
}
export function addBadge(badge: MonkeyTypes.Badge): void {
const snapshot = getSnapshot();
if (snapshot.inventory === undefined) {
snapshot.inventory = {
badges: [],
};
}
snapshot.inventory.badges.push(badge);
setSnapshot(snapshot);
}
export function setStreak(streak: number): void {
const snapshot = getSnapshot();
snapshot.streak = streak;

View file

@ -143,7 +143,7 @@ export async function update(
export async function updateXpBar(
currentXp: number,
addedXp: number,
breakdown: Record<string, number>
breakdown?: Record<string, number>
): Promise<void> {
skipBreakdown = false;
const startingLevel = Misc.getLevel(currentXp);
@ -176,8 +176,12 @@ export async function updateXpBar(
async function animateXpBreakdown(
addedXp: number,
breakdown: Record<string, number>
breakdown?: Record<string, number>
): Promise<void> {
if (!breakdown) {
$("#menu .xpBar .xpGain").text(`+${addedXp}`);
return;
}
const delay = 1000;
let total = 0;
const xpGain = $("#menu .xpBar .xpGain");

View file

@ -0,0 +1,371 @@
import formatDistanceToNowStrict from "date-fns/formatDistanceToNowStrict";
import Ape from "../ape";
import { Auth } from "../firebase";
import * as AccountButton from "../elements/account-button";
import * as DB from "../db";
import * as NotificationEvent from "../observables/notification-event";
import * as BadgeController from "../controllers/badge-controller";
import * as Notifications from "../elements/notifications";
let accountAlerts: MonkeyTypes.MonkeyMail[] = [];
let maxMail = 0;
let mailToMarkRead: string[] = [];
let mailToDelete: string[] = [];
export function hide(): void {
if (!$("#alertsPopupWrapper").hasClass("hidden")) {
setBellButtonColored(false);
let mailUpdatedPromiseResolve: (value?: unknown) => void;
const mailUpdatedPromise = new Promise((resolve) => {
mailUpdatedPromiseResolve = resolve;
});
const badgesClaimed: string[] = [];
let totalXpClaimed = 0;
if (mailToMarkRead.length > 0 || mailToDelete.length > 0) {
Ape.users
.updateInbox({
mailIdsToMarkRead:
mailToMarkRead.length > 0 ? mailToMarkRead : undefined,
mailIdsToDelete: mailToDelete.length > 0 ? mailToDelete : undefined,
})
.then(async (updateResponse) => {
const status = (await updateResponse).status;
const message = (await updateResponse).message;
if (status !== 200) {
Notifications.add(`Failed to update inbox: ${message}`, -1);
return;
} else {
const rewardsClaimed = accountAlerts
.filter((ie) => {
return ie.rewards.length > 0 && mailToMarkRead.includes(ie.id);
})
.map((ie) => ie.rewards)
.reduce(function (a, b) {
return a.concat(b);
}, []);
for (const r of rewardsClaimed) {
if (r.type === "xp") {
totalXpClaimed += r.item as number;
} else if (r.type === "badge") {
const badge = BadgeController.getById(r.item.id);
badgesClaimed.push(badge.name);
DB.addBadge(r.item);
}
}
}
mailUpdatedPromiseResolve();
});
}
$("#alertsPopup").animate(
{
marginRight: "-10rem",
},
100,
"easeInCubic"
);
$("#alertsPopupWrapper")
.stop(true, true)
.css("opacity", 1)
.animate(
{
opacity: 0,
},
100,
() => {
mailUpdatedPromise.then(() => {
if (badgesClaimed.length > 0) {
Notifications.add(
`New badge${
badgesClaimed.length > 1 ? "s" : ""
} unlocked: ${badgesClaimed.join(", ")}`,
1,
5,
"Reward",
"gift"
);
}
if (totalXpClaimed > 0) {
const snapxp = DB.getSnapshot().xp;
AccountButton.updateXpBar(snapxp, totalXpClaimed);
DB.addXp(totalXpClaimed);
}
});
$("#alertsPopupWrapper").addClass("hidden");
}
);
}
}
export async function show(): Promise<void> {
if ($("#alertsPopupWrapper").hasClass("hidden")) {
$("#alertsPopup").css("marginRight", "-10rem").animate(
{
marginRight: 0,
},
100,
"easeOutCubic"
);
if (Auth.currentUser) {
$("#alertsPopup .accountAlerts").removeClass("hidden");
$("#alertsPopup .separator.accountSeparator").removeClass("hidden");
$("#alertsPopup .accountAlerts .list").html(`
<div class="preloader"><i class="fas fa-fw fa-spin fa-circle-notch"></i></div>`);
} else {
$("#alertsPopup .accountAlerts").addClass("hidden");
$("#alertsPopup .separator.accountSeparator").addClass("hidden");
}
accountAlerts = [];
mailToDelete = [];
mailToMarkRead = [];
$("#alertsPopupWrapper")
.stop(true, true)
.css("opacity", 0)
.removeClass("hidden")
.animate(
{
opacity: 1,
},
100,
() => {
if (Auth.currentUser) {
getAccountAlerts();
}
}
);
}
}
async function getAccountAlerts(): Promise<void> {
const inboxResponse = await Ape.users.getInbox();
$("#alertsPopup .accountAlerts .list").empty();
if (inboxResponse.status === 503) {
$("#alertsPopup .accountAlerts .list").html(`
<div class="nothing">
Account inboxes are temporarily unavailable.
</div>
`);
return;
} else if (inboxResponse.status !== 200) {
$("#alertsPopup .accountAlerts .list").html(`
<div class="nothing">
Error getting inbox: ${inboxResponse.message} Please try again later.
</div>
`);
return;
}
const inboxData = inboxResponse.data as {
inbox: MonkeyTypes.MonkeyMail[];
maxMail: number;
};
accountAlerts = inboxData.inbox;
if (accountAlerts.length === 0) {
$("#alertsPopup .accountAlerts .list").html(`
<div class="nothing">
Nothing to show
</div>
`);
return;
}
maxMail = inboxData.maxMail;
updateInboxSize();
for (const ie of accountAlerts) {
if (!ie.read && ie.rewards.length == 0) {
mailToMarkRead.push(ie.id);
}
let rewardsString = "";
if (ie.rewards.length > 0 && ie.read === false) {
rewardsString = `<div class="rewards">
<i class="fas fa-fw fa-gift"></i>
<span>${ie.rewards.length}</span>
</div>`;
}
$("#alertsPopup .accountAlerts .list").append(`
<div class="item" data-id="${ie.id}">
<div class="indicator ${ie.read ? "" : "main"}"></div>
<div class="timestamp">${formatDistanceToNowStrict(
new Date(ie.timestamp)
)} ago</div>
<div class="title">${ie.subject}</div>
<div class="body">
${ie.body}\n\n${rewardsString}
</div>
<div class="buttons">
${
ie.rewards.length > 0 && ie.read === false
? `<div class="markReadAlert textButton" aria-label="Claim" data-balloon-pos="left"><i class="fas fa-gift"></i></div>`
: ``
}
${
(ie.rewards.length > 0 && ie.read === true) ||
ie.rewards.length == 0
? `<div class="deleteAlert textButton" aria-label="Delete" data-balloon-pos="left"><i class="fas fa-trash"></i></div>`
: ``
}
</div>
</div>
`);
}
}
export function addPSA(message: string, level: number): void {
if ($("#alertsPopup .psas .list .nothing").length > 0) {
$("#alertsPopup .psas .list").empty();
}
let levelClass = "";
if (level === -1) {
levelClass = "error";
} else if (level === 1) {
levelClass = "main";
} else if (level === 0) {
levelClass = "sub";
}
$("#alertsPopup .psas .list").prepend(`
<div class="item">
<div class="indicator ${levelClass}"></div>
<div class="body">
${message}
</div>
</div>
`);
}
function addNotification(
message: string,
level: number,
customTitle?: string
): void {
if ($("#alertsPopup .notificationHistory .list .nothing").length > 0) {
$("#alertsPopup .notificationHistory .list").empty();
}
let title = "Notice";
let levelClass = "sub";
if (level === -1) {
levelClass = "error";
title = "Error";
} else if (level === 1) {
levelClass = "main";
title = "Success";
}
if (customTitle) {
title = customTitle;
}
$("#alertsPopup .notificationHistory .list").prepend(`
<div class="item">
<div class="indicator ${levelClass}"></div>
<div class="title">${title}</div>
<div class="body">
${message}
</div>
</div>
`);
if ($("#alertsPopup .notificationHistory .list").length > 25) {
$("#alertsPopup .notificationHistory .list .item:last").remove();
}
}
export function setBellButtonColored(tf: boolean): void {
if (tf) {
$("#top #menu .showAlerts").addClass("active");
} else {
$("#top #menu .showAlerts").removeClass("active");
}
}
function updateInboxSize(): void {
$("#alertsPopup .accountAlerts .title .right").text(
`${accountAlerts.length}/${maxMail}`
);
}
$("#top #menu .showAlerts").on("click", () => {
show();
});
$("#alertsPopupWrapper").on("mousedown", (e) => {
if ($(e.target).attr("id") === "alertsPopupWrapper") {
hide();
}
});
$("#alertsPopup .accountAlerts .list").on(
"click",
".item .buttons .deleteAlert",
(e) => {
const id = $(e.currentTarget).closest(".item").attr("data-id") as string;
mailToDelete.push(id);
$(e.currentTarget).closest(".item").remove();
accountAlerts = accountAlerts.filter((ie) => ie.id !== id);
if (accountAlerts.length === 0) {
$("#alertsPopup .accountAlerts .list").html(`
<div class="nothing">
Nothing to show
</div>
`);
}
updateInboxSize();
}
);
$("#alertsPopup .accountAlerts .list").on(
"click",
".item .buttons .markReadAlert",
(e) => {
const id = $(e.currentTarget).closest(".item").attr("data-id") as string;
mailToMarkRead.push(id);
const item = $(e.currentTarget).closest(".item");
item.find(".indicator").removeClass("main");
item.find(".buttons").empty();
item
.find(".buttons")
.append(
`<div class="deleteAlert textButton" aria-label="Delete" data-balloon-pos="left"><i class="fas fa-trash"></i></div>`
);
item.find(".rewards").animate(
{
opacity: 0,
height: 0,
marginTop: 0,
},
250,
"easeOutCubic",
() => {
item.find(".rewards").remove();
}
);
}
);
$(document).on("keydown", (e) => {
if (e.key === "Escape" && !$("#alertsPopupWrapper").hasClass("hidden")) {
hide();
}
});
NotificationEvent.subscribe((message, level, customTitle) => {
addNotification(message, level, customTitle);
});

View file

@ -1,6 +1,8 @@
import { debounce } from "throttle-debounce";
import * as Misc from "../utils/misc";
import * as BannerEvent from "../observables/banner-event";
// import * as Alerts from "./alerts";
import * as NotificationEvent from "../observables/notification-event";
function updateMargin(): void {
console.log("updating margin");
@ -231,7 +233,8 @@ export function add(
closeCallback?: () => void,
allowHTML?: boolean
): void {
// notificationHistory.push(
NotificationEvent.dispatch(message, level, customTitle);
new Notification(
"notification",
message,
@ -242,7 +245,6 @@ export function add(
closeCallback,
allowHTML
).show();
// );
}
export function addBanner(
@ -253,7 +255,6 @@ export function addBanner(
closeCallback?: () => void,
allowHTML?: boolean
): void {
// notificationHistory.push(
new Notification(
"banner",
message,
@ -264,7 +265,6 @@ export function addBanner(
closeCallback,
allowHTML
).show();
// );
}
const debouncedMarginUpdate = debounce(100, updateMargin);

View file

@ -2,6 +2,7 @@ import Ape from "../ape";
import { secondsToString } from "../utils/misc";
import * as Notifications from "./notifications";
import format from "date-fns/format";
import * as Alerts from "./alerts";
function clearMemory(): void {
window.localStorage.setItem("confirmedPSAs", JSON.stringify([]));
@ -64,10 +65,6 @@ export async function show(): Promise<void> {
}
const localmemory = getMemory();
latest.forEach((psa) => {
if (localmemory.includes(psa._id) && (psa.sticky ?? false) === false) {
return;
}
if (psa.date) {
const dateObj = new Date(psa.date);
const diff = psa.date - Date.now();
@ -90,6 +87,12 @@ export async function show(): Promise<void> {
);
}
Alerts.addPSA(psa.message, psa.level ?? -1);
if (localmemory.includes(psa._id) && (psa.sticky ?? false) === false) {
return;
}
Notifications.addBanner(
psa.message,
psa.level,

View file

@ -0,0 +1,26 @@
type SubscribeFunction = (
message: string,
level: number,
customTitle?: string
) => void;
const subscribers: SubscribeFunction[] = [];
export function subscribe(fn: SubscribeFunction): void {
subscribers.push(fn);
}
export function dispatch(
message: string,
level: number,
customTitle?: string
): void {
subscribers.forEach((fn) => {
try {
fn(message, level, customTitle);
} catch (e) {
console.error("Notification event subscriber threw an error");
console.error(e);
}
});
}

View file

@ -8,12 +8,10 @@ import * as AllTimeStats from "../account/all-time-stats";
import * as PbTables from "../account/pb-tables";
import * as LoadingPage from "./loading";
import * as Focus from "../test/focus";
import * as SignOutButton from "../account/sign-out-button";
import * as TodayTracker from "../test/today-tracker";
import * as Notifications from "../elements/notifications";
import Page from "./page";
import * as Misc from "../utils/misc";
import * as ActivePage from "../states/active-page";
import * as Profile from "../elements/profile";
import format from "date-fns/format";
@ -842,9 +840,6 @@ function fillContent(): void {
applyHistorySmoothing();
ChartController.accountActivity.updateColors();
LoadingPage.updateBar(100, true);
setTimeout(() => {
if (ActivePage.get() == "account") SignOutButton.show();
}, 125);
Focus.set(false);
Misc.swapElements(
$(".pageAccount .preloader"),
@ -1092,14 +1087,13 @@ export const page = new Page(
$(".page.pageAccount"),
"/account",
async () => {
SignOutButton.hide();
//
},
async () => {
reset();
},
async () => {
await update();
// SignOutButton.show();
},
async () => {
//

View file

@ -2,7 +2,6 @@ import Config from "../config";
import * as TestStats from "../test/test-stats";
import * as TestUI from "../test/test-ui";
import * as ManualRestart from "../test/manual-restart-tracker";
import * as TestConfig from "../test/test-config";
import * as TestLogic from "../test/test-logic";
import * as Funbox from "../test/funbox";
import Page from "./page";
@ -15,7 +14,6 @@ export const page = new Page(
async () => {
TestLogic.restart();
Funbox.clear();
TestConfig.hide();
$("#wordsInput").focusout();
},
async () => {
@ -23,7 +21,6 @@ export const page = new Page(
},
async () => {
updateTestPageAds(false);
TestConfig.show();
TestStats.resetIncomplete();
ManualRestart.set();
TestLogic.restart({

View file

@ -139,7 +139,7 @@ $("#customTestDurationPopup .button").on("click", () => {
apply();
});
$(document).on("click", "#top .config .time .textButton", (e) => {
$(document).on("click", "#testConfig .time .textButton", (e) => {
const mode = $(e.currentTarget).attr("timeConfig");
if (mode == "custom") {
show();

View file

@ -203,7 +203,7 @@ $(document).on("click", `${popup} .wordfilter`, () => {
WordFilterPopup.show();
});
$(document).on("click", "#top .config .customText .textButton", () => {
$(document).on("click", "#testConfig .customText .textButton", () => {
show();
});

View file

@ -71,7 +71,7 @@ $("#customWordAmountPopup .button").on("click", () => {
apply();
});
$(document).on("click", "#top .config .wordCount .textButton", (e) => {
$(document).on("click", "#testConfig .wordCount .textButton", (e) => {
const wrd = $(e.currentTarget).attr("wordCount");
if (wrd == "custom") {
show();

View file

@ -89,7 +89,7 @@ $("#mobileTestConfigPopupWrapper").on("click", (e) => {
}
});
$("#top .mobileConfig").on("click", () => {
$("#mobileTestConfig").on("click", () => {
showPopup();
});

View file

@ -394,7 +394,7 @@ $(document).on("click", "#toggleShowFavorites", (e) => {
searchForQuotes();
});
$(document).on("click", "#top .config .quoteLength .textButton", (e) => {
$(document).on("click", "#testConfig .quoteLength .textButton", (e) => {
const len = $(e.currentTarget).attr("quoteLength") ?? (0 as number);
if (len == -2) {
show();

View file

@ -12,6 +12,7 @@ export function set(foc: boolean, withCursor = false): void {
$("#bottom").addClass("focus");
if (!withCursor) $("body").css("cursor", "none");
$("#middle").addClass("focus");
$("#testConfig").addClass("focus");
$("#bannerCenter").addClass("focus");
$("#capsWarning").addClass("focus");
$("#ad-vertical-right-wrapper").addClass("focus");
@ -25,6 +26,7 @@ export function set(foc: boolean, withCursor = false): void {
$("#bottom").removeClass("focus");
$("body").css("cursor", "default");
$("#middle").removeClass("focus");
$("#testConfig").removeClass("focus");
$("#bannerCenter").removeClass("focus");
$("#capsWarning").removeClass("focus");
$("#app").removeClass("focus");

View file

@ -15,6 +15,7 @@ import * as Notifications from "../elements/notifications";
import * as Loader from "../elements/loader";
import QuotesController from "../controllers/quotes-controller";
import * as AdController from "../controllers/ad-controller";
import * as TestConfig from "./test-config";
import { Chart } from "chart.js";
import { Auth } from "../firebase";
@ -711,6 +712,8 @@ export async function update(
.animate({ scrollTop: 0 }, 250);
}
TestConfig.hide();
Misc.swapElements(
$("#typingTest"),
$("#result"),

View file

@ -1,5 +1,5 @@
import * as ConfigEvent from "../observables/config-event";
import * as Misc from "../utils/misc";
// import * as Misc from "../utils/misc";
// export function show() {
// $("#top .config").removeClass("hidden").css("opacity", 1);
@ -10,159 +10,312 @@ import * as Misc from "../utils/misc";
// }
export function show(): void {
$("#top .config")
.css("transition", "unset")
.stop(true, true)
.removeClass("hidden")
.css("opacity", 0)
.animate(
{
opacity: 1,
},
125,
() => {
$("#top .config").css("transition", "0.125s");
}
);
$("#testConfig").removeClass("invisible");
}
export function hide(): void {
$("#top .config")
.css("transition", "unset")
.stop(true, true)
.css("opacity", 1)
.animate(
{
opacity: 0,
},
125,
() => {
$("#top .config").addClass("hidden").css("transition", "0.125s");
}
);
$("#testConfig").addClass("invisible");
}
export function update(
export async function update(
previous: MonkeyTypes.Mode,
current: MonkeyTypes.Mode
): void {
): Promise<void> {
if (previous === current) return;
$("#top .config .mode .textButton").removeClass("active");
$("#top .config .mode .textButton[mode='" + current + "']").addClass(
"active"
);
$("#testConfig .mode .textButton").removeClass("active");
$("#testConfig .mode .textButton[mode='" + current + "']").addClass("active");
if (current == "time") {
// $("#top .config .wordCount").addClass("hidden");
// $("#top .config .time").removeClass("hidden");
// $("#top .config .customText").addClass("hidden");
$("#top .config .punctuationMode").removeClass("disabled");
$("#top .config .numbersMode").removeClass("disabled");
// $("#top .config .puncAndNum").removeClass("disabled");
// $("#top .config .punctuationMode").removeClass("hidden");
// $("#top .config .numbersMode").removeClass("hidden");
// $("#top .config .quoteLength").addClass("hidden");
} else if (current == "words") {
// $("#top .config .wordCount").removeClass("hidden");
// $("#top .config .time").addClass("hidden");
// $("#top .config .customText").addClass("hidden");
$("#top .config .punctuationMode").removeClass("disabled");
$("#top .config .numbersMode").removeClass("disabled");
// $("#top .config .puncAndNum").removeClass("disabled");
// $("#top .config .punctuationMode").removeClass("hidden");
// $("#top .config .numbersMode").removeClass("hidden");
// $("#top .config .quoteLength").addClass("hidden");
} else if (current == "custom") {
// $("#top .config .wordCount").addClass("hidden");
// $("#top .config .time").addClass("hidden");
// $("#top .config .customText").removeClass("hidden");
$("#top .config .punctuationMode").removeClass("disabled");
$("#top .config .numbersMode").removeClass("disabled");
// $("#top .config .puncAndNum").removeClass("disabled");
// $("#top .config .punctuationMode").removeClass("hidden");
// $("#top .config .numbersMode").removeClass("hidden");
// $("#top .config .quoteLength").addClass("hidden");
} else if (current == "quote") {
// $("#top .config .wordCount").addClass("hidden");
// $("#top .config .time").addClass("hidden");
// $("#top .config .customText").addClass("hidden");
$("#top .config .punctuationMode").addClass("disabled");
$("#top .config .numbersMode").addClass("disabled");
// $("#top .config .puncAndNum").addClass("disabled");
// $("#top .config .punctuationMode").removeClass("hidden");
// $("#top .config .numbersMode").removeClass("hidden");
// $("#result .stats .source").removeClass("hidden");
// $("#top .config .quoteLength").removeClass("hidden");
} else if (current == "zen") {
// $("#top .config .wordCount").addClass("hidden");
// $("#top .config .time").addClass("hidden");
// $("#top .config .customText").addClass("hidden");
// $("#top .config .punctuationMode").addClass("hidden");
// $("#top .config .numbersMode").addClass("hidden");
// $("#top .config .quoteLength").addClass("hidden");
}
// if (current == "time") {
// $("#testConfig .punctuationMode").removeClass("hidden");
// $("#testConfig .numbersMode").removeClass("hidden");
// $("#testConfig .leftSpacer").removeClass("hidden");
// } else if (current == "words") {
// $("#testConfig .punctuationMode").removeClass("hidden");
// $("#testConfig .numbersMode").removeClass("hidden");
// $("#testConfig .leftSpacer").removeClass("hidden");
// } else if (current == "custom") {
// $("#testConfig .punctuationMode").removeClass("hidden");
// $("#testConfig .numbersMode").removeClass("hidden");
// $("#testConfig .leftSpacer").removeClass("hidden");
// } else if (current == "quote") {
// $("#testConfig .punctuationMode").addClass("hidden");
// $("#testConfig .numbersMode").addClass("hidden");
// $("#testConfig .leftSpacer").addClass("hidden");
// } else if (current == "zen") {
// //
// }
const submenu = {
time: "time",
words: "wordCount",
custom: "customText",
quote: "quoteLength",
zen: "",
zen: "zen",
};
const animTime = 250;
const puncAndNumVisible = {
time: true,
words: true,
custom: true,
quote: false,
zen: false,
};
if (
puncAndNumVisible[previous] == false &&
puncAndNumVisible[current] == true
) {
//show
$("#testConfig .leftSpacer").removeClass("scrolled");
$("#testConfig .puncAndNum")
.css({
opacity: 0,
maxWidth: 0,
})
.animate(
{
opacity: 1,
maxWidth: "14rem",
},
animTime,
"easeInOutSine"
);
} else if (
puncAndNumVisible[previous] == true &&
puncAndNumVisible[current] == false
) {
//hide
$("#testConfig .leftSpacer").addClass("scrolled");
$("#testConfig .puncAndNum")
.css({
opacity: 1,
maxWidth: "14rem",
})
.animate(
{
opacity: 0,
maxWidth: "0",
},
animTime,
"easeInOutSine"
);
}
if (current == "zen") {
$(`#top .config .${submenu[previous]}`).animate(
{
opacity: 0,
},
animTime / 2,
() => {
$(`#top .config .${submenu[previous]}`).addClass("hidden");
}
);
$(`#top .config .puncAndNum`).animate(
{
opacity: 0,
},
animTime / 2,
() => {
$(`#top .config .puncAndNum`).addClass("invisible");
}
);
return;
$("#testConfig .rightSpacer").addClass("scrolled");
} else {
$("#testConfig .rightSpacer").removeClass("scrolled");
}
if (previous == "zen") {
setTimeout(() => {
$(`#top .config .${submenu[current]}`).removeClass("hidden");
$(`#top .config .${submenu[current]}`)
.css({ opacity: 0 })
.animate(
{
opacity: 1,
},
animTime / 2
);
$(`#top .config .puncAndNum`).removeClass("invisible");
$(`#top .config .puncAndNum`)
.css({ opacity: 0 })
.animate(
{
opacity: 1,
},
animTime / 2
);
}, animTime / 2);
return;
}
// const currentWidth = Math.round(
// document.querySelector("#testConfig .row")?.getBoundingClientRect().width ??
// 0
// );
Misc.swapElements(
$("#top .config ." + submenu[previous]),
$("#top .config ." + submenu[current]),
animTime
// if (puncAndNumVisible[current]) {
// $("#testConfig .punctuationMode").removeClass("hidden");
// $("#testConfig .numbersMode").removeClass("hidden");
// $("#testConfig .leftSpacer").removeClass("hidden");
// } else {
// $("#testConfig .punctuationMode").addClass("hidden");
// $("#testConfig .numbersMode").addClass("hidden");
// $("#testConfig .leftSpacer").addClass("hidden");
// }
// if (current == "zen") {
// $("#testConfig .rightSpacer").addClass("hidden");
// } else {
// $("#testConfig .rightSpacer").removeClass("hidden");
// }
const previousWidth = Math.round(
document
.querySelector(`#testConfig .${submenu[previous]}`)
?.getBoundingClientRect().width ?? 0
);
$(`#testConfig .${submenu[previous]}`).addClass("hidden");
$(`#testConfig .${submenu[current]}`).removeClass("hidden");
const currentWidth = Math.round(
document
.querySelector(`#testConfig .${submenu[current]}`)
?.getBoundingClientRect().width ?? 0
);
$(`#testConfig .${submenu[previous]}`).removeClass("hidden");
$(`#testConfig .${submenu[current]}`).addClass("hidden");
const widthDifference = currentWidth - previousWidth;
const widthStep = widthDifference / 2;
$(`#testConfig .${submenu[previous]}`)
.css({
opacity: 1,
width: previousWidth,
})
.animate(
{
width: previousWidth + widthStep,
opacity: 0,
},
animTime / 2,
"easeInSine",
() => {
$(`#testConfig .${submenu[previous]}`)
.css({
opacity: 1,
width: "unset",
})
.addClass("hidden");
$(`#testConfig .${submenu[current]}`)
.css({
opacity: 0,
width: previousWidth + widthStep,
})
.removeClass("hidden")
.animate(
{
opacity: 1,
width: currentWidth,
},
animTime / 2,
"easeOutSine",
() => {
$(`#testConfig .${submenu[current]}`).css("width", "unset");
}
);
}
);
// $(`#testConfig .${submenu[current]}`)
// .css({
// opacity: 0,
// maxWidth: previousWidth,
// })
// .removeClass("hidden")
// .animate(
// {
// maxWidth: currentWidth,
// opacity: 1,
// },
// 250,
// () => {
// $(`#testConfig .${submenu[current]}`).css({
// opacity: 1,
// maxWidth: "unset",
// });
// }
// );
// const newWidth = Math.round(
// document.querySelector("#testConfig .row")?.getBoundingClientRect().width ??
// 0
// );
// console.log(submenu[current], animTime, newWidth, currentWidth);
// if (current == "zen") {
// $(`#testConfig .${submenu[previous]}`).animate(
// {
// opacity: 0,
// },
// animTime / 2,
// () => {
// $(`#testConfig .${submenu[previous]}`).addClass("hidden");
// }
// );
// $(`#testConfig .puncAndNum`).animate(
// {
// opacity: 0,
// },
// animTime / 2,
// () => {
// $(`#testConfig .puncAndNum`).addClass("hidden");
// }
// );
// return;
// }
// if (previous == "zen") {
// setTimeout(() => {
// $(`#testConfig .${submenu[current]}`).removeClass("hidden");
// $(`#testConfig .${submenu[current]}`)
// .css({ opacity: 0 })
// .animate(
// {
// opacity: 1,
// },
// animTime / 2
// );
// $(`#testConfig .puncAndNum`).removeClass("hidden");
// $(`#testConfig .puncAndNum`)
// .css({ opacity: 0 })
// .animate(
// {
// opacity: 1,
// },
// animTime / 2
// );
// }, animTime / 2);
// return;
// }
// Misc.swapElements(
// $("#testConfig ." + submenu[previous]),
// $("#testConfig ." + submenu[current]),
// animTime
// );
}
export function updateExtras(
key: string,
value: MonkeyTypes.ConfigValues
): void {
if (key == "time") {
$("#testConfig .time .textButton").removeClass("active");
const timeCustom = ![15, 30, 60, 120].includes(value as number)
? "custom"
: value;
$(
"#testConfig .time .textButton[timeConfig='" + timeCustom + "']"
).addClass("active");
} else if (key == "words") {
$("#testConfig .wordCount .textButton").removeClass("active");
const wordCustom = ![10, 25, 50, 100, 200].includes(value as number)
? "custom"
: value;
$(
"#testConfig .wordCount .textButton[wordCount='" + wordCustom + "']"
).addClass("active");
} else if (key == "quoteLength") {
$("#testConfig .quoteLength .textButton").removeClass("active");
(value as MonkeyTypes.QuoteLength[]).forEach((ql) => {
$(
"#testConfig .quoteLength .textButton[quoteLength='" + ql + "']"
).addClass("active");
});
} else if (key == "numbers") {
if (!value) {
$("#testConfig .numbersMode.textButton").removeClass("active");
} else {
$("#testConfig .numbersMode.textButton").addClass("active");
}
} else if (key == "punctuation") {
if (!value) {
$("#testConfig .punctuationMode.textButton").removeClass("active");
} else {
$("#testConfig .punctuationMode.textButton").addClass("active");
}
}
}
export function showFavoriteQuoteLength(): void {
@ -179,5 +332,11 @@ ConfigEvent.subscribe((eventKey, eventValue, _nosave, eventPreviousValue) => {
eventPreviousValue as MonkeyTypes.Mode,
eventValue as MonkeyTypes.Mode
);
} else if (
["time", "quoteLength", "words", "numbers", "punctuation"].includes(
eventKey
)
) {
updateExtras(eventKey, eventValue);
}
});

View file

@ -54,6 +54,7 @@ import objectHash from "object-hash";
import * as AnalyticsController from "../controllers/analytics-controller";
import { Auth } from "../firebase";
import * as AdController from "../controllers/ad-controller";
import * as TestConfig from "./test-config";
let failReason = "";
const koInputVisual = document.getElementById("koInputVisual") as HTMLElement;
@ -553,6 +554,7 @@ export function restart(options = {} as RestartOptions): void {
AdController.updateTestPageAds(false);
Focus.set(false);
}
TestConfig.show();
TestUI.focusWords();
$("#monkey .fast").stop(true, true).css("opacity", 0);
$("#monkey").stop(true, true).css({ animationDuration: "0s" });
@ -1851,7 +1853,17 @@ $(document).on("keypress", "#restartTestButtonWithSameWordset", (event) => {
}
});
$(document).on("click", "#top .config .wordCount .textButton", (e) => {
$(document).on("click", "#testConfig .mode .textButton", (e) => {
if (TestUI.testRestarting) return;
if ($(e.currentTarget).hasClass("active")) return;
const mode = ($(e.currentTarget).attr("mode") ?? "time") as MonkeyTypes.Mode;
if (mode === undefined) return;
UpdateConfig.setMode(mode);
ManualRestart.set();
restart();
});
$(document).on("click", "#testConfig .wordCount .textButton", (e) => {
if (TestUI.testRestarting) return;
const wrd = $(e.currentTarget).attr("wordCount") ?? "15";
if (wrd != "custom") {
@ -1861,7 +1873,7 @@ $(document).on("click", "#top .config .wordCount .textButton", (e) => {
}
});
$(document).on("click", "#top .config .time .textButton", (e) => {
$(document).on("click", "#testConfig .time .textButton", (e) => {
if (TestUI.testRestarting) return;
const mode = $(e.currentTarget).attr("timeConfig") ?? "10";
if (mode != "custom") {
@ -1871,7 +1883,7 @@ $(document).on("click", "#top .config .time .textButton", (e) => {
}
});
$(document).on("click", "#top .config .quoteLength .textButton", (e) => {
$(document).on("click", "#testConfig .quoteLength .textButton", (e) => {
if (TestUI.testRestarting) return;
let len: MonkeyTypes.QuoteLength | MonkeyTypes.QuoteLength[] = <
MonkeyTypes.QuoteLength
@ -1886,30 +1898,20 @@ $(document).on("click", "#top .config .quoteLength .textButton", (e) => {
}
});
$(document).on("click", "#top .config .punctuationMode .textButton", () => {
$(document).on("click", "#testConfig .punctuationMode.textButton", () => {
if (TestUI.testRestarting) return;
UpdateConfig.setPunctuation(!Config.punctuation);
ManualRestart.set();
restart();
});
$(document).on("click", "#top .config .numbersMode .textButton", () => {
$(document).on("click", "#testConfig .numbersMode.textButton", () => {
if (TestUI.testRestarting) return;
UpdateConfig.setNumbers(!Config.numbers);
ManualRestart.set();
restart();
});
$(document).on("click", "#top .config .mode .textButton", (e) => {
if (TestUI.testRestarting) return;
if ($(e.currentTarget).hasClass("active")) return;
const mode = ($(e.currentTarget).attr("mode") ?? "time") as MonkeyTypes.Mode;
if (mode === undefined) return;
UpdateConfig.setMode(mode);
ManualRestart.set();
restart();
});
$("#practiseWordsPopup .button.missed").on("click", () => {
PractiseWords.hidePopup();
PractiseWords.init(true, false);

View file

@ -252,6 +252,7 @@ export async function screenshot(): Promise<void> {
}
function revertScreenshot(): void {
$("#testConfig").removeClass("invisible");
$("#ad-result-wrapper").removeClass("hidden");
$("#ad-result-small-wrapper").removeClass("hidden");
$("#notificationCenter").removeClass("hidden");
@ -287,6 +288,16 @@ export async function screenshot(): Promise<void> {
);
}
$(".pageTest .buttons").addClass("hidden");
$("#testConfig").addClass("invisible");
$("#notificationCenter").addClass("hidden");
$("#commandLineMobileButton").addClass("hidden");
$(".pageTest .loginTip").addClass("hidden");
$("noscript").addClass("hidden");
$("#nocss").addClass("hidden");
$("#ad-result-wrapper").addClass("hidden");
$("#ad-result-small-wrapper").addClass("hidden");
if (revertCookie) $("#cookiePopupWrapper").addClass("hidden");
const src = $("#result");
const sourceX = src.offset()?.left ?? 0; /*X position from div#target*/
const sourceY = src.offset()?.top ?? 0; /*Y position from div#target*/
@ -296,14 +307,6 @@ export async function screenshot(): Promise<void> {
const sourceHeight = <number>(
src.outerHeight(true)
); /*clientHeight/offsetHeight from div#target*/
$("#notificationCenter").addClass("hidden");
$("#commandLineMobileButton").addClass("hidden");
$(".pageTest .loginTip").addClass("hidden");
$("noscript").addClass("hidden");
$("#nocss").addClass("hidden");
$("#ad-result-wrapper").addClass("hidden");
$("#ad-result-small-wrapper").addClass("hidden");
if (revertCookie) $("#cookiePopupWrapper").addClass("hidden");
try {
const paddingX = Misc.convertRemToPixels(2);
const paddingY = Misc.convertRemToPixels(2);

View file

@ -473,6 +473,7 @@ declare namespace MonkeyTypes {
addedAt: number;
filterPresets: ResultFilters[];
xp: number;
inboxUnreadSize: number;
streak: number;
}
@ -739,4 +740,30 @@ declare namespace MonkeyTypes {
color?: string;
customStyle?: string;
}
interface MonkeyMail {
id: string;
subject: string;
body: string;
timestamp: number;
read: boolean;
rewards: AllRewards[];
}
interface Reward<T> {
type: string;
item: T;
}
interface XpReward extends Reward<number> {
type: "xp";
item: number;
}
interface BadgeReward extends Reward<Badge> {
type: "badge";
item: Badge;
}
type AllRewards = XpReward | BadgeReward;
}

View file

@ -1443,7 +1443,12 @@
<h1>font size</h1>
<div class="text">Change the font size of the test words.</div>
<div class="inputAndButton">
<input type="text" placeholder="font size" class="input" tabindex="0" />
<input
type="number"
placeholder="font size"
class="input"
tabindex="0"
/>
<div class="button save" tabindex="0" onclick="this.blur();">
<i class="fas fa-save fa-fw"></i>
</div>

View file

@ -1,4 +1,122 @@
<div class="page pageTest hidden">
<div id="testConfig">
<div class="row">
<div class="puncAndNum">
<div class="textButton punctuationMode">
<span
style="
font-weight: 900;
width: 1.25rem;
text-align: center;
display: inline-block;
letter-spacing: -0.1em;
font-size: 1.1em;
height: 0em;
"
>
!?
</span>
punctuation
</div>
<div class="textButton numbersMode">
<span
style="
font-weight: 900;
width: 1.25rem;
text-align: center;
display: inline-block;
letter-spacing: -0.1em;
font-size: 1.1em;
height: 0em;
"
>
15
</span>
numbers
</div>
</div>
<div class="spacer leftSpacer"></div>
<div class="mode">
<div class="textButton active" mode="time">
<i class="fas fa-fw fa-clock"></i>
time
</div>
<div class="textButton" mode="words">
<i class="fas fa-fw fa-font"></i>
words
</div>
<div class="textButton" mode="quote">
<i class="fas fa-fw fa-quote-left"></i>
quote
</div>
<div class="textButton" mode="zen">
<i class="fas fa-fw fa-mountain"></i>
zen
</div>
<div class="textButton" mode="custom">
<i class="fas fa-fw fa-wrench"></i>
custom
</div>
</div>
<div class="spacer rightSpacer"></div>
<div class="time">
<div class="textButton" timeConfig="15"><span>15</span></div>
<div class="textButton active" timeConfig="30"><span>30</span></div>
<div class="textButton" timeConfig="60"><span>60</span></div>
<div class="textButton" timeConfig="120"><span>120</span></div>
<div class="textButton" timeConfig="custom">
<i class="fas fa-fw fa-tools" style="margin-top: 0.1rem"></i>
</div>
</div>
<div class="wordCount hidden">
<div class="textButton" wordCount="10"><span>10</span></div>
<div class="textButton" wordCount="25"><span>25</span></div>
<div class="textButton active" wordCount="50"><span>50</span></div>
<div class="textButton" wordCount="100"><span>100</span></div>
<div class="textButton" wordCount="custom">
<i class="fas fa-fw fa-tools" style="margin-top: 0.1rem"></i>
</div>
</div>
<div class="quoteLength hidden">
<div class="textButton" quotelength="-1">all</div>
<div class="textButton" quotelength="0">short</div>
<div class="textButton active" quotelength="1">medium</div>
<div class="textButton" quotelength="2">long</div>
<div class="textButton" quotelength="3">thicc</div>
<div class="textButton favorite" quotelength="-3">
<i class="fas fa-heart" style="margin-top: 0.1rem"></i>
</div>
<div class="textButton" quotelength="-2">
<i class="fas fa-search" style="margin-top: 0.1rem"></i>
</div>
</div>
<div class="zen hidden">
<div
class="textButton"
style="width: 0; padding-left: 0; padding-right: 0"
>
</div>
</div>
<div class="customText hidden">
<div class="textButton">change</div>
</div>
</div>
</div>
<div id="mobileTestConfig">
<div class="textButton">
<i class="fas fa-fw fa-cog"></i>
Test Settings
</div>
</div>
<div id="typingTest">
<div id="capsWarning" class="hidden">
<i class="fas fa-lock"></i>
@ -327,4 +445,5 @@
</div>
<div class="ssWatermark hidden">monkeytype.com</div>
</div>
<div></div>
</div>

View file

@ -1,3 +1,36 @@
<div id="alertsPopupWrapper" class="popupWrapper hidden">
<div id="alertsPopup">
<div class="scrollWrapper">
<div class="accountAlerts">
<div class="title">
<div class="left">
<i class="fas fa-inbox"></i>
Inbox
</div>
<div class="right"></div>
</div>
<div class="list"><div class="nothing">Nothing to show</div></div>
</div>
<div class="separator accountSeparator"></div>
<div class="psas">
<div class="title">
<i class="fas fa-bullhorn"></i>
Announcements
</div>
<div class="list"><div class="nothing">Nothing to show</div></div>
</div>
<div class="separator"></div>
<div class="notificationHistory">
<div class="title">
<i class="fas fa-comment-alt"></i>
Notifications
</div>
<div class="list"><div class="nothing">Nothing to show</div></div>
</div>
</div>
</div>
</div>
<div id="simplePopupWrapper" class="popupWrapper hidden">
<div id="simplePopup" popupId=""></div>
</div>

View file

@ -99,6 +99,7 @@
<i class="fas fa-fw fa-cog"></i>
</div>
</a>
<div></div>
<a
class="textButton hidden account view-account"
tabindex="2"
@ -134,98 +135,34 @@
<i class="far fa-fw fa-user"></i>
</div>
</a>
<a
class="textButton showAlerts"
tabindex="2"
href=""
onclick="this.blur();"
data-link
>
<div class="icon">
<i class="fas fa-fw fa-bell"></i>
</div>
</a>
<a
class="textButton signInOut"
tabindex="2"
onclick="this.blur();"
data-link
>
<div class="icon">
<i class="fas fa-fw fa-sign-in-alt"></i>
</div>
</a>
</div>
<div class="config hidden">
<div class="mobileConfig">
<div class="textButton">
<i class="fas fa-bars"></i>
</div>
</div>
<div class="desktopConfig">
<div
class="puncAndNum"
style="display: grid; grid-auto-flow: column; padding-top: 0.1rem"
>
<div class="group punctuationMode">
<!-- <div class="title">time</div> -->
<div class="buttons">
<div class="textButton toggleButton" tabindex="2">punctuation</div>
</div>
</div>
<div class="group numbersMode">
<!-- <div class="title">time</div> -->
<div class="buttons">
<div class="textButton toggleButton" tabindex="2">numbers</div>
</div>
</div>
</div>
<div class="group mode">
<!-- <div class="title">mode</div> -->
<div class="buttons">
<div class="textButton active" mode="time" tabindex="2">time</div>
<div class="textButton" mode="words" tabindex="2">words</div>
<div class="textButton" mode="quote" tabindex="2">quote</div>
<div class="textButton" mode="zen" tabindex="2">zen</div>
<div class="textButton" mode="custom" tabindex="2">custom</div>
</div>
</div>
<div class="group wordCount hidden">
<!-- <div class="title">words</div> -->
<div class="buttons">
<div class="textButton" wordCount="10" tabindex="2">10</div>
<div class="textButton" wordCount="25" tabindex="2">25</div>
<div class="textButton active" wordCount="50" tabindex="2">50</div>
<div class="textButton" wordCount="100" tabindex="2">100</div>
<div class="textButton" wordCount="custom" tabindex="2">
<i class="fas fa-tools"></i>
</div>
</div>
</div>
<div class="group time">
<!-- <div class="title">time</div> -->
<div class="buttons">
<div class="textButton" timeConfig="15" tabindex="2">15</div>
<div class="textButton active" timeConfig="30" tabindex="2">30</div>
<div class="textButton" timeConfig="60" tabindex="2">60</div>
<div class="textButton" timeConfig="120" tabindex="2">120</div>
<div class="textButton" timeConfig="custom" tabindex="2">
<i class="fas fa-tools"></i>
</div>
</div>
</div>
<div class="group quoteLength hidden">
<!-- <div class="title">time</div> -->
<div class="buttons">
<div class="textButton" quoteLength="-1" tabindex="2">all</div>
<div class="textButton" quoteLength="0" tabindex="2">short</div>
<div class="textButton active" quoteLength="1" tabindex="2">
medium
</div>
<div class="textButton" quoteLength="2" tabindex="2">long</div>
<div class="textButton" quoteLength="3" tabindex="2">thicc</div>
<div class="textButton hidden favorite" quoteLength="-3" tabindex="2">
<i class="fas fa-heart"></i>
</div>
<div class="textButton" quoteLength="-2" tabindex="2">
<i class="fas fa-search"></i>
</div>
</div>
</div>
<div class="group customText hidden">
<!-- <div class="title">time</div> -->
<div class="buttons">
<div class="textButton">change</div>
</div>
</div>
</div>
</div>
<div
<!-- <div
class="signOut hidden"
style="grid-column: 3/4; grid-row: 1/2"
tabindex="0"
>
<i class="fas fa-sign-out-alt"></i>
sign out
</div>
</div> -->
</div>

View file

@ -39,7 +39,7 @@
</div>
<div id="centerContent" class="hidden">
<%= compilation.assets["html/top.html"].source() %>
<div id="middle">
<div id="middle" style="height: 100%">
<%= compilation.assets["html/pages/loading.html"].source() %> <%=
compilation.assets["html/pages/test.html"].source() %> <%=
compilation.assets["html/pages/about.html"].source() %> <%=