diff --git a/src/equicordplugins/channelBadges/index.tsx b/src/equicordplugins/channelBadges/index.tsx index b1a2ddb28..dba79c867 100644 --- a/src/equicordplugins/channelBadges/index.tsx +++ b/src/equicordplugins/channelBadges/index.tsx @@ -32,7 +32,7 @@ function renderBadge(id: number, title: string) { export default definePlugin({ name: "ChannelBadges", description: "Adds badges to channels based on their type", - authors: [EquicordDevs.creations], + authors: [EquicordDevs.creations, EquicordDevs.thororen], settings, patches: [ // TY TypingIndicator diff --git a/src/equicordplugins/characterCounter/index.tsx b/src/equicordplugins/characterCounter/index.tsx index bebabcc40..59b5f348d 100644 --- a/src/equicordplugins/characterCounter/index.tsx +++ b/src/equicordplugins/characterCounter/index.tsx @@ -9,142 +9,56 @@ import "./style.css"; import { definePluginSettings } from "@api/Settings"; import { EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { waitFor } from "@webpack"; -import { SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; - -let ChannelTextAreaClasses: Record | null = null; -let shouldShowColorEffects: boolean; -let position: boolean; +import { UserStore } from "@webpack/common"; const settings = definePluginSettings({ colorEffects: { type: OptionType.BOOLEAN, description: "Turn on or off color effects for getting close to the character limit", default: true, - onChange: value => { - shouldShowColorEffects = value; - } }, - position: { - type: OptionType.BOOLEAN, - description: "Move the character counter to the left side of the chat input", - default: false, - onChange: value => { - position = value; - - const charCounterDiv = document.querySelector(".vc-char-counter"); - if (charCounterDiv) { - if (value) charCounterDiv.classList.add("left"); - else charCounterDiv.classList.remove("left"); - } - } - } }); -const updateCharCounterOnChannelChange = async () => { - await waitForChatInput(); - addCharCounter(); -}; - -const waitForChatInput = async () => { - return waitFor([`${ChannelTextAreaClasses?.channelTextArea}`], () => document.querySelector(`.${ChannelTextAreaClasses?.channelTextArea}`)); -}; - -const addCharCounter = () => { - const chatTextArea: HTMLElement | null = document.querySelector(`.${ChannelTextAreaClasses?.channelTextArea}`); - if (!chatTextArea) return; - - let charCounterDiv: HTMLElement | null = document.querySelector(".vc-char-counter"); - if (!charCounterDiv) { - charCounterDiv = document.createElement("div"); - charCounterDiv.classList.add("vc-char-counter"); - - if (position) charCounterDiv.classList.add("left"); - - const premiumType = (UserStore.getCurrentUser().premiumType ?? 0); - const charMax = premiumType === 2 ? 4000 : 2000; - - charCounterDiv.innerHTML = `0/${charMax}`; - charCounterDiv.style.opacity = "0"; - } - - const chatInputContainer: HTMLElement | null = chatTextArea.closest("form"); - if (chatInputContainer && !chatInputContainer.contains(charCounterDiv)) { - chatTextArea.style.display = "flex"; - chatTextArea.style.flexDirection = "column"; - chatCounterPositionUpdate(chatInputContainer, chatTextArea, charCounterDiv); - - chatTextArea.appendChild(charCounterDiv); - } - - const chatInput: HTMLElement | null = chatTextArea.querySelector('div[contenteditable="true"]'); - - const updateCharCount = () => { - const text = chatInput?.textContent?.replace(/[\uFEFF\xA0]/g, "") || ""; - const charCount = text.trim().length; - - if (charCount !== 0) charCounterDiv.style.opacity = "1"; - else charCounterDiv.style.opacity = "0"; - - const charCountSpan: HTMLElement | null = charCounterDiv!.querySelector(".vc-char-count"); - charCountSpan!.textContent = `${charCount}`; - - const bottomPos = chatInputContainer!.offsetHeight; - charCounterDiv.style.bottom = `${bottomPos.toString()}px`; - - if (shouldShowColorEffects) { - const premiumType = (UserStore.getCurrentUser().premiumType ?? 0); - const charMax = premiumType === 2 ? 4000 : 2000; - const percentage = (charCount / charMax) * 100; - let color; - if (percentage < 50) { - color = "var(--text-muted)"; - } else if (percentage < 75) { - color = "var(--yellow-330)"; - } else if (percentage < 90) { - color = "var(--orange-330)"; - } else { - color = "var(--red-360)"; - } - charCountSpan!.style.color = color; - } - }; - - chatInput?.addEventListener("input", updateCharCount); - chatInput?.addEventListener("keydown", () => setTimeout(updateCharCount, 0)); - chatInput?.addEventListener("paste", () => setTimeout(updateCharCount, 0)); -}; - -const chatCounterPositionUpdate = (chatInputContainer: HTMLElement, chatTextArea: HTMLElement, charCounterDiv: HTMLElement) => { - chatTextArea.style.justifyContent = "flex-end"; - charCounterDiv.style.position = "absolute"; - - const bottomPos = (chatInputContainer.offsetHeight) - 10; // onload 68px, minus 10 to fix - charCounterDiv.style.bottom = `${bottomPos.toString()}px`; -}; - export default definePlugin({ name: "CharacterCounter", description: "Adds a character counter to the chat input", - authors: [EquicordDevs.creations, EquicordDevs.Panniku], - settings: settings, + authors: [EquicordDevs.creations, EquicordDevs.Panniku, EquicordDevs.thororen], + settings, + patches: [ + { + find: ".CREATE_FORUM_POST||", + replacement: { + match: /(textValue:(\i).{0,50}channelId:\i\.id\}\)),\i/, + replace: "$1,$self.getCharCounter($2)" + } + }, + { + find: "#{intl::PREMIUM_MESSAGE_LENGTH_UPSELL_TOOLTIP}", + replacement: { + match: /return \i\?\i\(\):\i\(\)/, + replace: "return null" + } + } + ], + getCharCounter(text: string) { + const premiumType = (UserStore.getCurrentUser().premiumType ?? 0); + const charMax = premiumType === 2 ? 4000 : 2000; + const { length } = text; - start: async () => { - shouldShowColorEffects = settings.store.colorEffects; - position = settings.store.position; + let color = "var(--primary-330)"; + if (settings.store.colorEffects) { + const percentage = (length / charMax) * 100; + if (percentage < 50) color = "var(--text-muted)"; + else if (percentage < 75) color = "var(--yellow-330)"; + else if (percentage < 90) color = "var(--orange-330)"; + else color = "var(--red-360)"; + } - waitFor(["buttonContainer", "channelTextArea"], m => (ChannelTextAreaClasses = m)); - await updateCharCounterOnChannelChange(); - - SelectedChannelStore.addChangeListener(updateCharCounterOnChannelChange); - SelectedGuildStore.addChangeListener(updateCharCounterOnChannelChange); - }, - - stop() { - const charCounterDiv = document.querySelector(".vc-char-counter"); - if (charCounterDiv) charCounterDiv.remove(); - - SelectedChannelStore.removeChangeListener(updateCharCounterOnChannelChange); - SelectedGuildStore.removeChangeListener(updateCharCounterOnChannelChange); + return ( +
+ {length}/ + {charMax} +
+ ); } }); diff --git a/src/equicordplugins/characterCounter/style.css b/src/equicordplugins/characterCounter/style.css index 066a1b9fc..6dcdb79ff 100644 --- a/src/equicordplugins/characterCounter/style.css +++ b/src/equicordplugins/characterCounter/style.css @@ -1,22 +1,13 @@ .vc-char-counter { font-size: 12px; color: var(--text-muted); - text-align: right; position: absolute; - right: 0; + bottom: 4px; + right: 6px; pointer-events: none; - z-index: 1; - margin: 0; - padding: 6px; - background-color: var(--background-tertiary); - border-radius: var(--radius-sm); - transition: opacity 0.3s ease; -} - -.vc-char-counter.left { - text-align: left; - right: auto; - left: 0; + z-index: 2; + background: transparent; + transition: color 0.3s ease; } .vc-char-counter .vc-char-count { @@ -25,4 +16,4 @@ .vc-char-counter .vc-char-max { color: var(--primary-330); -} +} \ No newline at end of file