From 4caaef0027f35e2ad741209bdcd2d977229b778a Mon Sep 17 00:00:00 2001 From: prism Date: Sat, 21 Feb 2026 00:21:23 +0100 Subject: [PATCH 1/2] chore: add .rules and symlink agent config files (#820) * chore: add .rules and symlink agent config files * Update rules for testing and file modification Clarify rules regarding testing commands and file modifications. --------- Co-authored-by: thororen <78185467+thororen1234@users.noreply.github.com> --- .rules | 211 +++++++++++++++++++++++++++++++++++++++++++++++ AGENTS.md | 241 +----------------------------------------------------- CLAUDE.md | 2 +- GEMINI.md | 1 + 4 files changed, 214 insertions(+), 241 deletions(-) create mode 100644 .rules mode change 100644 => 120000 AGENTS.md create mode 120000 GEMINI.md diff --git a/.rules b/.rules new file mode 100644 index 000000000..bb29e237f --- /dev/null +++ b/.rules @@ -0,0 +1,211 @@ +# Equicord Development Guidelines + +## Critical Rules + +- **NEVER** edit existing license headers. New files use 2026. +- Push back when the user idea is wrong or not correct. +- **NEVER** git checkout files without explicit permission. +- Always verify components/functions arent deprecated before using. +- **NEVER** use `any` for Discord objects. Import proper types from `@vencord/discord-types`. +- Fix with smallest possible change. No refactoring unless explicitly asked. +- Solve the problem at hand only. No patterns for patterns sake. +- **NEVER** overengineer. No premature abstractions, no helpers for one-time operations, no building for hypothetical futures. Three similar lines is better than a premature abstraction. +- Write modern, robust, professional code. Use current language features, proper error handling, and clean structure. +- Write natural human text in errors, descriptions, messages. No dashes or robotic formatting. Write like "Module not found" not "Module - not found". Keep it simple and conversational. + +## Code Rules + +- **DELETE** dead code, dont comment it. Git preserves history. +- No hardcoded values, unused imports, magic numbers. +- Import `classNameFactory` from `@utils/css` (NOT `@api/Styles` which is deprecated). **ALWAYS** use `cl()` for class names, never hardcode strings like `"vc-plugin-name-class"`. +- When combining multiple class names use `classes()` from `@utils/misc`, not template strings like `` `${a} ${b}` ``. +- Use utilities from `@utils/`, `@api/`, `@components/`. +- Use `Logger` from `@utils/Logger`, not `console.log`. +- Descriptions: capital first letter, end with period. +- Less code with same functionality is **ALWAYS** better. If it can be done in fewer lines without losing clarity, do it. +- Keep logic flat. Avoid deep nesting, prefer early returns, guard clauses, and simple control flow. +- **NEVER** add comments unless explicitly asked. +- Keep existing comments, they contain important context. +- Use `Map`/`Set`, `.some`/`.find`, no spread in loops, `Promise.all`. +- KISS over clever, flat over nested, explicit over implicit. + +## TypeScript + +- **Prefer:** optional chaining (`?.`), nullish coalescing (`??`), `const`, arrow functions +- **Use:** destructuring, template literals, object shorthand, array methods +- **Style:** early returns, trust inference, inline single-use variables + +## React + +- Wrap complex components with `ErrorBoundary.wrap(Component, { noop: true })`. +- Return `null` for conditional rendering, not `undefined`. +- **Forbidden:** `React.cloneElement`, `React.isValidElement`, `React.memo()`, `React.lazy`, `React.Children` +- Always return cleanup functions in `useEffect`. + +## Forbidden + +### Code + +- **No raw DOM manipulation.** No `document.querySelector`, no `MutationObserver`, no `element.style`. Always use webpack patches and React. +- Empty catch blocks. +- Hardcoded minified vars in patches (`e,t,n`). +- **NEVER** use `settings.use()` with arrays. Mutate then reassign. + +### Plugins + +- **No selfbot or API abuse.** Nothing that automates user actions, spoofs client state, or abuses Discord's API in any way. +- No plugins that only do something trivially achievable with existing built-in plugins or Discord features. +- No CSS-only plugins that only hide or redesign UI elements. +- No plugins targeting specific third-party bots (official Discord apps are fine). +- No untrusted third-party APIs. No plugins requiring users to supply their own API keys. +- Do not introduce new dependencies unless strictly necessary and well justified. + +## Anti-Patterns + +- `value !== null && value !== undefined` ⟹ `value` +- `array && array.length > 0` ⟹ `array.length` +- `settings?.store?.value` ⟹ `settings.store.value` +- `value || defaultValue` ⟹ `value ?? defaultValue` + +## Patching + +### Core Principles + +- Minimum code touched. Stability over cleverness. One patch per concern. +- Try multiple approaches, keep simplifying until you find the cleanest solution. +- Remove any regex character that doesnt change the match result. +- Not overengineered, not overlooked, just clean and future-proof. + +### Find Strings + +- Use `#{intl::KEY}` in find when possible, most stable anchor. +- If find matches multiple modules, add nearby stable string like `"),icon:"` or function name. +- `"#{intl::PIN_MESSAGE}),icon:"` is better than generic strings. + +### Match Patterns + +- Match only what you need to replace, let find do the targeting. +- Can use `#{intl::KEY}` in match too, gets canonicalized to hash. +- `/#{intl::KEY}\)/` beats `/label:\i\.pinned\?.{0,60}#{intl::KEY}\)/` +- `$&` keeps original, append/prepend to it. +- Use bounded gaps: `.{0,50}` not `.+?` or `.*?` +- Only use capture groups if reusing in replace. + +### NEVER Do + +- **Hardcoded minified vars:** `e,t,n,r,i,o,s,l,c,u,$_,xx,eD,eH,eW` — use `\i` instead +- **Minified chains:** `\i\.\i` alone — surround with stable strings +- **Unbounded gaps:** `.+?` or `.*?` — use `.{0,N}` +- **Generic patterns:** `/className:\i/` alone — add anchor +- **Raw intl hashes:** `.aA4Vce` — use `#{intl::KEY_NAME}` + +### Patch Examples + +**Clean replacement:** +```js +find: "#{intl::PIN_MESSAGE}),icon:" +match: /#{intl::PIN_MESSAGE}\)/ +replace: "$self.getPinLabel(arguments[0]))" +``` + +**Appending:** +```js +find: "#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}" +match: /#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}.{0,100}(?=])/ +replace: "$&,$self.renderTooltip(arguments[0].guild)" +``` + +**Wrapping:** +```js +find: "#{intl::THREE_USERS_TYPING}" +match: /(?<="aria-atomic":!0,children:)\i/ +replace: "$self.renderTypingUsers({ children: $& })" +``` + +## Plugin Interop + +- `isPluginEnabled(name)` from `@api/PluginManager` takes a string, checks required/isDependency/enabled. +- Import the plugin directly from its path to access `.name` and functions. +- Dont use `Vencord.Plugins.plugins` or `plugin.started`. Dont use `"as unknown as"` casting. + +```ts +import { isPluginEnabled } from "@api/PluginManager"; +import otherPlugin from "@equicordplugins/otherPlugin"; +if (!isPluginEnabled(otherPlugin.name)) return null; +otherPlugin.someFunction(); +``` + +## Reference + +### Types + +`Channel`, `Guild`, `GuildMember`, `User`, `Role`, `Message` from `@vencord/discord-types` + +### Components + +`Paragraph`, `BaseText`, `Flex`, `Button`, `ErrorCard` from `@components/` + +### Settings + +Use `definePluginSettings` from `@api/Settings`, not inline settings object. + +### Utilities + +- **@utils/clipboard** — `copyToClipboard` +- **@utils/discord** — `insertTextIntoChatInputBox`, `getCurrentChannel`, `getCurrentGuild`, `getIntlMessage`, `openUserProfile`, `openPrivateChannel`, `sendMessage`, `copyWithToast`, `getUniqueUsername`, `fetchUserProfile` +- **@utils/css** — `classNameFactory`, `classNameToSelector` +- **@utils/misc** — `classes`, `sleep`, `isObject`, `isObjectEmpty`, `pluralise`, `parseUrl`, `identity` +- **@utils/text** — `formatDuration`, `formatDurationMs`, `humanFriendlyJoin`, `makeCodeblock`, `toInlineCode`, `escapeRegExp` +- **@utils/modal** — `openModal`, `closeModal`, `ModalRoot`, `ModalHeader`, `ModalContent`, `ModalCloseButton` +- **@utils/margins** — `Margins` (`Margins.top8`, `Margins.bottom16`, etc.) +- **@utils/guards** — `isTruthy`, `isNonNullish` +- **@utils/web** — `saveFile`, `chooseFile` + +### Webpack Common + +#### IconUtils + +From `@webpack/common`. **NEVER** hardcode `cdn.discordapp.com` URLs. + +- `IconUtils.getUserAvatarURL(user, canAnimate?, size?)` +- `IconUtils.getDefaultAvatarURL(id)` +- `IconUtils.getUserBannerURL({ id, banner, canAnimate?, size })` +- `IconUtils.getGuildIconURL({ id, icon, size?, canAnimate? })` +- `IconUtils.getGuildBannerURL(guild, canAnimate?)` +- `IconUtils.getChannelIconURL({ id, icon })` +- `IconUtils.getEmojiURL({ id, animated, size })` +- `IconUtils.getApplicationIconURL(data)` +- `IconUtils.getGameAssetURL(data)` + +#### Stores + +`UserStore`, `GuildStore`, `ChannelStore`, `GuildMemberStore`, `SelectedChannelStore`, `SelectedGuildStore`, `PresenceStore`, `RelationshipStore`, `MessageStore`, `EmojiStore`, `ThemeStore`, `PermissionStore`, `VoiceStateStore` from `@webpack/common` + +#### Actions + +`RestAPI`, `FluxDispatcher`, `MessageActions`, `NavigationRouter`, `ChannelRouter`, `ChannelActionCreators`, `SettingsRouter` from `@webpack/common` + +#### Utils + +`Constants` (`Constants.Endpoints`), `SnowflakeUtils`, `Parser`, `PermissionsBits`, `moment`, `lodash`, `ColorUtils`, `ImageUtils`, `DateUtils`, `UsernameUtils`, `DisplayProfileUtils` from `@webpack/common` + +#### Components + +`Tooltip`, `TextInput`, `TextArea`, `Select`, `Slider`, `Avatar`, `Menu`, `Popout`, `ScrollerThin`, `Timestamp` from `@webpack/common` + +#### Toasts + +`Toasts`, `showToast` from `@webpack/common` + +### Imports + +- **Lazy** from `@webpack` — `findByPropsLazy`, `findStoreLazy`, `findComponentByCodeLazy`, `findExportedComponentLazy` +- **Common** from `@webpack/common` — `useState`, `useEffect`, `useCallback`, `useStateFromStores` + +### Never Hardcode + +- `"cdn.discordapp.com/avatars/"` etc. ⟹ `IconUtils` +- `"/api/v9"`, `"/users/@me"` ⟹ `Constants.Endpoints` or `RestAPI` +- `console.log/warn/error` ⟹ `Logger` from `@utils/Logger` +- `` `${a} ${b}` `` for class names ⟹ `classes(a, b)` from `@utils/misc` +- `"/assets/*.png"` for default avatars ⟹ `IconUtils.getDefaultAvatarURL(id)` diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index a19ead5af..000000000 --- a/AGENTS.md +++ /dev/null @@ -1,240 +0,0 @@ -# AGENTS.md - -**IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning.** When uncertain about APIs, patterns, or existing implementations, read the relevant source files rather than relying on assumptions. - ---- - -## Quick Reference - -| Task | Command/Location | -|------|------------------| -| Install | `pnpm install --frozen-lockfile` | -| Build | `pnpm build` | -| Dev/Watch | `pnpm dev` | -| Lint | `pnpm lint` | -| Type check | `pnpm testTsc` | -| Full test | `pnpm test` | -| New Equicord plugin | `src/equicordplugins/PluginName/index.ts` | -| New Vencord plugin | `src/plugins/PluginName/index.ts` | - -**Key Files Index:** -| Need | File | -|------|------| -| Plugin types | `src/utils/types.ts` | -| Settings API | `src/api/Settings.ts` | -| Constants/devs | `src/utils/constants.ts` | -| CSS utilities | `src/utils/css.ts` | -| Webpack common exports | `src/webpack/common/*.ts` | -| Example plugins | `src/plugins/*/index.ts` or `src/equicordplugins/*/index.ts` | -| Discord types | `@vencord/discord-types` (external) | - ---- - -## Project Overview - -**Equicord** is a Discord client mod forked from [Vencord](https://github.com/Vendicated/Vencord). It modifies the Discord web client by patching webpack modules at runtime to inject custom functionality. - -**Technology Stack:** TypeScript (strict), React, Webpack patching -**Package Manager:** pnpm | **License:** GPL-3.0-or-later - ---- - -## Workflow - -**Before writing code:** -1. Explore relevant source files to understand existing patterns -2. Check the Key Files Index for API/type references -3. Look at similar plugins for examples -4. Then proceed with implementation - -This "explore first, then act" approach produces better results than jumping straight to implementation. - ---- - -## Setup Commands - -| Command | Description | -|---------|-------------| -| `pnpm install --frozen-lockfile` | Install dependencies | -| `pnpm build` | Build project | -| `pnpm buildWeb` | Build for web | -| `pnpm dev` / `pnpm watch` | Start dev server (watch mode) | -| `pnpm watchWeb` | Watch web build | -| `pnpm lint` | Lint code | -| `pnpm lint:fix` | Fix lint issues | -| `pnpm lint-styles` | Lint CSS | -| `pnpm testTsc` | Type check | -| `pnpm test` | Full test suite (builds, type checks, lints, generates plugin JSON) | -| `pnpm generatePluginJson` | Generate plugin list | -| `pnpm generateEquicordPluginJson` | Generate Equicord plugin list | - -**Requirements:** Node.js >= 18, pnpm (see package.json for version) - ---- - -## Code Style - -**TypeScript:** Strict mode. Use inference - don't annotate obvious types. - -**Formatting:** Double quotes, semicolons required, single quotes only for escaping. - -**Patterns:** `?.` optional chaining, `??` nullish coalescing (never `||` for defaults), `const` over `let`, arrow functions, destructuring, template literals, early returns, flat code. - -**Philosophy:** Less code is better. No comments unless requested. Delete dead code, never comment it out. No overengineering or premature abstractions. Trust TypeScript inference. - -**Text:** Plugin/setting descriptions: capital first letter, end with period. Error messages: natural human text, no robotic formatting. - -**Performance:** `Map`/`Set` for lookups, `.find()`/`.some()` not `.filter()[0]`, no spread in loops, `Promise.all()` for parallel async. - -**Hygiene:** Delete dead code. No unused imports. No logging (`console.log`, `Logger`). No empty catch blocks. - ---- - -## Plugin Structure - -**Place Equicord plugins in `src/equicordplugins/PluginName/`, upstream/Vencord plugins in `src/plugins/PluginName/`.** - -```typescript -import definePlugin from "@utils/types"; -import { EquicordDevs } from "@utils/constants"; - -export default definePlugin({ - name: "PluginName", // PascalCase, matches directory name - description: "Does something.", // Capital first, period at end - authors: [EquicordDevs.Name], // EquicordDevs for new, Devs for upstream -}); -``` - -**Settings:** Use `definePluginSettings` from `@api/Settings`. Reject inline `options` objects. - -**Prefer declarative APIs:** `flux`, `contextMenus`, `chatBarButton`, `messagePopoverButton`, `managedStyle` instead of manual registration. - -**Reject deprecated fields:** `renderChatBarButton`, `renderMessagePopoverButton`, `options` - -**Lifecycle:** Anything registered in `start()` must be cleaned up in `stop()`. - ---- - -## Forbidden Patterns - -| Bad | Good | Reason | -|-----|------|--------| -| `value !== null && value !== undefined` | `value` or `isNonNullish(value)` | Verbose | -| `array && array.length > 0` | `array.length` | Redundant | -| `settings?.store?.value` | `settings.store.value` | Store always defined | -| `value \|\| defaultValue` | `value ?? defaultValue` | `\|\|` falsifies `0`, `""`, `false` | -| `` `${classA} ${classB}` `` | `classes(classA, classB)` | Handles null/false | -| `"vc-plugin-class"` hardcoded | `cl("class")` via `classNameFactory` | Typo-proof | -| `console.log/warn/error` | Remove it | No logging | -| `cdn.discordapp.com/...` | `IconUtils.*` methods | Handles animated, sizing | -| `/api/v9/...` | `Constants.Endpoints.*` | Endpoints change | -| `@api/Styles` | `@utils/css` | Deprecated | -| `any` for Discord objects | Import from `@vencord/discord-types` | Type safety | -| `as unknown as` | Find correct type | Unsafe | -| `React.memo()` | Remove it | Not needed | -| `React.cloneElement/isValidElement/Children` | Find another approach | Forbidden | -| `React.lazy(() => import(...))` | `LazyComponent` | Framework-integrated | -| Empty `catch {}` | Handle error | Silent failures | -| CSS-only plugins | Must have logic/patches | Not allowed | -| `document.querySelector(...)` | Use webpack patches | DOM forbidden | -| `Vencord.Plugins.plugins["X"]` | `isPluginEnabled` + import | Proper interop | -| `plugin.started` | `isPluginEnabled(plugin.name)` | Proper interop | -| Unexplained magic numbers | Named constants | Readability | -| Unused imports | Remove them | Cleanliness | - ---- - -## CSS, React, Settings - -**CSS:** Use `classNameFactory` from `@utils/css`: `const cl = classNameFactory("vc-my-plugin-");` Combine with `classes()` from `@utils/misc`. - -**React:** Return `null` for conditional rendering, never `undefined`. Wrap complex components with `ErrorBoundary.wrap()`. useEffect must return cleanup for subscriptions/timers. - -**Settings:** `settings.store.key` (reactive), `settings.plain.key` (non-reactive). Never `settings.use()` with arrays in variables. - ---- - -## Patch Quality - -Patches modify Discord's minified webpack modules. Stability is paramount. - -- **One patch per concern.** Each replacement does one thing. -- **Surgical.** Match only what needs replacing, let `find` target the module. -- **No hardcoded minified vars.** Use `\i`, never `e`, `t`, `n`, `r`, `i`, `eD`, `eH`. -- **Bounded gaps.** `.{0,50}` not `.+?` or `.*?`. -- **No generic patterns.** Add stable anchors. -- **No raw intl hashes.** Use `#{intl::KEY_NAME}`. -- **`$&`** for append/prepend, **`$self`** for plugin method calls. - ---- - -## Memory Leaks - -**Every `start()` must have matching `stop()`.** Common leaks: event listeners, intervals/timeouts, MutationObservers, context menu patches, chat bar buttons, styles, Flux subscriptions. - -**Prefer declarative APIs** that handle cleanup automatically: `flux`, `contextMenus`, `chatBarButton`, `messagePopoverButton`, `managedStyle`. - -**useEffect must return cleanup** for subscriptions, timers, observers, or any persistent resource. - ---- - -## Plugin Interop - -- `@equicordplugins/pluginName` for Equicord plugins -- `@plugins/pluginName` for Vencord/upstream plugins - -Use `isPluginEnabled(plugin.name)` to check if enabled. Never access `Vencord.Plugins.plugins["X"]` directly. - ---- - -## Platform-Specific Plugins - -Directory suffixes: `pluginName.desktop/`, `pluginName.web/`, `pluginName.discordDesktop/` - ---- - -## Built-in Utilities - -**@utils/misc:** `classes`, `sleep`, `isObject`, `isObjectEmpty`, `parseUrl`, `pluralise`, `identity` -**@utils/guards:** `isTruthy`, `isNonNullish` -**@utils/text:** `formatDuration`, `formatDurationMs`, `humanFriendlyJoin`, `makeCodeblock`, `toInlineCode`, `escapeRegExp` -**@utils/discord:** `getCurrentChannel`, `getCurrentGuild`, `getIntlMessage`, `openPrivateChannel`, `insertTextIntoChatInputBox`, `sendMessage`, `copyWithToast`, `openUserProfile`, `fetchUserProfile`, `getUniqueUsername`, `openInviteModal` -**@utils/css:** `classNameFactory`, `classNameToSelector` -**@utils/clipboard:** `copyToClipboard` -**@utils/modal:** `openModal`, `closeModal`, `ModalRoot`, `ModalHeader`, `ModalContent`, `ModalFooter`, `ModalCloseButton` -**@utils/margins:** `Margins.top8`, `.top16`, `.bottom8`, `.bottom16` etc. -**@utils/web:** `saveFile`, `chooseFile` -**@utils/lazy:** `proxyLazy`, `makeLazy` -**@utils/lazyReact:** `LazyComponent` -**@utils/react:** `useAwaiter`, `useForceUpdater`, `useTimer` -**@api/DataStore:** `get`, `set`, `del` (IndexedDB, async) -**@api/Commands:** `sendBotMessage`, `findOption` - -**@webpack/common:** Stores (`UserStore`, `GuildStore`, `ChannelStore`, 30+ more), Actions (`RestAPI`, `FluxDispatcher`, `MessageActions`, `NavigationRouter`), Utils (`Constants.Endpoints`, `SnowflakeUtils`, `Parser`, `PermissionsBits`, `moment`, `lodash`, `IconUtils`), Components (`Tooltip`, `TextInput`, `Select`, `Avatar`, `Menu`, `Popout`), Toasts (`Toasts`, `showToast`) - -**@webpack finders:** `findByPropsLazy`, `findByCodeLazy`, `findStoreLazy`, `findComponentByCodeLazy`, `findExportedComponentLazy` - -**@components/:** `ErrorBoundary`, `Flex`, `Button`, `Paragraph`, `Heading`, `BaseText`, `Span`, `ErrorCard`, `Link`, `CodeBlock`, `FormSwitch` - ---- - -## Ethical Guidelines & Acceptance Rules - -**Not accepted:** Fake deafen/mute, trolling plugins, selfbot/API abuse (auto-replies, animated statuses, message pruning, Nitro snipers). - -**Instant reject:** Simple slash-commands, text replacement, DOM manipulation, UI-only hide/redesign, third-party bot targeting, untrusted APIs, user-provided API keys, new dependencies without justification. - ---- - -## Git Workflow - -- Never commit to `main` (protected) -- Never commit to fork's `dev` branch -- Create feature branch from `dev`: `feature/plugin-name` or `fix/plugin-name` -- Keep commits atomic -- Squash commits before merging if addressing same issue -- Run `pnpm lint` and `pnpm build` before committing - -**PR title format:** `[PluginName] Description` - ---- diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 000000000..8a63b64bd --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +.rules \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 47dc3e3d8..8a63b64bd 120000 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1 +1 @@ -AGENTS.md \ No newline at end of file +.rules \ No newline at end of file diff --git a/GEMINI.md b/GEMINI.md new file mode 120000 index 000000000..8a63b64bd --- /dev/null +++ b/GEMINI.md @@ -0,0 +1 @@ +.rules \ No newline at end of file From 1cf516f228a6dcdeaf9fc7076b379a1814d18c23 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Fri, 20 Feb 2026 18:27:22 -0500 Subject: [PATCH 2/2] Fix Patch Finds --- src/equicordplugins/dragify/index.tsx | 2 +- src/equicordplugins/statusPresets/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/equicordplugins/dragify/index.tsx b/src/equicordplugins/dragify/index.tsx index 2338fdf54..183f67d1e 100644 --- a/src/equicordplugins/dragify/index.tsx +++ b/src/equicordplugins/dragify/index.tsx @@ -223,7 +223,7 @@ export default definePlugin({ }, // Member list items (server member list) { - find: "MemberListItem", + find: ".MEMBER_USER})]", replacement: { match: /(?<=useRawTargetDimensions.{0,250})onContextMenu:\i,(?=onMouseEnter:)/, replace: "$&draggable:!0,onDragStart:e=>$self.onUserDragStart(e,{id:arguments[0].user?.id}),\"data-dragify-user\":!0,\"data-user-id\":arguments[0].user?.id," diff --git a/src/equicordplugins/statusPresets/index.tsx b/src/equicordplugins/statusPresets/index.tsx index 113b4052b..4904bd273 100644 --- a/src/equicordplugins/statusPresets/index.tsx +++ b/src/equicordplugins/statusPresets/index.tsx @@ -150,7 +150,7 @@ export default definePlugin({ managedStyle, patches: [ { - find: '"CustomStatusModalWithPreview"', + find: '="custom-status-input";', replacement: { match: /(?<=(\i)\?\.state\?\?.*?)\{text:\i\.\i\.\i\(\i\.\i#{intl::SAVE}\)/, replace: "$self.renderRememberButton($1),$&"