Improvements, changes and fixes (#611)

This commit is contained in:
Nuckyz 2023-03-19 04:53:00 -03:00 committed by GitHub
parent 5873bde6a6
commit 0fb79b763d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 105 additions and 71 deletions

View file

@ -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);
} }

View file

@ -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);

View file

@ -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);
} }
}); });

View file

@ -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;

View file

@ -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{}",
} }
}, },
], ],

View file

@ -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();
} }

View file

@ -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;

View file

@ -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\)/,

View file

@ -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());`
} }
} }
], ],

View file

@ -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{}",
} }
}, },
], ],

View file

@ -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:).+?(?=,)/,