Merge remote-tracking branch 'upstream/master'
15
README.md
|
@ -1,6 +1,6 @@
|
|||
# monkeytype
|
||||
|
||||

|
||||
[](https://monkeytype.com/)
|
||||
<br />
|
||||
|
||||
<img align="left" alt="JavaScript" width="26px" src="https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/javascript/javascript.png" />
|
||||
|
@ -35,6 +35,13 @@ Recently, a Discord bot was added to autoassign roles on our server. You can fin
|
|||
|
||||
If you encounter a bug, or have a feature request - send me a message on Reddit, [create an issue](https://github.com/Miodec/monkeytype/issues), [create a discussion thread](https://github.com/Miodec/monkeytype/discussions), or [join the Discord server](https://www.discord.gg/monkeytype).
|
||||
|
||||
# Contribute
|
||||
|
||||
Refer to [CONTRIBUTING.md](https://github.com/Miodec/monkeytype/blob/master/CONTRIBUTING.md)
|
||||
|
||||
# Code Of Conduct
|
||||
|
||||
Before contributing to this repository please refer to [CODE_OF_CONDUCT.md](https://github.com/Miodec/monkeytype/blob/master/CODE_OF_CONDUCT.md)
|
||||
# Credits
|
||||
|
||||
Montydrei for the name suggestion
|
||||
|
@ -47,10 +54,4 @@ Contributors that have helped with implementing various features, adding themes
|
|||
|
||||
If you wish to support further development and feel extra awesome, you can do so [here](https://www.paypal.me/jackbartnik).
|
||||
|
||||
# Contribute
|
||||
|
||||
Refer to [CONTRIBUTING.md](https://github.com/Miodec/monkeytype/blob/master/CONTRIBUTING.md)
|
||||
|
||||
# Code Of Conduct
|
||||
|
||||
Before contributing to this repository please refer to [CODE_OF_CONDUCT.md](https://github.com/Miodec/monkeytype/blob/master/CODE_OF_CONDUCT.md)
|
||||
|
|
|
@ -1782,6 +1782,7 @@ exports.saveConfig = functions.https.onCall((request, response) => {
|
|||
}
|
||||
if (err) return;
|
||||
if (key === "resultFilters") return;
|
||||
if (key === "customBackground") return;
|
||||
let val = obj[key];
|
||||
if (Array.isArray(val)) {
|
||||
val.forEach((valarr) => {
|
||||
|
@ -2306,6 +2307,38 @@ exports.checkLeaderboards = functions.https.onRequest(
|
|||
return;
|
||||
}
|
||||
request = request.body.data;
|
||||
|
||||
function verifyValue(val) {
|
||||
let errCount = 0;
|
||||
if (val === null || val === undefined) {
|
||||
} else if (Array.isArray(val)) {
|
||||
//array
|
||||
val.forEach((val2) => {
|
||||
errCount += verifyValue(val2);
|
||||
});
|
||||
} else if (typeof val === "object" && !Array.isArray(val)) {
|
||||
//object
|
||||
Object.keys(val).forEach((valkey) => {
|
||||
errCount += verifyValue(val[valkey]);
|
||||
});
|
||||
} else {
|
||||
if (!/^[0-9a-zA-Z._\-\+]+$/.test(val)) errCount++;
|
||||
}
|
||||
return errCount;
|
||||
}
|
||||
let errCount = verifyValue(request);
|
||||
if (errCount > 0) {
|
||||
console.error(
|
||||
`error checking leaderboard for ${
|
||||
request.uid
|
||||
} error count ${errCount} - bad input - ${JSON.stringify(request.obj)}`
|
||||
);
|
||||
response.status(200).send({ data: {
|
||||
status: -999,
|
||||
message: "Bad input",
|
||||
}});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (request.emailVerified === false) {
|
||||
|
@ -2421,10 +2454,10 @@ exports.checkLeaderboards = functions.https.onRequest(
|
|||
console.error(
|
||||
`error in transaction checking leaderboards - ${error}`
|
||||
);
|
||||
return {
|
||||
response.status(200).send({ data: {
|
||||
status: -999,
|
||||
message: error,
|
||||
};
|
||||
}});
|
||||
});
|
||||
|
||||
let daily = await db
|
||||
|
@ -2499,10 +2532,10 @@ exports.checkLeaderboards = functions.https.onRequest(
|
|||
console.error(
|
||||
`error in transaction checking leaderboards - ${error}`
|
||||
);
|
||||
return {
|
||||
response.status(200).send({ data: {
|
||||
status: -999,
|
||||
message: error,
|
||||
};
|
||||
}});
|
||||
});
|
||||
|
||||
//send discord update
|
||||
|
|
20
gulpfile.js
|
@ -90,7 +90,6 @@ const refactoredSrc = [
|
|||
"./src/js/cloud-functions.js",
|
||||
"./src/js/misc.js",
|
||||
"./src/js/layouts.js",
|
||||
"./src/js/result-filters.js",
|
||||
"./src/js/sound.js",
|
||||
"./src/js/theme-colors.js",
|
||||
"./src/js/chart-controller.js",
|
||||
|
@ -106,11 +105,20 @@ const refactoredSrc = [
|
|||
"./src/js/account-controller.js",
|
||||
"./src/js/simple-popups.js",
|
||||
"./src/js/settings.js",
|
||||
"./src/js/input-controller.js",
|
||||
"./src/js/route-controller.js",
|
||||
"./src/js/ready.js",
|
||||
|
||||
"./src/js/account/all-time-stats.js",
|
||||
"./src/js/account/pb-tables.js",
|
||||
"./src/js/account/result-filters.js",
|
||||
"./src/js/account/verification-controller.js",
|
||||
"./src/js/account.js",
|
||||
|
||||
"./src/js/elements/monkey.js",
|
||||
"./src/js/elements/notifications.js",
|
||||
"./src/js/elements/leaderboards.js",
|
||||
"./src/js/elements/account-icon.js",
|
||||
"./src/js/elements/account-button.js",
|
||||
"./src/js/elements/loader.js",
|
||||
"./src/js/elements/sign-out-button.js",
|
||||
|
||||
|
@ -125,6 +133,7 @@ const refactoredSrc = [
|
|||
"./src/js/popups/edit-tags-popup.js",
|
||||
"./src/js/popups/custom-theme-popup.js",
|
||||
"./src/js/popups/import-settings-popup.js",
|
||||
"./src/js/popups/custom-background-filter.js",
|
||||
|
||||
"./src/js/settings/language-picker.js",
|
||||
"./src/js/settings/theme-picker.js",
|
||||
|
@ -156,12 +165,7 @@ const refactoredSrc = [
|
|||
|
||||
//legacy files
|
||||
//the order of files is important
|
||||
const globalSrc = [
|
||||
"./src/js/global-dependencies.js",
|
||||
"./src/js/account.js",
|
||||
"./src/js/script.js",
|
||||
"./src/js/exports.js",
|
||||
];
|
||||
const globalSrc = ["./src/js/global-dependencies.js", "./src/js/exports.js"];
|
||||
|
||||
//concatenates and lints legacy js files and writes the output to dist/gen/index.js
|
||||
task("cat", function () {
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
import * as Notifications from "./notifications";
|
||||
import * as UpdateConfig from "./config";
|
||||
import * as AccountButton from "./account-button";
|
||||
import * as Account from "./account";
|
||||
import * as CommandlineLists from "./commandline-lists";
|
||||
import * as VerificationController from "./verification-controller";
|
||||
import * as Misc from "./misc";
|
||||
import * as Settings from "./settings";
|
||||
import * as ChallengeController from "./challenge-controller";
|
||||
import Config from "./config";
|
||||
import * as CloudFunctions from "./cloud-functions";
|
||||
import * as AllTimeStats from "./all-time-stats";
|
||||
import * as DB from "./db";
|
||||
import * as TestLogic from "./test-logic";
|
||||
import * as UI from "./ui";
|
||||
|
||||
var gmailProvider = new firebase.auth.GoogleAuthProvider();
|
||||
|
||||
|
@ -17,7 +31,7 @@ export function signIn() {
|
|||
.auth()
|
||||
.signInWithEmailAndPassword(email, password)
|
||||
.then((e) => {
|
||||
// changePage("test");
|
||||
// UI.changePage("test");
|
||||
})
|
||||
.catch(function (error) {
|
||||
Notifications.add(error.message, -1);
|
||||
|
@ -34,7 +48,7 @@ export function signIn() {
|
|||
.auth()
|
||||
.signInWithEmailAndPassword(email, password)
|
||||
.then((e) => {
|
||||
// changePage("test");
|
||||
// UI.changePage("test");
|
||||
})
|
||||
.catch(function (error) {
|
||||
Notifications.add(error.message, -1);
|
||||
|
@ -96,19 +110,255 @@ export function signOut() {
|
|||
.signOut()
|
||||
.then(function () {
|
||||
Notifications.add("Signed out", 0, 2);
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 1000);
|
||||
|
||||
//TODO Bring this back when possible
|
||||
|
||||
// clearGlobalStats();
|
||||
// Settings.hideAccountSection();
|
||||
// updateAccountLoginButton();
|
||||
// changePage("login");
|
||||
// DB.setSnapshot(null);
|
||||
AllTimeStats.clear();
|
||||
Settings.hideAccountSection();
|
||||
AccountButton.update();
|
||||
UI.changePage("login");
|
||||
DB.setSnapshot(null);
|
||||
})
|
||||
.catch(function (error) {
|
||||
Notifications.add(error.message, -1);
|
||||
});
|
||||
}
|
||||
|
||||
function signUp() {
|
||||
$(".pageLogin .register .button").addClass("disabled");
|
||||
$(".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;
|
||||
|
||||
if (password != passwordVerify) {
|
||||
Notifications.add("Passwords do not match", 0, 3);
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
$(".pageLogin .register .button").removeClass("disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
CloudFunctions.namecheck({ name: nname }).then((d) => {
|
||||
if (d.data.resultCode === -1) {
|
||||
Notifications.add("Name unavailable", -1);
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
$(".pageLogin .register .button").removeClass("disabled");
|
||||
return;
|
||||
} else if (d.data.resultCode === -2) {
|
||||
Notifications.add(
|
||||
"Name cannot contain special characters or contain more than 14 characters. Can include _ . and -",
|
||||
-1
|
||||
);
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
$(".pageLogin .register .button").removeClass("disabled");
|
||||
return;
|
||||
} else if (d.data.resultCode === 1) {
|
||||
firebase
|
||||
.auth()
|
||||
.createUserWithEmailAndPassword(email, password)
|
||||
.then((user) => {
|
||||
// Account has been created here.
|
||||
// dontCheckUserName = true;
|
||||
let usr = user.user;
|
||||
usr
|
||||
.updateProfile({
|
||||
displayName: nname,
|
||||
})
|
||||
.then(async function () {
|
||||
// Update successful.
|
||||
await firebase
|
||||
.firestore()
|
||||
.collection("users")
|
||||
.doc(usr.uid)
|
||||
.set({ name: nname }, { merge: true });
|
||||
CloudFunctions.reserveName({ name: nname, uid: usr.uid }).catch(
|
||||
(e) => {
|
||||
console.error("Could not reserve name " + e);
|
||||
throw "Could not reserve name";
|
||||
}
|
||||
);
|
||||
usr.sendEmailVerification();
|
||||
AllTimeStats.clear();
|
||||
Notifications.add("Account created", 1, 3);
|
||||
$("#menu .icon-button.account .text").text(nname);
|
||||
try {
|
||||
firebase.analytics().logEvent("accountCreated", usr.uid);
|
||||
} catch (e) {
|
||||
console.log("Analytics unavailable");
|
||||
}
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
DB.setSnapshot({
|
||||
results: [],
|
||||
personalBests: {},
|
||||
tags: [],
|
||||
globalStats: {
|
||||
time: undefined,
|
||||
started: undefined,
|
||||
completed: undefined,
|
||||
},
|
||||
});
|
||||
if (TestLogic.notSignedInLastResult !== null) {
|
||||
TestLogic.setNotSignedInUid(usr.uid);
|
||||
CloudFunctions.testCompleted({
|
||||
uid: usr.uid,
|
||||
obj: TestLogic.notSignedInLastResult,
|
||||
});
|
||||
DB.getSnapshot().results.push(TestLogic.notSignedInLastResult);
|
||||
}
|
||||
UI.changePage("account");
|
||||
usr.sendEmailVerification();
|
||||
$(".pageLogin .register .button").removeClass("disabled");
|
||||
})
|
||||
.catch(function (error) {
|
||||
// An error happened.
|
||||
$(".pageLogin .register .button").removeClass("disabled");
|
||||
console.error(error);
|
||||
usr
|
||||
.delete()
|
||||
.then(function () {
|
||||
// User deleted.
|
||||
Notifications.add(
|
||||
"Account not created. " + error.message,
|
||||
-1
|
||||
);
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
})
|
||||
.catch(function (error) {
|
||||
// An error happened.
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
Notifications.add(
|
||||
"Something went wrong. " + error.message,
|
||||
-1
|
||||
);
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function (error) {
|
||||
// Handle Errors here.
|
||||
$(".pageLogin .register .button").removeClass("disabled");
|
||||
Notifications.add(error.message, -1);
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
});
|
||||
} else {
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
Notifications.add(
|
||||
"Something went wrong when checking name: " + d.data.message,
|
||||
-1
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(".pageLogin #forgotPasswordButton").click((e) => {
|
||||
let email = prompt("Email address");
|
||||
if (email) {
|
||||
firebase
|
||||
.auth()
|
||||
.sendPasswordResetEmail(email)
|
||||
.then(function () {
|
||||
// Email sent.
|
||||
Notifications.add("Email sent", 1, 2);
|
||||
})
|
||||
.catch(function (error) {
|
||||
// An error happened.
|
||||
Notifications.add(error.message, -1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(".pageLogin .login input").keyup((e) => {
|
||||
if (e.key == "Enter") {
|
||||
UpdateConfig.setChangedBeforeDb(false);
|
||||
signIn();
|
||||
}
|
||||
});
|
||||
|
||||
$(".pageLogin .login .button.signIn").click((e) => {
|
||||
UpdateConfig.setChangedBeforeDb(false);
|
||||
signIn();
|
||||
});
|
||||
|
||||
$(".pageLogin .login .button.signInWithGoogle").click((e) => {
|
||||
UpdateConfig.setChangedBeforeDb(false);
|
||||
signInWithGoogle();
|
||||
});
|
||||
|
||||
$(".signOut").click((e) => {
|
||||
signOut();
|
||||
});
|
||||
|
||||
firebase.auth().onAuthStateChanged(function (user) {
|
||||
if (user) {
|
||||
// User is signed in.
|
||||
$(".pageAccount .content p.accountVerificatinNotice").remove();
|
||||
if (user.emailVerified === false) {
|
||||
$(".pageAccount .content").prepend(
|
||||
`<p class="accountVerificatinNotice" style="text-align:center">Your account is not verified. Click <a onClick="sendVerificationEmail()">here</a> to resend the verification email.`
|
||||
);
|
||||
}
|
||||
AccountButton.update();
|
||||
AccountButton.loading(true);
|
||||
Account.getDataAndInit();
|
||||
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;
|
||||
$(".pageLogin .preloader").addClass("hidden");
|
||||
$("#menu .icon-button.account .text").text(displayName);
|
||||
|
||||
// showFavouriteThemesAtTheTop();
|
||||
CommandlineLists.updateThemeCommands();
|
||||
|
||||
let text = "Account created on " + user.metadata.creationTime;
|
||||
|
||||
const date1 = new Date(user.metadata.creationTime);
|
||||
const date2 = new Date();
|
||||
const diffTime = Math.abs(date2 - date1);
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
text += ` (${diffDays} day${diffDays != 1 ? "s" : ""} ago)`;
|
||||
|
||||
$(".pageAccount .group.createdDate").text(text);
|
||||
|
||||
if (VerificationController.data !== null) {
|
||||
VerificationController.verify(user);
|
||||
}
|
||||
}
|
||||
let theme = Misc.findGetParameter("customTheme");
|
||||
if (theme !== null) {
|
||||
try {
|
||||
theme = theme.split(",");
|
||||
UpdateConfig.setCustomThemeColors(theme);
|
||||
Notifications.add("Custom theme applied.", 1);
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
"Something went wrong. Reverting to default custom colors.",
|
||||
0
|
||||
);
|
||||
UpdateConfig.setCustomThemeColors(Config.defaultConfig.customThemeColors);
|
||||
}
|
||||
UpdateConfig.setCustomTheme(true);
|
||||
Settings.setCustomThemeInputs();
|
||||
}
|
||||
if (/challenge_.+/g.test(window.location.pathname)) {
|
||||
Notifications.add("Loading challenge", 0);
|
||||
let challengeName = window.location.pathname.split("_")[1];
|
||||
setTimeout(() => {
|
||||
ChallengeController.setup(challengeName);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
$(".pageLogin .register input").keyup((e) => {
|
||||
if ($(".pageLogin .register .button").hasClass("disabled")) return;
|
||||
if (e.key == "Enter") {
|
||||
signUp();
|
||||
}
|
||||
});
|
||||
|
||||
$(".pageLogin .register .button").click((e) => {
|
||||
if ($(".pageLogin .register .button").hasClass("disabled")) return;
|
||||
signUp();
|
||||
});
|
||||
|
|
31
src/js/account/all-time-stats.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import * as DB from "./db";
|
||||
|
||||
export function clear() {
|
||||
$(".pageAccount .globalTimeTyping .val").text(`-`);
|
||||
$(".pageAccount .globalTestsStarted .val").text(`-`);
|
||||
$(".pageAccount .globalTestsCompleted .val").text(`-`);
|
||||
}
|
||||
|
||||
export function update() {
|
||||
if (DB.getSnapshot().globalStats.time != undefined) {
|
||||
let th = Math.floor(DB.getSnapshot().globalStats.time / 3600);
|
||||
let tm = Math.floor((DB.getSnapshot().globalStats.time % 3600) / 60);
|
||||
let ts = Math.floor((DB.getSnapshot().globalStats.time % 3600) % 60);
|
||||
$(".pageAccount .globalTimeTyping .val").text(`
|
||||
|
||||
${th < 10 ? "0" + th : th}:${tm < 10 ? "0" + tm : tm}:${
|
||||
ts < 10 ? "0" + ts : ts
|
||||
}
|
||||
`);
|
||||
}
|
||||
if (DB.getSnapshot().globalStats.started != undefined) {
|
||||
$(".pageAccount .globalTestsStarted .val").text(
|
||||
DB.getSnapshot().globalStats.started
|
||||
);
|
||||
}
|
||||
if (DB.getSnapshot().globalStats.completed != undefined) {
|
||||
$(".pageAccount .globalTestsCompleted .val").text(
|
||||
DB.getSnapshot().globalStats.completed
|
||||
);
|
||||
}
|
||||
}
|
234
src/js/account/pb-tables.js
Normal file
|
@ -0,0 +1,234 @@
|
|||
import * as DB from "./db";
|
||||
|
||||
export function update() {
|
||||
$(".pageAccount .timePbTable tbody").html(`
|
||||
<tr>
|
||||
<td>15</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>30</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>60</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>120</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
`);
|
||||
$(".pageAccount .wordsPbTable tbody").html(`
|
||||
<tr>
|
||||
<td>10</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>25</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>50</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>100</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
`);
|
||||
|
||||
const pb = DB.getSnapshot().personalBests;
|
||||
let pbData;
|
||||
let text;
|
||||
|
||||
text = "";
|
||||
try {
|
||||
pbData = pb.time[15].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>15</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>15</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
try {
|
||||
pbData = pb.time[30].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>30</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>30</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
try {
|
||||
pbData = pb.time[60].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>60</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>60</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
try {
|
||||
pbData = pb.time[120].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>120</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>120</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
$(".pageAccount .timePbTable tbody").html(text);
|
||||
|
||||
text = "";
|
||||
try {
|
||||
pbData = pb.words[10].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>10</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>10</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
try {
|
||||
pbData = pb.words[25].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>25</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>25</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
try {
|
||||
pbData = pb.words[50].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>50</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>50</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
try {
|
||||
pbData = pb.words[100].sort((a, b) => b.wpm - a.wpm)[0];
|
||||
text += `<tr>
|
||||
<td>100</td>
|
||||
<td>${pbData.wpm}</td>
|
||||
<td>${pbData.raw === undefined ? "-" : pbData.raw}</td>
|
||||
<td>${pbData.acc === undefined ? "-" : pbData.acc + "%"}</td>
|
||||
<td>
|
||||
${pbData.consistency === undefined ? "-" : pbData.consistency + "%"}
|
||||
</td>
|
||||
</tr>`;
|
||||
} catch (e) {
|
||||
text += `<tr>
|
||||
<td>100</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>`;
|
||||
}
|
||||
$(".pageAccount .wordsPbTable tbody").html(text);
|
||||
}
|
454
src/js/account/result-filters.js
Normal file
|
@ -0,0 +1,454 @@
|
|||
import * as Misc from "./misc";
|
||||
import * as DB from "./db";
|
||||
import Config from "./config";
|
||||
import * as Notifications from "./notifications";
|
||||
import * as Account from "./account";
|
||||
import * as Funbox from "./funbox";
|
||||
|
||||
let defaultResultFilters = {
|
||||
difficulty: {
|
||||
normal: true,
|
||||
expert: true,
|
||||
master: true,
|
||||
},
|
||||
mode: {
|
||||
words: true,
|
||||
time: true,
|
||||
quote: true,
|
||||
zen: 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,
|
||||
},
|
||||
quoteLength: {
|
||||
short: true,
|
||||
medium: true,
|
||||
long: true,
|
||||
thicc: true,
|
||||
},
|
||||
punctuation: {
|
||||
on: true,
|
||||
off: true,
|
||||
},
|
||||
numbers: {
|
||||
on: true,
|
||||
off: true,
|
||||
},
|
||||
date: {
|
||||
last_day: false,
|
||||
last_week: false,
|
||||
last_month: false,
|
||||
all: true,
|
||||
},
|
||||
tags: {
|
||||
none: true,
|
||||
},
|
||||
language: {},
|
||||
funbox: {
|
||||
none: true,
|
||||
},
|
||||
};
|
||||
|
||||
export let filters;
|
||||
|
||||
Promise.all([Misc.getLanguageList(), Misc.getFunboxList()]).then((values) => {
|
||||
let languages = values[0];
|
||||
let funboxModes = values[1];
|
||||
languages.forEach((language) => {
|
||||
defaultResultFilters.language[language] = true;
|
||||
});
|
||||
funboxModes.forEach((funbox) => {
|
||||
defaultResultFilters.funbox[funbox.name] = true;
|
||||
});
|
||||
filters = defaultResultFilters;
|
||||
});
|
||||
|
||||
export function getFilters() {
|
||||
return filters;
|
||||
}
|
||||
|
||||
export function getGroup(group) {
|
||||
return filters[group];
|
||||
}
|
||||
|
||||
// export function setFilter(group, filter, value) {
|
||||
// filters[group][filter] = value;
|
||||
// }
|
||||
|
||||
export function getFilter(group, filter) {
|
||||
return filters[group][filter];
|
||||
}
|
||||
|
||||
// export function toggleFilter(group, filter) {
|
||||
// filters[group][filter] = !filters[group][filter];
|
||||
// }
|
||||
|
||||
export function loadTags(tags) {
|
||||
tags.forEach((tag) => {
|
||||
defaultResultFilters[tag.id] = true;
|
||||
});
|
||||
}
|
||||
|
||||
export function save() {
|
||||
Misc.setCookie("resultFilters", JSON.stringify(filters), 365);
|
||||
}
|
||||
|
||||
export function load() {
|
||||
// let newTags = $.cookie("activeTags");
|
||||
try {
|
||||
let newResultFilters = Misc.getCookie("resultFilters");
|
||||
if (newResultFilters !== undefined && newResultFilters !== "") {
|
||||
filters = JSON.parse(newResultFilters);
|
||||
save();
|
||||
} else {
|
||||
filters = defaultResultFilters;
|
||||
save();
|
||||
}
|
||||
} catch {
|
||||
filters = defaultResultFilters;
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
export function reset() {
|
||||
filters = defaultResultFilters;
|
||||
save();
|
||||
}
|
||||
|
||||
load();
|
||||
|
||||
export function updateActive() {
|
||||
let aboveChartDisplay = {};
|
||||
Object.keys(getFilters()).forEach((group) => {
|
||||
aboveChartDisplay[group] = {
|
||||
all: true,
|
||||
array: [],
|
||||
};
|
||||
Object.keys(getGroup(group)).forEach((filter) => {
|
||||
if (getFilter(group, filter)) {
|
||||
aboveChartDisplay[group].array.push(filter);
|
||||
} else {
|
||||
aboveChartDisplay[group].all = false;
|
||||
}
|
||||
let buttonEl;
|
||||
if (group === "date") {
|
||||
buttonEl = $(
|
||||
`.pageAccount .group.topFilters .filterGroup[group="${group}"] .button[filter="${filter}"]`
|
||||
);
|
||||
} else {
|
||||
buttonEl = $(
|
||||
`.pageAccount .group.filterButtons .filterGroup[group="${group}"] .button[filter="${filter}"]`
|
||||
);
|
||||
}
|
||||
if (getFilter(group, filter)) {
|
||||
buttonEl.addClass("active");
|
||||
} else {
|
||||
buttonEl.removeClass("active");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function addText(group) {
|
||||
let ret = "";
|
||||
ret += "<div class='group'>";
|
||||
if (group == "difficulty") {
|
||||
ret += `<span aria-label="Difficulty" data-balloon-pos="up"><i class="fas fa-fw fa-star"></i>`;
|
||||
} else if (group == "mode") {
|
||||
ret += `<span aria-label="Mode" data-balloon-pos="up"><i class="fas fa-fw fa-bars"></i>`;
|
||||
} else if (group == "punctuation") {
|
||||
ret += `<span aria-label="Punctuation" data-balloon-pos="up"><span class="punc" style="font-weight: 900;
|
||||
width: 1.25rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
letter-spacing: -.1rem;">!?</span>`;
|
||||
} else if (group == "numbers") {
|
||||
ret += `<span aria-label="Numbers" data-balloon-pos="up"><span class="numbers" style="font-weight: 900;
|
||||
width: 1.25rem;
|
||||
text-align: center;
|
||||
margin-right: .1rem;
|
||||
display: inline-block;
|
||||
letter-spacing: -.1rem;">15</span>`;
|
||||
} else if (group == "words") {
|
||||
ret += `<span aria-label="Words" data-balloon-pos="up"><i class="fas fa-fw fa-font"></i>`;
|
||||
} else if (group == "time") {
|
||||
ret += `<span aria-label="Time" data-balloon-pos="up"><i class="fas fa-fw fa-clock"></i>`;
|
||||
} else if (group == "date") {
|
||||
ret += `<span aria-label="Date" data-balloon-pos="up"><i class="fas fa-fw fa-calendar"></i>`;
|
||||
} else if (group == "tags") {
|
||||
ret += `<span aria-label="Tags" data-balloon-pos="up"><i class="fas fa-fw fa-tags"></i>`;
|
||||
} else if (group == "language") {
|
||||
ret += `<span aria-label="Language" data-balloon-pos="up"><i class="fas fa-fw fa-globe-americas"></i>`;
|
||||
} else if (group == "funbox") {
|
||||
ret += `<span aria-label="Funbox" data-balloon-pos="up"><i class="fas fa-fw fa-gamepad"></i>`;
|
||||
}
|
||||
if (aboveChartDisplay[group].all) {
|
||||
ret += "all";
|
||||
} else {
|
||||
if (group === "tags") {
|
||||
ret += aboveChartDisplay.tags.array
|
||||
.map((id) => {
|
||||
if (id == "none") return id;
|
||||
let name = DB.getSnapshot().tags.filter((t) => t.id == id)[0];
|
||||
if (name !== undefined) {
|
||||
return DB.getSnapshot().tags.filter((t) => t.id == id)[0].name;
|
||||
}
|
||||
})
|
||||
.join(", ");
|
||||
} else {
|
||||
ret += aboveChartDisplay[group].array.join(", ").replace(/_/g, " ");
|
||||
}
|
||||
}
|
||||
ret += "</span></div>";
|
||||
return ret;
|
||||
}
|
||||
|
||||
let chartString = "";
|
||||
|
||||
//date
|
||||
chartString += addText("date");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//mode
|
||||
chartString += addText("mode");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//time
|
||||
if (aboveChartDisplay.mode.array.includes("time")) {
|
||||
chartString += addText("time");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
}
|
||||
|
||||
//words
|
||||
if (aboveChartDisplay.mode.array.includes("words")) {
|
||||
chartString += addText("words");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
}
|
||||
|
||||
//diff
|
||||
chartString += addText("difficulty");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//punc
|
||||
chartString += addText("punctuation");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//numbers
|
||||
chartString += addText("numbers");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//language
|
||||
chartString += addText("language");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//funbox
|
||||
chartString += addText("funbox");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//tags
|
||||
chartString += addText("tags");
|
||||
|
||||
$(".pageAccount .group.chart .above").html(chartString);
|
||||
|
||||
Account.update();
|
||||
}
|
||||
|
||||
export function toggle(group, filter) {
|
||||
try {
|
||||
if (group === "date") {
|
||||
Object.keys(getGroup("date")).forEach((date) => {
|
||||
filters["date"][date] = false;
|
||||
});
|
||||
}
|
||||
filters[group][filter] = !filters[group][filter];
|
||||
save();
|
||||
} catch (e) {
|
||||
Notifications.add(
|
||||
"Something went wrong toggling filter. Reverting to defaults",
|
||||
0
|
||||
);
|
||||
console.log("toggling filter error");
|
||||
console.error(e);
|
||||
reset();
|
||||
updateActive();
|
||||
}
|
||||
}
|
||||
|
||||
export function updateTags() {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).empty();
|
||||
if (DB.getSnapshot().tags.length > 0) {
|
||||
$(".pageAccount .content .filterButtons .buttonsAndTitle.tags").removeClass(
|
||||
"hidden"
|
||||
);
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).append(`<div class="button" filter="none">no tag</div>`);
|
||||
DB.getSnapshot().tags.forEach((tag) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).append(`<div class="button" filter="${tag.id}">${tag.name}</div>`);
|
||||
});
|
||||
} else {
|
||||
$(".pageAccount .content .filterButtons .buttonsAndTitle.tags").addClass(
|
||||
"hidden"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
".pageAccount .filterButtons .buttonsAndTitle .buttons, .pageAccount .group.topFilters .buttonsAndTitle.testDate .buttons"
|
||||
).click(".button", (e) => {
|
||||
const filter = $(e.target).attr("filter");
|
||||
const group = $(e.target).parents(".buttons").attr("group");
|
||||
if ($(e.target).hasClass("allFilters")) {
|
||||
Object.keys(getFilters()).forEach((group) => {
|
||||
Object.keys(getGroup(group)).forEach((filter) => {
|
||||
if (group === "date") {
|
||||
filters[group][filter] = false;
|
||||
} else {
|
||||
filters[group][filter] = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
filters["date"]["all"] = true;
|
||||
} else if ($(e.target).hasClass("noFilters")) {
|
||||
Object.keys(getFilters()).forEach((group) => {
|
||||
if (group !== "date") {
|
||||
Object.keys(getGroup(group)).forEach((filter) => {
|
||||
filters[group][filter] = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (e.shiftKey) {
|
||||
Object.keys(getGroup(group)).forEach((filter) => {
|
||||
filters[group][filter] = false;
|
||||
});
|
||||
filters[group][filter] = true;
|
||||
} else {
|
||||
toggle(group, filter);
|
||||
// filters[group][filter] = !filters[group][filter];
|
||||
}
|
||||
}
|
||||
updateActive();
|
||||
save();
|
||||
});
|
||||
|
||||
$(".pageAccount .topFilters .button.allFilters").click((e) => {
|
||||
Object.keys(getFilters()).forEach((group) => {
|
||||
Object.keys(getGroup(group)).forEach((filter) => {
|
||||
if (group === "date") {
|
||||
filters[group][filter] = false;
|
||||
} else {
|
||||
filters[group][filter] = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
filters["date"]["all"] = true;
|
||||
updateActive();
|
||||
save();
|
||||
});
|
||||
|
||||
$(".pageAccount .topFilters .button.currentConfigFilter").click((e) => {
|
||||
Object.keys(getFilters()).forEach((group) => {
|
||||
Object.keys(getGroup(group)).forEach((filter) => {
|
||||
filters[group][filter] = false;
|
||||
});
|
||||
});
|
||||
|
||||
filters["difficulty"][Config.difficulty] = true;
|
||||
filters["mode"][Config.mode] = true;
|
||||
if (Config.mode === "time") {
|
||||
filters["time"][Config.time] = true;
|
||||
} else if (Config.mode === "words") {
|
||||
filters["words"][Config.words] = true;
|
||||
} else if (Config.mode === "quote") {
|
||||
Object.keys(getGroup("quoteLength")).forEach((ql) => {
|
||||
filters["quoteLength"][ql] = true;
|
||||
});
|
||||
}
|
||||
if (Config.punctuation) {
|
||||
filters["punctuation"]["on"] = true;
|
||||
} else {
|
||||
filters["punctuation"]["off"] = true;
|
||||
}
|
||||
if (Config.numbers) {
|
||||
filters["numbers"]["on"] = true;
|
||||
} else {
|
||||
filters["numbers"]["off"] = true;
|
||||
}
|
||||
if (Config.mode === "quote" && /english.*/.test(Config.language)) {
|
||||
filters["language"]["english"] = true;
|
||||
} else {
|
||||
filters["language"][Config.language] = true;
|
||||
}
|
||||
|
||||
if (Funbox.active === "none") {
|
||||
filters.funbox.none = true;
|
||||
} else {
|
||||
filters.funbox[Funbox.active] = true;
|
||||
}
|
||||
|
||||
filters["tags"]["none"] = true;
|
||||
DB.getSnapshot().tags.forEach((tag) => {
|
||||
if (tag.active === true) {
|
||||
filters["tags"]["none"] = false;
|
||||
filters["tags"][tag.id] = true;
|
||||
}
|
||||
});
|
||||
|
||||
filters["date"]["all"] = true;
|
||||
updateActive();
|
||||
save();
|
||||
console.log(getFilters());
|
||||
});
|
||||
|
||||
$(".pageAccount .topFilters .button.toggleAdvancedFilters").click((e) => {
|
||||
$(".pageAccount .filterButtons").slideToggle(250);
|
||||
$(".pageAccount .topFilters .button.toggleAdvancedFilters").toggleClass(
|
||||
"active"
|
||||
);
|
||||
});
|
||||
|
||||
Misc.getLanguageList().then((languages) => {
|
||||
languages.forEach((language) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.languages .buttons"
|
||||
).append(
|
||||
`<div class="button" filter="${language}">${language.replace(
|
||||
"_",
|
||||
" "
|
||||
)}</div>`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons"
|
||||
).append(`<div class="button" filter="none">none</div>`);
|
||||
Misc.getFunboxList().then((funboxModes) => {
|
||||
funboxModes.forEach((funbox) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.funbox .buttons"
|
||||
).append(
|
||||
`<div class="button" filter="${funbox.name}">${funbox.name.replace(
|
||||
/_/g,
|
||||
" "
|
||||
)}</div>`
|
||||
);
|
||||
});
|
||||
});
|
23
src/js/account/verification-controller.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import * as CloudFunctions from "./cloud-functions";
|
||||
import * as Notifications from "./notifications";
|
||||
import * as Settings from "./settings";
|
||||
import * as DB from "./db";
|
||||
|
||||
export let data = null;
|
||||
export function set(val) {
|
||||
data = val;
|
||||
}
|
||||
|
||||
export function verify(user) {
|
||||
Notifications.add("Verifying", 0, 3);
|
||||
data.uid = user.uid;
|
||||
CloudFunctions.verifyUser(data).then((data) => {
|
||||
if (data.data.status === 1) {
|
||||
Notifications.add(data.data.message, 1);
|
||||
DB.getSnapshot().discordId = data.data.did;
|
||||
Settings.updateDiscordSection();
|
||||
} else {
|
||||
Notifications.add(data.data.message, -1);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -61,7 +61,7 @@ if (Object.keys(layouts).length > 0) {
|
|||
});
|
||||
}
|
||||
|
||||
let commandsKeymapLayouts = {
|
||||
export let commandsKeymapLayouts = {
|
||||
title: "Change keymap layout...",
|
||||
list: [
|
||||
{
|
||||
|
@ -126,7 +126,7 @@ let commandsFunbox = {
|
|||
id: "changeFunboxNone",
|
||||
display: "none",
|
||||
exec: () => {
|
||||
if (Funbox.activate("none", null)) {
|
||||
if (Funbox.setFunbox("none", null)) {
|
||||
TestLogic.restart();
|
||||
}
|
||||
},
|
||||
|
@ -140,7 +140,7 @@ Misc.getFunboxList().then((funboxes) => {
|
|||
id: "changeFunbox" + funbox.name,
|
||||
display: funbox.name.replace(/_/g, " "),
|
||||
exec: () => {
|
||||
if (Funbox.activate(funbox.name, funbox.type)) {
|
||||
if (Funbox.setFunbox(funbox.name, funbox.type)) {
|
||||
TestLogic.restart();
|
||||
}
|
||||
},
|
||||
|
@ -413,7 +413,7 @@ let commandsDifficulty = {
|
|||
],
|
||||
};
|
||||
|
||||
let commandsEnableAds = {
|
||||
export let commandsEnableAds = {
|
||||
title: "Set enable ads...",
|
||||
list: [
|
||||
{
|
||||
|
@ -1117,7 +1117,7 @@ let commandsPageWidth = {
|
|||
],
|
||||
};
|
||||
|
||||
let themeCommands = {
|
||||
export let themeCommands = {
|
||||
title: "Change theme...",
|
||||
list: [],
|
||||
};
|
||||
|
@ -1596,6 +1596,15 @@ export let defaultCommands = {
|
|||
Commandline.show();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "changeCustomBackground",
|
||||
display: "Change custom background...",
|
||||
defaultValue: "",
|
||||
input: true,
|
||||
exec: (input) => {
|
||||
UpdateConfig.setCustomBackground(input);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "changeTheme",
|
||||
display: "Change theme...",
|
||||
|
|
|
@ -7,15 +7,18 @@ import * as TestUI from "./test-ui";
|
|||
|
||||
let commandLineMouseMode = false;
|
||||
|
||||
function showInput(command, placeholder) {
|
||||
function showInput(command, placeholder, defaultValue = "") {
|
||||
$("#commandLineWrapper").removeClass("hidden");
|
||||
$("#commandLine").addClass("hidden");
|
||||
$("#commandInput").removeClass("hidden");
|
||||
$("#commandInput input").attr("placeholder", placeholder);
|
||||
$("#commandInput input").val("");
|
||||
$("#commandInput input").val(defaultValue);
|
||||
$("#commandInput input").focus();
|
||||
$("#commandInput input").attr("command", "");
|
||||
$("#commandInput input").attr("command", command);
|
||||
if (defaultValue != ""){
|
||||
$("#commandInput input").select();
|
||||
}
|
||||
}
|
||||
|
||||
function showFound() {
|
||||
|
@ -142,7 +145,7 @@ function trigger(command) {
|
|||
if (obj.id == command) {
|
||||
if (obj.input) {
|
||||
input = true;
|
||||
showInput(obj.id, obj.display);
|
||||
showInput(obj.id, obj.display, obj.defaultValue);
|
||||
} else {
|
||||
obj.exec();
|
||||
if (obj.subgroup !== null && obj.subgroup !== undefined) {
|
||||
|
@ -498,6 +501,6 @@ $(document).keydown((e) => {
|
|||
});
|
||||
|
||||
$(document).on("click", "#commandLineMobileButton", () => {
|
||||
CommandlineLists.setCurrent(CommandlineLists.defaultCommands);
|
||||
CommandlineLists.setCurrent([CommandlineLists.defaultCommands]);
|
||||
show();
|
||||
});
|
||||
|
|
|
@ -15,6 +15,8 @@ import * as LanguagePicker from "./language-picker";
|
|||
import * as TestLogic from "./test-logic";
|
||||
import * as PaceCaret from "./pace-caret";
|
||||
import * as UI from "./ui";
|
||||
import * as CommandlineLists from "./commandline-lists";
|
||||
import * as BackgroundFilter from "./custom-background-filter";
|
||||
|
||||
export let cookieConfig = null;
|
||||
export let dbConfigLoaded = false;
|
||||
|
@ -75,11 +77,11 @@ let defaultConfig = {
|
|||
savedLayout: "default",
|
||||
confidenceMode: "off",
|
||||
indicateTypos: false,
|
||||
timerStyle: "text",
|
||||
timerStyle: "mini",
|
||||
colorfulMode: false,
|
||||
randomTheme: "off",
|
||||
timerColor: "black",
|
||||
timerOpacity: "0.25",
|
||||
timerColor: "main",
|
||||
timerOpacity: "1",
|
||||
stopOnError: "off",
|
||||
showAllLines: false,
|
||||
keymapMode: "off",
|
||||
|
@ -113,6 +115,9 @@ let defaultConfig = {
|
|||
monkey: false,
|
||||
repeatQuotes: "off",
|
||||
oppositeShiftMode: "off",
|
||||
customBackground: "",
|
||||
customBackgroundSize: "cover",
|
||||
customBackgroundFilter: [0, 1, 1, 1, 1],
|
||||
};
|
||||
|
||||
function isConfigKeyValid(name) {
|
||||
|
@ -472,6 +477,10 @@ export function setPaceCaret(val, nosave) {
|
|||
if (val == undefined) {
|
||||
val = "off";
|
||||
}
|
||||
// if (val == "pb" && firebase.auth().currentUser === null) {
|
||||
// Notifications.add("PB pace caret is unavailable without an account", 0);
|
||||
// return;
|
||||
// }
|
||||
// if (config.mode === "zen" && val != "off") {
|
||||
// Notifications.add(`Can't use pace caret with zen mode.`, 0);
|
||||
// val = "off";
|
||||
|
@ -833,7 +842,7 @@ export function toggleHideExtraLetters() {
|
|||
|
||||
export function setTimerStyle(style, nosave) {
|
||||
if (style == null || style == undefined) {
|
||||
style = "bar";
|
||||
style = "mini";
|
||||
}
|
||||
config.timerStyle = style;
|
||||
if (!nosave) saveToCookie();
|
||||
|
@ -1148,12 +1157,17 @@ export function setIndicateTypos(it, nosave) {
|
|||
|
||||
export function setCustomTheme(boolean, nosave) {
|
||||
if (boolean !== undefined) config.customTheme = boolean;
|
||||
if (boolean) {
|
||||
ThemeController.set("custom");
|
||||
} else if (!boolean && !nosave) {
|
||||
ThemeController.set(config.theme);
|
||||
}
|
||||
if (!nosave) saveToCookie();
|
||||
}
|
||||
|
||||
export function setTheme(name, nosave) {
|
||||
config.theme = name;
|
||||
setCustomTheme(false, true);
|
||||
setCustomTheme(false, true, true);
|
||||
ThemeController.set(config.theme);
|
||||
if (!nosave) saveToCookie();
|
||||
}
|
||||
|
@ -1338,6 +1352,44 @@ export function setFontSize(fontSize, nosave) {
|
|||
if (!nosave) saveToCookie();
|
||||
}
|
||||
|
||||
export function setCustomBackground(value, nosave) {
|
||||
if (value == null || value == undefined) {
|
||||
value = "";
|
||||
}
|
||||
value = value.trim();
|
||||
if (
|
||||
/(https|http):\/\/(www\.|).+\..+\/.+(\.png|\.gif|\.jpeg|\.jpg)/gi.test(
|
||||
value
|
||||
) ||
|
||||
value == ""
|
||||
) {
|
||||
config.customBackground = value;
|
||||
CommandlineLists.defaultCommands.list.filter(
|
||||
(command) => command.id == "changeCustomBackground"
|
||||
)[0].defaultValue = value;
|
||||
ThemeController.applyCustomBackground();
|
||||
if (!nosave) saveToCookie();
|
||||
} else {
|
||||
Notifications.add("Invalid custom background URL", 0);
|
||||
}
|
||||
}
|
||||
|
||||
export function setCustomBackgroundSize(value, nosave) {
|
||||
if (value != "cover" && value != "contain" && value != "max") {
|
||||
value = "cover";
|
||||
}
|
||||
config.customBackgroundSize = value;
|
||||
ThemeController.applyCustomBackgroundSize();
|
||||
if (!nosave) saveToCookie();
|
||||
}
|
||||
|
||||
export function setCustomBackgroundFilter(array, nosave) {
|
||||
config.customBackgroundFilter = array;
|
||||
BackgroundFilter.loadConfig(config.customBackgroundFilter);
|
||||
BackgroundFilter.apply();
|
||||
if (!nosave) saveToCookie();
|
||||
}
|
||||
|
||||
export function apply(configObj) {
|
||||
if (configObj == null || configObj == undefined) {
|
||||
Notifications.add("Could not apply config", -1, 3);
|
||||
|
@ -1350,8 +1402,11 @@ export function apply(configObj) {
|
|||
});
|
||||
if (configObj && configObj != null && configObj != "null") {
|
||||
setTheme(configObj.theme, true);
|
||||
setCustomTheme(configObj.customTheme, true);
|
||||
setCustomThemeColors(configObj.customThemeColors, true);
|
||||
setCustomTheme(configObj.customTheme, true, true);
|
||||
setCustomBackground(configObj.customBackground, true);
|
||||
setCustomBackgroundSize(configObj.customBackgroundSize, true);
|
||||
setCustomBackgroundFilter(configObj.customBackgroundFilter, true);
|
||||
setQuickTabMode(configObj.quickTab, true);
|
||||
setKeyTips(configObj.showKeyTips, true);
|
||||
setTimeConfig(configObj.time, true);
|
||||
|
@ -1626,6 +1681,10 @@ export function loadFromCookie() {
|
|||
loadDone();
|
||||
}
|
||||
|
||||
export function setConfig(newConfig) {
|
||||
config = newConfig;
|
||||
}
|
||||
|
||||
export let loadPromise = new Promise((v) => {
|
||||
loadDone = v;
|
||||
});
|
||||
|
|
10
src/js/db.js
|
@ -1,5 +1,5 @@
|
|||
import { loadTags } from "./result-filters";
|
||||
import * as AccountButton from "./account-icon";
|
||||
import * as AccountButton from "./account-button";
|
||||
import * as CloudFunctions from "./cloud-functions";
|
||||
import * as Notifications from "./notifications";
|
||||
|
||||
|
@ -17,8 +17,12 @@ export function getSnapshot() {
|
|||
}
|
||||
|
||||
export function setSnapshot(newSnapshot) {
|
||||
delete newSnapshot.banned;
|
||||
delete newSnapshot.verified;
|
||||
try {
|
||||
delete newSnapshot.banned;
|
||||
} catch {}
|
||||
try {
|
||||
delete newSnapshot.verified;
|
||||
} catch {}
|
||||
dbSnapshot = newSnapshot;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,3 +10,5 @@ global.snapshot = DB.getSnapshot;
|
|||
global.config = Config;
|
||||
// global.addnotif = Notifications.add;
|
||||
global.link = AccountController.linkWithGoogle;
|
||||
|
||||
global.filters = ResultFilters.filters;
|
||||
|
|
|
@ -9,45 +9,14 @@ Chart.plugins.register(chartAnnotation);
|
|||
|
||||
import * as DB from "./db";
|
||||
import * as Misc from "./misc";
|
||||
import * as CloudFunctions from "./cloud-functions";
|
||||
import * as Monkey from "./monkey";
|
||||
import * as Notifications from "./notifications";
|
||||
import * as ResultFilters from "./result-filters";
|
||||
import * as Leaderboards from "./leaderboards";
|
||||
import * as Sound from "./sound";
|
||||
import * as CustomText from "./custom-text";
|
||||
import * as ShiftTracker from "./shift-tracker";
|
||||
import * as TestStats from "./test-stats";
|
||||
import * as ThemeColors from "./theme-colors";
|
||||
import * as ChartController from "./chart-controller";
|
||||
import * as Caret from "./caret";
|
||||
import * as ManualRestart from "./manual-restart-tracker";
|
||||
import Config, * as UpdateConfig from "./config";
|
||||
import * as Focus from "./focus";
|
||||
import * as AccountButton from "./account-icon";
|
||||
import * as TestUI from "./test-ui";
|
||||
import * as Keymap from "./keymap";
|
||||
import Config from "./config";
|
||||
import * as SimplePopups from "./simple-popups";
|
||||
import * as AccountController from "./account-controller";
|
||||
import "./caps-warning";
|
||||
import * as LiveAcc from "./live-acc";
|
||||
import * as TimerProgress from "./timer-progress";
|
||||
import * as TestLogic from "./test-logic";
|
||||
import * as Funbox from "./funbox";
|
||||
import * as PaceCaret from "./pace-caret";
|
||||
import * as TagController from "./tag-controller";
|
||||
import * as TestTimer from "./test-timer";
|
||||
import * as UI from "./ui";
|
||||
import * as CommandlineLists from "./commandline-lists";
|
||||
import * as ChallengeController from "./challenge-controller";
|
||||
import * as TestConfig from "./test-config";
|
||||
import * as MiniResultChart from "./mini-result-chart";
|
||||
import * as SignOutButton from "./sign-out-button";
|
||||
import "./support-popup";
|
||||
import "./version-popup";
|
||||
import * as LayoutEmulator from "./layout-emulator";
|
||||
import * as AccountController from "./account-controller";
|
||||
import * as ResultTagsPopup from "./result-tags-popup";
|
||||
import * as Settings from "./settings";
|
||||
import * as SimplePopups from "./simple-popups";
|
||||
import * as ThemePicker from "./theme-picker";
|
||||
import "./custom-theme-popup";
|
||||
import "./import-settings-popup";
|
||||
import "./input-controller";
|
||||
import "./ready";
|
||||
|
|
|
@ -1,129 +1,25 @@
|
|||
//test timer
|
||||
|
||||
//ui
|
||||
let verifyUserWhenLoggedIn = null;
|
||||
|
||||
///
|
||||
|
||||
// let CustomText = "The quick brown fox jumps over the lazy dog".split(" ");
|
||||
// let CustomText.isWordRandom = false;
|
||||
// let CustomText.word = 1;
|
||||
|
||||
(function (history) {
|
||||
var pushState = history.pushState;
|
||||
history.pushState = function (state) {
|
||||
if (Funbox.active === "memory" && state !== "/") {
|
||||
Funbox.resetMemoryTimer();
|
||||
}
|
||||
return pushState.apply(history, arguments);
|
||||
};
|
||||
})(window.history);
|
||||
|
||||
function changePage(page) {
|
||||
if (UI.pageTransition) {
|
||||
return;
|
||||
}
|
||||
let activePage = $(".page.active");
|
||||
$(".page").removeClass("active");
|
||||
$("#wordsInput").focusout();
|
||||
if (page == "test" || page == "") {
|
||||
UI.setPageTransition(true);
|
||||
UI.swapElements(
|
||||
activePage,
|
||||
$(".page.pageTest"),
|
||||
250,
|
||||
() => {
|
||||
UI.setPageTransition(false);
|
||||
TestUI.focusWords();
|
||||
$(".page.pageTest").addClass("active");
|
||||
history.pushState("/", null, "/");
|
||||
},
|
||||
() => {
|
||||
TestConfig.show();
|
||||
}
|
||||
);
|
||||
SignOutButton.hide();
|
||||
// restartCount = 0;
|
||||
// incompleteTestSeconds = 0;
|
||||
TestStats.resetIncomplete();
|
||||
ManualRestart.set();
|
||||
TestLogic.restart();
|
||||
} else if (page == "about") {
|
||||
UI.setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
UI.swapElements(activePage, $(".page.pageAbout"), 250, () => {
|
||||
UI.setPageTransition(false);
|
||||
history.pushState("about", null, "about");
|
||||
$(".page.pageAbout").addClass("active");
|
||||
});
|
||||
TestConfig.hide();
|
||||
SignOutButton.hide();
|
||||
} else if (page == "settings") {
|
||||
UI.setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
UI.swapElements(activePage, $(".page.pageSettings"), 250, () => {
|
||||
UI.setPageTransition(false);
|
||||
history.pushState("settings", null, "settings");
|
||||
$(".page.pageSettings").addClass("active");
|
||||
});
|
||||
Settings.update();
|
||||
TestConfig.hide();
|
||||
SignOutButton.hide();
|
||||
} else if (page == "account") {
|
||||
if (!firebase.auth().currentUser) {
|
||||
changePage("login");
|
||||
} else {
|
||||
UI.setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
UI.swapElements(
|
||||
activePage,
|
||||
$(".page.pageAccount"),
|
||||
250,
|
||||
() => {
|
||||
UI.setPageTransition(false);
|
||||
history.pushState("account", null, "account");
|
||||
$(".page.pageAccount").addClass("active");
|
||||
},
|
||||
() => {
|
||||
SignOutButton.show();
|
||||
}
|
||||
);
|
||||
refreshAccountPage();
|
||||
TestConfig.hide();
|
||||
}
|
||||
} else if (page == "login") {
|
||||
if (firebase.auth().currentUser != null) {
|
||||
changePage("account");
|
||||
} else {
|
||||
UI.setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
UI.swapElements(activePage, $(".page.pageLogin"), 250, () => {
|
||||
UI.setPageTransition(false);
|
||||
history.pushState("login", null, "login");
|
||||
$(".page.pageLogin").addClass("active");
|
||||
});
|
||||
TestConfig.hide();
|
||||
SignOutButton.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(window).on("popstate", (e) => {
|
||||
let state = e.originalEvent.state;
|
||||
if (state == "" || state == "/") {
|
||||
// show test
|
||||
changePage("test");
|
||||
} else if (state == "about") {
|
||||
// show about
|
||||
changePage("about");
|
||||
} else if (state == "account" || state == "login") {
|
||||
if (firebase.auth().currentUser) {
|
||||
changePage("account");
|
||||
} else {
|
||||
changePage("login");
|
||||
}
|
||||
}
|
||||
});
|
||||
import * as TestLogic from "./test-logic";
|
||||
import * as TestUI from "./test-ui";
|
||||
import * as TestStats from "./test-stats";
|
||||
import * as Monkey from "./monkey";
|
||||
import Config, * as UpdateConfig from "./config";
|
||||
import * as Keymap from "./keymap";
|
||||
import * as Misc from "./misc";
|
||||
import * as LiveAcc from "./live-acc";
|
||||
import * as Funbox from "./funbox";
|
||||
import * as Sound from "./sound";
|
||||
import * as Caret from "./caret";
|
||||
import * as ManualRestart from "./manual-restart-tracker";
|
||||
import * as Notifications from "./notifications";
|
||||
import * as CustomText from "./custom-text";
|
||||
import * as UI from "./ui";
|
||||
import * as Settings from "./settings";
|
||||
import * as LayoutEmulator from "./layout-emulator";
|
||||
import * as PaceCaret from "./pace-caret";
|
||||
import * as TimerProgress from "./timer-progress";
|
||||
import * as TestTimer from "./test-timer";
|
||||
import * as Focus from "./focus";
|
||||
import * as ShiftTracker from "./shift-tracker";
|
||||
|
||||
$("#wordsInput").keypress((event) => {
|
||||
event.preventDefault();
|
||||
|
@ -131,106 +27,6 @@ $("#wordsInput").keypress((event) => {
|
|||
|
||||
let dontInsertSpace = false;
|
||||
|
||||
$(document).keyup((event) => {
|
||||
if (!event.originalEvent.isTrusted) return;
|
||||
|
||||
if (TestUI.resultVisible) return;
|
||||
let now = performance.now();
|
||||
let diff = Math.abs(TestStats.keypressTimings.duration.current - now);
|
||||
if (TestStats.keypressTimings.duration.current !== -1) {
|
||||
TestStats.pushKeypressDuration(diff);
|
||||
// keypressStats.duration.array.push(diff);
|
||||
}
|
||||
TestStats.setKeypressDuration(now);
|
||||
// keypressStats.duration.current = now;
|
||||
Monkey.stop();
|
||||
});
|
||||
|
||||
$(document).keydown(function (event) {
|
||||
if (!(event.key == " ") && !event.originalEvent.isTrusted) return;
|
||||
|
||||
if (!TestUI.resultVisible) {
|
||||
TestStats.recordKeypressSpacing();
|
||||
}
|
||||
|
||||
Monkey.type();
|
||||
|
||||
//autofocus
|
||||
let pageTestActive = !$(".pageTest").hasClass("hidden");
|
||||
let commandLineVisible = !$("#commandLineWrapper").hasClass("hidden");
|
||||
let wordsFocused = $("#wordsInput").is(":focus");
|
||||
let modePopupVisible =
|
||||
!$("#customTextPopupWrapper").hasClass("hidden") ||
|
||||
!$("#customWordAmountPopupWrapper").hasClass("hidden") ||
|
||||
!$("#customTestDurationPopupWrapper").hasClass("hidden") ||
|
||||
!$("#quoteSearchPopupWrapper").hasClass("hidden") ||
|
||||
!$("#wordFilterPopupWrapper").hasClass("hidden");
|
||||
if (
|
||||
pageTestActive &&
|
||||
!commandLineVisible &&
|
||||
!modePopupVisible &&
|
||||
!TestUI.resultVisible &&
|
||||
!wordsFocused &&
|
||||
event.key !== "Enter"
|
||||
) {
|
||||
TestUI.focusWords();
|
||||
wordsFocused = true;
|
||||
// if (Config.showOutOfFocusWarning) return;
|
||||
}
|
||||
|
||||
//tab
|
||||
if (
|
||||
(event.key == "Tab" && !Config.swapEscAndTab) ||
|
||||
(event.key == "Escape" && Config.swapEscAndTab)
|
||||
) {
|
||||
handleTab(event);
|
||||
// event.preventDefault();
|
||||
}
|
||||
|
||||
//blocking firefox from going back in history with backspace
|
||||
if (event.key === "Backspace" && wordsFocused) {
|
||||
let t = /INPUT|SELECT|TEXTAREA/i;
|
||||
if (
|
||||
!t.test(event.target.tagName) ||
|
||||
event.target.disabled ||
|
||||
event.target.readOnly
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// keypressStats.duration.current = performance.now();
|
||||
TestStats.setKeypressDuration(performance.now());
|
||||
|
||||
if (TestUI.testRestarting) {
|
||||
return;
|
||||
}
|
||||
|
||||
//backspace
|
||||
const isBackspace =
|
||||
event.key === "Backspace" ||
|
||||
(Config.capsLockBackspace && event.key === "CapsLock");
|
||||
if (isBackspace && wordsFocused) {
|
||||
handleBackspace(event);
|
||||
}
|
||||
|
||||
if (event.key === "Enter" && Funbox.active === "58008" && wordsFocused) {
|
||||
event.key = " ";
|
||||
}
|
||||
|
||||
//space or enter
|
||||
if (event.key === " " && wordsFocused) {
|
||||
handleSpace(event, false);
|
||||
}
|
||||
|
||||
if (wordsFocused && !commandLineVisible) {
|
||||
handleAlpha(event);
|
||||
}
|
||||
|
||||
let acc = Misc.roundTo2(TestStats.calculateAccuracy());
|
||||
LiveAcc.update(acc);
|
||||
});
|
||||
|
||||
function handleTab(event) {
|
||||
if (TestUI.resultCalculating) {
|
||||
event.preventDefault();
|
||||
|
@ -256,96 +52,42 @@ function handleTab(event) {
|
|||
// );
|
||||
return;
|
||||
} else if (
|
||||
$(".pageTest").hasClass("active") &&
|
||||
!TestUI.resultCalculating &&
|
||||
$("#commandLineWrapper").hasClass("hidden") &&
|
||||
$("#simplePopupWrapper").hasClass("hidden")
|
||||
) {
|
||||
if (Config.quickTab) {
|
||||
if (Config.mode == "zen" && !event.shiftKey) {
|
||||
//ignore
|
||||
} else {
|
||||
if (event.shiftKey) ManualRestart.set();
|
||||
|
||||
if (
|
||||
TestLogic.active &&
|
||||
Config.repeatQuotes === "typing" &&
|
||||
Config.mode === "quote"
|
||||
) {
|
||||
TestLogic.restart(true, false, event);
|
||||
if ($(".pageTest").hasClass("active")) {
|
||||
if (Config.quickTab) {
|
||||
if (Config.mode == "zen" && !event.shiftKey) {
|
||||
//ignore
|
||||
} else {
|
||||
TestLogic.restart(false, false, event);
|
||||
if (event.shiftKey) ManualRestart.set();
|
||||
event.preventDefault();
|
||||
if (
|
||||
TestLogic.active &&
|
||||
Config.repeatQuotes === "typing" &&
|
||||
Config.mode === "quote"
|
||||
) {
|
||||
TestLogic.restart(true, false, event);
|
||||
} else {
|
||||
TestLogic.restart(false, false, event);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
!TestUI.resultVisible &&
|
||||
((TestLogic.hasTab && event.shiftKey) ||
|
||||
(!TestLogic.hasTab && Config.mode !== "zen") ||
|
||||
(Config.mode === "zen" && event.shiftKey))
|
||||
) {
|
||||
event.preventDefault();
|
||||
$("#restartTestButton").focus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
!TestUI.resultVisible &&
|
||||
((TestLogic.hasTab && event.shiftKey) ||
|
||||
(!TestLogic.hasTab && Config.mode !== "zen") ||
|
||||
(Config.mode === "zen" && event.shiftKey))
|
||||
) {
|
||||
event.preventDefault();
|
||||
$("#restartTestButton").focus();
|
||||
}
|
||||
} else if (Config.quickTab) {
|
||||
UI.changePage("test");
|
||||
}
|
||||
} else if (Config.quickTab) {
|
||||
changePage("test");
|
||||
}
|
||||
|
||||
// } else if (
|
||||
// !event.ctrlKey &&
|
||||
// (
|
||||
// (!event.shiftKey && !TestLogic.hasTab) ||
|
||||
// (event.shiftKey && TestLogic.hasTab) ||
|
||||
// TestUI.resultVisible
|
||||
// ) &&
|
||||
// Config.quickTab &&
|
||||
// !$(".pageLogin").hasClass("active") &&
|
||||
// !resultCalculating &&
|
||||
// $("#commandLineWrapper").hasClass("hidden") &&
|
||||
// $("#simplePopupWrapper").hasClass("hidden")
|
||||
// ) {
|
||||
// event.preventDefault();
|
||||
// if ($(".pageTest").hasClass("active")) {
|
||||
// if (
|
||||
// (Config.mode === "words" && Config.words < 1000) ||
|
||||
// (Config.mode === "time" && Config.time < 3600) ||
|
||||
// Config.mode === "quote" ||
|
||||
// (Config.mode === "custom" &&
|
||||
// CustomText.isWordRandom &&
|
||||
// CustomText.word < 1000) ||
|
||||
// (Config.mode === "custom" &&
|
||||
// CustomText.isTimeRandom &&
|
||||
// CustomText.time < 3600) ||
|
||||
// (Config.mode === "custom" &&
|
||||
// !CustomText.isWordRandom &&
|
||||
// CustomText.text.length < 1000)
|
||||
// ) {
|
||||
// if (TestLogic.active) {
|
||||
// let testNow = performance.now();
|
||||
// let testSeconds = Misc.roundTo2((testNow - testStart) / 1000);
|
||||
// let afkseconds = keypressPerSecond.filter(
|
||||
// (x) => x.count == 0 && x.mod == 0
|
||||
// ).length;
|
||||
// incompleteTestSeconds += testSeconds - afkseconds;
|
||||
// restartCount++;
|
||||
// }
|
||||
// TestLogic.restart();
|
||||
// } else {
|
||||
// Notifications.add("Quick restart disabled for long tests", 0);
|
||||
// }
|
||||
// } else {
|
||||
// changePage("test");
|
||||
// }
|
||||
// } else if (
|
||||
// !Config.quickTab &&
|
||||
// TestLogic.hasTab &&
|
||||
// event.shiftKey &&
|
||||
// !TestUI.resultVisible
|
||||
// ) {
|
||||
// event.preventDefault();
|
||||
// $("#restartTestButton").focus();
|
||||
// }
|
||||
}
|
||||
|
||||
function handleBackspace(event) {
|
||||
|
@ -966,81 +708,102 @@ function handleAlpha(event) {
|
|||
Caret.updatePosition();
|
||||
}
|
||||
|
||||
ManualRestart.set();
|
||||
UpdateConfig.loadFromCookie();
|
||||
Misc.getReleasesFromGitHub();
|
||||
// getPatreonNames();
|
||||
$(document).keyup((event) => {
|
||||
if (!event.originalEvent.isTrusted) return;
|
||||
|
||||
let mappedRoutes = {
|
||||
"/": "pageTest",
|
||||
"/login": "pageLogin",
|
||||
"/settings": "pageSettings",
|
||||
"/about": "pageAbout",
|
||||
"/account": "pageAccount",
|
||||
"/verify": "pageTest",
|
||||
};
|
||||
|
||||
function handleInitialPageClasses(el) {
|
||||
$(el).removeClass("hidden");
|
||||
$(el).addClass("active");
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
handleInitialPageClasses(
|
||||
$(".page." + mappedRoutes[window.location.pathname])
|
||||
);
|
||||
if (window.location.pathname === "/") {
|
||||
$("#top .config").removeClass("hidden");
|
||||
if (TestUI.resultVisible) return;
|
||||
let now = performance.now();
|
||||
let diff = Math.abs(TestStats.keypressTimings.duration.current - now);
|
||||
if (TestStats.keypressTimings.duration.current !== -1) {
|
||||
TestStats.pushKeypressDuration(diff);
|
||||
// keypressStats.duration.array.push(diff);
|
||||
}
|
||||
$("body").css("transition", ".25s");
|
||||
if (Config.quickTab) {
|
||||
$("#restartTestButton").addClass("hidden");
|
||||
}
|
||||
if (!Misc.getCookie("merchbannerclosed")) {
|
||||
$(".merchBanner").removeClass("hidden");
|
||||
} else {
|
||||
$(".merchBanner").remove();
|
||||
}
|
||||
$("#centerContent")
|
||||
.css("opacity", "0")
|
||||
.removeClass("hidden")
|
||||
.stop(true, true)
|
||||
.animate({ opacity: 1 }, 250, () => {
|
||||
if (window.location.pathname === "/verify") {
|
||||
const fragment = new URLSearchParams(window.location.hash.slice(1));
|
||||
if (fragment.has("access_token")) {
|
||||
const accessToken = fragment.get("access_token");
|
||||
const tokenType = fragment.get("token_type");
|
||||
verifyUserWhenLoggedIn = {
|
||||
accessToken: accessToken,
|
||||
tokenType: tokenType,
|
||||
};
|
||||
history.replaceState("/", null, "/");
|
||||
}
|
||||
} else if (window.location.pathname === "/account") {
|
||||
// history.replaceState("/", null, "/");
|
||||
} else if (/challenge_.+/g.test(window.location.pathname)) {
|
||||
//do nothing
|
||||
// }
|
||||
} else if (window.location.pathname !== "/") {
|
||||
let page = window.location.pathname.replace("/", "");
|
||||
changePage(page);
|
||||
}
|
||||
});
|
||||
Settings.settingsFillPromise.then(Settings.update);
|
||||
TestStats.setKeypressDuration(now);
|
||||
// keypressStats.duration.current = now;
|
||||
Monkey.stop();
|
||||
});
|
||||
|
||||
//TODO move after account is a module
|
||||
$(document).on("click", "#top .logo", (e) => {
|
||||
changePage("test");
|
||||
});
|
||||
$(document).keydown(function (event) {
|
||||
if (!(event.key == " ") && !event.originalEvent.isTrusted) return;
|
||||
|
||||
$(document).on("click", "#top #menu .icon-button", (e) => {
|
||||
if ($(e.currentTarget).hasClass("leaderboards")) {
|
||||
Leaderboards.show();
|
||||
} else {
|
||||
const href = $(e.currentTarget).attr("href");
|
||||
ManualRestart.set();
|
||||
changePage(href.replace("/", ""));
|
||||
if (!TestUI.resultVisible) {
|
||||
TestStats.recordKeypressSpacing();
|
||||
}
|
||||
|
||||
Monkey.type();
|
||||
|
||||
//autofocus
|
||||
let pageTestActive = !$(".pageTest").hasClass("hidden");
|
||||
let commandLineVisible = !$("#commandLineWrapper").hasClass("hidden");
|
||||
let wordsFocused = $("#wordsInput").is(":focus");
|
||||
let modePopupVisible =
|
||||
!$("#customTextPopupWrapper").hasClass("hidden") ||
|
||||
!$("#customWordAmountPopupWrapper").hasClass("hidden") ||
|
||||
!$("#customTestDurationPopupWrapper").hasClass("hidden") ||
|
||||
!$("#quoteSearchPopupWrapper").hasClass("hidden") ||
|
||||
!$("#wordFilterPopupWrapper").hasClass("hidden");
|
||||
if (
|
||||
pageTestActive &&
|
||||
!commandLineVisible &&
|
||||
!modePopupVisible &&
|
||||
!TestUI.resultVisible &&
|
||||
!wordsFocused &&
|
||||
event.key !== "Enter"
|
||||
) {
|
||||
TestUI.focusWords();
|
||||
wordsFocused = true;
|
||||
// if (Config.showOutOfFocusWarning) return;
|
||||
}
|
||||
|
||||
//tab
|
||||
if (
|
||||
(event.key == "Tab" && !Config.swapEscAndTab) ||
|
||||
(event.key == "Escape" && Config.swapEscAndTab)
|
||||
) {
|
||||
handleTab(event);
|
||||
// event.preventDefault();
|
||||
}
|
||||
|
||||
//blocking firefox from going back in history with backspace
|
||||
if (event.key === "Backspace" && wordsFocused) {
|
||||
let t = /INPUT|SELECT|TEXTAREA/i;
|
||||
if (
|
||||
!t.test(event.target.tagName) ||
|
||||
event.target.disabled ||
|
||||
event.target.readOnly
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// keypressStats.duration.current = performance.now();
|
||||
TestStats.setKeypressDuration(performance.now());
|
||||
|
||||
if (TestUI.testRestarting) {
|
||||
return;
|
||||
}
|
||||
|
||||
//backspace
|
||||
const isBackspace =
|
||||
event.key === "Backspace" ||
|
||||
(Config.capsLockBackspace && event.key === "CapsLock");
|
||||
if (isBackspace && wordsFocused) {
|
||||
handleBackspace(event);
|
||||
}
|
||||
|
||||
if (event.key === "Enter" && Funbox.active === "58008" && wordsFocused) {
|
||||
event.key = " ";
|
||||
}
|
||||
|
||||
//space or enter
|
||||
if (event.key === " " && wordsFocused) {
|
||||
handleSpace(event, false);
|
||||
}
|
||||
|
||||
if (wordsFocused && !commandLineVisible) {
|
||||
handleAlpha(event);
|
||||
}
|
||||
|
||||
let acc = Misc.roundTo2(TestStats.calculateAccuracy());
|
||||
LiveAcc.update(acc);
|
||||
});
|
118
src/js/popups/custom-background-filter.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
import * as UpdateConfig from "./config";
|
||||
import * as Notifications from "./notifications";
|
||||
|
||||
let filters = {
|
||||
blur: {
|
||||
value: 0,
|
||||
default: 0,
|
||||
},
|
||||
brightness: {
|
||||
value: 1,
|
||||
default: 1,
|
||||
},
|
||||
saturate: {
|
||||
value: 1,
|
||||
default: 1,
|
||||
},
|
||||
opacity: {
|
||||
value: 1,
|
||||
default: 1,
|
||||
},
|
||||
};
|
||||
|
||||
export function getCSS() {
|
||||
let ret = "";
|
||||
Object.keys(filters).forEach((filterKey) => {
|
||||
if (filters[filterKey].value != filters[filterKey].default) {
|
||||
ret += `${filterKey}(${filters[filterKey].value}${
|
||||
filterKey == "blur" ? "rem" : ""
|
||||
}) `;
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function apply() {
|
||||
let filterCSS = getCSS();
|
||||
$(".customBackground").css({
|
||||
filter: filterCSS,
|
||||
});
|
||||
}
|
||||
|
||||
function syncSliders() {
|
||||
$(".section.customBackgroundFilter .blur input").val(filters["blur"].value);
|
||||
$(".section.customBackgroundFilter .brightness input").val(
|
||||
filters["brightness"].value
|
||||
);
|
||||
$(".section.customBackgroundFilter .saturate input").val(
|
||||
filters["saturate"].value
|
||||
);
|
||||
$(".section.customBackgroundFilter .opacity input").val(
|
||||
filters["opacity"].value
|
||||
);
|
||||
}
|
||||
|
||||
$(".section.customBackgroundFilter .blur input").on("input", (e) => {
|
||||
filters["blur"].value = $(
|
||||
".section.customBackgroundFilter .blur input"
|
||||
).val();
|
||||
updateNumbers();
|
||||
apply();
|
||||
});
|
||||
|
||||
$(".section.customBackgroundFilter .brightness input").on("input", (e) => {
|
||||
filters["brightness"].value = $(
|
||||
".section.customBackgroundFilter .brightness input"
|
||||
).val();
|
||||
updateNumbers();
|
||||
apply();
|
||||
});
|
||||
|
||||
$(".section.customBackgroundFilter .saturate input").on("input", (e) => {
|
||||
filters["saturate"].value = $(
|
||||
".section.customBackgroundFilter .saturate input"
|
||||
).val();
|
||||
updateNumbers();
|
||||
apply();
|
||||
});
|
||||
|
||||
$(".section.customBackgroundFilter .opacity input").on("input", (e) => {
|
||||
filters["opacity"].value = $(
|
||||
".section.customBackgroundFilter .opacity input"
|
||||
).val();
|
||||
updateNumbers();
|
||||
apply();
|
||||
});
|
||||
|
||||
$(".section.customBackgroundFilter .save.button").click((e) => {
|
||||
let arr = [];
|
||||
Object.keys(filters).forEach((filterKey) => {
|
||||
arr.push(filters[filterKey].value);
|
||||
});
|
||||
UpdateConfig.setCustomBackgroundFilter(arr, false);
|
||||
Notifications.add("Custom background filters saved", 1);
|
||||
});
|
||||
|
||||
export function loadConfig(config) {
|
||||
filters.blur.value = config[0];
|
||||
filters.brightness.value = config[1];
|
||||
filters.saturate.value = config[2];
|
||||
filters.opacity.value = config[3];
|
||||
updateNumbers();
|
||||
syncSliders();
|
||||
}
|
||||
|
||||
function updateNumbers() {
|
||||
$(".section.customBackgroundFilter .blur .value").html(
|
||||
parseFloat(filters.blur.value).toFixed(1)
|
||||
);
|
||||
$(".section.customBackgroundFilter .brightness .value").html(
|
||||
parseFloat(filters.brightness.value).toFixed(1)
|
||||
);
|
||||
$(".section.customBackgroundFilter .saturate .value").html(
|
||||
parseFloat(filters.saturate.value).toFixed(1)
|
||||
);
|
||||
$(".section.customBackgroundFilter .opacity .value").html(
|
||||
parseFloat(filters.opacity.value).toFixed(1)
|
||||
);
|
||||
}
|
54
src/js/ready.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
import * as ManualRestart from "./manual-restart-tracker";
|
||||
import Config, * as UpdateConfig from "./config";
|
||||
import * as Misc from "./misc";
|
||||
import * as VerificationController from "./verification-controller";
|
||||
import * as Settings from "./settings";
|
||||
import * as RouteController from "./route-controller";
|
||||
import * as UI from "./ui";
|
||||
|
||||
ManualRestart.set();
|
||||
UpdateConfig.loadFromCookie();
|
||||
Misc.getReleasesFromGitHub();
|
||||
|
||||
$(document).ready(() => {
|
||||
RouteController.handleInitialPageClasses(window.location.pathname);
|
||||
if (window.location.pathname === "/") {
|
||||
$("#top .config").removeClass("hidden");
|
||||
}
|
||||
$("body").css("transition", ".25s");
|
||||
if (Config.quickTab) {
|
||||
$("#restartTestButton").addClass("hidden");
|
||||
}
|
||||
if (!Misc.getCookie("merchbannerclosed")) {
|
||||
$(".merchBanner").removeClass("hidden");
|
||||
} else {
|
||||
$(".merchBanner").remove();
|
||||
}
|
||||
$("#centerContent")
|
||||
.css("opacity", "0")
|
||||
.removeClass("hidden")
|
||||
.stop(true, true)
|
||||
.animate({ opacity: 1 }, 250, () => {
|
||||
if (window.location.pathname === "/verify") {
|
||||
const fragment = new URLSearchParams(window.location.hash.slice(1));
|
||||
if (fragment.has("access_token")) {
|
||||
const accessToken = fragment.get("access_token");
|
||||
const tokenType = fragment.get("token_type");
|
||||
VerificationController.set({
|
||||
accessToken: accessToken,
|
||||
tokenType: tokenType,
|
||||
});
|
||||
history.replaceState("/", null, "/");
|
||||
}
|
||||
} else if (window.location.pathname === "/account") {
|
||||
// history.replaceState("/", null, "/");
|
||||
} else if (/challenge_.+/g.test(window.location.pathname)) {
|
||||
//do nothing
|
||||
// }
|
||||
} else if (window.location.pathname !== "/") {
|
||||
let page = window.location.pathname.replace("/", "");
|
||||
UI.changePage(page);
|
||||
}
|
||||
});
|
||||
Settings.settingsFillPromise.then(Settings.update);
|
||||
});
|
|
@ -1,149 +0,0 @@
|
|||
import * as Misc from "./misc";
|
||||
import * as DB from "./db";
|
||||
|
||||
let defaultResultFilters = {
|
||||
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,
|
||||
},
|
||||
quoteLength: {
|
||||
short: true,
|
||||
medium: true,
|
||||
long: true,
|
||||
thicc: true,
|
||||
},
|
||||
punctuation: {
|
||||
on: true,
|
||||
off: true,
|
||||
},
|
||||
numbers: {
|
||||
on: true,
|
||||
off: true,
|
||||
},
|
||||
date: {
|
||||
last_day: false,
|
||||
last_week: false,
|
||||
last_month: false,
|
||||
all: true,
|
||||
},
|
||||
tags: {
|
||||
none: true,
|
||||
},
|
||||
language: {},
|
||||
funbox: {
|
||||
none: true,
|
||||
},
|
||||
};
|
||||
|
||||
let filters = defaultResultFilters;
|
||||
|
||||
Misc.getLanguageList().then((languages) => {
|
||||
languages.forEach((language) => {
|
||||
defaultResultFilters.language[language] = true;
|
||||
});
|
||||
});
|
||||
|
||||
Misc.getFunboxList().then((funboxModes) => {
|
||||
funboxModes.forEach((funbox) => {
|
||||
defaultResultFilters.funbox[funbox.name] = true;
|
||||
});
|
||||
});
|
||||
|
||||
export function getFilters() {
|
||||
return filters;
|
||||
}
|
||||
|
||||
export function getGroup(group) {
|
||||
return filters[group];
|
||||
}
|
||||
|
||||
export function setFilter(group, filter, value) {
|
||||
filters[group][filter] = value;
|
||||
}
|
||||
|
||||
export function getFilter(group, filter) {
|
||||
return filters[group][filter];
|
||||
}
|
||||
|
||||
export function toggleFilter(group, filter) {
|
||||
filters[group][filter] = !filters[group][filter];
|
||||
}
|
||||
|
||||
export function loadTags(tags) {
|
||||
tags.forEach((tag) => {
|
||||
defaultResultFilters.tags[tag.id] = true;
|
||||
});
|
||||
}
|
||||
|
||||
export function save() {
|
||||
Misc.setCookie("resultFilters", JSON.stringify(filters), 365);
|
||||
}
|
||||
|
||||
export function load() {
|
||||
// let newTags = $.cookie("activeTags");
|
||||
try {
|
||||
let newResultFilters = Misc.getCookie("resultFilters");
|
||||
if (newResultFilters !== undefined && newResultFilters !== "") {
|
||||
filters = JSON.parse(newResultFilters);
|
||||
save();
|
||||
} else {
|
||||
filters = defaultResultFilters;
|
||||
save();
|
||||
}
|
||||
} catch {
|
||||
filters = defaultResultFilters;
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
export function reset() {
|
||||
filters = defaultResultFilters;
|
||||
save();
|
||||
}
|
||||
|
||||
load();
|
||||
|
||||
export function updateTags() {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).empty();
|
||||
if (DB.getSnapshot().tags.length > 0) {
|
||||
$(".pageAccount .content .filterButtons .buttonsAndTitle.tags").removeClass(
|
||||
"hidden"
|
||||
);
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).append(`<div class="button" filter="none">no tag</div>`);
|
||||
DB.getSnapshot().tags.forEach((tag) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).append(`<div class="button" filter="${tag.id}">${tag.name}</div>`);
|
||||
});
|
||||
} else {
|
||||
$(".pageAccount .content .filterButtons .buttonsAndTitle.tags").addClass(
|
||||
"hidden"
|
||||
);
|
||||
}
|
||||
}
|
44
src/js/route-controller.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import * as Funbox from "./funbox";
|
||||
import * as UI from "./ui";
|
||||
|
||||
let mappedRoutes = {
|
||||
"/": "pageTest",
|
||||
"/login": "pageLogin",
|
||||
"/settings": "pageSettings",
|
||||
"/about": "pageAbout",
|
||||
"/account": "pageAccount",
|
||||
"/verify": "pageTest",
|
||||
};
|
||||
|
||||
export function handleInitialPageClasses(pathname) {
|
||||
let el = $(".page." + mappedRoutes[pathname]);
|
||||
$(el).removeClass("hidden");
|
||||
$(el).addClass("active");
|
||||
}
|
||||
|
||||
(function (history) {
|
||||
var pushState = history.pushState;
|
||||
history.pushState = function (state) {
|
||||
if (Funbox.active === "memory" && state !== "/") {
|
||||
Funbox.resetMemoryTimer();
|
||||
}
|
||||
return pushState.apply(history, arguments);
|
||||
};
|
||||
})(window.history);
|
||||
|
||||
$(window).on("popstate", (e) => {
|
||||
let state = e.originalEvent.state;
|
||||
if (state == "" || state == "/") {
|
||||
// show test
|
||||
UI.changePage("test");
|
||||
} else if (state == "about") {
|
||||
// show about
|
||||
UI.changePage("about");
|
||||
} else if (state == "account" || state == "login") {
|
||||
if (firebase.auth().currentUser) {
|
||||
UI.changePage("account");
|
||||
} else {
|
||||
UI.changePage("login");
|
||||
}
|
||||
}
|
||||
});
|
|
@ -267,6 +267,10 @@ async function initGroups() {
|
|||
"alwaysShowCPM",
|
||||
UpdateConfig.setAlwaysShowCPM
|
||||
);
|
||||
groups.customBackgroundSize = new SettingsGroup(
|
||||
"customBackgroundSize",
|
||||
UpdateConfig.setCustomBackgroundSize
|
||||
);
|
||||
}
|
||||
|
||||
async function fillSettingsPage() {
|
||||
|
@ -369,6 +373,10 @@ async function fillSettingsPage() {
|
|||
})
|
||||
.appendTo(fontsEl);
|
||||
});
|
||||
|
||||
$(".pageSettings .section.customBackgroundSize input").val(
|
||||
Config.customBackground
|
||||
);
|
||||
}
|
||||
|
||||
export let settingsFillPromise = fillSettingsPage();
|
||||
|
@ -420,7 +428,7 @@ export function updateDiscordSection() {
|
|||
function setActiveFunboxButton() {
|
||||
$(`.pageSettings .section.funbox .button`).removeClass("active");
|
||||
$(
|
||||
`.pageSettings .section.funbox .button[funbox='${Funbox.active}']`
|
||||
`.pageSettings .section.funbox .button[funbox='${Funbox.funboxSaved}']`
|
||||
).addClass("active");
|
||||
}
|
||||
|
||||
|
@ -616,7 +624,7 @@ $(".pageSettings .section.discordIntegration #unlinkDiscordButton").click(
|
|||
$(document).on("click", ".pageSettings .section.funbox .button", (e) => {
|
||||
let funbox = $(e.currentTarget).attr("funbox");
|
||||
let type = $(e.currentTarget).attr("type");
|
||||
Funbox.activate(funbox, type);
|
||||
Funbox.setFunbox(funbox, type);
|
||||
setActiveFunboxButton();
|
||||
});
|
||||
|
||||
|
@ -727,3 +735,34 @@ $(".pageSettings .sectionGroupTitle").click((e) => {
|
|||
);
|
||||
}
|
||||
});
|
||||
|
||||
$(".pageSettings #resetPersonalBestsButton").on("click", (e) => {
|
||||
SimplePopups.list.resetPersonalBests.show();
|
||||
});
|
||||
|
||||
$(".pageSettings #updateAccountEmail").on("click", (e) => {
|
||||
SimplePopups.list.updateEmail.show();
|
||||
});
|
||||
|
||||
$(".pageSettings .section.customBackgroundSize .inputAndButton .save").on(
|
||||
"click",
|
||||
(e) => {
|
||||
UpdateConfig.setCustomBackground(
|
||||
$(
|
||||
".pageSettings .section.customBackgroundSize .inputAndButton input"
|
||||
).val()
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$(".pageSettings .section.customBackgroundSize .inputAndButton input").keypress(
|
||||
(e) => {
|
||||
if (e.keyCode == 13) {
|
||||
UpdateConfig.setCustomBackground(
|
||||
$(
|
||||
".pageSettings .section.customBackgroundSize .inputAndButton input"
|
||||
).val()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -5,6 +5,7 @@ import * as Notifications from "./notifications";
|
|||
import * as CommandlineLists from "./commandline-lists";
|
||||
import * as ThemeColors from "./theme-colors";
|
||||
import * as ChartController from "./chart-controller";
|
||||
import * as UI from "./ui";
|
||||
|
||||
export function updateActiveButton() {
|
||||
$(`.pageSettings .section.themes .theme`).removeClass("active");
|
||||
|
@ -99,9 +100,28 @@ function toggleFavourite(themename) {
|
|||
}
|
||||
|
||||
export function updateActiveTab() {
|
||||
Config.customTheme === true
|
||||
? $(".pageSettings .section.themes .tabs .button[tab='custom']").click()
|
||||
: $(".pageSettings .section.themes .tabs .button[tab='preset']").click();
|
||||
$(".pageSettings .section.themes .tabs .button").removeClass("active");
|
||||
if (!Config.customTheme) {
|
||||
$(".pageSettings .section.themes .tabs .button[tab='preset']").addClass(
|
||||
"active"
|
||||
);
|
||||
|
||||
UI.swapElements(
|
||||
$('.pageSettings .section.themes .tabContainer [tabContent="custom"]'),
|
||||
$('.pageSettings .section.themes .tabContainer [tabContent="preset"]'),
|
||||
250
|
||||
);
|
||||
} else {
|
||||
$(".pageSettings .section.themes .tabs .button[tab='custom']").addClass(
|
||||
"active"
|
||||
);
|
||||
|
||||
UI.swapElements(
|
||||
$('.pageSettings .section.themes .tabContainer [tabContent="preset"]'),
|
||||
$('.pageSettings .section.themes .tabContainer [tabContent="custom"]'),
|
||||
250
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$("#shareCustomThemeButton").click((e) => {
|
||||
|
@ -138,7 +158,7 @@ $(".pageSettings .section.themes .tabs .button").click((e) => {
|
|||
setCustomInputs();
|
||||
if ($target.attr("tab") == "preset") {
|
||||
UpdateConfig.setCustomTheme(false);
|
||||
ThemeController.set(Config.theme);
|
||||
// ThemeController.set(Config.theme);
|
||||
// applyCustomThemeColors();
|
||||
// UI.swapElements(
|
||||
// $('.pageSettings .section.themes .tabContainer [tabContent="custom"]'),
|
||||
|
@ -147,7 +167,7 @@ $(".pageSettings .section.themes .tabs .button").click((e) => {
|
|||
// );
|
||||
} else {
|
||||
UpdateConfig.setCustomTheme(true);
|
||||
ThemeController.set("custom");
|
||||
// ThemeController.set("custom");
|
||||
// applyCustomThemeColors();
|
||||
// UI.swapElements(
|
||||
// $('.pageSettings .section.themes .tabContainer [tabContent="preset"]'),
|
||||
|
@ -202,7 +222,7 @@ $(".pageSettings .saveCustomThemeButton").click((e) => {
|
|||
|
||||
$(".pageSettings #loadCustomColorsFromPreset").click((e) => {
|
||||
// previewTheme(Config.theme);
|
||||
ThemeController.preview(Config.theme);
|
||||
$("#currentTheme").attr("href", `themes/${Config.theme}.css`);
|
||||
|
||||
ThemeController.colorVars.forEach((e) => {
|
||||
document.documentElement.style.setProperty(e, "");
|
||||
|
|
|
@ -79,42 +79,42 @@ export function init() {
|
|||
{
|
||||
sounds: [
|
||||
new Audio("../sound/click4/click4_1.wav"),
|
||||
new Audio("../sound/click4/click4_1.wav"),
|
||||
new Audio("../sound/click4/click4_11.wav"),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
{
|
||||
sounds: [
|
||||
new Audio("../sound/click4/click4_2.wav"),
|
||||
new Audio("../sound/click4/click4_2.wav"),
|
||||
new Audio("../sound/click4/click4_22.wav"),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
{
|
||||
sounds: [
|
||||
new Audio("../sound/click4/click4_3.wav"),
|
||||
new Audio("../sound/click4/click4_3.wav"),
|
||||
new Audio("../sound/click4/click4_33.wav"),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
{
|
||||
sounds: [
|
||||
new Audio("../sound/click4/click4_4.wav"),
|
||||
new Audio("../sound/click4/click4_4.wav"),
|
||||
new Audio("../sound/click4/click4_44.wav"),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
{
|
||||
sounds: [
|
||||
new Audio("../sound/click4/click4_5.wav"),
|
||||
new Audio("../sound/click4/click4_5.wav"),
|
||||
new Audio("../sound/click4/click4_55.wav"),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
{
|
||||
sounds: [
|
||||
new Audio("../sound/click4/click4_6.wav"),
|
||||
new Audio("../sound/click4/click4_6.wav"),
|
||||
new Audio("../sound/click4/click4_66.wav"),
|
||||
],
|
||||
counter: 0,
|
||||
},
|
||||
|
|
|
@ -7,6 +7,8 @@ import Config, * as UpdateConfig from "./config";
|
|||
import * as Settings from "./settings";
|
||||
|
||||
export let active = "none";
|
||||
export let funboxSaved = "none";
|
||||
export let modeSaved = null;
|
||||
let memoryTimer = null;
|
||||
let memoryInterval = null;
|
||||
|
||||
|
@ -71,12 +73,8 @@ export function toggleScript(...params) {
|
|||
}
|
||||
|
||||
export async function activate(funbox, mode) {
|
||||
if (TestLogic.active || TestUI.resultVisible) {
|
||||
Notifications.add(
|
||||
"You can only change the funbox before starting a test.",
|
||||
0
|
||||
);
|
||||
return false;
|
||||
if (funbox === undefined || funbox === null) {
|
||||
funbox = funboxSaved;
|
||||
}
|
||||
if (Misc.getCurrentLanguage().ligatures) {
|
||||
if (funbox == "choo_choo" || funbox == "earthquake") {
|
||||
|
@ -96,8 +94,12 @@ export async function activate(funbox, mode) {
|
|||
|
||||
$("#wordsWrapper").removeClass("hidden");
|
||||
// }
|
||||
|
||||
if (mode === null || mode === undefined) {
|
||||
if (funbox === "none" && mode === undefined) {
|
||||
mode = null;
|
||||
} else if (
|
||||
(funbox !== "none" && mode === undefined) ||
|
||||
(funbox !== "none" && mode === null)
|
||||
) {
|
||||
let list = await Misc.getFunboxList();
|
||||
mode = list.filter((f) => f.name === funbox)[0].type;
|
||||
}
|
||||
|
@ -162,3 +164,16 @@ export async function activate(funbox, mode) {
|
|||
TestUI.updateModesNotice();
|
||||
return true;
|
||||
}
|
||||
export function setFunbox(funbox, mode) {
|
||||
if (TestLogic.active || TestUI.resultVisible) {
|
||||
Notifications.add(
|
||||
"You can only change the funbox before starting a test.",
|
||||
0
|
||||
);
|
||||
return false;
|
||||
}
|
||||
funboxSaved = funbox;
|
||||
modeSaved = mode;
|
||||
active = funbox;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -246,6 +246,6 @@ export function refreshKeys(layout) {
|
|||
}
|
||||
|
||||
$(document).on("click", ".keymap .r5 #KeySpace", (e) => {
|
||||
CommandlineLists.setCurrent(CommandlineLists.commandsKeymapLayouts);
|
||||
CommandlineLists.setCurrent([CommandlineLists.commandsKeymapLayouts]);
|
||||
Commandline.show();
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ export function show(data, mode2) {
|
|||
let string = "";
|
||||
if (data.needsToVerifyEmail === true) {
|
||||
string = `please verify your email<br>to access leaderboards - <a onClick="sendVerificationEmail()">resend email</a>`;
|
||||
} else if (data.lbBanned) {
|
||||
} else if (data.banned || data.lbBanned) {
|
||||
string = "banned";
|
||||
} else if (data.name === false) {
|
||||
string = "update your name to access leaderboards";
|
||||
|
|
|
@ -22,7 +22,7 @@ import * as QuoteSearchPopup from "./quote-search-popup";
|
|||
import * as PbCrown from "./pb-crown";
|
||||
import * as TestTimer from "./test-timer";
|
||||
import * as OutOfFocus from "./out-of-focus";
|
||||
import * as AccountButton from "./account-icon";
|
||||
import * as AccountButton from "./account-button";
|
||||
import * as DB from "./db";
|
||||
import * as ThemeColors from "./theme-colors";
|
||||
import * as CloudFunctions from "./cloud-functions";
|
||||
|
@ -576,6 +576,9 @@ export async function init() {
|
|||
// } else {
|
||||
TestUI.showWords();
|
||||
// }
|
||||
if ($(".pageTest").hasClass("active")) {
|
||||
Funbox.activate();
|
||||
}
|
||||
}
|
||||
|
||||
export function restart(withSameWordset = false, nosave = false, event) {
|
||||
|
@ -697,6 +700,7 @@ export function restart(withSameWordset = false, nosave = false, event) {
|
|||
input.reset();
|
||||
PaceCaret.init();
|
||||
TestUI.showWords();
|
||||
Funbox.activate();
|
||||
}
|
||||
if (Config.mode === "quote") {
|
||||
setRepeated(false);
|
||||
|
@ -924,6 +928,7 @@ export function finish(difficultyFailed = false) {
|
|||
LiveAcc.hide();
|
||||
TimerProgress.hide();
|
||||
Keymap.hide();
|
||||
Funbox.activate("none", null);
|
||||
let stats = TestStats.calculateStats();
|
||||
if (stats === undefined) {
|
||||
stats = {
|
||||
|
@ -1653,8 +1658,8 @@ export function finish(difficultyFailed = false) {
|
|||
if (Config.blindMode) {
|
||||
testType += "<br>blind";
|
||||
}
|
||||
if (Funbox.active !== "none") {
|
||||
testType += "<br>" + Funbox.active.replace(/_/g, " ");
|
||||
if (Funbox.funboxSaved !== "none") {
|
||||
testType += "<br>" + Funbox.funboxSaved.replace(/_/g, " ");
|
||||
}
|
||||
if (Config.difficulty == "expert") {
|
||||
testType += "<br>expert";
|
||||
|
@ -1708,6 +1713,33 @@ export function finish(difficultyFailed = false) {
|
|||
$("#result .stats .source").addClass("hidden");
|
||||
}
|
||||
|
||||
if (Funbox.funboxSaved !== "none") {
|
||||
ChartController.result.options.annotation.annotations.push({
|
||||
enabled: false,
|
||||
type: "line",
|
||||
mode: "horizontal",
|
||||
scaleID: "wpm",
|
||||
value: 0,
|
||||
borderColor: "transparent",
|
||||
borderWidth: 1,
|
||||
borderDash: [2, 2],
|
||||
label: {
|
||||
backgroundColor: "transparent",
|
||||
fontFamily: Config.fontFamily.replace(/_/g, " "),
|
||||
fontSize: 11,
|
||||
fontStyle: "normal",
|
||||
fontColor: ThemeColors.sub,
|
||||
xPadding: 6,
|
||||
yPadding: 6,
|
||||
cornerRadius: 3,
|
||||
position: "left",
|
||||
enabled: true,
|
||||
content: `${Funbox.funboxSaved}`,
|
||||
yAdjust: -11,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
ChartController.result.options.scales.yAxes[0].ticks.max = maxChartVal;
|
||||
ChartController.result.options.scales.yAxes[1].ticks.max = maxChartVal;
|
||||
|
||||
|
|
|
@ -255,6 +255,14 @@ export function screenshot() {
|
|||
if (firebase.auth().currentUser == null)
|
||||
$(".pageTest .loginTip").removeClass("hidden");
|
||||
}
|
||||
setTimeout(() => {
|
||||
$("#notificationCenter").removeClass("hidden");
|
||||
$("#commandLineMobileButton").removeClass("hidden");
|
||||
$(".pageTest .ssWatermark").addClass("hidden");
|
||||
$(".pageTest .buttons").removeClass("hidden");
|
||||
if (firebase.auth().currentUser == null)
|
||||
$(".pageTest .loginTip").removeClass("hidden");
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
export function updateWordElement(showError) {
|
||||
|
|
|
@ -149,3 +149,27 @@ export function randomiseTheme() {
|
|||
export function clearRandom() {
|
||||
randomTheme = null;
|
||||
}
|
||||
|
||||
export function applyCustomBackground() {
|
||||
$(".customBackground").css({
|
||||
backgroundImage: `url(${Config.customBackground})`,
|
||||
backgroundAttachment: "fixed",
|
||||
});
|
||||
if (Config.customBackground === "") {
|
||||
$("#words").removeClass("noErrorBorder");
|
||||
} else {
|
||||
$("#words").addClass("noErrorBorder");
|
||||
}
|
||||
}
|
||||
|
||||
export function applyCustomBackgroundSize() {
|
||||
if (Config.customBackgroundSize == "max") {
|
||||
$(".customBackground").css({
|
||||
backgroundSize: "100% 100%",
|
||||
});
|
||||
} else if (Config.customBackgroundSize != "") {
|
||||
$(".customBackground").css({
|
||||
backgroundSize: Config.customBackgroundSize,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
119
src/js/ui.js
|
@ -6,6 +6,15 @@ import * as TestLogic from "./test-logic";
|
|||
import * as CustomText from "./custom-text";
|
||||
import * as CommandlineLists from "./commandline-lists";
|
||||
import * as Commandline from "./commandline";
|
||||
import * as TestUI from "./test-ui";
|
||||
import * as TestConfig from "./test-config";
|
||||
import * as SignOutButton from "./sign-out-button";
|
||||
import * as TestStats from "./test-stats";
|
||||
import * as ManualRestart from "./manual-restart-tracker";
|
||||
import * as Settings from "./settings";
|
||||
import * as Account from "./account";
|
||||
import * as Leaderboards from "./leaderboards";
|
||||
import * as Funbox from "./funbox";
|
||||
|
||||
export let pageTransition = false;
|
||||
|
||||
|
@ -99,6 +108,100 @@ export function swapElements(
|
|||
}
|
||||
}
|
||||
|
||||
export function changePage(page) {
|
||||
if (pageTransition) {
|
||||
return;
|
||||
}
|
||||
let activePage = $(".page.active");
|
||||
$(".page").removeClass("active");
|
||||
$("#wordsInput").focusout();
|
||||
if (page == "test" || page == "") {
|
||||
setPageTransition(true);
|
||||
swapElements(
|
||||
activePage,
|
||||
$(".page.pageTest"),
|
||||
250,
|
||||
() => {
|
||||
setPageTransition(false);
|
||||
TestUI.focusWords();
|
||||
$(".page.pageTest").addClass("active");
|
||||
history.pushState("/", null, "/");
|
||||
},
|
||||
() => {
|
||||
TestConfig.show();
|
||||
}
|
||||
);
|
||||
SignOutButton.hide();
|
||||
// restartCount = 0;
|
||||
// incompleteTestSeconds = 0;
|
||||
TestStats.resetIncomplete();
|
||||
ManualRestart.set();
|
||||
TestLogic.restart();
|
||||
Funbox.activate(Funbox.funboxSaved, Funbox.modeSaved);
|
||||
} else if (page == "about") {
|
||||
setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
swapElements(activePage, $(".page.pageAbout"), 250, () => {
|
||||
setPageTransition(false);
|
||||
history.pushState("about", null, "about");
|
||||
$(".page.pageAbout").addClass("active");
|
||||
});
|
||||
Funbox.activate("none", null);
|
||||
TestConfig.hide();
|
||||
SignOutButton.hide();
|
||||
} else if (page == "settings") {
|
||||
setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
swapElements(activePage, $(".page.pageSettings"), 250, () => {
|
||||
setPageTransition(false);
|
||||
history.pushState("settings", null, "settings");
|
||||
$(".page.pageSettings").addClass("active");
|
||||
});
|
||||
Funbox.activate("none", null);
|
||||
Settings.update();
|
||||
TestConfig.hide();
|
||||
SignOutButton.hide();
|
||||
} else if (page == "account") {
|
||||
if (!firebase.auth().currentUser) {
|
||||
changePage("login");
|
||||
} else {
|
||||
setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
swapElements(
|
||||
activePage,
|
||||
$(".page.pageAccount"),
|
||||
250,
|
||||
() => {
|
||||
setPageTransition(false);
|
||||
history.pushState("account", null, "account");
|
||||
$(".page.pageAccount").addClass("active");
|
||||
},
|
||||
() => {
|
||||
SignOutButton.show();
|
||||
}
|
||||
);
|
||||
Funbox.activate("none", null);
|
||||
Account.update();
|
||||
TestConfig.hide();
|
||||
}
|
||||
} else if (page == "login") {
|
||||
if (firebase.auth().currentUser != null) {
|
||||
changePage("account");
|
||||
} else {
|
||||
setPageTransition(true);
|
||||
TestLogic.restart();
|
||||
swapElements(activePage, $(".page.pageLogin"), 250, () => {
|
||||
setPageTransition(false);
|
||||
history.pushState("login", null, "login");
|
||||
$(".page.pageLogin").addClass("active");
|
||||
});
|
||||
Funbox.activate("none", null);
|
||||
TestConfig.hide();
|
||||
SignOutButton.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firebase.app().options.projectId === "monkey-type-dev-67af4") {
|
||||
$("#top .logo .bottom").text("monkey-dev");
|
||||
$("head title").text("Monkey Dev");
|
||||
|
@ -152,7 +255,7 @@ $(document).on("click", "#bottom .leftright .right .current-theme", (e) => {
|
|||
// if (Config.customTheme) {
|
||||
// toggleCustomTheme();
|
||||
// }
|
||||
CommandlineLists.setCurrent(CommandlineLists.themeCommands);
|
||||
CommandlineLists.setCurrent([CommandlineLists.themeCommands]);
|
||||
Commandline.show();
|
||||
}
|
||||
});
|
||||
|
@ -191,3 +294,17 @@ window.addEventListener("beforeunload", (event) => {
|
|||
$(window).resize(() => {
|
||||
Caret.updatePosition();
|
||||
});
|
||||
|
||||
$(document).on("click", "#top .logo", (e) => {
|
||||
changePage("test");
|
||||
});
|
||||
|
||||
$(document).on("click", "#top #menu .icon-button", (e) => {
|
||||
if ($(e.currentTarget).hasClass("leaderboards")) {
|
||||
Leaderboards.show();
|
||||
} else {
|
||||
const href = $(e.currentTarget).attr("href");
|
||||
ManualRestart.set();
|
||||
changePage(href.replace("/", ""));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -44,6 +44,22 @@ input {
|
|||
font-family: var(--font);
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
-webkit-appearance: none;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 1rem;
|
||||
border-radius: var(--roundness);
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
padding: 0;
|
||||
width: 2rem;
|
||||
height: 1rem;
|
||||
border-radius: var(--roundness);
|
||||
background-color: var(--main-color);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="color"] {
|
||||
-webkit-appearance: none;
|
||||
padding: 0;
|
||||
|
@ -107,10 +123,22 @@ body {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
background: var(--bg-color);
|
||||
font-family: var(--font);
|
||||
color: var(--main-color);
|
||||
overflow-x: hidden;
|
||||
background: var(--bg-color);
|
||||
}
|
||||
|
||||
.customBackground {
|
||||
content: "";
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
html {
|
||||
|
@ -1496,12 +1524,12 @@ a:hover {
|
|||
@keyframes caretFlashHard {
|
||||
0%,
|
||||
50% {
|
||||
opacity: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
51%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2465,6 +2493,11 @@ key {
|
|||
1px 1px 0px var(--bg-color), -1px 1px 0px var(--bg-color);
|
||||
}
|
||||
|
||||
#words.noErrorBorder {
|
||||
.word.error {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
// .word letter {
|
||||
// transition: .1s;
|
||||
// height: 1rem;
|
||||
|
@ -2714,6 +2747,56 @@ key {
|
|||
}
|
||||
}
|
||||
|
||||
&.customBackgroundSize {
|
||||
.inputAndButton {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
input {
|
||||
grid-column: 1/3;
|
||||
}
|
||||
|
||||
.save {
|
||||
grid-column: 3/4;
|
||||
height: auto;
|
||||
|
||||
.fas {
|
||||
margin-right: 0rem;
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.customBackgroundFilter {
|
||||
.groups {
|
||||
grid-area: buttons;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 2rem;
|
||||
margin-top: 2rem;
|
||||
.group {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 2fr;
|
||||
gap: 1rem;
|
||||
.title,
|
||||
.value {
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.saveContainer {
|
||||
grid-column: -1/-3;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
.fas {
|
||||
margin-right: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.customTheme {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
justify-items: stretch;
|
||||
|
@ -2960,7 +3043,8 @@ key {
|
|||
&.keymapLayout,
|
||||
&.fontFamily,
|
||||
&.funbox,
|
||||
&.keymapStyle {
|
||||
&.keymapStyle,
|
||||
&.customBackgroundFilter {
|
||||
grid-template-columns: 2fr 1fr;
|
||||
grid-template-areas:
|
||||
"title tabs"
|
||||
|
@ -3515,6 +3599,15 @@ key {
|
|||
}
|
||||
}
|
||||
|
||||
.pageSettings .section.customBackgroundFilter {
|
||||
.groups {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.saveContainer {
|
||||
grid-column: -1/-2;
|
||||
}
|
||||
}
|
||||
|
||||
#commandLine,
|
||||
#commandLineInput {
|
||||
width: 500px !important;
|
||||
|
|
BIN
static/images/favicon/apple-touch-icon-120x120.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
static/images/favicon/apple-touch-icon-152x152.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
static/images/favicon/apple-touch-icon-180x180.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
static/images/favicon/apple-touch-icon-60x60.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
static/images/favicon/apple-touch-icon-76x76.png
Normal file
After Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
|
@ -14,7 +14,32 @@
|
|||
<link rel="stylesheet" href="themes/serika_dark.css" id="currentTheme" />
|
||||
<link rel="stylesheet" href="" id="funBoxTheme" />
|
||||
<link id="favicon" rel="shortcut icon" href="images/fav.png" />
|
||||
<link rel="shortcut icon" href="images/fav.png" />
|
||||
<link rel="shortcut icon" href="images/favicon/fav.png" />
|
||||
<link
|
||||
href="images/favicon/apple-touch-icon-180x180.png"
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
/>
|
||||
<link
|
||||
href="images/favicon/apple-touch-icon-152x152.png"
|
||||
rel="apple-touch-icon"
|
||||
sizes="152x152"
|
||||
/>
|
||||
<link
|
||||
href="images/favicon/apple-touch-icon-120x120.png"
|
||||
rel="apple-touch-icon"
|
||||
sizes="120x120"
|
||||
/>
|
||||
|
||||
<link
|
||||
href="images/favicon/apple-touch-icon-76x76.png"
|
||||
rel="apple-touch-icon"
|
||||
sizes="76x76"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
href="images/favicon/apple-touch-icon-60x60.png"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"
|
||||
|
@ -54,7 +79,7 @@
|
|||
</script>
|
||||
<script async src="https://s.nitropay.com/ads-693.js"></script>
|
||||
</head>
|
||||
|
||||
<div class="customBackground"></div>
|
||||
<body>
|
||||
<div id="backgroundLoader" style="display: none"></div>
|
||||
<div id="notificationCenter">
|
||||
|
@ -875,7 +900,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div id="timerWrapper">
|
||||
<div id="timer"></div>
|
||||
<div id="timer" class="timerMain"></div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-around">
|
||||
<div id="nitropay_ad_left" class="hidden"></div>
|
||||
|
@ -1067,10 +1092,10 @@
|
|||
<div id="caret" class="default size15"></div>
|
||||
<div id="paceCaret" class="default size15 hidden"></div>
|
||||
<input id="wordsInput" class="" tabindex="0" autocomplete="off" />
|
||||
<div id="timerNumber">
|
||||
<div id="timerNumber" class="timerMain">
|
||||
<div>60</div>
|
||||
</div>
|
||||
<div id="miniTimerAndLiveWpm">
|
||||
<div id="miniTimerAndLiveWpm" class="timerMain size15">
|
||||
<div class="time hidden">1:00</div>
|
||||
<div class="wpm">60</div>
|
||||
<div class="acc">100%</div>
|
||||
|
@ -1256,7 +1281,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="largeLiveWpmAndAcc">
|
||||
<div id="largeLiveWpmAndAcc" class="timerMain">
|
||||
<div id="liveWpm" class="hidden">123</div>
|
||||
<div id="liveAcc" class="hidden">100%%</div>
|
||||
</div>
|
||||
|
@ -2920,6 +2945,92 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section customBackgroundSize">
|
||||
<h1>custom background</h1>
|
||||
<div class="text">
|
||||
Set an image url to be a custom background image. Cover fits
|
||||
the image to cover the screen. Contain fits the image to be
|
||||
fully visible. Max fits the image corner to corner.
|
||||
</div>
|
||||
<div>
|
||||
<div class="inputAndButton">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="image url"
|
||||
class="input"
|
||||
tabindex="0"
|
||||
onClick="this.select();"
|
||||
/>
|
||||
<div
|
||||
class="button save"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
<i class="fas fa-save fa-fw"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div
|
||||
class="button"
|
||||
customBackgroundSize="cover"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
cover
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
customBackgroundSize="contain"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
contain
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
customBackGroundSize="max"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
max
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section customBackgroundFilter">
|
||||
<h1>custom background filter</h1>
|
||||
<div class="text">
|
||||
Apply various effects to the custom background.
|
||||
</div>
|
||||
<div class="groups">
|
||||
<div class="group blur">
|
||||
<div class="title">blur</div>
|
||||
<div class="value"></div>
|
||||
<input type="range" min="0" max="5" value="0" step="0.1" />
|
||||
</div>
|
||||
<div class="group brightness">
|
||||
<div class="title">brightness</div>
|
||||
<div class="value"></div>
|
||||
<input type="range" min="0" max="2" value="1" step="0.1" />
|
||||
</div>
|
||||
<div class="group saturate">
|
||||
<div class="title">saturate</div>
|
||||
<div class="value"></div>
|
||||
<input type="range" min="0" max="2" value="1" step="0.1" />
|
||||
</div>
|
||||
<div class="group opacity">
|
||||
<div class="title">opacity</div>
|
||||
<div class="value"></div>
|
||||
<input type="range" min="0" max="1" value="1" step="0.1" />
|
||||
</div>
|
||||
<div class="saveContainer">
|
||||
<div class="save button" style="grid-column: 3">
|
||||
<!-- <i class="fas fa-save fa-fw"></i> -->
|
||||
save
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section themes">
|
||||
<h1>theme</h1>
|
||||
<div class="tabs">
|
||||
|
@ -3225,7 +3336,7 @@
|
|||
class="button off danger"
|
||||
id="resetPersonalBestsButton"
|
||||
tabindex="0"
|
||||
onclick="this.blur();simplePopups.resetPersonalBests.show();"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
reset personal bests
|
||||
</div>
|
||||
|
@ -3241,7 +3352,7 @@
|
|||
class="button off danger"
|
||||
id="updateAccountEmail"
|
||||
tabindex="0"
|
||||
onclick="this.blur();simplePopups.updateEmail.show();"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
update email
|
||||
</div>
|
||||
|
|
|
@ -167,8 +167,6 @@
|
|||
"málo",
|
||||
"myslit",
|
||||
"stejně",
|
||||
"-li",
|
||||
"Český",
|
||||
"moc",
|
||||
"problém",
|
||||
"milión",
|
||||
|
|
|
@ -26,9 +26,7 @@
|
|||
"tak",
|
||||
"po",
|
||||
"už",
|
||||
"V",
|
||||
"co",
|
||||
"A",
|
||||
"jsou",
|
||||
"nebo",
|
||||
"které",
|
||||
|
@ -54,22 +52,18 @@
|
|||
"ještě",
|
||||
"bude",
|
||||
"ze",
|
||||
"Na",
|
||||
"také",
|
||||
"která",
|
||||
"ji",
|
||||
"pak",
|
||||
"být",
|
||||
"ani",
|
||||
"To",
|
||||
"před",
|
||||
"při",
|
||||
"není",
|
||||
"však",
|
||||
"jejich",
|
||||
"Ale",
|
||||
"toho",
|
||||
"Je",
|
||||
"kde",
|
||||
"své",
|
||||
"tam",
|
||||
|
@ -78,7 +72,6 @@
|
|||
"tom",
|
||||
"tím",
|
||||
"tu",
|
||||
"Když",
|
||||
"či",
|
||||
"protože",
|
||||
"něco",
|
||||
|
@ -115,11 +108,9 @@
|
|||
"teď",
|
||||
"mají",
|
||||
"něj",
|
||||
"Co",
|
||||
"nám",
|
||||
"proto",
|
||||
"přes",
|
||||
"Jak",
|
||||
"nich",
|
||||
"již",
|
||||
"jim",
|
||||
|
@ -135,15 +126,12 @@
|
|||
"vám",
|
||||
"sebe",
|
||||
"mít",
|
||||
"Z",
|
||||
"dobře",
|
||||
"ti",
|
||||
"všechny",
|
||||
"nikdy",
|
||||
"I",
|
||||
"vás",
|
||||
"vůbec",
|
||||
"Po",
|
||||
"proti",
|
||||
"jeden",
|
||||
"svou",
|
||||
|
@ -156,13 +144,10 @@
|
|||
"moc",
|
||||
"například",
|
||||
"stále",
|
||||
"Pokud",
|
||||
"pokud",
|
||||
"tady",
|
||||
"Tak",
|
||||
"lidí",
|
||||
"místo",
|
||||
"Já",
|
||||
"S",
|
||||
"svého",
|
||||
"víc",
|
||||
"zase",
|
||||
|
@ -175,14 +160,11 @@
|
|||
"případě",
|
||||
"dnes",
|
||||
"den",
|
||||
"O",
|
||||
"době",
|
||||
"Ve",
|
||||
"dvě",
|
||||
"práce",
|
||||
"mohl",
|
||||
"lze",
|
||||
"pokud",
|
||||
"korun",
|
||||
"mohou",
|
||||
"často",
|
||||
|
@ -198,13 +180,11 @@
|
|||
"vlastní",
|
||||
"život",
|
||||
"ta",
|
||||
"Za",
|
||||
"takže",
|
||||
"člověk",
|
||||
"jde",
|
||||
"dál",
|
||||
"svých",
|
||||
"Pro",
|
||||
"sobě",
|
||||
"ním",
|
||||
"měli",
|
||||
|
@ -212,7 +192,6 @@
|
|||
"on",
|
||||
"taky",
|
||||
"svůj",
|
||||
"li",
|
||||
"děti",
|
||||
"mám",
|
||||
"znovu",
|
||||
|
@ -220,9 +199,7 @@
|
|||
"poslední",
|
||||
"především",
|
||||
"každý",
|
||||
"Už",
|
||||
"příliš",
|
||||
"Podle",
|
||||
"jednou",
|
||||
"možná",
|
||||
"ovšem",
|
||||
|
@ -232,12 +209,9 @@
|
|||
"úplně",
|
||||
"nové",
|
||||
"sebou",
|
||||
"Pak",
|
||||
"jenom",
|
||||
"K",
|
||||
"téměř",
|
||||
"Kč",
|
||||
"Do",
|
||||
"jež",
|
||||
"něm",
|
||||
"čas",
|
||||
|
@ -258,7 +232,6 @@
|
|||
"zcela",
|
||||
"nejen",
|
||||
"těch",
|
||||
"Ne",
|
||||
"života",
|
||||
"později",
|
||||
"tento",
|
||||
|
@ -273,9 +246,7 @@
|
|||
"tohoto",
|
||||
"kdyby",
|
||||
"opravdu",
|
||||
"U",
|
||||
"větší",
|
||||
"Při",
|
||||
"nikdo",
|
||||
"věci",
|
||||
"století",
|
||||
|
@ -283,12 +254,10 @@
|
|||
"světa",
|
||||
"během",
|
||||
"tisíc",
|
||||
"Byl",
|
||||
"celý",
|
||||
"dlouho",
|
||||
"abych",
|
||||
"těchto",
|
||||
"Jeho",
|
||||
"dalších",
|
||||
"tě",
|
||||
"pořád",
|
||||
|
@ -296,7 +265,6 @@
|
|||
"jej",
|
||||
"velké",
|
||||
"někdy",
|
||||
"Jako",
|
||||
"patří",
|
||||
"díky",
|
||||
"nyní",
|
||||
|
@ -308,7 +276,6 @@
|
|||
"rychle",
|
||||
"můžete",
|
||||
"opět",
|
||||
"Ten",
|
||||
"města",
|
||||
"ni",
|
||||
"jinak",
|
||||
|
@ -333,11 +300,8 @@
|
|||
"samozřejmě",
|
||||
"jednoho",
|
||||
"vody",
|
||||
"Bylo",
|
||||
"sem",
|
||||
"Proč",
|
||||
"doby",
|
||||
"Od",
|
||||
"začal",
|
||||
"bychom",
|
||||
"straně",
|
||||
|
@ -348,7 +312,6 @@
|
|||
"ně",
|
||||
"svém",
|
||||
"čtyři",
|
||||
"Ty",
|
||||
"chtěl",
|
||||
"zatím",
|
||||
"vše",
|
||||
|
@ -366,13 +329,12 @@
|
|||
"pět",
|
||||
"nějaké",
|
||||
"ať",
|
||||
"Ano",
|
||||
"ano",
|
||||
"ona",
|
||||
"Teď",
|
||||
"strany",
|
||||
"rád",
|
||||
"domu",
|
||||
"No",
|
||||
"no",
|
||||
"sama",
|
||||
"doma",
|
||||
"mnohem",
|
||||
|
@ -381,7 +343,6 @@
|
|||
"země",
|
||||
"vidět",
|
||||
"např.",
|
||||
"Jen",
|
||||
"máme",
|
||||
"možnost",
|
||||
"méně",
|
||||
|
@ -408,7 +369,6 @@
|
|||
"my",
|
||||
"ruku",
|
||||
"hlavu",
|
||||
"Byla",
|
||||
"skoro",
|
||||
"hlavní",
|
||||
"jehož",
|
||||
|
@ -422,7 +382,6 @@
|
|||
"prý",
|
||||
"večer",
|
||||
"roky",
|
||||
"Možná",
|
||||
"musel",
|
||||
"naopak",
|
||||
"rámci",
|
||||
|
@ -441,8 +400,7 @@
|
|||
"školy",
|
||||
"dveře",
|
||||
"určitě",
|
||||
"České",
|
||||
"Není",
|
||||
"české",
|
||||
"lidi",
|
||||
"mnou",
|
||||
"znamená",
|
||||
|
@ -450,7 +408,6 @@
|
|||
"mimo",
|
||||
"lety",
|
||||
"paní",
|
||||
"Takže",
|
||||
"půl",
|
||||
"ostatní",
|
||||
"svět",
|
||||
|
@ -468,7 +425,7 @@
|
|||
"firmy",
|
||||
"Praze",
|
||||
"jedno",
|
||||
"Jenže",
|
||||
"jenže",
|
||||
"zatímco",
|
||||
"nemůže",
|
||||
"největší",
|
||||
|
@ -476,13 +433,10 @@
|
|||
"alespoň",
|
||||
"nebyla",
|
||||
"místa",
|
||||
"Jsem",
|
||||
"naší",
|
||||
"Proto",
|
||||
"nový",
|
||||
"množství",
|
||||
"žádný",
|
||||
"Ani",
|
||||
"dětí",
|
||||
"situace",
|
||||
"dobré",
|
||||
|
@ -491,14 +445,11 @@
|
|||
"většinou",
|
||||
"zařízení",
|
||||
"mělo",
|
||||
"Ještě",
|
||||
"poprvé",
|
||||
"přišel",
|
||||
"budu",
|
||||
"malé",
|
||||
"tato",
|
||||
"Ta",
|
||||
"české",
|
||||
"jít",
|
||||
"jich",
|
||||
"udělat",
|
||||
|
@ -540,9 +491,7 @@
|
|||
"situaci",
|
||||
"mé",
|
||||
"mnoha",
|
||||
"Jsou",
|
||||
"řízení",
|
||||
"První",
|
||||
"druhou",
|
||||
"Jan",
|
||||
"jenž",
|
||||
|
@ -550,9 +499,7 @@
|
|||
"jiný",
|
||||
"ČR",
|
||||
"spíš",
|
||||
"Kdo",
|
||||
"muže",
|
||||
"Protože",
|
||||
"budeme",
|
||||
"máte",
|
||||
"zeptal",
|
||||
|
@ -576,7 +523,6 @@
|
|||
"problémy",
|
||||
"viděl",
|
||||
"přesto",
|
||||
"ano",
|
||||
"oba",
|
||||
"dům",
|
||||
"stavu",
|
||||
|
@ -591,20 +537,16 @@
|
|||
"kterých",
|
||||
"hlas",
|
||||
"počet",
|
||||
"Mám",
|
||||
"došlo",
|
||||
"začátku",
|
||||
"pomalu",
|
||||
"Před",
|
||||
"m",
|
||||
"Tento",
|
||||
"prostor",
|
||||
"vlasy",
|
||||
"obvykle",
|
||||
"prvním",
|
||||
"velice",
|
||||
"srdce",
|
||||
"Další",
|
||||
"skupiny",
|
||||
"velkou",
|
||||
"tělo",
|
||||
|
@ -619,14 +561,11 @@
|
|||
"postupně",
|
||||
"dříve",
|
||||
"docela",
|
||||
"Kromě",
|
||||
"dny",
|
||||
"ulici",
|
||||
"trhu",
|
||||
"konce",
|
||||
"Až",
|
||||
"podařilo",
|
||||
"Že",
|
||||
"slovo",
|
||||
"jasné",
|
||||
"každé",
|
||||
|
@ -647,27 +586,22 @@
|
|||
"dolů",
|
||||
"šest",
|
||||
"jejím",
|
||||
"Její",
|
||||
"naprosto",
|
||||
"metrů",
|
||||
"domácí",
|
||||
"věcí",
|
||||
"abychom",
|
||||
"základě",
|
||||
"Měl",
|
||||
"Právě",
|
||||
"občas",
|
||||
"sociální",
|
||||
"nutné",
|
||||
"území",
|
||||
"ven",
|
||||
"Nebo",
|
||||
"nohy",
|
||||
"zájem",
|
||||
"dát",
|
||||
"hrát",
|
||||
"věku",
|
||||
"Má",
|
||||
"různé",
|
||||
"tvoří",
|
||||
"pravdu",
|
||||
|
@ -681,9 +615,6 @@
|
|||
"takhle",
|
||||
"způsob",
|
||||
"myslím",
|
||||
"Myslím",
|
||||
"Dnes",
|
||||
"Mezi",
|
||||
"cesty",
|
||||
"menší",
|
||||
"ví",
|
||||
|
@ -717,9 +648,7 @@
|
|||
"projektu",
|
||||
"umění",
|
||||
"muset",
|
||||
"Tato",
|
||||
"aspoň",
|
||||
"Díky",
|
||||
"přijde",
|
||||
"náš",
|
||||
"čeká",
|
||||
|
@ -768,7 +697,6 @@
|
|||
"městě",
|
||||
"dřív",
|
||||
"štěstí",
|
||||
"Jejich",
|
||||
"vzduchu",
|
||||
"dělá",
|
||||
"vede",
|
||||
|
@ -779,15 +707,12 @@
|
|||
"moci",
|
||||
"věděl",
|
||||
"aniž",
|
||||
"Každý",
|
||||
"musíme",
|
||||
"Navíc",
|
||||
"zvláštní",
|
||||
"mého",
|
||||
"snadno",
|
||||
"cestě",
|
||||
"dvacet",
|
||||
"Také",
|
||||
"policie",
|
||||
"dlouhé",
|
||||
"šlo",
|
||||
|
@ -806,30 +731,22 @@
|
|||
"přišla",
|
||||
"podobě",
|
||||
"vztah",
|
||||
"Tohle",
|
||||
"střední",
|
||||
"informací",
|
||||
"Kdyby",
|
||||
"starší",
|
||||
"dávno",
|
||||
"auta",
|
||||
"Jde",
|
||||
"Všichni",
|
||||
"Jestli",
|
||||
"strach",
|
||||
"začíná",
|
||||
"vrátil",
|
||||
"Nic",
|
||||
"průběhu",
|
||||
"zákona",
|
||||
"všeho",
|
||||
"jejího",
|
||||
"Zatímco",
|
||||
"svému",
|
||||
"ředitel",
|
||||
"možnosti",
|
||||
"konec",
|
||||
"Stejně",
|
||||
"začne",
|
||||
"udělal",
|
||||
"pěti",
|
||||
|
@ -864,7 +781,6 @@
|
|||
"Evropě",
|
||||
"program",
|
||||
"minulosti",
|
||||
"Nikdy",
|
||||
"činnosti",
|
||||
"uvnitř",
|
||||
"taková",
|
||||
|
@ -881,7 +797,6 @@
|
|||
"těžké",
|
||||
"státu",
|
||||
"výsledky",
|
||||
"Asi",
|
||||
"staré",
|
||||
"republiky",
|
||||
"kdysi",
|
||||
|
@ -892,7 +807,6 @@
|
|||
"očí",
|
||||
"finanční",
|
||||
"představuje",
|
||||
"Nakonec",
|
||||
"dodal",
|
||||
"utkání",
|
||||
"myslí",
|
||||
|
@ -904,10 +818,8 @@
|
|||
"Jana",
|
||||
"každého",
|
||||
"představit",
|
||||
"My",
|
||||
"radost",
|
||||
"buď",
|
||||
"Tady",
|
||||
"chtějí",
|
||||
"potřeba",
|
||||
"jaký",
|
||||
|
@ -915,9 +827,7 @@
|
|||
"měsíců",
|
||||
"druhého",
|
||||
"měsíce",
|
||||
"Přesto",
|
||||
"uprostřed",
|
||||
"Samozřejmě",
|
||||
"podmínky",
|
||||
"žen",
|
||||
"prostřednictvím",
|
||||
|
@ -946,28 +856,21 @@
|
|||
"jedná",
|
||||
"stala",
|
||||
"takovou",
|
||||
"Potom",
|
||||
"děje",
|
||||
"náměstí",
|
||||
"špatně",
|
||||
"auto",
|
||||
"prohlásil",
|
||||
"Tím",
|
||||
"jasně",
|
||||
"On",
|
||||
"zdraví",
|
||||
"čem",
|
||||
"anebo",
|
||||
"Například",
|
||||
"Jeden",
|
||||
"pokoje",
|
||||
"dostala",
|
||||
"podstatě",
|
||||
"Tam",
|
||||
"stran",
|
||||
"nemocnice",
|
||||
"bys",
|
||||
"Ze",
|
||||
"miliardy",
|
||||
"Pavel",
|
||||
"otázku",
|
||||
|
@ -995,9 +898,7 @@
|
|||
"sedm",
|
||||
"rozhodl",
|
||||
"nejde",
|
||||
"Během",
|
||||
"vliv",
|
||||
"Jo",
|
||||
"světla",
|
||||
"č.",
|
||||
"přičemž",
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<div class="logo">
|
||||
<div class="top">monkey see</div>
|
||||
<div class="bottom">
|
||||
monkeytype
|
||||
<a href="/ " style="text-decoration:none; color:inherit;">monkeytype</a>
|
||||
<span style="color: var(--text-color)">Privacy Policy</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,41 +1,29 @@
|
|||
{
|
||||
"language": "english",
|
||||
"groups": [
|
||||
[
|
||||
0,
|
||||
100
|
||||
],
|
||||
[
|
||||
101,
|
||||
300
|
||||
],
|
||||
[
|
||||
301,
|
||||
600
|
||||
],
|
||||
[
|
||||
601,
|
||||
9999
|
||||
]
|
||||
[0, 100],
|
||||
[101, 300],
|
||||
[301, 600],
|
||||
[601, 9999]
|
||||
],
|
||||
"quotes": [
|
||||
{
|
||||
"text": "You have the power to heal your life, and you need to know that.",
|
||||
"source": "Meditations to Heal Your Life",
|
||||
"id": 1,
|
||||
"length": 64
|
||||
"length": 64,
|
||||
"id": 1
|
||||
},
|
||||
{
|
||||
"text": "They don't know that we know they know we know.",
|
||||
"source": "Friends",
|
||||
"id": 2,
|
||||
"length": 47
|
||||
"length": 47,
|
||||
"id": 2
|
||||
},
|
||||
{
|
||||
"text": "Don't it make you sad to know that life is more than who you are?",
|
||||
"source": "Name",
|
||||
"id": 3,
|
||||
"length": 65
|
||||
"length": 65,
|
||||
"id": 3
|
||||
},
|
||||
{
|
||||
"text": "Leave something for someone but don't leave someone for something.",
|
||||
|
@ -29780,7 +29768,7 @@
|
|||
"length": 309
|
||||
},
|
||||
{
|
||||
"text": "All depression has its roots in self-pity, and all self-pity is rooted in people taking themselves too seriously. At the time Switters had disputed her assertion. Even at seventeen, he was aware that depression could have chemical causes. The key word here is roots, Maestra had countered. The roots of depression. For most people, self-awareness and self-pity blossom simultaneously in early adolescence. It's about that time that we start viewing the world as something other than a whoop-de-doo playground, we start to experience personally how threatening it can be, how cruel and unjust. At the very moment when we become, for the first time, both introspective and socially conscientious, we receive the bad news that the world, by and large, doesn't give a rat's ass. Even an old tomato like me can recall how painful, scary, and disillusioning that realization was. So, there's a tendency, then, to slip into rage and self-pity, which if indulged, can fester into bouts of depression. Yeah but Maestra-. Don't interrupt. Now, unless someone stronger and wiser - a friend, a parent, a novelist, filmmaker, teacher, or musician - can josh us out of it, can elevate us and show us how petty and pompous and monumentally useless it is to take ourselves so seriously, then depression can become a habit, which, in tern, can produce a neurological imprint. Are you with me? Gradually, our brain chemistry becomes conditioned to react to negative stimuli in a particular, predictable way. One thing'll go wrong and it'll automatically switch on its blender and mix us that black cocktail, the ol' doomsday daiquiri, and before we know it, we're soused to the gills from the inside out. Once depression has become electrochemically integrated, it can be extremely difficult to philosophically or psychologically override it; by then it's playing by physical rules, a whole different ball game. That's why, Switters my dearest, every time you've shown signs of feeling sorry for yourself, I've played my blues records really loud or read to you from The Horse's Mouth. And that's why when you've exhibited the slightest tendency toward self-importance, I've reminded you that you and me - you and I: excuse me - may be every bit as important as the President or the pope or the biggest prime-time icon in Hollywood, but none of us is much more than a pimple on the ass-end of creation, so let's not get carried away with ourselves. Preventive medicine, boy. It's preventive medicine. But what about self-esteem? Heh! Self-esteem is for sissies. Accept that you're a pimple and try to keep a lively sense of humor about it. That way lies grace-and maybe even glory.",
|
||||
"text": "All depression has its roots in self-pity, and all self-pity is rooted in people taking themselves too seriously. At the time Switters had disputed her assertion. Even at seventeen, he was aware that depression could have chemical causes. The key word here is roots, Maestra had countered. The roots of depression. For most people, self-awareness and self-pity blossom simultaneously in early adolescence. It's about that time that we start viewing the world as something other than a whoop-de-doo playground, we start to experience personally how threatening it can be, how cruel and unjust. At the very moment when we become, for the first time, both introspective and socially conscientious, we receive the bad news that the world, by and large, doesn't give a rat's ass. Even an old tomato like me can recall how painful, scary, and disillusioning that realization was. So, there's a tendency, then, to slip into rage and self-pity, which if indulged, can fester into bouts of depression. Yeah but Maestra-. Don't interrupt. Now, unless someone stronger and wiser - a friend, a parent, a novelist, filmmaker, teacher, or musician - can josh us out of it, can elevate us and show us how petty and pompous and monumentally useless it is to take ourselves so seriously, then depression can become a habit, which, in turn, can produce a neurological imprint. Are you with me? Gradually, our brain chemistry becomes conditioned to react to negative stimuli in a particular, predictable way. One thing'll go wrong and it'll automatically switch on its blender and mix us that black cocktail, the ol' doomsday daiquiri, and before we know it, we're soused to the gills from the inside out. Once depression has become electrochemically integrated, it can be extremely difficult to philosophically or psychologically override it; by then it's playing by physical rules, a whole different ball game. That's why, Switters my dearest, every time you've shown signs of feeling sorry for yourself, I've played my blues records really loud or read to you from The Horse's Mouth. And that's why when you've exhibited the slightest tendency toward self-importance, I've reminded you that you and me - you and I: excuse me - may be every bit as important as the President or the pope or the biggest prime-time icon in Hollywood, but none of us is much more than a pimple on the ass-end of creation, so let's not get carried away with ourselves. Preventive medicine, boy. It's preventive medicine. But what about self-esteem? Heh! Self-esteem is for sissies. Accept that you're a pimple and try to keep a lively sense of humor about it. That way lies grace-and maybe even glory.",
|
||||
"source": "Fierce Invalids Home from Hot Climates",
|
||||
"id": 5013,
|
||||
"length": 2663
|
||||
|
@ -30112,32 +30100,32 @@
|
|||
{
|
||||
"text": "NO ADMITTANCE. NOT EVEN TO AUTHORIZED PERSONNEL. YOU ARE WASTING YOUR TIME HERE. GO AWAY.",
|
||||
"source": "Mostly Harmless",
|
||||
"id": 5068,
|
||||
"length": 89
|
||||
"length": 89,
|
||||
"id": 5068
|
||||
},
|
||||
{
|
||||
"text": "He had a nasty feeling that that might be an idiotic thing to do, but he did it anyway, and sure enough it had turned out to be an idiotic thing to do. You live and learn. At any rate, you live.",
|
||||
"source": "Mostly Harmless",
|
||||
"id": 5069,
|
||||
"length": 194
|
||||
"length": 194,
|
||||
"id": 5069
|
||||
},
|
||||
{
|
||||
"text": "Fall, though, is the worst. Few things are worse than fall in New York, Some of the things that live in the lower intestines of rats would disagree, but most of the things that live in the lower intestines of rats are highly disagreeable anyways, so their opinion can and should be discounted.",
|
||||
"source": "Mostly Harmless",
|
||||
"id": 5070,
|
||||
"length": 293
|
||||
"length": 293,
|
||||
"id": 5070
|
||||
},
|
||||
{
|
||||
"text": "Every single decision we make, every breath we draw, opens some doors and closes many others. Most of them we don't nonce, Some we do.",
|
||||
"source": "Mostly Harmless",
|
||||
"id": 5071,
|
||||
"length": 134
|
||||
"length": 134,
|
||||
"id": 5071
|
||||
},
|
||||
{
|
||||
"text": "At every level, vital instructions were missing, and the instructions about what to do in the event of discovering that vital instructions were missing, were also missing.",
|
||||
"source": "Mostly Harmless",
|
||||
"id": 5072,
|
||||
"length": 171
|
||||
"length": 171,
|
||||
"id": 5072
|
||||
},
|
||||
{
|
||||
"text": "If you set your goals ridiculously high and it's a failure, you will fail above everyone else's success.",
|
||||
|
@ -32384,16 +32372,242 @@
|
|||
"id": 5446
|
||||
},
|
||||
{
|
||||
"text": "My intent, here, is to tell our story in a dramatically truthful way. While the facts may be less than accurate, please understand that the emotion is true. The intent is true. And, dramatically speaking, intention is everything.",
|
||||
"source": "Enzo, The Art of Racing in the Rain (Garth Stein)",
|
||||
"length": 229,
|
||||
"text": "Do not pity the dead, Harry. Pity the living, and, above all those who live without love.",
|
||||
"source": "Albus Dumbledore",
|
||||
"length": 89,
|
||||
"id": 5447
|
||||
},
|
||||
{
|
||||
"text": "A winner, a champion, will accept his fate. He will continue with his wheels in the dirt. He will do his best to maintain his line and gradually get himself back on the track when it is safe to do so. Yes, he loses a few places in the race. Yes, he is at a disadvantage. But he is still racing. He is still alive.",
|
||||
"source": "The Art of Racing in the Rain (Garth Stein)",
|
||||
"length": 313,
|
||||
"text": "It does not do well to dwell on dreams and forget to live.",
|
||||
"source": "Albus Dumbledore",
|
||||
"length": 58,
|
||||
"id": 5448
|
||||
},
|
||||
{
|
||||
"text": "Have you ever had a dream, Neo, that you seemed so sure it was real? But if were unable to wake up from that dream, how would you tell the difference between the dream world & the real world?",
|
||||
"source": "The Matrix",
|
||||
"length": 191,
|
||||
"id": 5449
|
||||
},
|
||||
{
|
||||
"text": "If real is what you can feel, smell, taste and see, then 'real' is simply electrical signals interpreted by your brain.",
|
||||
"source": "The Matrix",
|
||||
"length": 119,
|
||||
"id": 5450
|
||||
},
|
||||
{
|
||||
"text": "If you ain’t scared… you ain’t human.",
|
||||
"source": "Alby, The Maze Runner",
|
||||
"length": 37,
|
||||
"id": 5451
|
||||
},
|
||||
{
|
||||
"text": "It's kind of hard to ask a dead guy what he did wrong.",
|
||||
"source": "Minho, The Maze Runner",
|
||||
"length": 54,
|
||||
"id": 5452
|
||||
},
|
||||
{
|
||||
"text": "I promised I'd save him, take him home! I promised him!",
|
||||
"source": "Thomas, The Maze Runner",
|
||||
"length": 55,
|
||||
"id": 5453
|
||||
},
|
||||
{
|
||||
"text": "Good that.",
|
||||
"source": "Newt, The Maze Runner",
|
||||
"length": 10,
|
||||
"id": 5454
|
||||
},
|
||||
{
|
||||
"text": "Maybe you should just press the button",
|
||||
"source": "The Maze Runner",
|
||||
"length": "38",
|
||||
"id": 5455
|
||||
},
|
||||
{
|
||||
"text": "I just...feel like I need to save everyone. To redeem myself.",
|
||||
"source": "Thomas, The Maze Runner",
|
||||
"length": 61,
|
||||
"id": 5456
|
||||
},
|
||||
{
|
||||
"text": "People who live in glass houses should shut the f*** up.",
|
||||
"source": "Anorak's Almanac, Ready Player One",
|
||||
"length": 56,
|
||||
"id": 5457
|
||||
},
|
||||
{
|
||||
"text": "Going outside is highly overrated.",
|
||||
"source": "Anorak's Almanac, Ready Player One",
|
||||
"length": 34,
|
||||
"id": 5458
|
||||
},
|
||||
{
|
||||
"text": "No one in the world gets what they want and that is beautiful",
|
||||
"source": "Ready Player One",
|
||||
"length": 61,
|
||||
"id": 5459
|
||||
},
|
||||
{
|
||||
"text": "You'd be amazed how much research you can get done when you have no life whatsoever",
|
||||
"source": "Wade Watts, Ready Player One",
|
||||
"length": 83,
|
||||
"id": 5460
|
||||
},
|
||||
{
|
||||
"text": "Being human totally sucks most of the time. Videogames are the only thing that make life bearable.",
|
||||
"source": "Anorak's Almanac, Ready Player One",
|
||||
"length": 98,
|
||||
"id": 5461
|
||||
},
|
||||
{
|
||||
"text": "You're probably wondering what's going to happen to you. That's easy. The same thing is going to happen to you that has happened to every other human being who has ever lived. You're going to die. We all die. That's just how it is.",
|
||||
"source": "Ready Player One",
|
||||
"length": 231,
|
||||
"id": 5462
|
||||
},
|
||||
{
|
||||
"text": "For a bunch of hair-less apes, we've actually managed to invent some pretty incredible things.",
|
||||
"source": "Ready Player One",
|
||||
"length": 94,
|
||||
"id": 5463
|
||||
},
|
||||
{
|
||||
"text": "I was watching a collection of vintage '80s cereal commercials when I paused to wonder why cereal manufacturers no longer included toy prizes inside every box. It was a tradegy, in my opinion. Another sign that civilization was going straight down the tubes.",
|
||||
"source": "Wade Watts, Ready Player One",
|
||||
"length": 258,
|
||||
"id": 5464
|
||||
},
|
||||
{
|
||||
"text": "My friend Kira always said that life is like an extremely difficult, horribly unbalanced videogame. When you’re born, you’re given a randomly generated character, with a randomly determined name, race, face, and social class. Your body is your avatar, and you spawn in a random geographic location, at a random moment in human history, surrounded by a random group of people, and then you have to try to survive for as long as you can. Sometimes the game might seem easy. Even fun. Other times it might be so difficult you want to give up and quit. But unfortunately, in this game you only get one life. When your body grows too hungry or thirsty or ill or injured or old, your health meter runs out and then it’s Game Over. Some people play the game for a hundred years without ever figuring out that it’s a game, or that there is a way to win it. To win the videogame of life you just have to try to make the experience of being forced to play it as pleasant as possible, for yourself, and for all of the other players you encounter in your travels. Kira says that if everyone played the game to win, it’d be a lot more fun for everyone.",
|
||||
"source": "Anorak's Almanac, Ready Player Two",
|
||||
"length": 1139,
|
||||
"id": 5465
|
||||
},
|
||||
{
|
||||
"text": "Human beings were never meant to participate in a worldwide social network comprised of billions of people. We were designed by evolution to be hunter-gatherers, with the mental capacity to interact and socialize with the other members of our tribe—a tribe made up of a few hundred other people at most. Interacting with thousands or even millions of other people on a daily basis was way too much for our ape-descended melons to handle. That was why social media had been gradually driving the entire population of the world insane since it emerged back around the turn of the century.",
|
||||
"source": "Ready Player Two",
|
||||
"length": 586,
|
||||
"id": 5466
|
||||
},
|
||||
{
|
||||
"text": "Everybody wants to rule the world.",
|
||||
"source": "Wade Watts, Ready Player Two",
|
||||
"length": 34,
|
||||
"id": 5467
|
||||
},
|
||||
{
|
||||
"text": "How the f*** do you negotiate with a piece of software?",
|
||||
"source": "Wade Watts, Ready Player Two",
|
||||
"length": 55,
|
||||
"id": 5468
|
||||
},
|
||||
{
|
||||
"text": "The world’s population was fast approaching ten billion people, and Mother Earth was making it abundantly clear that she could no longer sustain all of us",
|
||||
"source": "Wade Watts, Ready Player Two",
|
||||
"length": 154,
|
||||
"id": 5469
|
||||
},
|
||||
{
|
||||
"text": "You get tough like me and you don't get hurt. You look out for yourself and nothin' can touch you...",
|
||||
"source": "Dally, The Outsiders",
|
||||
"length": 100,
|
||||
"id": 5470
|
||||
},
|
||||
{
|
||||
"text": "Things are rough all over.",
|
||||
"source": "Cherry, The Outsiders"
|
||||
},
|
||||
{
|
||||
"text": "I am a greaser. I am a JD and a hood. I blacken the name of our fair city. I beat up people. I rob gas stations. I am a manace to society. Man do I have fun!",
|
||||
"source": "The Outsiders",
|
||||
"length": 157,
|
||||
"id": 5471
|
||||
},
|
||||
{
|
||||
"text": "You still have a lot of time to make yourself be what you want. There's still lots of good in the world. Tell Dally. I don't think he knows.",
|
||||
"source": "Johnny, The Outsiders",
|
||||
"length": 140,
|
||||
"id": 5472
|
||||
},
|
||||
{
|
||||
"text": "Happy Hunger Games! And may the odds be in your favor.",
|
||||
"source": "The Hunger Games",
|
||||
"length": 54,
|
||||
"id": 5473
|
||||
},
|
||||
{
|
||||
"text": "Destroying things is much easier than making them.",
|
||||
"source": "The Hunger Games",
|
||||
"length": 50,
|
||||
"id": 5474
|
||||
},
|
||||
{
|
||||
"text": "You have only one life, make the most of it.",
|
||||
"source": "Holes",
|
||||
"length": 44,
|
||||
"id": 5475
|
||||
},
|
||||
{
|
||||
"text": "Nothing in life is easy, but that's no reason to give up. You'll be surprised what you can accomplish when you set your mind to it.",
|
||||
"source": "Holes",
|
||||
"length": 131,
|
||||
"id": 5476
|
||||
},
|
||||
{
|
||||
"text": "You may have done some bad things, but that doesn't mean you're a bad kid",
|
||||
"source": "Holes",
|
||||
"length": 73,
|
||||
"id": 5477
|
||||
},
|
||||
{
|
||||
"text": "Don't ask for guarantees. And don't look to be saved in any one thing, person, machine, or library. Do your own bit of saving, and if you drown, at least die knowing you where heading for shore.",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 192,
|
||||
"id": 5478
|
||||
},
|
||||
{
|
||||
"text": "I still love books. Nothing a computer can do can compare to a book. You can't really put a book on the Internet. Three companies have offered to put books by me on the Net, and I said, 'If you can make something that has a nice jacket, nice paper with that nice smell, then we'll talk.' All the computer can give you is a manuscript. People don't want to read manuscripts. They want to read books. Books smell good. They look good. You can press it to your bosom. You can carry it in your pocket.",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 497,
|
||||
"id": 5479
|
||||
},
|
||||
{
|
||||
"text": "It was a pleasure to burn.",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 26,
|
||||
"id": 4580
|
||||
},
|
||||
{
|
||||
"text": "I don't talk things, Sir. I talk the meaning of things.",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 55,
|
||||
"id": 5481
|
||||
},
|
||||
{
|
||||
"text": "Our civilization is flinging itself to pieces. Stand back from the centrifuge",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 77,
|
||||
"id": 5482
|
||||
},
|
||||
{
|
||||
"text": "Live as if you'd drop dead in ten seconds.",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 42,
|
||||
"id": 5483
|
||||
},
|
||||
{
|
||||
"text": "Have you ever watched the jet cars race on the boulevard?...I sometimes think drivers don’t know what grass is, or flowers, because they never see them slowly...If you showed a driver a green blur, Oh yes! He'd say, that’s grass! A pink blur! That’s a rose garden! White blurs are houses. Brown blurs are cows.",
|
||||
"source": "Fahrenheit 451",
|
||||
"length": 310,
|
||||
"id": 5484
|
||||
},
|
||||
{
|
||||
"text": "My father picked me up from school one day and we played hookey and went to the beach. It was too cold to go in the water so we sat on a blanket and ate pizza. When I got home my sneakers were full of sand and I dumped it on my bedroom floor. I didn't know the difference, I was six. My mother screamed at me for the mess but he wasn't mad. He said that billions of years ago the world 's shifting and ocean moving brought that sand to that spot on the beach and then I took it away. Every day he said we change the world. Which is a nice thought until I think about how many days and lifetimes I would need to bring a shoe full of sand home until there is no beach. Until it made a difference to anyone. Every day we change the world. But to change the world in a way that means anything that takes more time than most people have. it never happens all at once. Its slow. Its methodical. Its exhausting. We don't all have the stomach for it.",
|
||||
"source": "Mr. Robot",
|
||||
"length": 942,
|
||||
"id": 5485
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,10 @@
|
|||
{
|
||||
"language": "german",
|
||||
"groups": [
|
||||
[
|
||||
0,
|
||||
100
|
||||
],
|
||||
[
|
||||
101,
|
||||
300
|
||||
],
|
||||
[
|
||||
301,
|
||||
600
|
||||
],
|
||||
[
|
||||
601,
|
||||
9999
|
||||
]
|
||||
[0, 100],
|
||||
[101, 300],
|
||||
[301, 600],
|
||||
[601, 9999]
|
||||
],
|
||||
"quotes": [
|
||||
{
|
||||
|
@ -320,7 +308,7 @@
|
|||
"id": 50
|
||||
},
|
||||
{
|
||||
"text": "Das schauerlichste Übel also, der Tod, geht uns nichts an; denn solange wir existieren, ist der Tod nicht da, und wenn der Tod da ist, existieren wir nicht mehr.",
|
||||
"text": "Das schauerlichste Übel, also der Tod, geht uns nichts an; denn solange wir existieren, ist der Tod nicht da, und wenn der Tod da ist, existieren wir nicht mehr.",
|
||||
"source": "Epikur",
|
||||
"length": 161,
|
||||
"id": 51
|
||||
|
@ -722,4 +710,4 @@
|
|||
"id": 117
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
BIN
static/sound/click4/click4_11.wav
Normal file
BIN
static/sound/click4/click4_22.wav
Normal file
BIN
static/sound/click4/click4_33.wav
Normal file
BIN
static/sound/click4/click4_44.wav
Normal file
BIN
static/sound/click4/click4_55.wav
Normal file
BIN
static/sound/click4/click4_66.wav
Normal file
|
@ -4,6 +4,11 @@
|
|||
"bgColor": "#111",
|
||||
"textColor": "#eee"
|
||||
},
|
||||
{
|
||||
"name": "muted",
|
||||
"bgColor": "#525252",
|
||||
"textColor": "#B1E4E3"
|
||||
},
|
||||
{
|
||||
"name": "dark_magic_girl",
|
||||
"bgColor": "#091f2c",
|
||||
|
@ -69,6 +74,11 @@
|
|||
"bgColor": "#0f1f2c",
|
||||
"textColor": "#56c3b7"
|
||||
},
|
||||
{
|
||||
"name": "mountain",
|
||||
"bgColor": "#0f0f0f",
|
||||
"textColor": "#e7e7e7"
|
||||
},
|
||||
{
|
||||
"name": "laser",
|
||||
"bgColor": "#221b44",
|
||||
|
|
11
static/themes/mountain.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
:root {
|
||||
--bg-color: #0f0f0f;
|
||||
--main-color: #e7e7e7;
|
||||
--caret-color: #f5f5f5;
|
||||
--sub-color: #4c4c4c;
|
||||
--text-color: #e7e7e7;
|
||||
--error-color: #ac8c8c;
|
||||
--error-extra-color: #c49ea0;
|
||||
--colorful-error-color: #aca98a;
|
||||
--colorful-error-extra-color: #c4c19e;
|
||||
}
|
8
static/themes/muted.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
:root {
|
||||
--bg-color: #525252;
|
||||
--main-color: #C5B4E3;
|
||||
--caret-color: #B1E4E3;
|
||||
--sub-color: #939eae;
|
||||
--text-color: #B1E4E3;
|
||||
--error-color: #EDC1CD;
|
||||
}
|