diff --git a/src/equicordplugins/chatButtonsPlus/index.tsx b/src/equicordplugins/chatButtonsPlus/index.tsx
index 9ea64a434..2366a1450 100644
--- a/src/equicordplugins/chatButtonsPlus/index.tsx
+++ b/src/equicordplugins/chatButtonsPlus/index.tsx
@@ -27,7 +27,7 @@ let buttonEntries: ButtonEntry[] = [];
const BUTTON_ENTRIES_KEY = "ChatButtonsPlus_buttonEntries";
function generateId(): string {
- return Date.now().toString(36) + Math.random().toString(36).substr(2);
+ return Date.now().toString(36) + Math.random().toString(36).substring(2);
}
async function handleButtonClick(context: string) {
@@ -67,9 +67,32 @@ async function removeButtonEntry(id: string, forceUpdate: () => void) {
}
}
+async function resetAllButtons(forceUpdate: () => void) {
+ try {
+ buttonEntries.length = 0;
+ await DataStore.set(BUTTON_ENTRIES_KEY, []);
+ forceUpdate();
+ } catch (error) {
+ console.error("ChatButtonsPlus: Failed to reset buttons:", error);
+ }
+}
+
function ButtonEntries() {
const update = useForceUpdater();
+ React.useEffect(() => {
+ const loadEntries = async () => {
+ try {
+ const storedEntries = await DataStore.get(BUTTON_ENTRIES_KEY) ?? [];
+ buttonEntries = storedEntries;
+ update();
+ } catch (error) {
+ console.error("ChatButtonsPlus: Failed to load entries:", error);
+ }
+ };
+ loadEntries();
+ }, []);
+
async function setLabel(id: string, value: string) {
try {
const index = buttonEntries.findIndex(entry => entry.id === id);
@@ -87,7 +110,7 @@ function ButtonEntries() {
try {
const index = buttonEntries.findIndex(entry => entry.id === id);
if (index !== -1) {
- buttonEntries[index].message = value.trim() || "Hello!";
+ buttonEntries[index].message = value;
await DataStore.set(BUTTON_ENTRIES_KEY, buttonEntries);
update();
}
@@ -99,10 +122,12 @@ function ButtonEntries() {
async function setSvg(id: string, value: string) {
try {
const index = buttonEntries.findIndex(entry => entry.id === id);
- if (index !== -1 && isValidSvg(value.trim())) {
- buttonEntries[index].svg = value.trim();
- await DataStore.set(BUTTON_ENTRIES_KEY, buttonEntries);
- update();
+ if (index !== -1) {
+ if (value.trim() === "" || isValidSvg(value.trim())) {
+ buttonEntries[index].svg = value.trim();
+ await DataStore.set(BUTTON_ENTRIES_KEY, buttonEntries);
+ update();
+ }
}
} catch (error) {
console.error("ChatButtonsPlus: Failed to update SVG:", error);
@@ -185,19 +210,23 @@ function ButtonEntries() {
Message to Send
- setMessage(entry.id, e)}
+ onChange={e => setMessage(entry.id, e.target.value)}
+ rows={2}
/>
Custom SVG Path (24x24 viewBox)
-
setSvg(entry.id, e)}
+ onChange={e => setSvg(entry.id, e.target.value)}
+ rows={3}
/>
Enter SVG path elements for a 24x24 viewBox. Use "currentColor" for the fill to match Discord's theme.
@@ -210,7 +239,16 @@ function ButtonEntries() {
return (
<>
{elements}
- addButtonEntry(update)}>Add Button
+
+ addButtonEntry(update)}>Add Button
+ resetAllButtons(update)}
+ look={Button.Looks.OUTLINED}
+ color={Button.Colors.RED}
+ >
+ Reset All
+
+
>
);
}
diff --git a/src/equicordplugins/chatButtonsPlus/styles.css b/src/equicordplugins/chatButtonsPlus/styles.css
index e3b15338a..d896da97e 100644
--- a/src/equicordplugins/chatButtonsPlus/styles.css
+++ b/src/equicordplugins/chatButtonsPlus/styles.css
@@ -49,4 +49,30 @@
font-size: 12px;
color: var(--text-muted);
margin-top: 3px;
+}
+
+.chatButtonsPlus-textarea {
+ width: 100%;
+ padding: 8px 12px;
+ border: 2px solid var(--text-muted);
+ border-radius: 4px;
+ background-color: var(--background-secondary);
+ color: var(--header-primary);
+ font-family: var(--font-primary);
+ font-size: 14px;
+ resize: vertical;
+ min-height: 60px;
+ box-sizing: border-box;
+}
+
+.chatButtonsPlus-textarea:focus {
+ outline: none;
+ border-color: var(--brand-experiment);
+ box-shadow: 0 0 0 1px var(--brand-experiment);
+}
+
+.chatButtonsPlus-actions {
+ display: flex;
+ gap: 10px;
+ margin-top: 15px;
}
\ No newline at end of file
diff --git a/src/equicordplugins/fixFileExtensions/index.tsx b/src/equicordplugins/fixFileExtensions/index.tsx
index 4d1ee6ba8..c1dfc3a93 100644
--- a/src/equicordplugins/fixFileExtensions/index.tsx
+++ b/src/equicordplugins/fixFileExtensions/index.tsx
@@ -11,12 +11,13 @@ import definePlugin, { ReporterTestable } from "@utils/types";
import { CloudUpload } from "@vencord/discord-types";
const extensionMap = {
- "ogg": [".ogv", ".oga", ".ogx", ".ogm", ".spx", ".opus"],
- "jpg": [".jpg", ".jpeg", ".jfif", ".jpe", ".jif", ".jfi", ".pjpeg", ".pjp"],
- "svg": [".svgz"],
- "mp4": [".m4v", ".m4r", ".m4p"],
- "m4a": [".m4b"],
- "mov": [".movie", ".qt"],
+ "ogg": [".ogv", ".oga", ".ogx", ".ogm", ".spx", ".opus", ".flac", ".aac", ".wma"],
+ "jpg": [".jpeg", ".jfif", ".jpe", ".jif", ".jfi", ".pjpeg", ".pjp", ".bmp", ".tiff", ".tif", ".webp"],
+ "svg": [".svgz", ".ai", ".eps"],
+ "mp4": [".m4v", ".m4r", ".m4p", ".avi", ".mkv", ".wmv", ".flv", ".3gp", ".webm"],
+ "m4a": [".m4b", ".aiff", ".wav"],
+ "mov": [".movie", ".qt", ".asf", ".rm", ".rmvb"],
+ "png": [".ico", ".cur"],
};
export const reverseExtensionMap = Object.entries(extensionMap).reduce((acc, [target, exts]) => {
@@ -50,6 +51,6 @@ export default definePlugin({
const ext = extIdx !== -1 ? file.slice(extIdx) : "";
const newExt = reverseExtensionMap[ext] || ext;
- return fileName + newExt;
+ upload.filename = fileName + newExt;
},
});
diff --git a/src/equicordplugins/guildPickerDumper/index.tsx b/src/equicordplugins/guildPickerDumper/index.tsx
index 8fa7c34de..0607864d2 100644
--- a/src/equicordplugins/guildPickerDumper/index.tsx
+++ b/src/equicordplugins/guildPickerDumper/index.tsx
@@ -12,6 +12,8 @@ import type { Guild } from "@vencord/discord-types";
import { EmojiStore, Menu, StickersStore } from "@webpack/common";
import { zipSync } from "fflate";
+const StickerExt = [, "png", "apng", "json", "gif"] as const;
+
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => {
// Assuming "privacy" is the correct ID for the group you want to modify.
const group = findGroupChildrenByChildId("privacy", children);
@@ -36,16 +38,44 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
return console.log("Server not found!");
}
- const fetchAsset = async e => {
- const ext = e.animated ? ".gif" : ".png";
- const filename = e.id + ext;
- const url = isEmojis
- ? `https://${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/emojis/${filename}?size=512&quality=lossless`
- : `https://${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}/stickers/${filename}?size=4096&lossless=true`;
+ const getProxyEndpoint = () => {
+ const rawEndpoint = window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT;
+ return rawEndpoint.startsWith("//") ? rawEndpoint.slice(2) : rawEndpoint;
+ };
+
+ const fetchAsset = async (e: any) => {
+ let ext: string;
+ let url: string;
+ const endpoint = getProxyEndpoint();
+
+ if (isEmojis) {
+ ext = e.animated ? ".gif" : ".png";
+ url = `https://${endpoint}/emojis/${e.id}${ext}?size=512&quality=lossless`;
+ } else {
+ ext = "." + StickerExt[e.format_type];
+ const urlExt = e.format_type === 2 ? ".png" : ext;
+ url = `https://${endpoint}/stickers/${e.id}${urlExt}?size=4096&lossless=true`;
+ }
+
+ const sanitizedName = e.name.replace(/[<>:"/\\|?*]/g, "_");
+ let filename = `${sanitizedName}_${e.id}${ext}`;
+
+ let response = await fetch(url);
+
+ if (!isEmojis && e.format_type === 2 && (!response.ok || response.headers.get("content-type")?.includes("text"))) {
+ const gifUrl = `https://${endpoint}/stickers/${e.id}.gif?size=4096&lossless=true`;
+ const gifResponse = await fetch(gifUrl);
+
+ if (gifResponse.ok && !gifResponse.headers.get("content-type")?.includes("text")) {
+ response = gifResponse;
+ ext = ".gif";
+ filename = `${sanitizedName}_${e.id}${ext}`;
+ }
+ }
- const response = await fetch(url);
const blob = await response.blob();
- return { file: new Uint8Array(await blob.arrayBuffer()), filename };
+ const arrayBuffer = await blob.arrayBuffer();
+ return { file: new Uint8Array(arrayBuffer), filename };
};
const assetPromises = items.map(e => fetchAsset(e));