diff --git a/package.json b/package.json index f01640ad1..6dc74c3c5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.14.12.0", + "version": "1.14.13.0", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { diff --git a/src/plugins/_api/contextMenu.ts b/src/plugins/_api/contextMenu.ts index adcec76b0..8e4bea79e 100644 --- a/src/plugins/_api/contextMenu.ts +++ b/src/plugins/_api/contextMenu.ts @@ -17,7 +17,23 @@ */ import { Devs } from "@utils/constants"; +import { canonicalizeMatch } from "@utils/patches"; import definePlugin from "@utils/types"; +import { Menu } from "@webpack/common"; + +// duplicate values have multiple branches with different types. Just include all to be safe +const nameMap = { + radio: "MenuRadioItem", + separator: "MenuSeparator", + checkbox: "MenuCheckboxItem", + groupstart: "MenuGroup", + + control: "MenuControlItem", + compositecontrol: "MenuControlItem", + + item: "MenuItem", + customitem: "MenuItem", +}; export default definePlugin({ name: "ContextMenuAPI", @@ -26,13 +42,6 @@ export default definePlugin({ required: true, patches: [ - { - find: "♫ (つ。◕‿‿◕。)つ ♪", - replacement: { - match: /(?=let{navId:)(?<=function \i\((\i)\).+?)/, - replace: "$1=Vencord.Api.ContextMenu._usePatchContextMenu($1);" - } - }, { find: "navId:", all: true, @@ -48,6 +57,54 @@ export default definePlugin({ } } ] - } - ] + }, + + { + find: "Menu API only allows Items", + replacement: [ + // Patch the central context menu handler + { + match: /(?=let{navId:)(?<=function \i\((\i)\).+?)/, + replace: "$1=Vencord.Api.ContextMenu._usePatchContextMenu($1);" + }, + + // Demangle Discord's Menu Item module + { + match: /(?<=(\(\i\.type===(\i\.\i)\).{0,50}?navigable:.+Menu API).+?)}$/s, + replace: (_, m) => { + const registerCalls = [] as string[]; + + const typeCheckRe = canonicalizeMatch(/\(\i\.type===(\i\.\i)\)/g); // if (t.type === m.MenuItem) + const pushTypeRe = /type:"(\w+)"/g; // push({type:"item"}) + + let typeMatch: RegExpExecArray | null; + while ((typeMatch = typeCheckRe.exec(m)) !== null) { + const component = typeMatch[1]; + // Set the starting index of the second regex to that of the first to start + // matching from after the if + pushTypeRe.lastIndex = typeCheckRe.lastIndex; + + // extract the first type: "..." + const type = pushTypeRe.exec(m)?.[1]; + if (type && type in nameMap) { + const name = nameMap[type]; + registerCalls.push(`$self.registerMenuItem("${name}",${component})`); + } + } + + if (registerCalls.length < 6) { + console.warn("[MenuItemDemanglerAPI] Expected to remap 6 items, only remapped", registerCalls.length); + } + + return `${registerCalls.join(";")};}`; + }, + } + ], + }, + ], + + registerMenuItem(name: string, component: any) { + Object.defineProperty(component, "name", { value: name }); + Menu[name] = component; + } }); diff --git a/src/plugins/_api/menuItemDemangler.ts b/src/plugins/_api/menuItemDemangler.ts deleted file mode 100644 index 72b8fee6d..000000000 --- a/src/plugins/_api/menuItemDemangler.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { Devs } from "@utils/constants"; -import { canonicalizeMatch } from "@utils/patches"; -import definePlugin from "@utils/types"; -import { Menu } from "@webpack/common"; - -// duplicate values have multiple branches with different types. Just include all to be safe -const nameMap = { - radio: "MenuRadioItem", - separator: "MenuSeparator", - checkbox: "MenuCheckboxItem", - groupstart: "MenuGroup", - - control: "MenuControlItem", - compositecontrol: "MenuControlItem", - - item: "MenuItem", - customitem: "MenuItem", -}; - -export default definePlugin({ - name: "MenuItemDemanglerAPI", - description: "Demangles Discord's Menu Item module", - authors: [Devs.Ven], - required: true, - patches: [ - { - find: "Menu API only allows Items", - replacement: { - match: /(?<=(\(\i\.type===(\i\.\i)\).{0,50}?navigable:.+Menu API).+?)}$/s, - replace: (_, m) => { - const registerCalls = [] as string[]; - - const typeCheckRe = canonicalizeMatch(/\(\i\.type===(\i\.\i)\)/g); // if (t.type === m.MenuItem) - const pushTypeRe = /type:"(\w+)"/g; // push({type:"item"}) - - let typeMatch: RegExpExecArray | null; - while ((typeMatch = typeCheckRe.exec(m)) !== null) { - const component = typeMatch[1]; - // Set the starting index of the second regex to that of the first to start - // matching from after the if - pushTypeRe.lastIndex = typeCheckRe.lastIndex; - - // extract the first type: "..." - const type = pushTypeRe.exec(m)?.[1]; - if (type && type in nameMap) { - const name = nameMap[type]; - registerCalls.push(`$self.registerMenuItem("${name}",${component})`); - } - } - - if (registerCalls.length < 6) { - console.warn("[MenuItemDemanglerAPI] Expected to remap 6 items, only remapped", registerCalls.length); - } - - return `${registerCalls.join(";")};}`; - }, - }, - }, - ], - - registerMenuItem(name: string, component: any) { - Object.defineProperty(component, "name", { value: name }); - Menu[name] = component; - } -}); diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 05d817470..badcca853 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -395,7 +395,7 @@ export default definePlugin({ { // Modify the expanded prop to use the boolean if the above patch fails, or check if the folder is expanded from the list if it succeeds // Also export the list of expanded folders to the child folder component if the patch above succeeds, else export undefined - match: /(?<=\(0,\i\.jsxs?\)\(\i,\{folderNode:(\i),expanded:)\i(?=,)/, + match: /(?<=\.\.\.\i,folderNode:(\i),expanded:)\i(?=,)/, replace: (isExpandedOrExpandedIds, folderNote) => "" + `typeof ${isExpandedOrExpandedIds}==="boolean"?${isExpandedOrExpandedIds}:${isExpandedOrExpandedIds}.has(${folderNote}.id),` + `betterFoldersExpandedIds:${isExpandedOrExpandedIds} instanceof Set?${isExpandedOrExpandedIds}:void 0` diff --git a/src/plugins/noMosaic/index.ts b/src/plugins/noMosaic/index.ts new file mode 100644 index 000000000..b5fffba00 --- /dev/null +++ b/src/plugins/noMosaic/index.ts @@ -0,0 +1,53 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +const settings = definePluginSettings({ + inlineVideo: { + description: "Play videos without carousel modal", + type: OptionType.BOOLEAN, + default: true, + restartNeeded: true + } +}); + +export default definePlugin({ + name: "NoMosaic", + authors: [Devs.AutumnVN], + description: "Removes Discord image mosaic", + tags: ["Media", "Appearance", "Chat"], + searchTerms: ["image", "mosaic", "media"], + + settings, + + patches: [ + { + find: '"PLAINTEXT_PREVIEW":"OTHER"', + replacement: { + match: /"IMAGE"===\i\|\|"VIDEO"===\i\|\|"CLIP"===\i/, + replace: "false" + } + }, + { + find: "return{visualMediaItems:", + replacement: { + match: /return{visualMediaItems:.+?props:(\i)(?=.{0,20}?\1\.item\.uniqueId)/, + replace: '$&,useFullWidth:["IMAGE","VIDEO","CLIP"].includes($1.item?.type)?false:undefined' + } + }, + { + find: "renderAttachments(", + predicate: () => settings.store.inlineVideo, + replacement: { + match: /url:(\i)\.url\}\);return /, + replace: "$&$1.content_type?.startsWith('image/')&&" + } + }, + ] +}); diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index efcfe6770..651985f67 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -108,8 +108,8 @@ export default definePlugin({ find: 'tutorialId:"whos-online', replacement: [ { - match: /(#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.+}\):null,).{0,100}?— ",\i\]\}\)\]/, - replace: (_, rest) => `${rest}$self.RoleGroupColor(arguments[0])]` + match: /(#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.+}\):null,).{0,100}?(?:—|\\u2014) ",\i\]\}\)\]/, + replace: "$1$self.RoleGroupColor(arguments[0])]" }, ], predicate: () => settings.store.memberList @@ -118,7 +118,7 @@ export default definePlugin({ find: "#{intl::THREAD_BROWSER_PRIVATE}", replacement: [ { - match: /children:\[\i," — ",\i\]/, + match: /children:\[\i," (?:—|\\u2014) ",\i\]/, replace: "children:[$self.RoleGroupColor(arguments[0])]" }, ],