From 63b0be5dcb7b1d9e4855f6e7c095d2483b9a51c7 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:53:21 -0400 Subject: [PATCH 01/70] lint --- src/components/settings/tabs/vencord/index.tsx | 4 ++-- src/plugins/customRPC/index.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/settings/tabs/vencord/index.tsx b/src/components/settings/tabs/vencord/index.tsx index 25b567411..45314324b 100644 --- a/src/components/settings/tabs/vencord/index.tsx +++ b/src/components/settings/tabs/vencord/index.tsx @@ -65,8 +65,8 @@ function EquicordSettings() { description?: string; restartRequired?: boolean; warning?: string; - } - > = [ + }> + = [ { key: "useQuickCss", title: "Enable Custom CSS", diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx index 774cba0e1..887e2c912 100644 --- a/src/plugins/customRPC/index.tsx +++ b/src/plugins/customRPC/index.tsx @@ -230,7 +230,7 @@ function startTimestampLoop() { if (timestampMode !== TimestampMode.CUSTOM || !startTime || !endTime) return; const duration = endTime - startTime; if (duration <= 0) return; - + stopTimestampLoop(); loopAnchor = Date.now(); @@ -262,7 +262,7 @@ export default definePlugin({ settings, start() { - startTimestampLoop(); + startTimestampLoop(); setRpc(); }, stop() { From ba14a9ca870e256737fcc7bceae268151d78b3a4 Mon Sep 17 00:00:00 2001 From: prism Date: Thu, 30 Apr 2026 17:36:09 +0200 Subject: [PATCH 02/70] declutter: show avatars in shop (#1035) --- src/equicordplugins/declutter/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx index 29f43a149..63ebcdc0e 100644 --- a/src/equicordplugins/declutter/index.tsx +++ b/src/equicordplugins/declutter/index.tsx @@ -168,10 +168,10 @@ export default definePlugin({ patches: [ { // Avatar decoration - find: "getAvatarDecorationURL:", + find: "{avatarDecoration:void 0!==", replacement: { - match: /(?<=function \i\(\i\){)(?=.{0,150}let{avatarDecoration)/, - replace: "$&return null;" + match: /\{avatarDecoration:void 0!==(\i)\?\1:\i,canAnimate:/, + replace: "{avatarDecoration:void 0!==$1?$1:null,canAnimate:" }, predicate: () => settings.store.removeAvatarDecoration && !isPluginEnabled("Decor"), }, From 0cb8a34ec678a9b25697500bb3fd8d2f8865672e Mon Sep 17 00:00:00 2001 From: Key Date: Thu, 30 Apr 2026 16:38:47 +0100 Subject: [PATCH 03/70] FileUpload: add pixelvault host and fallback uploader order configuration (#1032) * FileUpload: add pixelvault host - also add optional configuration of fallback order * FileUpload: improve UI of fallback order rows --- src/equicordplugins/fileUpload/native.ts | 42 ++++++++ src/equicordplugins/fileUpload/settings.tsx | 98 ++++++++++++++++++- src/equicordplugins/fileUpload/styles.css | 37 ++++++- src/equicordplugins/fileUpload/types.ts | 23 ++++- .../fileUpload/utils/upload.ts | 90 ++++++++++++++--- 5 files changed, 270 insertions(+), 20 deletions(-) diff --git a/src/equicordplugins/fileUpload/native.ts b/src/equicordplugins/fileUpload/native.ts index e20121dc5..1cd40c374 100644 --- a/src/equicordplugins/fileUpload/native.ts +++ b/src/equicordplugins/fileUpload/native.ts @@ -376,6 +376,48 @@ export async function uploadToFilebin( } } +export async function uploadToPixelVault( + _: IpcMainInvokeEvent, + fileBuffer: ArrayBuffer, + filename: string, + uploadKey: string +): Promise { + try { + const formData = new FormData(); + formData.append("file", new Blob([fileBuffer]), filename); + + const response = await fetch("https://pixelvault.co/", { + method: "POST", + headers: { + Authorization: uploadKey + }, + body: formData + }); + + const text = await response.text(); + let data: { resource?: string; url?: string; } | null = null; + + try { + data = text ? JSON.parse(text) : null; + } catch { + data = null; + } + + if (!response.ok) { + return { success: false, error: `Upload failed: ${response.status} ${text}` }; + } + + const url = data?.resource || data?.url || text.trim(); + if (!url) { + return { success: false, error: "No URL returned from upload" }; + } + + return { success: true, url }; + } catch (e) { + return { success: false, error: e instanceof Error ? e.message : "Unknown error" }; + } +} + export async function fetchFile( _: IpcMainInvokeEvent, diff --git a/src/equicordplugins/fileUpload/settings.tsx b/src/equicordplugins/fileUpload/settings.tsx index 9f2951b16..234b8d85c 100644 --- a/src/equicordplugins/fileUpload/settings.tsx +++ b/src/equicordplugins/fileUpload/settings.tsx @@ -8,14 +8,18 @@ import { definePluginSettings } from "@api/Settings"; import { Button } from "@components/Button"; import { SettingsSection } from "@components/settings/tabs/plugins/components/Common"; import { Switch } from "@components/Switch"; +import { classNameFactory } from "@utils/css"; import { useForceUpdater } from "@utils/react"; import { OptionType } from "@utils/types"; import { React, Select, showToast, TextArea, TextInput, Toasts } from "@webpack/common"; import { CORS_PROXY } from "./constants"; -import { ServiceType } from "./types"; +import { fallbackServiceOrder, serviceLabels, ServiceType } from "./types"; import { parseShareXConfig } from "./utils/sharex"; +const defaultFallbackOrder = fallbackServiceOrder.join(","); +const cl = classNameFactory("vc-file-upload-settings-"); + const serviceOptions = [ { label: "Zipline", value: ServiceType.ZIPLINE, default: true }, { label: "E-Z Host", value: ServiceType.EZHOST }, @@ -29,6 +33,7 @@ const serviceOptions = [ { label: "buzzheavier.com", value: ServiceType.BUZZHEAVIER }, { label: "temp.sh", value: ServiceType.TEMPSH }, { label: "filebin.net", value: ServiceType.FILEBIN }, + { label: "PixelVault", value: ServiceType.PIXELVAULT }, { label: "ShareX Custom Uploader", value: ServiceType.SHAREX } ]; @@ -190,6 +195,18 @@ export const settings = definePluginSettings({ default: "", hidden: true }, + fallbackOrder: { + type: OptionType.STRING, + description: "Fallback uploader order", + default: defaultFallbackOrder, + hidden: true + }, + pixelVaultKey: { + type: OptionType.STRING, + description: "PixelVault upload key", + default: "", + hidden: true + }, uploadTimeoutMs: { type: OptionType.NUMBER, description: "Upload timeout in milliseconds", @@ -271,6 +288,72 @@ function SettingTextInput(props: { ); } +function FallbackOrderSettings() { + const update = useForceUpdater(); + const { store } = settings; + const [dragIndex, setDragIndex] = React.useState(null); + const [order, setOrder] = React.useState(() => { + const configured = (store.fallbackOrder || defaultFallbackOrder) + .split(/[\n,]/) + .map(entry => entry.trim()) + .filter((entry): entry is ServiceType => Object.values(ServiceType).includes(entry as ServiceType)); + + return configured.length === fallbackServiceOrder.length && new Set(configured).size === fallbackServiceOrder.length + ? configured + : fallbackServiceOrder; + }); + + const commitOrder = (nextOrder: ServiceType[]) => { + setOrder(nextOrder); + store.fallbackOrder = nextOrder.join(","); + update(); + }; + + return ( + +
+ {order.map((service, index) => ( +
{ + setDragIndex(index); + event.dataTransfer.effectAllowed = "move"; + event.dataTransfer.setData("text/plain", String(index)); + }} + onDragOver={event => event.preventDefault()} + onDrop={event => { + event.preventDefault(); + const sourceIndex = dragIndex ?? Number(event.dataTransfer.getData("text/plain")); + if (!Number.isInteger(sourceIndex) || sourceIndex === index || sourceIndex < 0 || sourceIndex >= order.length) { + setDragIndex(null); + return; + } + + const nextOrder = [...order]; + const [moved] = nextOrder.splice(sourceIndex, 1); + nextOrder.splice(index, 0, moved); + setDragIndex(null); + commitOrder(nextOrder); + }} + onDragEnd={() => setDragIndex(null)} + data-dragging={dragIndex === index} + > + {serviceLabels[service]} + Drag +
+ ))} +
+
+ +
+
+ ); +} + export function SettingsComponent() { const update = useForceUpdater(); const { store } = settings; @@ -282,6 +365,7 @@ export function SettingsComponent() { const isCatbox = store.serviceType === ServiceType.CATBOX; const isLitterbox = store.serviceType === ServiceType.LITTERBOX; const isGofile = store.serviceType === ServiceType.GOFILE; + const isPixelVault = store.serviceType === ServiceType.PIXELVAULT; const isShareX = store.serviceType === ServiceType.SHAREX; const validateShareXConfig = () => { @@ -482,6 +566,16 @@ export function SettingsComponent() { /> )} + {isPixelVault && ( + store.pixelVaultKey = v} + placeholder="Your PixelVault upload key" + /> + )} + {isShareX && ( <> + + ); } diff --git a/src/equicordplugins/fileUpload/styles.css b/src/equicordplugins/fileUpload/styles.css index 67bcf3893..609929b15 100644 --- a/src/equicordplugins/fileUpload/styles.css +++ b/src/equicordplugins/fileUpload/styles.css @@ -70,4 +70,39 @@ .vc-file-upload-progress-wrap[data-phase="success"] .vc-file-upload-progress-fill { background: var(--status-positive); -} \ No newline at end of file +} + +.vc-file-upload-settings-fallback-order-list { + display: grid; + gap: 6px; +} + +.vc-file-upload-settings-fallback-order-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 8px 10px; + border-radius: 8px; + border: 1px solid var(--border-subtle); + background: var(--background-secondary); + color: var(--text-default); + cursor: grab; +} + +.vc-file-upload-settings-fallback-order-item[data-dragging="true"] { + background: var(--background-modifier-hover); +} + +.vc-file-upload-settings-fallback-order-label { + color: var(--text-default); +} + +.vc-file-upload-settings-fallback-order-handle { + color: var(--text-muted); + font-size: 12px; +} + +.vc-file-upload-settings-fallback-order-actions { + margin-top: 8px; +} diff --git a/src/equicordplugins/fileUpload/types.ts b/src/equicordplugins/fileUpload/types.ts index 2f7c52b57..26bd99d00 100644 --- a/src/equicordplugins/fileUpload/types.ts +++ b/src/equicordplugins/fileUpload/types.ts @@ -17,7 +17,8 @@ export enum ServiceType { TMPFILES = "tmpfiles", BUZZHEAVIER = "buzzheavier", TEMPSH = "tempsh", - FILEBIN = "filebin" + FILEBIN = "filebin", + PIXELVAULT = "pixelvault" } export const serviceLabels: Record = { @@ -33,9 +34,27 @@ export const serviceLabels: Record = { [ServiceType.TMPFILES]: "tmpfiles.org", [ServiceType.BUZZHEAVIER]: "buzzheavier.com", [ServiceType.TEMPSH]: "temp.sh", - [ServiceType.FILEBIN]: "filebin.net" + [ServiceType.FILEBIN]: "filebin.net", + [ServiceType.PIXELVAULT]: "PixelVault" }; +export const fallbackServiceOrder: ServiceType[] = [ + ServiceType.ZIPLINE, + ServiceType.EZHOST, + ServiceType.NEST, + ServiceType.S3, + ServiceType.CATBOX, + ServiceType.ZEROX0, + ServiceType.LITTERBOX, + ServiceType.GOFILE, + ServiceType.TMPFILES, + ServiceType.BUZZHEAVIER, + ServiceType.TEMPSH, + ServiceType.FILEBIN, + ServiceType.PIXELVAULT, + ServiceType.SHAREX +]; + export interface UploadResponse { files: { id: string; diff --git a/src/equicordplugins/fileUpload/utils/upload.ts b/src/equicordplugins/fileUpload/utils/upload.ts index 48ba36891..ee749ba8c 100644 --- a/src/equicordplugins/fileUpload/utils/upload.ts +++ b/src/equicordplugins/fileUpload/utils/upload.ts @@ -6,7 +6,7 @@ import { normalizeCorsProxyUrl, toProxiedUrl } from "@equicordplugins/fileUpload/constants"; import { settings } from "@equicordplugins/fileUpload/settings"; -import { serviceLabels, ServiceType, ShareXUploaderConfig, UploadResponse } from "@equicordplugins/fileUpload/types"; +import { fallbackServiceOrder, serviceLabels, ServiceType, ShareXUploaderConfig, UploadResponse } from "@equicordplugins/fileUpload/types"; import { copyToClipboard } from "@utils/clipboard"; import { insertTextIntoChatInputBox } from "@utils/discord"; import { Logger } from "@utils/Logger"; @@ -77,6 +77,18 @@ function isUploadCancelledError(error: unknown): boolean { return message.includes("cancelled") || message.includes("canceled") || message.includes("aborted") || message.includes("aborterror"); } +function getFallbackServices(): ServiceType[] { + const configuredOrder = (settings.store as { fallbackOrder?: string; }).fallbackOrder || fallbackServiceOrder.join(","); + const services = configuredOrder + .split(/[\n,]/) + .map(service => service.trim()) + .filter((service): service is ServiceType => Object.values(ServiceType).includes(service as ServiceType)); + + return services.length === fallbackServiceOrder.length && new Set(services).size === fallbackServiceOrder.length + ? services + : fallbackServiceOrder; +} + function emitUploadState() { for (const listener of uploadStateListeners) { listener(); @@ -363,6 +375,8 @@ export function isConfigured(): boolean { case ServiceType.TEMPSH: case ServiceType.FILEBIN: return true; + case ServiceType.PIXELVAULT: + return Boolean((settings.store as { pixelVaultKey?: string; }).pixelVaultKey); case ServiceType.SHAREX: try { parseShareXConfigFromSettings(); @@ -647,6 +661,59 @@ async function uploadToFilebin(fileBlob: Blob, filename: string): Promise { + const { pixelVaultKey } = settings.store as { pixelVaultKey?: string; }; + + if (!pixelVaultKey?.trim()) { + throw new Error("PixelVault upload key is required"); + } + + if (Native) { + const result = await Native.uploadToPixelVault(await fileBlob.arrayBuffer(), filename, pixelVaultKey.trim()); + + if (!result.success) { + throw new Error(result.error || "Upload failed"); + } + + if (!result.url) { + throw new Error("No URL returned from upload"); + } + + return result.url; + } + + const formData = new FormData(); + formData.append("file", fileBlob, filename); + + const response = await fetchWithTimeout("https://pixelvault.co/", { + method: "POST", + headers: { + Authorization: pixelVaultKey.trim() + }, + body: formData + }); + + const text = await response.text(); + let data: { resource?: string; url?: string; } | null = null; + + try { + data = text ? JSON.parse(text) : null; + } catch { + data = null; + } + + if (!response.ok) { + throw new Error(`Upload failed: ${response.status} ${text}`); + } + + const url = data?.resource || data?.url || text.trim(); + if (!url) { + throw new Error("No URL returned from upload"); + } + + return url; +} + async function uploadToService(serviceType: ServiceType, fileBlob: Blob, filename: string): Promise { switch (serviceType) { case ServiceType.ZIPLINE: @@ -675,22 +742,13 @@ async function uploadToService(serviceType: ServiceType, fileBlob: Blob, filenam return uploadToTempSh(fileBlob, filename); case ServiceType.FILEBIN: return uploadToFilebin(fileBlob, filename); + case ServiceType.PIXELVAULT: + return uploadToPixelVault(fileBlob, filename); default: throw new Error("Unknown service type"); } } -const FALLBACK_SERVICES: ServiceType[] = [ - ServiceType.CATBOX, - ServiceType.LITTERBOX, - ServiceType.ZEROX0, - ServiceType.TMPFILES, - ServiceType.GOFILE, - ServiceType.BUZZHEAVIER, - ServiceType.TEMPSH, - ServiceType.FILEBIN -]; - const EXE_BLOCKED_SERVICES = new Set([ ServiceType.CATBOX, ServiceType.LITTERBOX, @@ -768,12 +826,12 @@ function buildUploadOrder(primary: ServiceType, fileName: string): ServiceType[] const disableFallbacks = Boolean((settings.store as { disableFallbacks?: boolean; }).disableFallbacks); const effectivePrimary = normalizePrimaryService(primary, fileName); - if (disableFallbacks || effectivePrimary === ServiceType.SHAREX || effectivePrimary === ServiceType.S3 || effectivePrimary === ServiceType.ZIPLINE || effectivePrimary === ServiceType.NEST || effectivePrimary === ServiceType.EZHOST) { - return [effectivePrimary]; + const order: ServiceType[] = [effectivePrimary]; + if (disableFallbacks) { + return order; } - const order: ServiceType[] = [effectivePrimary]; - for (const fallback of FALLBACK_SERVICES) { + for (const fallback of getFallbackServices()) { if (fallback !== effectivePrimary && canServiceHandleFile(fallback, fileName)) { order.push(fallback); } From 94691093b36bb3c31840e45fdf3359795d2e4d63 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:49:06 -0400 Subject: [PATCH 04/70] Declutter: Fix Decor Conflict --- src/equicordplugins/declutter/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx index 63ebcdc0e..e37f9218d 100644 --- a/src/equicordplugins/declutter/index.tsx +++ b/src/equicordplugins/declutter/index.tsx @@ -11,6 +11,7 @@ import { definePluginSettings, migrateOldSettingToNewPlugin, migratePluginSettin import { Divider } from "@components/Divider"; import { HeadingSecondary } from "@components/Heading"; import { Notice } from "@components/Notice"; +import decor from "@plugins/decor"; import { classNameFactory } from "@utils/css"; import { Devs, EquicordDevs } from "@utils/index"; import definePlugin, { OptionType } from "@utils/types"; @@ -170,10 +171,10 @@ export default definePlugin({ // Avatar decoration find: "{avatarDecoration:void 0!==", replacement: { - match: /\{avatarDecoration:void 0!==(\i)\?\1:\i,canAnimate:/, - replace: "{avatarDecoration:void 0!==$1?$1:null,canAnimate:" + match: /\{avatarDecoration:(.{0,30}void 0!==\i\?\i:)\i/, + replace: "{avatarDecoration:$1null" }, - predicate: () => settings.store.removeAvatarDecoration && !isPluginEnabled("Decor"), + predicate: () => settings.store.removeAvatarDecoration && !isPluginEnabled(decor.name), }, { // Nameplate From 53869f2df9e16cb01ac2f8bc6b61abe0d7a90ca9 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:00:15 -0400 Subject: [PATCH 05/70] Declutter: test fix --- src/equicordplugins/declutter/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx index e37f9218d..b897392a5 100644 --- a/src/equicordplugins/declutter/index.tsx +++ b/src/equicordplugins/declutter/index.tsx @@ -171,7 +171,7 @@ export default definePlugin({ // Avatar decoration find: "{avatarDecoration:void 0!==", replacement: { - match: /\{avatarDecoration:(.{0,30}void 0!==\i\?\i:)\i/, + match: /\{avatarDecoration:(.{0,40}void 0!==\i\?\i:)\i/, replace: "{avatarDecoration:$1null" }, predicate: () => settings.store.removeAvatarDecoration && !isPluginEnabled(decor.name), From 60f524bba59b80ca87df496235c99564f4c2e5d3 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:01:54 -0400 Subject: [PATCH 06/70] #1027 --- src/equicordplugins/userpluginInstaller.dev/index.tsx | 2 ++ src/equicordplugins/userpluginInstaller.dev/native.ts | 11 +++++++++-- .../userpluginInstaller.dev/yaml-js.d.ts | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/equicordplugins/userpluginInstaller.dev/yaml-js.d.ts diff --git a/src/equicordplugins/userpluginInstaller.dev/index.tsx b/src/equicordplugins/userpluginInstaller.dev/index.tsx index 98e884661..b0919edf6 100644 --- a/src/equicordplugins/userpluginInstaller.dev/index.tsx +++ b/src/equicordplugins/userpluginInstaller.dev/index.tsx @@ -95,6 +95,8 @@ export default definePlugin({ cancelText: "Later" }); + await Native.ensurePluginsDirectory(); + plSettings.customEntries.push(this.section); this.pluginsWithUpdates.registerCallback((value, id) => { diff --git a/src/equicordplugins/userpluginInstaller.dev/native.ts b/src/equicordplugins/userpluginInstaller.dev/native.ts index 1203b4a85..579190072 100644 --- a/src/equicordplugins/userpluginInstaller.dev/native.ts +++ b/src/equicordplugins/userpluginInstaller.dev/native.ts @@ -8,7 +8,7 @@ import { NativeSettings } from "@main/settings"; import { exec, spawn } from "child_process"; import { BrowserWindow, dialog, shell, WebContentsView } from "electron"; import { existsSync, readdirSync, readFileSync } from "fs"; -import { readdir, readFile, rm } from "fs/promises"; +import { mkdir, readdir, readFile, rm } from "fs/promises"; import { basename, join } from "path"; import yaml from "yaml-js"; @@ -19,12 +19,19 @@ import setGitPathContent from "./misc/setGitPath.txt"; // @ts-ignore fuck off import updateValidateContent from "./misc/updateValidate.txt"; // see above -const PLUGIN_META_REGEX = /export default definePlugin\((?:\s|\/(?:\/|\*).*)*{\s*(?:\s|\/(?:\/|\*).*)*name:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*,(?:\s|\/(?:\/|\*).*)*(?:\s|\/(?:\/|\*).*)*description:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*/; +const PLUGIN_META_REGEX = /export default definePlugin\((?:\s|\/(?:\/|\*).*)*{\s*(?:\s|\/(?:\/|\*).*)*name:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*,(?:\s|\/(?:\/|\*).*)*.+(?:\s|\/(?:\/|\*).*)*description:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*/; // if edited, also edit in misc/constants.ts!!! const CLONE_LINK_REGEX = /https:\/\/(?:((?:git(?:hub|lab)\.com|git\.(?:[a-zA-Z0-9]|\.)+|codeberg\.org))\/(?!user-attachments)((?:[a-zA-Z0-9]|-)+)\/((?:[a-zA-Z0-9]|-|\.)+)(?:\.git)?|(plugins\.(nin0)\.dev)\/((?:[a-zA-Z0-9]|-|\.)+))(?:\/)?/; const vencordPath = ["desktop", "equibop"].includes(basename(__dirname)) ? join(__dirname, "../") : __dirname; +export async function ensurePluginsDirectory(_: any) { + if (!IS_DEV) return; + try { + await mkdir(join(vencordPath, "../src/userplugins"), { recursive: true }); + } catch(e) { } +} + export async function rmPlugin(_, name: string): Promise { // eslint-disable-next-line return new Promise(async (resolve, reject) => { diff --git a/src/equicordplugins/userpluginInstaller.dev/yaml-js.d.ts b/src/equicordplugins/userpluginInstaller.dev/yaml-js.d.ts new file mode 100644 index 000000000..0119167a7 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/yaml-js.d.ts @@ -0,0 +1,9 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +declare module "yaml-js" { + export function load(yaml: string): any; +} From 6b209b2ab2786d9383e20da2c714fb56290833ac Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:08:11 -0400 Subject: [PATCH 07/70] declutter --- src/equicordplugins/declutter/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx index b897392a5..6ed8a4245 100644 --- a/src/equicordplugins/declutter/index.tsx +++ b/src/equicordplugins/declutter/index.tsx @@ -169,10 +169,10 @@ export default definePlugin({ patches: [ { // Avatar decoration - find: "{avatarDecoration:void 0!==", + find: "isAvatarDecorationAnimating:", replacement: { - match: /\{avatarDecoration:(.{0,40}void 0!==\i\?\i:)\i/, - replace: "{avatarDecoration:$1null" + match: /(?<=\{avatarDecoration:.{0,40}?)(void 0!==\i\?\i:)\i(?=\)?,canAnimate:)/, + replace: "$1null" }, predicate: () => settings.store.removeAvatarDecoration && !isPluginEnabled(decor.name), }, From 29c18e8ec1f16c0b1bafc015d958f19ffb694b49 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:14:46 -0400 Subject: [PATCH 08/70] Try to fix indexeddb stuff --- src/equicordplugins/equicordHelper/index.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/equicordplugins/equicordHelper/index.tsx b/src/equicordplugins/equicordHelper/index.tsx index 1123c8dff..73c144006 100644 --- a/src/equicordplugins/equicordHelper/index.tsx +++ b/src/equicordplugins/equicordHelper/index.tsx @@ -309,6 +309,20 @@ export default definePlugin({ } ], predicate: () => Settings.winNativeTitleBar, + }, + { + find: ".completeOperation(", + replacement: { + match: /(?<=this\.nextId\(\);)(\i\(\i\)),(.{0,200}reject:\i\}\))/, + replace: "$2,$1" + } + }, + { + find: "discarding speculative database", + replacement: { + match: /await (\i)\((\i)\)(?=;.{0,15}this\.databases)/, + replace: "$&.catch(()=>null)" + } } ], renderMessageAccessory(props) { From cd1b5dea31954cea338ae9c341212b43315b5025 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:15:52 -0400 Subject: [PATCH 09/70] EquicordHelper: note down patches --- src/equicordplugins/equicordHelper/index.tsx | 30 +++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/equicordplugins/equicordHelper/index.tsx b/src/equicordplugins/equicordHelper/index.tsx index 73c144006..05d040a22 100644 --- a/src/equicordplugins/equicordHelper/index.tsx +++ b/src/equicordplugins/equicordHelper/index.tsx @@ -172,6 +172,22 @@ export default definePlugin({ } ] }, + // Fix a race condition? + { + find: ".completeOperation(", + replacement: { + match: /(?<=this\.nextId\(\);)(\i\(\i\)),(.{0,200}reject:\i\}\))/, + replace: "$2,$1" + } + }, + // catch if it cant open + { + find: "discarding speculative database", + replacement: { + match: /await (\i)\((\i)\)(?=;.{0,15}this\.databases)/, + replace: "$&.catch(()=>null)" + } + }, // When focused on voice channel or group chat voice call { find: ".STATUS_WARNING_BACKGROUND})})", @@ -310,20 +326,6 @@ export default definePlugin({ ], predicate: () => Settings.winNativeTitleBar, }, - { - find: ".completeOperation(", - replacement: { - match: /(?<=this\.nextId\(\);)(\i\(\i\)),(.{0,200}reject:\i\}\))/, - replace: "$2,$1" - } - }, - { - find: "discarding speculative database", - replacement: { - match: /await (\i)\((\i)\)(?=;.{0,15}this\.databases)/, - replace: "$&.catch(()=>null)" - } - } ], renderMessageAccessory(props) { return ( From caab1fd59abf0d5a7625e9e93ab2a2612971fe8f Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:16:39 -0400 Subject: [PATCH 10/70] fix most patches --- src/equicordplugins/equicordHelper/index.tsx | 2 +- .../instantScreenshare/index.tsx | 2 +- src/equicordplugins/questify/index.tsx | 28 +++++-------------- src/plugins/implicitRelationships/index.ts | 2 +- 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/equicordplugins/equicordHelper/index.tsx b/src/equicordplugins/equicordHelper/index.tsx index 05d040a22..40ddf07a0 100644 --- a/src/equicordplugins/equicordHelper/index.tsx +++ b/src/equicordplugins/equicordHelper/index.tsx @@ -281,7 +281,7 @@ export default definePlugin({ }, // Removes Modal Animation { - find: "renderLurkerModeUpsellPopout,position:", + find: ".SWITCH_THUMB_BACKGROUND_SELECTED_DEFAULT)", predicate: () => settings.store.noModalAnimation, replacement: { match: /200:300/g, diff --git a/src/equicordplugins/instantScreenshare/index.tsx b/src/equicordplugins/instantScreenshare/index.tsx index b947da3c1..c65def667 100644 --- a/src/equicordplugins/instantScreenshare/index.tsx +++ b/src/equicordplugins/instantScreenshare/index.tsx @@ -100,7 +100,7 @@ export default definePlugin({ }, }, { - find: "keybindActionTypes()", + find: '"push-to-talk-priority"', predicate: () => settings.store.keybindScreenshare, replacement: { match: /=\[(\{id:.{0,25}value:\i\.\i\.UNASSIGNED)/, diff --git a/src/equicordplugins/questify/index.tsx b/src/equicordplugins/questify/index.tsx index 1a20baa65..fb7100dcb 100644 --- a/src/equicordplugins/questify/index.tsx +++ b/src/equicordplugins/questify/index.tsx @@ -1400,9 +1400,9 @@ export default definePlugin({ patches: [ { // Needed for GuildlessServerListItemComponent component in components.tsx - find: "=\"DOWNLOAD_APPS\";function", + find: '="DOWNLOAD_APPS";function', replacement: { - match: /(?<=function\(\i,\i,\i\){\i.\i\(\i,{)(?=.{0,25000}?ariaHidden:!0,asContainer:!\i,children:\i}\)}var \i=\i\(\d+\);let (\i)=\i.forwardRef\(function)/, + match: /(?=\i:\(\)=>\i.*?asContainer:!\i.{0,50};let (\i)=\i.forwardRef\(function)/, replace: "GuildlessServerListItemComponent:()=>$1," } }, @@ -1809,24 +1809,6 @@ export default definePlugin({ } ] }, - { - // Adds support for dev://experiment/2025-12-quest-cta-refactor-rollout - find: "WATCH_VIDEO?async()=>{await", - replacement: [ - { - match: /(?=let{quest:)/, - replace: "const questifyText=$self.getQuestUnacceptedButtonText(arguments[0].quest)??$self.getQuestAcceptedButtonText(arguments[0].quest);" - }, - { - match: /(?<=}\),)(\i\?\.\(\))/, - replace: "!$self.processQuestForAutoComplete(arguments[0].quest,true)&&($1)" - }, - { - match: /(?<=,text:)(\i),icon:\i/, - replace: "questifyText??$1" - } - ] - }, { // Same thing as above, maybe? Different location though. find: ".ACCEPT_QUEST),", @@ -1842,7 +1824,11 @@ export default definePlugin({ { match: /(?<="primary",onClick:)(\i)/, replace: "()=>{!$self.processQuestForAutoComplete(arguments[0].quest,true)&&$1()}" - } + }, + { + match: /(?<=\}\),)(\i\?\.\(\))/, + replace: "!$self.processQuestForAutoComplete(arguments[0].quest,true)&&($1)" + }, ] }, { diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 8600894f2..6a51c89a4 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -96,7 +96,7 @@ export default definePlugin({ { find: ".REQUEST_GUILD_MEMBERS,", replacement: { - match: /\.send\(\i\.\i\.REQUEST_GUILD_MEMBERS,{/, + match: /\.send\(\i\.REQUEST_GUILD_MEMBERS,{/, replace: "$&nonce:arguments[1].nonce," } }, From c1022cc3920f49420e571efe0fadb097387c1b89 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 21:10:10 -0400 Subject: [PATCH 11/70] fix some more patches --- src/plugins/decor/index.tsx | 14 ++++---------- src/plugins/experiments/index.tsx | 18 ++---------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx index 6bb5eb097..03f468b23 100644 --- a/src/plugins/decor/index.tsx +++ b/src/plugins/decor/index.tsx @@ -111,16 +111,10 @@ export default definePlugin({ // Patch avatar decoration preview to display Decor avatar decorations as if they are purchased { find: "#{intl::PREMIUM_UPSELL_PROFILE_AVATAR_DECO_INLINE_UPSELL_DESCRIPTION}", - replacement: [ - { - match: /(#{intl::PREMIUM_UPSELL_PROFILE_AVATAR_DECO_INLINE_UPSELL_DESCRIPTION}.+?return null!=(\i)&&\()(null==\i)/, - replace: (_, rest, avatarDecoration, hasPurchase) => `${rest}(${avatarDecoration}.skuId!==$self.SKU_ID&&${avatarDecoration}.skuId!==$self.RAW_SKU_ID&&${hasPurchase})` - }, - { - match: /(?<==)\i=>{let{user:\i,guildId:\i,avatarDecoration:/, - replace: "$self.AvatarDecorationModalPreview=$&" - } - ] + replacement: { + match: /(?<==)\i=>{let{user:\i,guildId:\i,avatarDecoration:/, + replace: "$self.AvatarDecorationModalPreview=$&" + } } ], settings, diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index 9105d2d86..ed6e67cee 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -15,13 +15,11 @@ import { Devs, IS_MAC } from "@utils/constants"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { React } from "@webpack/common"; +import { ExperimentStore, React } from "@webpack/common"; import hideBugReport from "./hideBugReport.css?managed"; const KbdStyles = findByPropsLazy("key", "combo"); -let BugReporterExperiment: any; - const modKey = IS_MAC ? "cmd" : "ctrl"; const altKey = IS_MAC ? "opt" : "alt"; @@ -147,19 +145,7 @@ export default definePlugin({ } ] }, - { - find: "2026-01-bug-reporter", - replacement: { - match: /(?<==)(?=\(0,\i\(.+?\)\.\i\)\({name:"2026-01-bug-reporter")/, - replace: "$self.BugReporterExperiment=" - } - } ], - - set BugReporterExperiment(value: any) { - BugReporterExperiment = value; - }, - matchExperiment(url: string, label: string): boolean { const items = url.split("/"); const labelCleaned = label.replace(/[^a-zA-Z0-9]+/g, "").toLowerCase(); @@ -167,7 +153,7 @@ export default definePlugin({ return !!labelCleaned && urlEndCleaned !== undefined && labelCleaned === urlEndCleaned; }, - start: () => !BugReporterExperiment.getConfig().hasBugReporterAccess && enableStyle(hideBugReport), + start: () => ExperimentStore.getUserExperimentBucket("2026-01-bug-reporter") > 0 && enableStyle(hideBugReport), stop: () => disableStyle(hideBugReport), settingsAboutComponent: () => { From 68e465c0b77726ff9b3ef42c678bd85a53e0e7a2 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 21:34:11 -0400 Subject: [PATCH 12/70] NoTrack: Noop --- src/plugins/_core/noTrack.ts | 4 ++-- src/plugins/implicitRelationships/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts index ea7c9f09f..6fcb4daba 100644 --- a/src/plugins/_core/noTrack.ts +++ b/src/plugins/_core/noTrack.ts @@ -44,8 +44,8 @@ export default definePlugin({ find: "AnalyticsActionHandlers.handle", predicate: () => settings.store.disableAnalytics, replacement: { - match: /^.+$/, - replace: "()=>{}", + match: /\(0,\i\.analyticsTrackingStoreMaker\)/, + replace: "(()=>{})", }, }, { diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 6a51c89a4..143316e41 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -96,7 +96,7 @@ export default definePlugin({ { find: ".REQUEST_GUILD_MEMBERS,", replacement: { - match: /\.send\(\i\.REQUEST_GUILD_MEMBERS,{/, + match: /\.send\(\i\.(?:\i\.)?REQUEST_GUILD_MEMBERS,{/, replace: "$&nonce:arguments[1].nonce," } }, From 14508c1537611d2bb9567380dec21c82139a8434 Mon Sep 17 00:00:00 2001 From: thororen <78185467+thororen1234@users.noreply.github.com> Date: Thu, 30 Apr 2026 22:28:32 -0400 Subject: [PATCH 13/70] Fix NoTrack, Experiments & ImplicitRelationships (#4162) --- src/plugins/_core/noTrack.ts | 4 ++-- src/plugins/experiments/index.tsx | 17 +++-------------- src/plugins/implicitRelationships/index.ts | 4 ++-- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts index ea7c9f09f..6fcb4daba 100644 --- a/src/plugins/_core/noTrack.ts +++ b/src/plugins/_core/noTrack.ts @@ -44,8 +44,8 @@ export default definePlugin({ find: "AnalyticsActionHandlers.handle", predicate: () => settings.store.disableAnalytics, replacement: { - match: /^.+$/, - replace: "()=>{}", + match: /\(0,\i\.analyticsTrackingStoreMaker\)/, + replace: "(()=>{})", }, }, { diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index 7447d532f..034b2323a 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -25,12 +25,11 @@ import { Devs, IS_MAC } from "@utils/constants"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { Forms, React } from "@webpack/common"; +import { ExperimentStore, Forms, React } from "@webpack/common"; import hideBugReport from "./hideBugReport.css?managed"; const KbdStyles = findByPropsLazy("key", "combo"); -let BugReporterExperiment: any; const modKey = IS_MAC ? "cmd" : "ctrl"; const altKey = IS_MAC ? "opt" : "alt"; @@ -128,20 +127,10 @@ export default definePlugin({ replace: "$&if($1==null)return;" } }, - { - find: "2026-01-bug-reporter", - replacement: { - match: /(?<==)(?=\(0,\i\(.+?\)\.\i\)\({name:"2026-01-bug-reporter")/, - replace: "$self.BugReporterExperiment=" - } - } + ], - set BugReporterExperiment(value: any) { - BugReporterExperiment = value; - }, - - start: () => !BugReporterExperiment.getConfig().hasBugReporterAccess && enableStyle(hideBugReport), + start: () => ExperimentStore.getUserExperimentBucket("2026-01-bug-reporter") > 0 && enableStyle(hideBugReport), stop: () => disableStyle(hideBugReport), settingsAboutComponent: () => { diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 3af463e3f..905b341a6 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -96,8 +96,8 @@ export default definePlugin({ { find: ".REQUEST_GUILD_MEMBERS,", replacement: { - match: /\.send\(\i\.\i\.REQUEST_GUILD_MEMBERS,{/, - replace: "$&nonce:arguments[1].nonce," + match: /\.REQUEST_GUILD_MEMBERS,{/, + replace: "$&nonce:arguments[1]?.nonce," } }, { From 359386daed5128df89a39b724f86fcc13e3a791b Mon Sep 17 00:00:00 2001 From: Key Date: Fri, 1 May 2026 03:32:18 +0100 Subject: [PATCH 14/70] fix(QuickReply): bug in the conflict check for NoBlockedMessages (#1039) --- src/plugins/quickReply/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/quickReply/index.ts b/src/plugins/quickReply/index.ts index 3696a5b34..1c963873a 100644 --- a/src/plugins/quickReply/index.ts +++ b/src/plugins/quickReply/index.ts @@ -143,7 +143,7 @@ function getNextMessage(isUp: boolean, isReply: boolean) { if (!isReply && m.author.id !== meId) return false; // editing only own messages if (!MessageTypeSets.REPLYABLE.has(m.type) || m.hasFlag(MessageFlags.EPHEMERAL)) return false; if (settings.store.ignoreBlockedAndIgnored && RelationshipStore.isBlockedOrIgnored(m.author.id)) return false; - if (hasNoBlockedMessages && NoBlockedMessagesPlugin.isSuppressed(m)) return false; + if (hasNoBlockedMessages && NoBlockedMessagesPlugin.isSuppressed(m).suppressed) return false; return true; }); From 599d761005fc09c3f5824b5d267ae552b6e8a9af Mon Sep 17 00:00:00 2001 From: Jake <134332787+justjxke@users.noreply.github.com> Date: Fri, 1 May 2026 03:33:38 +0100 Subject: [PATCH 15/70] fix: restore icon viewer and zip preview icons (#1036) --- scripts/build/common.mjs | 2 +- scripts/generatePluginList.ts | 4 +-- src/components/Icons.tsx | 28 +++++++++++++++++++ .../_core/concatenatedModules.tsx | 2 +- src/equicordplugins/zipPreview/components.tsx | 16 +++++------ src/equicordplugins/zipPreview/style.css | 11 ++++---- 6 files changed, 46 insertions(+), 17 deletions(-) diff --git a/scripts/build/common.mjs b/scripts/build/common.mjs index 5e55e1b63..a009f0f0b 100644 --- a/scripts/build/common.mjs +++ b/scripts/build/common.mjs @@ -147,7 +147,7 @@ export const globPlugins = kind => ({ }); build.onLoad({ filter, namespace: "import-plugins" }, async () => { - const pluginDirs = ["plugins/_api", "plugins/_core", "plugins", "equicordplugins", "equicordplugins/_api", "userplugins"]; + const pluginDirs = ["plugins/_api", "plugins/_core", "plugins", "equicordplugins/_api", "equicordplugins/_core", "equicordplugins", "userplugins"]; let code = ""; let pluginsCode = "\n"; let metaCode = "\n"; diff --git a/scripts/generatePluginList.ts b/scripts/generatePluginList.ts index 76a03bd60..d4cb347e9 100644 --- a/scripts/generatePluginList.ts +++ b/scripts/generatePluginList.ts @@ -31,11 +31,11 @@ import { getEntryPoint, isPluginFile, parseDevs, parseEquicordDevs, parseFile, P let dirs: string[]; if (equicordFlag) { - dirs = ["src/equicordplugins"]; + dirs = ["src/equicordplugins/_core", "src/equicordplugins"]; } else if (vencordFlag) { dirs = ["src/plugins", "src/plugins/_core"]; } else { - dirs = ["src/plugins", "src/plugins/_core", "src/equicordplugins"]; + dirs = ["src/plugins", "src/plugins/_core", "src/equicordplugins/_core", "src/equicordplugins"]; } const outputPath = args.find(a => !a.startsWith("--")) ?? null; diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx index c0ff49a33..afee7b18a 100644 --- a/src/components/Icons.tsx +++ b/src/components/Icons.tsx @@ -730,6 +730,34 @@ export function ClockIcon(props: IconProps) { ); } +export function ChevronSmallDownIcon(props: IconProps) { + return ( + + + + ); +} + +export function ChevronSmallUpIcon(props: IconProps) { + return ( + + + + ); +} + export function DownArrow(props: IconProps) { return ( (null); const animationTimeoutRef = useRef(null); const loadRequestIdRef = useRef(0); @@ -148,9 +150,7 @@ export function ZipPreviewInline(props: ZipPreviewAttachmentProps) { setExpanded(!isExpanded); }} > - {isExpanded - ? - : } + ); @@ -193,8 +193,8 @@ function ZipPreviewBreadcrumb({ path, onNavigate }: { path: string; onNavigate: if (!path) { return (
- - / + + /
); } @@ -203,7 +203,7 @@ function ZipPreviewBreadcrumb({ path, onNavigate }: { path: string; onNavigate: return (
- + + ))} +
+ ); +} + function FallbackOrderSettings() { const update = useForceUpdater(); const { store } = settings; @@ -413,21 +467,18 @@ export function SettingsComponent() { return ( <> - - v === store.embedProxyService} - select={v => { - store.embedProxyService = v; - update(); - }} - serialize={v => v} - placeholder="Select an embed proxy service" - /> - - )} + {store.embedProxyEnabled && ( + + v === (store.uploadTimeoutMs || 300000)} - select={v => { - store.uploadTimeoutMs = v; - update(); - }} - serialize={v => v} - placeholder="Select timeout" + + store.corsProxyUrl = v} + placeholder="https://your-cors-proxy.example.com" /> - + + + codeberg.org/key/corsproxy + + + + v === state} serialize={v => String(v)} - isDisabled={option.disabled?.call(definedSettings) ?? false} - {...option.componentProps} + isDisabled={isSettingDisabled(definedSettings, setting)} + {...setting.componentProps} /> ); diff --git a/src/components/settings/tabs/plugins/components/SliderSetting.tsx b/src/components/settings/tabs/plugins/components/SliderSetting.tsx index 85a52da29..55828ae21 100644 --- a/src/components/settings/tabs/plugins/components/SliderSetting.tsx +++ b/src/components/settings/tabs/plugins/components/SliderSetting.tsx @@ -16,18 +16,19 @@ * along with this program. If not, see . */ -import { PluginOptionSlider } from "@utils/types"; +import { isSettingDisabled } from "@api/PluginManager"; +import { PluginSettingSliderDef } from "@utils/types"; import { React, Slider, useState } from "@webpack/common"; import { resolveError, SettingProps, SettingsSection } from "./Common"; -export function SliderSetting({ option, pluginSettings, definedSettings, id, onChange }: SettingProps) { - const def = pluginSettings[id] ?? option.default; +export function SliderSetting({ setting, pluginSettings, definedSettings, id, onChange }: SettingProps) { + const def = pluginSettings[id] ?? setting.default; const [error, setError] = useState(null); function handleChange(newValue: number): void { - const isValid = option.isValid?.call(definedSettings, newValue) ?? true; + const isValid = setting.isValid?.call(definedSettings, newValue) ?? true; setError(resolveError(isValid)); @@ -37,17 +38,17 @@ export function SliderSetting({ option, pluginSettings, definedSettings, id, onC } return ( - + String(v.toFixed(2))} - stickToMarkers={option.stickToMarkers ?? true} - disabled={option.disabled?.call(definedSettings) ?? false} - {...option.componentProps} + stickToMarkers={setting.stickToMarkers ?? true} + disabled={isSettingDisabled(definedSettings, setting)} + {...setting.componentProps} /> ); diff --git a/src/components/settings/tabs/plugins/components/TextSetting.tsx b/src/components/settings/tabs/plugins/components/TextSetting.tsx index ad60a1111..cd61a3b8e 100644 --- a/src/components/settings/tabs/plugins/components/TextSetting.tsx +++ b/src/components/settings/tabs/plugins/components/TextSetting.tsx @@ -16,17 +16,18 @@ * along with this program. If not, see . */ -import { PluginOptionString } from "@utils/types"; +import { isSettingDisabled } from "@api/PluginManager"; +import { PluginSettingStringDef } from "@utils/types"; import { React, TextArea, TextInput, useState } from "@webpack/common"; import { resolveError, SettingProps, SettingsSection } from "./Common"; -export function TextSetting({ option, pluginSettings, definedSettings, id, onChange }: SettingProps) { - const [state, setState] = useState(pluginSettings[id] ?? option.default ?? null); +export function TextSetting({ setting, pluginSettings, definedSettings, id, onChange }: SettingProps) { + const [state, setState] = useState(pluginSettings[id] ?? setting.default ?? null); const [error, setError] = useState(null); function handleChange(newValue: string) { - const isValid = option.isValid?.call(definedSettings, newValue) ?? true; + const isValid = setting.isValid?.call(definedSettings, newValue) ?? true; setState(newValue); setError(resolveError(isValid)); @@ -37,22 +38,22 @@ export function TextSetting({ option, pluginSettings, definedSettings, id, onCha } return ( - - {option.multiline + + {setting.multiline ?