mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-02-03 04:19:06 +08:00
Add Custom Text Storage (#2648) by Fero
* Add custom text * changed function return type * added popups for saving and deleting saved texts * moved saved texts to their own file logic changes styling changes Co-authored-by: Miodec <bartnikjack@gmail.com>
This commit is contained in:
parent
965482959d
commit
1622f37efd
6 changed files with 254 additions and 21 deletions
|
@ -6,6 +6,7 @@ import Config, * as UpdateConfig from "../config";
|
|||
import * as Misc from "../misc";
|
||||
import * as WordFilterPopup from "./word-filter-popup";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
import * as SavedTextsPopup from "./saved-texts-popup";
|
||||
|
||||
const wrapper = "#customTextPopupWrapper";
|
||||
const popup = "#customTextPopup";
|
||||
|
@ -107,8 +108,16 @@ $(`${popup} .randomInputFields .time input`).keypress(() => {
|
|||
$(`${popup} .randomInputFields .wordcount input`).val("");
|
||||
});
|
||||
|
||||
$("#customTextPopup .apply").click(() => {
|
||||
let text = ($("#customTextPopup textarea").val() as string).normalize();
|
||||
$(`${popup} .buttonsTop .showSavedTexts`).on("click", () => {
|
||||
SavedTextsPopup.show();
|
||||
});
|
||||
|
||||
$(`${popup} .buttonsTop .saveCustomText`).on("click", () => {
|
||||
hide();
|
||||
});
|
||||
|
||||
function apply(): void {
|
||||
let text = ($(`${popup} textarea`).val() as string).normalize();
|
||||
text = text.trim();
|
||||
// text = text.replace(/[\r]/gm, " ");
|
||||
text = text.replace(/\\\\t/gm, "\t");
|
||||
|
@ -120,26 +129,20 @@ $("#customTextPopup .apply").click(() => {
|
|||
// text = text.replace(/(\n)+/g, "\n");
|
||||
// text = text.replace(/(\r)+/g, "\r");
|
||||
text = text.replace(/( *(\r\n|\r|\n) *)/g, "\n ");
|
||||
if ($("#customTextPopup .typographyCheck input").prop("checked")) {
|
||||
if ($(`${popup} .typographyCheck input`).prop("checked")) {
|
||||
text = Misc.cleanTypographySymbols(text);
|
||||
}
|
||||
// text = Misc.remove_non_ascii(text);
|
||||
text = text.replace(/[\u2060]/g, "");
|
||||
CustomText.setText(text.split(CustomText.delimiter));
|
||||
CustomText.setWord(
|
||||
parseInt($("#customTextPopup .wordcount input").val() as string)
|
||||
);
|
||||
CustomText.setTime(
|
||||
parseInt($("#customTextPopup .time input").val() as string)
|
||||
);
|
||||
CustomText.setWord(parseInt($(`${popup} .wordcount input`).val() as string));
|
||||
CustomText.setTime(parseInt($(`${popup} .time input`).val() as string));
|
||||
|
||||
CustomText.setIsWordRandom(
|
||||
$("#customTextPopup .checkbox input").prop("checked") &&
|
||||
!isNaN(CustomText.word)
|
||||
$(`${popup} .checkbox input`).prop("checked") && !isNaN(CustomText.word)
|
||||
);
|
||||
CustomText.setIsTimeRandom(
|
||||
$("#customTextPopup .checkbox input").prop("checked") &&
|
||||
!isNaN(CustomText.time)
|
||||
$(`${popup} .checkbox input`).prop("checked") && !isNaN(CustomText.time)
|
||||
);
|
||||
|
||||
if (
|
||||
|
@ -184,9 +187,13 @@ $("#customTextPopup .apply").click(() => {
|
|||
if (Config.mode !== "custom") UpdateConfig.setMode("custom");
|
||||
TestLogic.restart();
|
||||
hide();
|
||||
}
|
||||
|
||||
$(document).on("click", `${popup} .button.apply`, () => {
|
||||
apply();
|
||||
});
|
||||
|
||||
$("#customTextPopup .wordfilter").click(() => {
|
||||
$(document).on("click", `${popup} .wordfilter`, () => {
|
||||
WordFilterPopup.show();
|
||||
});
|
||||
|
||||
|
|
56
frontend/src/scripts/popups/saved-texts-popup.ts
Normal file
56
frontend/src/scripts/popups/saved-texts-popup.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import * as CustomText from "../test/custom-text";
|
||||
|
||||
export async function show(): Promise<void> {
|
||||
const names = CustomText.getCustomTextNames();
|
||||
const listEl = $(`#savedTextsPopup .list`).empty();
|
||||
let list = "";
|
||||
if (names.length === 0) {
|
||||
list += "<div>No saved custom texts found</div>";
|
||||
} else {
|
||||
for (const name of names) {
|
||||
list += `<div class="savedText">
|
||||
<div class="button name">${name}</div>
|
||||
<div class="button delete">
|
||||
<i class="fas fa-fw fa-trash"></i>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
listEl.html(list);
|
||||
$("#savedTextsPopupWrapper").removeClass("hidden");
|
||||
$("#customTextPopupWrapper").addClass("hidden");
|
||||
}
|
||||
|
||||
function hide(full = false): void {
|
||||
$("#savedTextsPopupWrapper").addClass("hidden");
|
||||
if (!full) $("#customTextPopupWrapper").removeClass("hidden");
|
||||
}
|
||||
|
||||
function applySaved(name: string): void {
|
||||
const text = CustomText.getCustomText(name);
|
||||
$(`#customTextPopupWrapper textarea`).val(text.join(CustomText.delimiter));
|
||||
}
|
||||
|
||||
$(document).on(
|
||||
"click",
|
||||
`#savedTextsPopupWrapper .list .savedText .button.name`,
|
||||
(e) => {
|
||||
const name = $(e.target).text();
|
||||
applySaved(name);
|
||||
hide();
|
||||
}
|
||||
);
|
||||
|
||||
$(document).on(
|
||||
"click",
|
||||
`#savedTextsPopupWrapper .list .savedText .button.delete`,
|
||||
() => {
|
||||
hide(true);
|
||||
}
|
||||
);
|
||||
|
||||
$("#savedTextsPopupWrapper").mousedown((e) => {
|
||||
if ($(e.target).attr("id") === "savedTextsPopupWrapper") {
|
||||
hide();
|
||||
}
|
||||
});
|
|
@ -7,6 +7,9 @@ import * as Loader from "../elements/loader";
|
|||
import * as Notifications from "../elements/notifications";
|
||||
import * as Settings from "../pages/settings";
|
||||
import * as ApeKeysPopup from "../popups/ape-keys-popup";
|
||||
import * as CustomText from "../test/custom-text";
|
||||
import * as CustomTextPopup from "../popups/custom-text-popup";
|
||||
import * as SavedTextsPopup from "./saved-texts-popup";
|
||||
|
||||
type Input = {
|
||||
placeholder: string;
|
||||
|
@ -885,6 +888,52 @@ list["editApeKey"] = new SimplePopup(
|
|||
}
|
||||
);
|
||||
|
||||
list["saveCustomText"] = new SimplePopup(
|
||||
"saveCustomText",
|
||||
"text",
|
||||
"Save custom text",
|
||||
[
|
||||
{
|
||||
placeholder: "Name",
|
||||
initVal: "",
|
||||
},
|
||||
],
|
||||
"",
|
||||
"Save",
|
||||
(_thisPopup, input) => {
|
||||
const text = ($(`#customTextPopup textarea`).val() as string).normalize();
|
||||
CustomText.setCustomText(input, text);
|
||||
Notifications.add("Custom text saved", 1);
|
||||
CustomTextPopup.show();
|
||||
},
|
||||
() => {
|
||||
//
|
||||
},
|
||||
() => {
|
||||
//
|
||||
}
|
||||
);
|
||||
|
||||
list["deleteCustomText"] = new SimplePopup(
|
||||
"deleteCustomText",
|
||||
"text",
|
||||
"Delete custom text",
|
||||
[],
|
||||
"Are you sure?",
|
||||
"Delete",
|
||||
(_thisPopup) => {
|
||||
CustomText.deleteCustomText(_thisPopup.parameters[0]);
|
||||
Notifications.add("Custom text deleted", 1);
|
||||
SavedTextsPopup.show();
|
||||
},
|
||||
(_thisPopup) => {
|
||||
_thisPopup.text = `Are you sure you want to delete custom text ${_thisPopup.parameters[0]}?`;
|
||||
},
|
||||
() => {
|
||||
//
|
||||
}
|
||||
);
|
||||
|
||||
$(".pageSettings .section.discordIntegration #unlinkDiscordButton").click(
|
||||
() => {
|
||||
list["unlinkDiscord"].show();
|
||||
|
@ -923,6 +972,19 @@ $("#apeKeysPopup .generateApeKey").on("click", () => {
|
|||
list["generateApeKey"].show();
|
||||
});
|
||||
|
||||
$(`#customTextPopup .buttonsTop .saveCustomText`).on("click", () => {
|
||||
list["saveCustomText"].show();
|
||||
});
|
||||
|
||||
$(document).on(
|
||||
"click",
|
||||
`#savedTextsPopupWrapper .list .savedText .button.delete`,
|
||||
(e) => {
|
||||
const name = $(e.target).siblings(".button.name").text();
|
||||
list["deleteCustomText"].show([name]);
|
||||
}
|
||||
);
|
||||
|
||||
$(document).on("click", "#apeKeysPopup table tbody tr .button.delete", (e) => {
|
||||
const keyId = $(e.target).closest("tr").attr("keyId") as string;
|
||||
list["deleteApeKey"].show([keyId]);
|
||||
|
|
|
@ -1,4 +1,14 @@
|
|||
export let text = "The quick brown fox jumps over the lazy dog".split(" ");
|
||||
export let text = [
|
||||
"The",
|
||||
"quick",
|
||||
"brown",
|
||||
"fox",
|
||||
"jumps",
|
||||
"over",
|
||||
"the",
|
||||
"lazy",
|
||||
"dog",
|
||||
];
|
||||
export let isWordRandom = false;
|
||||
export let isTimeRandom = false;
|
||||
export let word: number;
|
||||
|
@ -28,3 +38,36 @@ export function setWord(val: number): void {
|
|||
export function setDelimiter(val: string): void {
|
||||
delimiter = val;
|
||||
}
|
||||
|
||||
type CustomTextObject = { [key: string]: string };
|
||||
|
||||
export function getCustomText(name: string): string[] {
|
||||
const customText = getCustomTextObject();
|
||||
|
||||
return customText[name].split(/ +/);
|
||||
}
|
||||
|
||||
export function setCustomText(name: string, text: string | string[]): void {
|
||||
const customText = getCustomTextObject();
|
||||
|
||||
if (typeof text === "string") customText[name] = text;
|
||||
else customText[name] = text.join(" ");
|
||||
|
||||
window.localStorage.setItem("customText", JSON.stringify(customText));
|
||||
}
|
||||
|
||||
export function deleteCustomText(name: string): void {
|
||||
const customText = getCustomTextObject();
|
||||
|
||||
if (customText[name]) delete customText[name];
|
||||
|
||||
window.localStorage.setItem("customText", JSON.stringify(customText));
|
||||
}
|
||||
|
||||
function getCustomTextObject(): CustomTextObject {
|
||||
return JSON.parse(window.localStorage.getItem("customText") ?? "{}");
|
||||
}
|
||||
|
||||
export function getCustomTextNames(): string[] {
|
||||
return Object.keys(getCustomTextObject());
|
||||
}
|
||||
|
|
|
@ -20,9 +20,24 @@
|
|||
display: grid;
|
||||
gap: 1rem;
|
||||
width: 60vw;
|
||||
.wordfilter {
|
||||
width: 33%;
|
||||
justify-self: right;
|
||||
|
||||
.buttonsTop {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.savedTexts {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
.title {
|
||||
color: var(--sub-color);
|
||||
}
|
||||
.buttons {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
|
@ -61,6 +76,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
#savedTextsPopupWrapper {
|
||||
#savedTextsPopup {
|
||||
color: var(--sub-color);
|
||||
background: var(--bg-color);
|
||||
border-radius: var(--roundness);
|
||||
padding: 2rem;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
width: 400px;
|
||||
|
||||
.title {
|
||||
font-size: 1.5rem;
|
||||
color: var(--sub-color);
|
||||
}
|
||||
|
||||
.list {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
.savedText {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
grid-template-columns: 1fr 3rem;
|
||||
.button .fas {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#wordFilterPopupWrapper {
|
||||
#wordFilterPopup {
|
||||
color: var(--sub-color);
|
||||
|
|
|
@ -372,9 +372,23 @@
|
|||
</div>
|
||||
<div id="customTextPopupWrapper" class="popupWrapper hidden">
|
||||
<div id="customTextPopup" action="">
|
||||
<div class="wordfilter button">
|
||||
<i class="fas fa-filter"></i>
|
||||
Words filter
|
||||
<div class="buttonsTop">
|
||||
<div class="button saveCustomText">
|
||||
<i class="fas fa-save"></i>
|
||||
Save
|
||||
</div>
|
||||
<div class="button showSavedTexts">
|
||||
<i class="fas fa-folder"></i>
|
||||
Show saved texts
|
||||
</div>
|
||||
<div class="button wordfilter">
|
||||
<i class="fas fa-filter"></i>
|
||||
Words filter
|
||||
</div>
|
||||
</div>
|
||||
<div class="savedTexts hidden" style="display: none">
|
||||
<div class="title">saved texts</div>
|
||||
<div class="buttons"></div>
|
||||
</div>
|
||||
<textarea class="textarea" placeholder="Custom text"></textarea>
|
||||
<div class="inputs">
|
||||
|
@ -419,6 +433,12 @@
|
|||
<div class="button apply">ok</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="savedTextsPopupWrapper" class="popupWrapper hidden">
|
||||
<div id="savedTextsPopup">
|
||||
<div class="title">Saved texts</div>
|
||||
<div class="list"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wordFilterPopupWrapper" class="popupWrapper hidden">
|
||||
<div id="wordFilterPopup">
|
||||
<div class="group">
|
||||
|
|
Loading…
Reference in a new issue