aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/api/ContextMenu.ts9
-rw-r--r--src/plugins/apiContextMenu.ts46
-rw-r--r--src/plugins/devCompanion.dev.tsx33
-rw-r--r--src/plugins/emoteCloner.tsx6
-rw-r--r--src/plugins/invisibleChat/index.tsx4
-rw-r--r--src/plugins/messageActions.ts10
-rw-r--r--src/plugins/reverseImageSearch.tsx6
-rw-r--r--src/plugins/showHiddenChannels/index.tsx4
-rw-r--r--src/plugins/silentMessageToggle.tsx50
-rw-r--r--src/plugins/silentTyping.tsx4
-rw-r--r--src/plugins/volumeBooster.ts (renamed from src/plugins/volumeBooster.desktop.ts)4
11 files changed, 105 insertions, 71 deletions
diff --git a/src/api/ContextMenu.ts b/src/api/ContextMenu.ts
index 9a8d7b6..3f73a41 100644
--- a/src/api/ContextMenu.ts
+++ b/src/api/ContextMenu.ts
@@ -23,13 +23,13 @@ import type { ReactElement } from "react";
* @param children The rendered context menu elements
* @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example
*/
-export type NavContextMenuPatchCallback = (children: Array<React.ReactElement>, args?: Array<any>) => void;
+export type NavContextMenuPatchCallback = (children: Array<React.ReactElement>, ...args: Array<any>) => void;
/**
* @param The navId of the context menu being patched
* @param children The rendered context menu elements
* @param args Any arguments passed into making the context menu, like the guild, channel, user or message for example
*/
-export type GlobalContextMenuPatchCallback = (navId: string, children: Array<React.ReactElement>, args?: Array<any>) => void;
+export type GlobalContextMenuPatchCallback = (navId: string, children: Array<React.ReactElement>, ...args: Array<any>) => void;
const ContextMenuLogger = new Logger("ContextMenu");
@@ -119,12 +119,13 @@ interface ContextMenuProps {
}
export function _patchContextMenu(props: ContextMenuProps) {
+ props.contextMenuApiArguments ??= [];
const contextMenuPatches = navPatches.get(props.navId);
if (contextMenuPatches) {
for (const patch of contextMenuPatches) {
try {
- patch(props.children, props.contextMenuApiArguments);
+ patch(props.children, ...props.contextMenuApiArguments);
} catch (err) {
ContextMenuLogger.error(`Patch for ${props.navId} errored,`, err);
}
@@ -133,7 +134,7 @@ export function _patchContextMenu(props: ContextMenuProps) {
for (const patch of globalPatches) {
try {
- patch(props.navId, props.children, props.contextMenuApiArguments);
+ patch(props.navId, props.children, ...props.contextMenuApiArguments);
} catch (err) {
ContextMenuLogger.error("Global patch errored,", err);
}
diff --git a/src/plugins/apiContextMenu.ts b/src/plugins/apiContextMenu.ts
index 1874f5f..88a1eb9 100644
--- a/src/plugins/apiContextMenu.ts
+++ b/src/plugins/apiContextMenu.ts
@@ -18,9 +18,28 @@
import { Settings } from "@api/settings";
import { Devs } from "@utils/constants";
-import definePlugin from "@utils/types";
+import definePlugin, { type PatchReplacement } from "@utils/types";
import { addListener, removeListener } from "@webpack";
+/**
+ * The last var name corresponding to the Context Menu API (Discord, not ours) module
+ */
+let lastVarName = "";
+
+/**
+ * @param target The patch replacement object
+ * @param exportKey The key exporting the build Context Menu component function
+ */
+function makeReplacementProxy(target: PatchReplacement, exportKey: string) {
+ return new Proxy(target, {
+ get(_, p) {
+ if (p === "match") return RegExp(`${exportKey},{(?<=${lastVarName}\\.${exportKey},{)`, "g");
+ // @ts-expect-error
+ return Reflect.get(...arguments);
+ }
+ });
+}
+
function listener(exports: any, id: number) {
if (!Settings.plugins.ContextMenuAPI.enabled) return removeListener(listener);
@@ -37,13 +56,24 @@ function listener(exports: any, id: number) {
all: true,
noWarn: true,
find: "navId:",
- replacement: [{
- match: RegExp(`${id}(?<=(\\i)=.+?).+$`),
- replace: (code, varName) => {
- const regex = RegExp(`${key},{(?<=${varName}\\.${key},{)`, "g");
- return code.replace(regex, "$&contextMenuApiArguments:arguments,");
- }
- }]
+ replacement: [
+ {
+ // Set the lastVarName for our proxy to use
+ match: RegExp(`${id}(?<=(\\i)=.+?)`),
+ replace: (id, varName) => {
+ lastVarName = varName;
+ return id;
+ }
+ },
+ /**
+ * We are using a proxy here to utilize the whole code the patcher gives us, instead of matching the entire module (which is super slow)
+ * Our proxy returns the corresponding match for that module utilizing lastVarName, which is set by the patch before
+ */
+ makeReplacementProxy({
+ match: "", // Needed to canonicalizeDescriptor
+ replace: "$&contextMenuApiArguments:arguments,",
+ }, key)
+ ]
});
removeListener(listener);
diff --git a/src/plugins/devCompanion.dev.tsx b/src/plugins/devCompanion.dev.tsx
index cea71e0..c3d4d6a 100644
--- a/src/plugins/devCompanion.dev.tsx
+++ b/src/plugins/devCompanion.dev.tsx
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { addContextMenuPatch } from "@api/ContextMenu";
+import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu";
import { showNotification } from "@api/Notifications";
import { Devs } from "@utils/constants";
import Logger from "@utils/Logger";
@@ -221,6 +221,21 @@ function initWs(isManual = false) {
});
}
+const contextMenuPatch: NavContextMenuPatchCallback = kids => {
+ if (kids.some(k => k?.props?.id === NAV_ID)) return;
+
+ kids.unshift(
+ <Menu.MenuItem
+ id={NAV_ID}
+ label="Reconnect Dev Companion"
+ action={() => {
+ socket?.close(1000, "Reconnecting");
+ initWs(true);
+ }}
+ />
+ );
+};
+
export default definePlugin({
name: "DevCompanion",
description: "Dev Companion Plugin",
@@ -229,24 +244,12 @@ export default definePlugin({
start() {
initWs();
- addContextMenuPatch("user-settings-cog", kids => {
- if (kids.some(k => k?.props?.id === NAV_ID)) return;
-
- kids.unshift(
- <Menu.MenuItem
- id={NAV_ID}
- label="Reconnect Dev Companion"
- action={() => {
- socket?.close(1000, "Reconnecting");
- initWs(true);
- }}
- />
- );
- });
+ addContextMenuPatch("user-settings-cog", contextMenuPatch);
},
stop() {
socket?.close(1000, "Plugin Stopped");
socket = void 0;
+ removeContextMenuPatch("user-settings-cog", contextMenuPatch);
}
});
diff --git a/src/plugins/emoteCloner.tsx b/src/plugins/emoteCloner.tsx
index eba77c7..609ef08 100644
--- a/src/plugins/emoteCloner.tsx
+++ b/src/plugins/emoteCloner.tsx
@@ -176,9 +176,9 @@ function CloneModal({ id, name: emojiName, isAnimated }: { id: string; name: str
);
}
-const messageContextMenuPatch: NavContextMenuPatchCallback = (children, args) => {
- if (!args?.[0]) return;
- const { favoriteableId, emoteClonerDataAlt, itemHref, itemSrc, favoriteableType } = args[0];
+const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
+ if (!props) return;
+ const { favoriteableId, emoteClonerDataAlt, itemHref, itemSrc, favoriteableType } = props;
if (!emoteClonerDataAlt || favoriteableType !== "emoji") return;
diff --git a/src/plugins/invisibleChat/index.tsx b/src/plugins/invisibleChat/index.tsx
index d3358be..d30bb7c 100644
--- a/src/plugins/invisibleChat/index.tsx
+++ b/src/plugins/invisibleChat/index.tsx
@@ -131,8 +131,8 @@ export default definePlugin({
{
find: ".activeCommandOption",
replacement: {
- match: /(.)\.push.{1,50}\(\i,\{.{1,30}\},"gift"\)\)/,
- replace: "$&;try{$1.push($self.chatBarIcon())}catch{}",
+ match: /(.)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
+ replace: "$&;try{$2||$1.push($self.chatBarIcon())}catch{}",
}
},
],
diff --git a/src/plugins/messageActions.ts b/src/plugins/messageActions.ts
index b71a9f1..f244554 100644
--- a/src/plugins/messageActions.ts
+++ b/src/plugins/messageActions.ts
@@ -20,13 +20,15 @@ import { addClickListener, removeClickListener } from "@api/MessageEvents";
import { migratePluginSettings } from "@api/settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
-import { findByPropsLazy, findLazy } from "@webpack";
-import { UserStore } from "@webpack/common";
+import { findByPropsLazy } from "@webpack";
+import { PermissionStore, UserStore } from "@webpack/common";
let isDeletePressed = false;
const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true);
const keyup = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = false);
+const MANAGE_CHANNELS = 1n << 4n;
+
migratePluginSettings("MessageClickActions", "MessageQuickActions");
export default definePlugin({
@@ -50,8 +52,6 @@ export default definePlugin({
start() {
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");
- const PermissionStore = findByPropsLazy("can", "initialize");
- const Permissions = findLazy(m => typeof m.MANAGE_MESSAGES === "bigint");
const EditStore = findByPropsLazy("isEditing", "isEditingAny");
document.addEventListener("keydown", keydown);
@@ -64,7 +64,7 @@ export default definePlugin({
MessageActions.startEditMessage(chan.id, msg.id, msg.content);
event.preventDefault();
}
- } else if (Vencord.Settings.plugins.MessageClickActions.enableDeleteOnClick && (isMe || PermissionStore.can(Permissions.MANAGE_MESSAGES, chan))) {
+ } else if (Vencord.Settings.plugins.MessageClickActions.enableDeleteOnClick && (isMe || PermissionStore.can(MANAGE_CHANNELS, chan))) {
MessageActions.deleteMessage(chan.id, msg.id);
event.preventDefault();
}
diff --git a/src/plugins/reverseImageSearch.tsx b/src/plugins/reverseImageSearch.tsx
index 47954ba..88c0b16 100644
--- a/src/plugins/reverseImageSearch.tsx
+++ b/src/plugins/reverseImageSearch.tsx
@@ -34,9 +34,9 @@ function search(src: string, engine: string) {
open(engine + encodeURIComponent(src), "_blank");
}
-const imageContextMenuPatch: NavContextMenuPatchCallback = (children, args) => {
- if (!args?.[0]) return;
- const { reverseImageSearchType, itemHref, itemSrc } = args[0];
+const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
+ if (!props) return;
+ const { reverseImageSearchType, itemHref, itemSrc } = props;
if (!reverseImageSearchType || reverseImageSearchType !== "img") return;
diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx
index 70c5045..eb49468 100644
--- a/src/plugins/showHiddenChannels/index.tsx
+++ b/src/plugins/showHiddenChannels/index.tsx
@@ -321,9 +321,7 @@ export default definePlugin({
],
},
{
- // The module wasn't being found, so lets just escape everything
- // eslint-disable-next-line no-useless-escape
- find: "\^https\:\/\/\(\?\:canary\.\|ptb\.\)\?discord.com\/channels\/\(\\\\\d\+\|",
+ find: "\"^/guild-stages/(\\\\d+)(?:/)?(\\\\d+)?\"",
replacement: {
// Make mentions of hidden channels work
match: /\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL,\i\)/,
diff --git a/src/plugins/silentMessageToggle.tsx b/src/plugins/silentMessageToggle.tsx
index 09fb4e7..8d33f81 100644
--- a/src/plugins/silentMessageToggle.tsx
+++ b/src/plugins/silentMessageToggle.tsx
@@ -40,28 +40,30 @@ function SilentMessageToggle() {
return (
<Tooltip text="Toggle Silent Message">
{tooltipProps => (
- <Button
- {...tooltipProps}
- onClick={() => setEnabled(prev => !prev)}
- size=""
- look={ButtonLooks.BLANK}
- innerClassName={ButtonWrapperClasses.button}
- style={{ margin: "0px 8px" }}
- >
- <div className={ButtonWrapperClasses.buttonWrapper}>
- <svg
- width="24"
- height="24"
- viewBox="0 0 24 24"
- >
- <g fill="currentColor">
- <path d="M18 10.7101C15.1085 9.84957 13 7.17102 13 4C13 3.69264 13.0198 3.3899 13.0582 3.093C12.7147 3.03189 12.3611 3 12 3C8.686 3 6 5.686 6 9V14C6 15.657 4.656 17 3 17V18H21V17C19.344 17 18 15.657 18 14V10.7101ZM8.55493 19C9.24793 20.19 10.5239 21 11.9999 21C13.4759 21 14.7519 20.19 15.4449 19H8.55493Z" />
- <path d="M18.2624 5.50209L21 2.5V1H16.0349V2.49791H18.476L16 5.61088V7H21V5.50209H18.2624Z" />
- {!enabled && <line x1="22" y1="2" x2="2" y2="22" stroke="var(--red-500)" stroke-width="2.5" />}
- </g>
- </svg>
- </div>
- </Button>
+ <div style={{ display: "flex" }}>
+ <Button
+ {...tooltipProps}
+ onClick={() => setEnabled(prev => !prev)}
+ size=""
+ look={ButtonLooks.BLANK}
+ innerClassName={ButtonWrapperClasses.button}
+ style={{ margin: "0px 8px" }}
+ >
+ <div className={ButtonWrapperClasses.buttonWrapper}>
+ <svg
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ >
+ <g fill="currentColor">
+ <path d="M18 10.7101C15.1085 9.84957 13 7.17102 13 4C13 3.69264 13.0198 3.3899 13.0582 3.093C12.7147 3.03189 12.3611 3 12 3C8.686 3 6 5.686 6 9V14C6 15.657 4.656 17 3 17V18H21V17C19.344 17 18 15.657 18 14V10.7101ZM8.55493 19C9.24793 20.19 10.5239 21 11.9999 21C13.4759 21 14.7519 20.19 15.4449 19H8.55493Z" />
+ <path d="M18.2624 5.50209L21 2.5V1H16.0349V2.49791H18.476L16 5.61088V7H21V5.50209H18.2624Z" />
+ {!enabled && <line x1="22" y1="2" x2="2" y2="22" stroke="var(--red-500)" stroke-width="2.5" />}
+ </g>
+ </svg>
+ </div>
+ </Button>
+ </div>
)}
</Tooltip>
);
@@ -75,8 +77,8 @@ export default definePlugin({
{
find: ".activeCommandOption",
replacement: {
- match: /"gift"\)\);(?<=(\i)\.push.+?)/,
- replace: (m, array) => `${m}${array}.push($self.SilentMessageToggle());`
+ match: /"gift"\)\);(?<=(\i)\.push.+?disabled:(\i),.+?)/,
+ replace: (m, array, disabled) => `${m}${disabled}||${array}.push($self.SilentMessageToggle());`
}
}
],
diff --git a/src/plugins/silentTyping.tsx b/src/plugins/silentTyping.tsx
index 83f6415..d0edaac 100644
--- a/src/plugins/silentTyping.tsx
+++ b/src/plugins/silentTyping.tsx
@@ -82,8 +82,8 @@ export default definePlugin({
find: ".activeCommandOption",
predicate: () => settings.store.showIcon,
replacement: {
- match: /(.)\.push.{1,50}\(\i,\{.{1,30}\},"gift"\)\)/,
- replace: "$&;try{$1.push($self.chatBarIcon())}catch{}",
+ match: /(.)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
+ replace: "$&;try{$2||$1.push($self.chatBarIcon())}catch{}",
}
},
],
diff --git a/src/plugins/volumeBooster.desktop.ts b/src/plugins/volumeBooster.ts
index 7d81449..3f692c7 100644
--- a/src/plugins/volumeBooster.desktop.ts
+++ b/src/plugins/volumeBooster.ts
@@ -56,8 +56,8 @@ export default definePlugin({
find: "AudioContextSettingsMigrated",
replacement: [
{
- match: /(?<=updateAsync\("audioContextSettings".{0,50})(?=return (\i)\.volume=(\i))/,
- replace: (_, volumeOptions, newVolume) => `if(${newVolume}>200)return ${volumeOptions}.volume=200;`
+ match: /(?<=updateAsync\("audioContextSettings".{0,350}return \i\.volume=)\i(?=})/,
+ replace: "$&>200?200:$&"
},
{
match: /(?<=Object\.entries\(\i\.localMutes\).+?volume:).+?(?=,)/,