feat(charCounter): fix position and qols (#50)

* squash (#10)

:3

* whar

* inline this

* fixes by creations
This commit is contained in:
panbread 2024-10-13 00:37:31 +04:00 committed by GitHub
parent 0e0674fd98
commit 22d772c8d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 107 additions and 98 deletions

View file

@ -8,17 +8,13 @@ import "./style.css";
import { definePluginSettings } from "@api/Settings"; import { definePluginSettings } from "@api/Settings";
import { EquicordDevs } from "@utils/constants"; import { EquicordDevs } from "@utils/constants";
import { getCurrentChannel } from "@utils/discord";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { waitFor } from "@webpack"; import { waitFor } from "@webpack";
import { UserStore } from "@webpack/common"; import { SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common";
let ChannelTextAreaClasses; let ChannelTextAreaClasses: Record<string, string> | null = null;
let shouldShowColorEffects: boolean; let shouldShowColorEffects: boolean;
let position: boolean; let position: boolean;
let forceLeft = false;
waitFor(["buttonContainer", "channelTextArea"], m => (ChannelTextAreaClasses = m));
const settings = definePluginSettings({ const settings = definePluginSettings({
colorEffects: { colorEffects: {
@ -36,50 +32,47 @@ const settings = definePluginSettings({
onChange: value => { onChange: value => {
position = value; position = value;
const charCounterDiv = document.querySelector(".char-counter"); const charCounterDiv = document.querySelector(".vc-char-counter");
if (charCounterDiv) { if (charCounterDiv) {
if (value) { if (value) charCounterDiv.classList.add("left");
charCounterDiv.classList.add("left"); else charCounterDiv.classList.remove("left");
} else {
charCounterDiv.classList.remove("left");
}
} }
} }
} }
}); });
export default definePlugin({ const updateCharCounterOnChannelChange = async () => {
name: "CharacterCounter", await waitForChatInput();
description: "Adds a character counter to the chat input", addCharCounter();
authors: [EquicordDevs.creations], };
settings: settings,
start() { const waitForChatInput = async () => {
const premiumType = (UserStore.getCurrentUser().premiumType ?? 0); return waitFor([`${ChannelTextAreaClasses?.channelTextArea}`], () => document.querySelector(`.${ChannelTextAreaClasses?.channelTextArea}`));
const charMax = premiumType === 2 ? 4000 : 2000; };
shouldShowColorEffects = settings.store.colorEffects;
position = settings.store.position;
const addCharCounter = () => { const addCharCounter = () => {
const chatTextArea: HTMLElement | null = document.querySelector(`.${ChannelTextAreaClasses?.channelTextArea}`); const chatTextArea: HTMLElement | null = document.querySelector(`.${ChannelTextAreaClasses?.channelTextArea}`);
if (!chatTextArea) return; if (!chatTextArea) return;
let charCounterDiv: HTMLElement | null = document.querySelector(".char-counter"); let charCounterDiv: HTMLElement | null = document.querySelector(".vc-char-counter");
if (!charCounterDiv) { if (!charCounterDiv) {
charCounterDiv = document.createElement("div"); charCounterDiv = document.createElement("div");
charCounterDiv.classList.add("char-counter"); charCounterDiv.classList.add("vc-char-counter");
if (position || forceLeft) charCounterDiv.classList.add("left"); if (position) charCounterDiv.classList.add("left");
charCounterDiv.innerHTML = `<span class="char-count">0</span>/<span class="char-max">${charMax}</span>`; const premiumType = (UserStore.getCurrentUser().premiumType ?? 0);
const charMax = premiumType === 2 ? 4000 : 2000;
charCounterDiv.innerHTML = `<span class="vc-char-count">0</span>/<span class="vc-char-max">${charMax}</span>`;
charCounterDiv.style.opacity = "0";
} }
const chatInputContainer: HTMLElement | null = chatTextArea.closest("form"); const chatInputContainer: HTMLElement | null = chatTextArea.closest("form");
if (chatInputContainer && !chatInputContainer.contains(charCounterDiv)) { if (chatInputContainer && !chatInputContainer.contains(charCounterDiv)) {
chatTextArea.style.display = "flex"; chatTextArea.style.display = "flex";
chatTextArea.style.flexDirection = "column"; chatTextArea.style.flexDirection = "column";
chatCounterPositionUpdate(chatTextArea, charCounterDiv); chatCounterPositionUpdate(chatInputContainer, chatTextArea, charCounterDiv);
chatTextArea.appendChild(charCounterDiv); chatTextArea.appendChild(charCounterDiv);
} }
@ -89,20 +82,29 @@ export default definePlugin({
const updateCharCount = () => { const updateCharCount = () => {
const text = chatInput?.textContent?.replace(/[\uFEFF\xA0]/g, "") || ""; const text = chatInput?.textContent?.replace(/[\uFEFF\xA0]/g, "") || "";
const charCount = text.trim().length; const charCount = text.trim().length;
const charCountSpan: HTMLElement | null = charCounterDiv!.querySelector(".char-count");
if (charCount !== 0) charCounterDiv.style.opacity = "1";
else charCounterDiv.style.opacity = "0";
const charCountSpan: HTMLElement | null = charCounterDiv!.querySelector(".vc-char-count");
charCountSpan!.textContent = `${charCount}`; charCountSpan!.textContent = `${charCount}`;
const bottomPos = chatInputContainer!.offsetHeight;
charCounterDiv.style.bottom = `${bottomPos.toString()}px`;
if (shouldShowColorEffects) { if (shouldShowColorEffects) {
const premiumType = (UserStore.getCurrentUser().premiumType ?? 0);
const charMax = premiumType === 2 ? 4000 : 2000;
const percentage = (charCount / charMax) * 100; const percentage = (charCount / charMax) * 100;
let color; let color;
if (percentage < 50) { if (percentage < 50) {
color = "#888"; color = "var(--text-muted)";
} else if (percentage < 75) { } else if (percentage < 75) {
color = "#ff9900"; color = "var(--yellow-330)";
} else if (percentage < 90) { } else if (percentage < 90) {
color = "#ff6600"; color = "var(--orange-330)";
} else { } else {
color = "#ff0000"; color = "var(--red-360)";
} }
charCountSpan!.style.color = color; charCountSpan!.style.color = color;
} }
@ -113,31 +115,36 @@ export default definePlugin({
chatInput?.addEventListener("paste", () => setTimeout(updateCharCount, 0)); chatInput?.addEventListener("paste", () => setTimeout(updateCharCount, 0));
}; };
const chatCounterPositionUpdate = (chatTextArea: HTMLElement, charCounterDiv: HTMLElement) => { const chatCounterPositionUpdate = (chatInputContainer: HTMLElement, chatTextArea: HTMLElement, charCounterDiv: HTMLElement) => {
const position = "flex-end"; chatTextArea.style.justifyContent = "flex-end";
chatTextArea.style.justifyContent = position;
charCounterDiv.style.position = "absolute"; charCounterDiv.style.position = "absolute";
const bottomPos = (chatInputContainer.offsetHeight) - 10; // onload 68px, minus 10 to fix
charCounterDiv.style.bottom = `${bottomPos.toString()}px`;
}; };
const observeDOMChanges = () => { export default definePlugin({
const observer = new MutationObserver(() => { name: "CharacterCounter",
const chatTextArea = document.querySelector(`.${ChannelTextAreaClasses?.channelTextArea}`); description: "Adds a character counter to the chat input",
if (chatTextArea && !document.querySelector(".char-counter")) { authors: [EquicordDevs.creations, EquicordDevs.Panniku],
const currentChannel = getCurrentChannel(); settings: settings,
forceLeft = currentChannel?.rateLimitPerUser !== 0;
addCharCounter(); start: async () => {
} shouldShowColorEffects = settings.store.colorEffects;
}); position = settings.store.position;
observer.observe(document.body, { childList: true, subtree: true }); waitFor(["buttonContainer", "channelTextArea"], m => (ChannelTextAreaClasses = m));
}; await updateCharCounterOnChannelChange();
observeDOMChanges(); SelectedChannelStore.addChangeListener(updateCharCounterOnChannelChange);
SelectedGuildStore.addChangeListener(updateCharCounterOnChannelChange);
}, },
stop() { stop() {
const charCounterDiv = document.querySelector(".char-counter"); const charCounterDiv = document.querySelector(".vc-char-counter");
if (charCounterDiv) charCounterDiv.remove(); if (charCounterDiv) charCounterDiv.remove();
SelectedChannelStore.removeChangeListener(updateCharCounterOnChannelChange);
SelectedGuildStore.removeChangeListener(updateCharCounterOnChannelChange);
} }
}); });

View file

@ -1,26 +1,28 @@
.char-counter { .vc-char-counter {
font-size: 12px; font-size: 12px;
color: var(--text-muted); color: var(--text-muted);
text-align: right; text-align: right;
position: absolute; position: absolute;
bottom: -15px;
right: 0; right: 0;
pointer-events: none; pointer-events: none;
z-index: 1; z-index: 1;
margin: 0; margin: 0;
padding: 0; padding: 6px;
background-color: var(--background-tertiary);
border-radius: var(--radius-sm);
transition: opacity 0.3s ease;
} }
.char-counter.left { .vc-char-counter.left {
text-align: left; text-align: left;
right: auto; right: auto;
left: 0; left: 0;
} }
.char-counter .char-count { .vc-char-counter .vc-char-count {
transition: color 0.3s ease; transition: color 0.3s ease;
} }
.char-counter .char-max { .vc-char-counter .vc-char-max {
color: var(--text-muted); color: var(--primary-330);
} }