Improvements, changes and fixes (#611)
This commit is contained in:
parent
5873bde6a6
commit
0fb79b763d
@ -23,13 +23,13 @@ import type { ReactElement } from "react";
|
|||||||
* @param children The rendered context menu elements
|
* @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
|
* @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 The navId of the context menu being patched
|
||||||
* @param children The rendered context menu elements
|
* @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
|
* @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");
|
const ContextMenuLogger = new Logger("ContextMenu");
|
||||||
|
|
||||||
@ -119,12 +119,13 @@ interface ContextMenuProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function _patchContextMenu(props: ContextMenuProps) {
|
export function _patchContextMenu(props: ContextMenuProps) {
|
||||||
|
props.contextMenuApiArguments ??= [];
|
||||||
const contextMenuPatches = navPatches.get(props.navId);
|
const contextMenuPatches = navPatches.get(props.navId);
|
||||||
|
|
||||||
if (contextMenuPatches) {
|
if (contextMenuPatches) {
|
||||||
for (const patch of contextMenuPatches) {
|
for (const patch of contextMenuPatches) {
|
||||||
try {
|
try {
|
||||||
patch(props.children, props.contextMenuApiArguments);
|
patch(props.children, ...props.contextMenuApiArguments);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ContextMenuLogger.error(`Patch for ${props.navId} errored,`, err);
|
ContextMenuLogger.error(`Patch for ${props.navId} errored,`, err);
|
||||||
}
|
}
|
||||||
@ -133,7 +134,7 @@ export function _patchContextMenu(props: ContextMenuProps) {
|
|||||||
|
|
||||||
for (const patch of globalPatches) {
|
for (const patch of globalPatches) {
|
||||||
try {
|
try {
|
||||||
patch(props.navId, props.children, props.contextMenuApiArguments);
|
patch(props.navId, props.children, ...props.contextMenuApiArguments);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ContextMenuLogger.error("Global patch errored,", err);
|
ContextMenuLogger.error("Global patch errored,", err);
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,28 @@
|
|||||||
|
|
||||||
import { Settings } from "@api/settings";
|
import { Settings } from "@api/settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin, { type PatchReplacement } from "@utils/types";
|
||||||
import { addListener, removeListener } from "@webpack";
|
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) {
|
function listener(exports: any, id: number) {
|
||||||
if (!Settings.plugins.ContextMenuAPI.enabled) return removeListener(listener);
|
if (!Settings.plugins.ContextMenuAPI.enabled) return removeListener(listener);
|
||||||
|
|
||||||
@ -37,13 +56,24 @@ function listener(exports: any, id: number) {
|
|||||||
all: true,
|
all: true,
|
||||||
noWarn: true,
|
noWarn: true,
|
||||||
find: "navId:",
|
find: "navId:",
|
||||||
replacement: [{
|
replacement: [
|
||||||
match: RegExp(`${id}(?<=(\\i)=.+?).+$`),
|
{
|
||||||
replace: (code, varName) => {
|
// Set the lastVarName for our proxy to use
|
||||||
const regex = RegExp(`${key},{(?<=${varName}\\.${key},{)`, "g");
|
match: RegExp(`${id}(?<=(\\i)=.+?)`),
|
||||||
return code.replace(regex, "$&contextMenuApiArguments:arguments,");
|
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);
|
removeListener(listener);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* 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 { showNotification } from "@api/Notifications";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import Logger from "@utils/Logger";
|
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({
|
export default definePlugin({
|
||||||
name: "DevCompanion",
|
name: "DevCompanion",
|
||||||
description: "Dev Companion Plugin",
|
description: "Dev Companion Plugin",
|
||||||
@ -229,24 +244,12 @@ export default definePlugin({
|
|||||||
|
|
||||||
start() {
|
start() {
|
||||||
initWs();
|
initWs();
|
||||||
addContextMenuPatch("user-settings-cog", kids => {
|
addContextMenuPatch("user-settings-cog", contextMenuPatch);
|
||||||
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);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
socket?.close(1000, "Plugin Stopped");
|
socket?.close(1000, "Plugin Stopped");
|
||||||
socket = void 0;
|
socket = void 0;
|
||||||
|
removeContextMenuPatch("user-settings-cog", contextMenuPatch);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -176,9 +176,9 @@ function CloneModal({ id, name: emojiName, isAnimated }: { id: string; name: str
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageContextMenuPatch: NavContextMenuPatchCallback = (children, args) => {
|
const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
|
||||||
if (!args?.[0]) return;
|
if (!props) return;
|
||||||
const { favoriteableId, emoteClonerDataAlt, itemHref, itemSrc, favoriteableType } = args[0];
|
const { favoriteableId, emoteClonerDataAlt, itemHref, itemSrc, favoriteableType } = props;
|
||||||
|
|
||||||
if (!emoteClonerDataAlt || favoriteableType !== "emoji") return;
|
if (!emoteClonerDataAlt || favoriteableType !== "emoji") return;
|
||||||
|
|
||||||
|
@ -131,8 +131,8 @@ export default definePlugin({
|
|||||||
{
|
{
|
||||||
find: ".activeCommandOption",
|
find: ".activeCommandOption",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(.)\.push.{1,50}\(\i,\{.{1,30}\},"gift"\)\)/,
|
match: /(.)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
||||||
replace: "$&;try{$1.push($self.chatBarIcon())}catch{}",
|
replace: "$&;try{$2||$1.push($self.chatBarIcon())}catch{}",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -20,13 +20,15 @@ import { addClickListener, removeClickListener } from "@api/MessageEvents";
|
|||||||
import { migratePluginSettings } from "@api/settings";
|
import { migratePluginSettings } from "@api/settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { UserStore } from "@webpack/common";
|
import { PermissionStore, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
let isDeletePressed = false;
|
let isDeletePressed = false;
|
||||||
const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true);
|
const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true);
|
||||||
const keyup = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = false);
|
const keyup = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = false);
|
||||||
|
|
||||||
|
const MANAGE_CHANNELS = 1n << 4n;
|
||||||
|
|
||||||
migratePluginSettings("MessageClickActions", "MessageQuickActions");
|
migratePluginSettings("MessageClickActions", "MessageQuickActions");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
@ -50,8 +52,6 @@ export default definePlugin({
|
|||||||
|
|
||||||
start() {
|
start() {
|
||||||
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");
|
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");
|
||||||
const PermissionStore = findByPropsLazy("can", "initialize");
|
|
||||||
const Permissions = findLazy(m => typeof m.MANAGE_MESSAGES === "bigint");
|
|
||||||
const EditStore = findByPropsLazy("isEditing", "isEditingAny");
|
const EditStore = findByPropsLazy("isEditing", "isEditingAny");
|
||||||
|
|
||||||
document.addEventListener("keydown", keydown);
|
document.addEventListener("keydown", keydown);
|
||||||
@ -64,7 +64,7 @@ export default definePlugin({
|
|||||||
MessageActions.startEditMessage(chan.id, msg.id, msg.content);
|
MessageActions.startEditMessage(chan.id, msg.id, msg.content);
|
||||||
event.preventDefault();
|
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);
|
MessageActions.deleteMessage(chan.id, msg.id);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,9 @@ function search(src: string, engine: string) {
|
|||||||
open(engine + encodeURIComponent(src), "_blank");
|
open(engine + encodeURIComponent(src), "_blank");
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageContextMenuPatch: NavContextMenuPatchCallback = (children, args) => {
|
const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
|
||||||
if (!args?.[0]) return;
|
if (!props) return;
|
||||||
const { reverseImageSearchType, itemHref, itemSrc } = args[0];
|
const { reverseImageSearchType, itemHref, itemSrc } = props;
|
||||||
|
|
||||||
if (!reverseImageSearchType || reverseImageSearchType !== "img") return;
|
if (!reverseImageSearchType || reverseImageSearchType !== "img") return;
|
||||||
|
|
||||||
|
@ -321,9 +321,7 @@ export default definePlugin({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// The module wasn't being found, so lets just escape everything
|
find: "\"^/guild-stages/(\\\\d+)(?:/)?(\\\\d+)?\"",
|
||||||
// eslint-disable-next-line no-useless-escape
|
|
||||||
find: "\^https\:\/\/\(\?\:canary\.\|ptb\.\)\?discord.com\/channels\/\(\\\\\d\+\|",
|
|
||||||
replacement: {
|
replacement: {
|
||||||
// Make mentions of hidden channels work
|
// Make mentions of hidden channels work
|
||||||
match: /\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL,\i\)/,
|
match: /\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL,\i\)/,
|
||||||
|
@ -40,28 +40,30 @@ function SilentMessageToggle() {
|
|||||||
return (
|
return (
|
||||||
<Tooltip text="Toggle Silent Message">
|
<Tooltip text="Toggle Silent Message">
|
||||||
{tooltipProps => (
|
{tooltipProps => (
|
||||||
<Button
|
<div style={{ display: "flex" }}>
|
||||||
{...tooltipProps}
|
<Button
|
||||||
onClick={() => setEnabled(prev => !prev)}
|
{...tooltipProps}
|
||||||
size=""
|
onClick={() => setEnabled(prev => !prev)}
|
||||||
look={ButtonLooks.BLANK}
|
size=""
|
||||||
innerClassName={ButtonWrapperClasses.button}
|
look={ButtonLooks.BLANK}
|
||||||
style={{ margin: "0px 8px" }}
|
innerClassName={ButtonWrapperClasses.button}
|
||||||
>
|
style={{ margin: "0px 8px" }}
|
||||||
<div className={ButtonWrapperClasses.buttonWrapper}>
|
>
|
||||||
<svg
|
<div className={ButtonWrapperClasses.buttonWrapper}>
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
width="24"
|
||||||
viewBox="0 0 24 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" />
|
<g fill="currentColor">
|
||||||
<path d="M18.2624 5.50209L21 2.5V1H16.0349V2.49791H18.476L16 5.61088V7H21V5.50209H18.2624Z" />
|
<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" />
|
||||||
{!enabled && <line x1="22" y1="2" x2="2" y2="22" stroke="var(--red-500)" stroke-width="2.5" />}
|
<path d="M18.2624 5.50209L21 2.5V1H16.0349V2.49791H18.476L16 5.61088V7H21V5.50209H18.2624Z" />
|
||||||
</g>
|
{!enabled && <line x1="22" y1="2" x2="2" y2="22" stroke="var(--red-500)" stroke-width="2.5" />}
|
||||||
</svg>
|
</g>
|
||||||
</div>
|
</svg>
|
||||||
</Button>
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
@ -75,8 +77,8 @@ export default definePlugin({
|
|||||||
{
|
{
|
||||||
find: ".activeCommandOption",
|
find: ".activeCommandOption",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /"gift"\)\);(?<=(\i)\.push.+?)/,
|
match: /"gift"\)\);(?<=(\i)\.push.+?disabled:(\i),.+?)/,
|
||||||
replace: (m, array) => `${m}${array}.push($self.SilentMessageToggle());`
|
replace: (m, array, disabled) => `${m}${disabled}||${array}.push($self.SilentMessageToggle());`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -82,8 +82,8 @@ export default definePlugin({
|
|||||||
find: ".activeCommandOption",
|
find: ".activeCommandOption",
|
||||||
predicate: () => settings.store.showIcon,
|
predicate: () => settings.store.showIcon,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(.)\.push.{1,50}\(\i,\{.{1,30}\},"gift"\)\)/,
|
match: /(.)\.push.{1,30}disabled:(\i),.{1,20}\},"gift"\)\)/,
|
||||||
replace: "$&;try{$1.push($self.chatBarIcon())}catch{}",
|
replace: "$&;try{$2||$1.push($self.chatBarIcon())}catch{}",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -56,8 +56,8 @@ export default definePlugin({
|
|||||||
find: "AudioContextSettingsMigrated",
|
find: "AudioContextSettingsMigrated",
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /(?<=updateAsync\("audioContextSettings".{0,50})(?=return (\i)\.volume=(\i))/,
|
match: /(?<=updateAsync\("audioContextSettings".{0,350}return \i\.volume=)\i(?=})/,
|
||||||
replace: (_, volumeOptions, newVolume) => `if(${newVolume}>200)return ${volumeOptions}.volume=200;`
|
replace: "$&>200?200:$&"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /(?<=Object\.entries\(\i\.localMutes\).+?volume:).+?(?=,)/,
|
match: /(?<=Object\.entries\(\i\.localMutes\).+?volume:).+?(?=,)/,
|
Loading…
Reference in New Issue
Block a user