diff --git a/frontend/src/html/popups.html b/frontend/src/html/popups.html
index 6c2e4910d..d4546009a 100644
--- a/frontend/src/html/popups.html
+++ b/frontend/src/html/popups.html
@@ -462,10 +462,14 @@
periods to the end of lines if you wish.
-
diff --git a/frontend/src/ts/modals/custom-text.ts b/frontend/src/ts/modals/custom-text.ts
index 4179d6900..13f2a50b8 100644
--- a/frontend/src/ts/modals/custom-text.ts
+++ b/frontend/src/ts/modals/custom-text.ts
@@ -16,15 +16,82 @@ const popup = "#customTextModal .modal";
type State = {
textarea: string;
lastSavedTextareaState: string;
+ longCustomTextWarning: boolean;
+ randomWordsChecked: boolean;
+ randomWordInputs: {
+ word: string;
+ time: string;
+ section: string;
+ };
+ pipeDelimiterChecked: boolean;
+ replaceNewlines: "off" | "space" | "period";
+ replaceControlCharactersChecked: boolean;
+ replaceFancyTypographyChecked: boolean;
};
const state: State = {
textarea: CustomText.text.join(" "),
lastSavedTextareaState: CustomText.text.join(" "),
+ longCustomTextWarning: false,
+ randomWordsChecked: false,
+ randomWordInputs: {
+ word: "",
+ time: "",
+ section: "",
+ },
+ pipeDelimiterChecked: false,
+ replaceNewlines: "off",
+ replaceControlCharactersChecked: true,
+ replaceFancyTypographyChecked: true,
};
-function updateLongTextWarning(): void {
- if (CustomTextState.isCustomTextLong() === true) {
+function updateUI(): void {
+ if (state.randomWordsChecked) {
+ $(`${popup} .randomWordsCheckbox input`).prop("checked", true);
+ $(`${popup} .inputs .randomInputFields`).removeClass("disabled");
+ } else {
+ $(`${popup} .randomWordsCheckbox input`).prop("checked", false);
+ $(`${popup} .inputs .randomInputFields`).addClass("disabled");
+ }
+
+ if (state.pipeDelimiterChecked) {
+ $(`${popup} .delimiterCheck input`).prop("checked", true);
+ } else {
+ $(`${popup} .delimiterCheck input`).prop("checked", false);
+ }
+
+ $(`${popup} .replaceNewLinesButtons .button`).removeClass("active");
+
+ if (state.replaceNewlines !== "off") {
+ $(`${popup} .inputs .replaceNewLinesButtons`).removeClass("disabled");
+ $(
+ `${popup} .replaceNewLinesButtons .button[data-replace-new-lines=${state.replaceNewlines}]`
+ ).addClass("active");
+ } else {
+ $(`${popup} .inputs .replaceNewLinesButtons`).addClass("disabled");
+ }
+
+ $(`${popup} textarea`).val(state.textarea);
+
+ if (state.pipeDelimiterChecked) {
+ $(`${popup} .randomInputFields .sectioncount `).removeClass("hidden");
+ state.randomWordInputs.word = "";
+ $(`${popup} .randomInputFields .wordcount `).addClass("hidden");
+ } else {
+ state.randomWordInputs.section = "";
+ $(`${popup} .randomInputFields .sectioncount `).addClass("hidden");
+ $(`${popup} .randomInputFields .wordcount `).removeClass("hidden");
+ }
+
+ $(`${popup} .randomInputFields .wordcount input`).val(
+ state.randomWordInputs.word
+ );
+ $(`${popup} .randomInputFields .time input`).val(state.randomWordInputs.time);
+ $(`${popup} .randomInputFields .sectioncount input`).val(
+ state.randomWordInputs.section
+ );
+
+ if (state.longCustomTextWarning) {
$(`${popup} .longCustomTextWarning`).removeClass("hidden");
$(`${popup} .randomWordsCheckbox input`).prop("checked", false);
$(`${popup} .delimiterCheck input`).prop("checked", false);
@@ -37,40 +104,17 @@ function updateLongTextWarning(): void {
}
}
-//todo: rewrite this file to use a state object instead of constantly directly accessing the DOM
-
async function beforeAnimation(
modalEl: HTMLElement,
modalChainData?: IncomingData
): Promise {
- updateLongTextWarning();
-
- if (
+ state.longCustomTextWarning = CustomTextState.isCustomTextLong() ?? false;
+ state.randomWordsChecked =
CustomText.isSectionRandom ||
CustomText.isTimeRandom ||
- CustomText.isWordRandom
- ) {
- $(`${popup} .randomWordsCheckbox input`).prop("checked", true);
- } else {
- $(`${popup} .randomWordsCheckbox input`).prop("checked", false);
- }
-
- if (CustomText.delimiter === "|") {
- $(`${popup} .delimiterCheck input`).prop("checked", true);
- } else {
- $(`${popup} .delimiterCheck input`).prop("checked", false);
- }
-
- if ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) {
- $(`${popup} .inputs .randomInputFields`).removeClass("disabled");
- } else {
- $(`${popup} .inputs .randomInputFields`).addClass("disabled");
- }
- if ($(`${popup} .replaceNewlineWithSpace input`).prop("checked") as boolean) {
- $(`${popup} .inputs .replaceNewLinesButtons`).removeClass("disabled");
- } else {
- $(`${popup} .inputs .replaceNewLinesButtons`).addClass("disabled");
- }
+ CustomText.isWordRandom;
+ state.pipeDelimiterChecked = CustomText.delimiter === "|";
+ // state.replaceNewlinesChecked = false;
if (CustomTextState.isCustomTextLong()) {
// if we are in long custom text mode, always reset the textarea state to the current text
@@ -83,7 +127,7 @@ async function beforeAnimation(
Notifications.add("Disabled long custom text progress tracking", 0, {
duration: 5,
});
- updateLongTextWarning();
+ state.longCustomTextWarning = false;
}
const newText =
@@ -92,12 +136,15 @@ async function beforeAnimation(
: state.textarea + " " + modalChainData.text;
state.textarea = newText;
}
- $(`${popup} textarea`).val(state.textarea);
- $(`${popup} .wordcount input`).val(
- CustomText.word === -1 ? "" : CustomText.word
- );
- $(`${popup} .time input`).val(CustomText.time === -1 ? "" : CustomText.time);
+ state.randomWordInputs.word =
+ CustomText.word === -1 ? "" : `${CustomText.word}`;
+ state.randomWordInputs.time =
+ CustomText.time === -1 ? "" : `${CustomText.time}`;
+ state.randomWordInputs.section =
+ CustomText.section === -1 ? "" : `${CustomText.section}`;
+
+ updateUI();
}
async function afterAnimation(): Promise {
@@ -119,39 +166,6 @@ function hide(): void {
void modal.hide();
}
-function handleDelimiterChange(): void {
- let delimiter;
- if ($(`${popup} .delimiterCheck input`).prop("checked") as boolean) {
- delimiter = "|";
-
- $(`${popup} .randomInputFields .sectioncount `).removeClass("hidden");
-
- $(`${popup} .randomInputFields .wordcount input `).val("");
- $(`${popup} .randomInputFields .wordcount `).addClass("hidden");
- } else {
- delimiter = " ";
- $(`${popup} .randomInputFields .sectioncount input `).val("");
- $(`${popup} .randomInputFields .sectioncount `).addClass("hidden");
- $(`${popup} .randomInputFields .wordcount `).removeClass("hidden");
- }
- if (
- $(`${popup} textarea`).val() !== CustomText.text.join(CustomText.delimiter)
- ) {
- const currentText = $(`${popup} textarea`).val() as string;
- const currentTextSplit = currentText.split(CustomText.delimiter);
- let newtext = currentTextSplit.join(delimiter);
- newtext = newtext.replace(/\n /g, "\n");
- $(`${popup} textarea`).val(newtext);
- state.textarea = newtext;
- } else {
- let newtext = CustomText.text.join(delimiter);
- newtext = newtext.replace(/\n /g, "\n");
- $(`${popup} textarea`).val(newtext);
- state.textarea = newtext;
- }
- CustomText.setDelimiter(delimiter);
-}
-
function handleFileOpen(): void {
const file = ($(`#fileInput`)[0] as HTMLInputElement).files?.[0];
if (file) {
@@ -167,8 +181,8 @@ function handleFileOpen(): void {
reader.onload = (readerEvent): void => {
const content = readerEvent.target?.result as string;
- $(`${popup} textarea`).val(content);
state.textarea = content;
+ updateUI();
$(`#fileInput`).val("");
};
reader.onerror = (): void => {
@@ -193,9 +207,7 @@ function cleanUpText(): string[] {
//replace zero width characters
text = text.replace(/[\u200B-\u200D\u2060\uFEFF]/g, "");
- if (
- $(`${popup} .replaceControlCharacters input`).prop("checked") as boolean
- ) {
+ if (state.replaceControlCharactersChecked) {
text = text.replace(/([^\\]|^)\\t/gm, "$1\t");
text = text.replace(/([^\\]|^)\\n/gm, "$1\n");
text = text.replace(/\\\\t/gm, "\\t");
@@ -204,19 +216,12 @@ function cleanUpText(): string[] {
text = text.replace(/ +/gm, " ");
text = text.replace(/( *(\r\n|\r|\n) *)/g, "\n ");
- if ($(`${popup} .typographyCheck input`).prop("checked") as boolean) {
+ if (state.replaceFancyTypographyChecked) {
text = Misc.cleanTypographySymbols(text);
}
- if ($(`${popup} .replaceNewlineWithSpace input`).prop("checked") as boolean) {
- let periods = true;
- if (
- $(
- $(`${popup} .replaceNewLinesButtons .button`)[0] as HTMLElement
- ).hasClass("active")
- ) {
- periods = false;
- }
+ if (state.replaceNewlines !== "off") {
+ const periods = state.replaceNewlines === "period";
if (periods) {
text = text.replace(/\n/gm, ". ");
text = text.replace(/\.\. /gm, ". ");
@@ -241,30 +246,17 @@ function apply(): void {
CustomText.setText(cleanUpText());
- CustomText.setWord(
- parseInt(($(`${popup} .wordcount input`).val() as string) || "-1")
- );
- CustomText.setTime(
- parseInt(($(`${popup} .time input`).val() as string) || "-1")
- );
+ CustomText.setWord(parseInt(state.randomWordInputs.word || "-1"));
+ CustomText.setTime(parseInt(state.randomWordInputs.time || "-1"));
+ CustomText.setSection(parseInt(state.randomWordInputs.section || "-1"));
- CustomText.setSection(
- parseInt(($(`${popup} .sectioncount input`).val() as string) || "-1")
- );
- CustomText.setIsWordRandom(
- ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) &&
- CustomText.word > -1
- );
- CustomText.setIsTimeRandom(
- ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) &&
- CustomText.time > -1
- );
+ CustomText.setIsWordRandom(state.randomWordsChecked && CustomText.word > -1);
+ CustomText.setIsTimeRandom(state.randomWordsChecked && CustomText.time > -1);
CustomText.setIsSectionRandom(
- ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) &&
- CustomText.section > -1
+ state.randomWordsChecked && CustomText.section > -1
);
if (
- ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) &&
+ state.randomWordsChecked &&
!CustomText.isTimeRandom &&
!CustomText.isWordRandom &&
!CustomText.isSectionRandom
@@ -280,7 +272,8 @@ function apply(): void {
}
if (
- ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) &&
+ // ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) &&
+ state.randomWordsChecked &&
CustomText.isTimeRandom &&
CustomText.isWordRandom
) {
@@ -315,39 +308,64 @@ function apply(): void {
}
async function setup(modalEl: HTMLElement): Promise {
- modalEl
- .querySelector(".delimiterCheck input")
- ?.addEventListener("change", handleDelimiterChange);
modalEl
.querySelector("#fileInput")
?.addEventListener("change", handleFileOpen);
modalEl
.querySelector(".randomWordsCheckbox input")
- ?.addEventListener("change", () => {
- if ($(`${popup} .randomWordsCheckbox input`).prop("checked") as boolean) {
- $(`${popup} .inputs .randomInputFields`).removeClass("disabled");
+ ?.addEventListener("change", (e) => {
+ state.randomWordsChecked = (e.target as HTMLInputElement).checked;
+ updateUI();
+ });
+ modalEl
+ .querySelector(".typographyCheck input")
+ ?.addEventListener("change", (e) => {
+ state.replaceFancyTypographyChecked = (
+ e.target as HTMLInputElement
+ ).checked;
+ updateUI();
+ });
+ modalEl
+ .querySelector(".delimiterCheck input")
+ ?.addEventListener("change", (e) => {
+ state.pipeDelimiterChecked = (e.target as HTMLInputElement).checked;
+ if (state.textarea !== CustomText.text.join(CustomText.delimiter)) {
+ const currentTextSplit = state.textarea.split(CustomText.delimiter);
+ let newtext = currentTextSplit.join(
+ state.pipeDelimiterChecked ? "|" : " "
+ );
+ newtext = newtext.replace(/\n /g, "\n");
+ state.textarea = newtext;
} else {
- $(`${popup} .inputs .randomInputFields`).addClass("disabled");
+ let newtext = CustomText.text.join(
+ state.pipeDelimiterChecked ? "|" : " "
+ );
+ newtext = newtext.replace(/\n /g, "\n");
+ state.textarea = newtext;
}
+ CustomText.setDelimiter(state.pipeDelimiterChecked ? "|" : " ");
+ updateUI();
});
modalEl
.querySelector(".replaceNewlineWithSpace input")
- ?.addEventListener("change", () => {
- if (
- $(`${popup} .replaceNewlineWithSpace input`).prop("checked") as boolean
- ) {
- $(`${popup} .inputs .replaceNewLinesButtons`).removeClass("disabled");
+ ?.addEventListener("change", (e) => {
+ const checked = (e.target as HTMLInputElement).checked;
+ if (checked === false) {
+ state.replaceNewlines = "off";
} else {
- $(`${popup} .inputs .replaceNewLinesButtons`).addClass("disabled");
+ state.replaceNewlines = "space";
}
+ updateUI();
});
const replaceNewLinesButtons = modalEl.querySelectorAll(
".replaceNewLinesButtons .button"
);
for (const button of replaceNewLinesButtons) {
- button.addEventListener("click", () => {
- $(`${popup} .replaceNewLinesButtons .button`).removeClass("active");
- $(button).addClass("active");
+ button.addEventListener("click", (e) => {
+ state.replaceNewlines = (e.target as HTMLElement).dataset[
+ "replaceNewLines"
+ ] as "space" | "period";
+ updateUI();
});
}
const textarea = modalEl.querySelector("textarea");
@@ -372,7 +390,7 @@ async function setup(modalEl: HTMLElement): Promise {
state.textarea = area.value;
});
textarea?.addEventListener("keypress", (e) => {
- if (Misc.isElementVisible(`#customTextModal .longCustomTextWarning`)) {
+ if (state.longCustomTextWarning) {
e.preventDefault();
return;
}
@@ -384,29 +402,35 @@ async function setup(modalEl: HTMLElement): Promise {
CustomTextState.getCustomTextName() !== ""
) {
CustomTextState.setCustomTextName("", undefined);
+ state.longCustomTextWarning = false;
Notifications.add("Disabled long custom text progress tracking", 0, {
duration: 5,
});
- updateLongTextWarning();
}
});
modalEl
.querySelector(".randomInputFields .wordcount input")
- ?.addEventListener("keypress", (e) => {
- $(`${popup} .randomInputFields .time input`).val("");
- $(`${popup} .randomInputFields .sectioncount input`).val("");
+ ?.addEventListener("input", (e) => {
+ state.randomWordInputs.time = "";
+ state.randomWordInputs.word = (e.target as HTMLInputElement).value;
+ state.randomWordInputs.section = "";
+ updateUI();
});
modalEl
.querySelector(".randomInputFields .time input")
- ?.addEventListener("keypress", (e) => {
- $(`${popup} .randomInputFields .wordcount input`).val("");
- $(`${popup} .randomInputFields .sectioncount input`).val("");
+ ?.addEventListener("input", (e) => {
+ state.randomWordInputs.time = (e.target as HTMLInputElement).value;
+ state.randomWordInputs.word = "";
+ state.randomWordInputs.section = "";
+ updateUI();
});
modalEl
.querySelector(".randomInputFields .sectioncount input")
- ?.addEventListener("keypress", (e) => {
- $(`${popup} .randomInputFields .time input`).val("");
- $(`${popup} .randomInputFields .wordcount input`).val("");
+ ?.addEventListener("input", (e) => {
+ state.randomWordInputs.time = "";
+ state.randomWordInputs.word = "";
+ state.randomWordInputs.section = (e.target as HTMLInputElement).value;
+ updateUI();
});
modalEl.querySelector(".button.apply")?.addEventListener("click", () => {
apply();
@@ -434,7 +458,8 @@ async function setup(modalEl: HTMLElement): Promise {
modalEl
.querySelector(".longCustomTextWarning")
?.addEventListener("click", () => {
- $(`#customTextModal .longCustomTextWarning`).addClass("hidden");
+ state.longCustomTextWarning = false;
+ updateUI();
});
}