From 8c5217f9f2ac527ae9c2c53543bf5b958e1aa325 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 21 Jul 2024 00:54:41 +0200 Subject: [PATCH 01/24] require node>=20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3724a6e..6345e4a0 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "sourceDir": "./dist/firefox-unpacked" }, "engines": { - "node": ">=18", + "node": ">=20", "pnpm": ">=9" } } From f9fb3bbba713613d156d1b7150f9551b373397e3 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 21 Jul 2024 01:29:46 +0200 Subject: [PATCH 02/24] fix watch erroring when clean building --- scripts/build/common.mts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/build/common.mts b/scripts/build/common.mts index 054a5667..3bc3dc39 100644 --- a/scripts/build/common.mts +++ b/scripts/build/common.mts @@ -261,6 +261,20 @@ export const stylePlugin: Plugin = { } }; +let buildsFinished = Promise.resolve(); +const buildsFinishedPlugin: Plugin = { + name: "builds-finished-plugin", + setup({ onEnd }) { + if (!watch) return; + + let resolve: () => void; + const done = new Promise(r => resolve = r); + buildsFinished = buildsFinished.then(() => done); + + onEnd(() => resolve()); + }, +}; + export const commonOpts = { logLevel: "info", bundle: true, @@ -268,7 +282,7 @@ export const commonOpts = { sourcemap: watch ? "inline" : "external", legalComments: "linked", banner, - plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin], + plugins: [fileUrlPlugin, gitHashPlugin, gitRemotePlugin, stylePlugin, buildsFinishedPlugin], external: ["~plugins", "~git-hash", "~git-remote", "/assets/*"], inject: ["./scripts/build/inject/react.mjs"], jsxFactory: "VencordCreateElement", @@ -286,6 +300,8 @@ export async function buildOrWatchAll() { if (watch) { const contexts = await Promise.all(builds.map(context)); await Promise.all(contexts.map(ctx => ctx.watch())); + + await buildsFinished; } else { try { await Promise.all(builds.map(build)); From 7781dface9b0ea448d191a718beaabf14c6dfbc5 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 21 Jul 2024 02:52:28 +0200 Subject: [PATCH 03/24] fix: apply update only on quit --- src/main/patcher.ts | 6 +----- src/main/updater/http.ts | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/patcher.ts b/src/main/patcher.ts index 6ab4162d..2c274028 100644 --- a/src/main/patcher.ts +++ b/src/main/patcher.ts @@ -27,11 +27,7 @@ import { IS_VANILLA } from "./utils/constants"; console.log("[Vencord] Starting up..."); // FIXME: remove at some point -const isLegacyNonAsarVencord = IS_STANDALONE && !__dirname.endsWith(".asar"); -if (isLegacyNonAsarVencord) { - console.warn("This is a legacy non asar install! Migrating to asar and restarting..."); - require("./updater/http").migrateLegacyToAsar(); -} +export const isLegacyNonAsarVencord = IS_STANDALONE && !__dirname.endsWith(".asar"); // Our injector file at app/index.js const injectorPath = require.main!.filename; diff --git a/src/main/updater/http.ts b/src/main/updater/http.ts index bd70b51d..70670a03 100644 --- a/src/main/updater/http.ts +++ b/src/main/updater/http.ts @@ -16,10 +16,15 @@ * along with this program. If not, see . */ +import { isLegacyNonAsarVencord } from "@main/patcher"; import { IpcEvents } from "@shared/IpcEvents"; import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent"; import { app, dialog, ipcMain } from "electron"; -import { writeFileSync as originalWriteFileSync } from "original-fs"; +import { + existsSync as originalExistsSync, + renameSync as originalRenameSync, + writeFileSync as originalWriteFileSync, +} from "original-fs"; import { join } from "path"; import gitHash from "~git-hash"; @@ -31,6 +36,8 @@ import { ASAR_FILE, serializeErrors } from "./common"; const API_BASE = `https://api.github.com/repos/${gitRemote}`; let PendingUpdate: string | null = null; +let hasUpdateToApplyOnQuit = false; + async function githubGet(endpoint: string) { return get(API_BASE + endpoint, { headers: { @@ -76,7 +83,8 @@ async function applyUpdates() { if (!PendingUpdate) return true; const data = await get(PendingUpdate); - originalWriteFileSync(__dirname, data); + originalWriteFileSync(__dirname + ".new", data); + hasUpdateToApplyOnQuit = true; PendingUpdate = null; @@ -88,7 +96,7 @@ ipcMain.handle(IpcEvents.GET_UPDATES, serializeErrors(calculateGitChanges)); ipcMain.handle(IpcEvents.UPDATE, serializeErrors(fetchUpdates)); ipcMain.handle(IpcEvents.BUILD, serializeErrors(applyUpdates)); -export async function migrateLegacyToAsar() { +async function migrateLegacyToAsar() { try { const isFlatpak = process.platform === "linux" && !!process.env.FLATPAK_ID; if (isFlatpak) throw "Flatpak Discord can't automatically be migrated."; @@ -112,3 +120,26 @@ export async function migrateLegacyToAsar() { }); } } + +function applyPreviousUpdate() { + originalRenameSync(__dirname + ".new", __dirname); + + app.relaunch(); + app.exit(); +} + + +app.on("will-quit", () => { + if (hasUpdateToApplyOnQuit) + originalRenameSync(__dirname + ".new", __dirname); +}); + +if (isLegacyNonAsarVencord) { + console.warn("This is a legacy non asar install! Migrating to asar and restarting..."); + migrateLegacyToAsar(); +} + +if (originalExistsSync(__dirname + ".new")) { + console.warn("Found previous not applied update, applying now and restarting..."); + applyPreviousUpdate(); +} From 485452f65adbcb3b12b5413d14c0cc65cb182379 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:13:32 -0400 Subject: [PATCH 04/24] Equicord Protocol --- src/api/Commands/index.ts | 2 +- .../newPluginsManager/index.tsx | 2 +- src/equicordplugins/title/index.ts | 2 +- src/equicordplugins/vencordRPC/index.ts | 2 +- src/main/index.ts | 25 +++++++++++++++++++ src/plugins/xsOverlay.desktop/index.ts | 4 +-- src/utils/themes/usercss/compiler.ts | 2 +- 7 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/api/Commands/index.ts b/src/api/Commands/index.ts index ef4db171..147f720a 100644 --- a/src/api/Commands/index.ts +++ b/src/api/Commands/index.ts @@ -67,7 +67,7 @@ export const _handleCommand = function (cmd: Command, args: Argument[], ctx: Com sendBotMessage(ctx.channel.id, { content: `${msg}:\n${makeCodeblock(reason)}`, author: { - username: "Vencord" + username: "Equicord" } }); }; diff --git a/src/equicordplugins/newPluginsManager/index.tsx b/src/equicordplugins/newPluginsManager/index.tsx index 8c693882..294036ab 100644 --- a/src/equicordplugins/newPluginsManager/index.tsx +++ b/src/equicordplugins/newPluginsManager/index.tsx @@ -12,7 +12,7 @@ import { openNewPluginsModal } from "./NewPluginsModal"; export default definePlugin({ name: "NewPluginsManager", - description: "Utility that notifies you when new plugins are added to Vencord", + description: "Utility that notifies you when new plugins are added to Equicord", authors: [Devs.Sqaaakoi], flux: { async POST_CONNECTION_OPEN() { diff --git a/src/equicordplugins/title/index.ts b/src/equicordplugins/title/index.ts index 0314f815..9e67a72a 100644 --- a/src/equicordplugins/title/index.ts +++ b/src/equicordplugins/title/index.ts @@ -15,7 +15,7 @@ const rootTitle = { base: null as string | null }; export const settings = definePluginSettings({ title: { type: OptionType.STRING, - default: "Vencord", + default: "Equicord", description: "Window title prefix", onChange: setTitle, }, diff --git a/src/equicordplugins/vencordRPC/index.ts b/src/equicordplugins/vencordRPC/index.ts index 5a0cba47..e0e2f13f 100644 --- a/src/equicordplugins/vencordRPC/index.ts +++ b/src/equicordplugins/vencordRPC/index.ts @@ -241,7 +241,7 @@ async function createActivity(): Promise { let { type } = settings.store; - let appName = "Vencord"; + let appName = "Equicord"; let details = ""; let state = ""; let imageBig = ""; diff --git a/src/main/index.ts b/src/main/index.ts index cc2eb14e..8f6a677a 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -53,6 +53,31 @@ if (IS_VESKTOP || !IS_VANILLA) { } }); + protocol.registerFileProtocol("equicord", ({ url: unsafeUrl }, cb) => { + let url = unsafeUrl.slice("equicord://".length); + if (url.endsWith("/")) url = url.slice(0, -1); + if (url.startsWith("/themes/")) { + const theme = url.slice("/themes/".length); + const safeUrl = ensureSafePath(THEMES_DIR, theme); + if (!safeUrl) { + cb({ statusCode: 403 }); + return; + } + cb(safeUrl.replace(/\?v=\d+$/, "")); + return; + } + switch (url) { + case "renderer.js.map": + case "preload.js.map": + case "patcher.js.map": + case "main.js.map": + cb(join(__dirname, url)); + break; + default: + cb({ statusCode: 403 }); + } + }); + try { if (RendererSettings.store.enableReactDevtools) installExt("fmkadmapgofadopljbjfkapdkoienihi") diff --git a/src/plugins/xsOverlay.desktop/index.ts b/src/plugins/xsOverlay.desktop/index.ts index 8b06475c..b48c4d7a 100644 --- a/src/plugins/xsOverlay.desktop/index.ts +++ b/src/plugins/xsOverlay.desktop/index.ts @@ -271,7 +271,7 @@ function sendMsgNotif(titleString: string, content: string, message: Message) { content: content, useBase64Icon: true, icon: result, - sourceApp: "Vencord" + sourceApp: "Equicord" }; Native.sendToOverlay(msgData); }); @@ -290,7 +290,7 @@ function sendOtherNotif(content: string, titleString: string) { content: content, useBase64Icon: false, icon: null, - sourceApp: "Vencord" + sourceApp: "Equicord" }; Native.sendToOverlay(msgData); } diff --git a/src/utils/themes/usercss/compiler.ts b/src/utils/themes/usercss/compiler.ts index 16e69677..d366ac13 100644 --- a/src/utils/themes/usercss/compiler.ts +++ b/src/utils/themes/usercss/compiler.ts @@ -68,7 +68,7 @@ export async function compileUsercss(fileName: string) { const preprocessorFn = preprocessors[preprocessor]; if (!preprocessorFn) { - UserCSSLogger.error("File", fileName, "requires preprocessor", preprocessor, "which isn't known to Vencord"); + UserCSSLogger.error("File", fileName, "requires preprocessor", preprocessor, "which isn't known to Equicord"); return null; } From b8cb056f13631fb0946aae814cf9ce92111a052d Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:13:52 -0400 Subject: [PATCH 05/24] Rename emojiDumper to be uppercase --- src/equicordplugins/emojiDumper/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/emojiDumper/index.tsx b/src/equicordplugins/emojiDumper/index.tsx index 2a80b64d..6c6b390e 100644 --- a/src/equicordplugins/emojiDumper/index.tsx +++ b/src/equicordplugins/emojiDumper/index.tsx @@ -23,7 +23,7 @@ const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }; export default definePlugin({ - name: "emojiDumper", + name: "EmojiDumper", description: "Context menu to dump and download a server's emojis.", authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Woosh], start() { From 5b4fb13ab354144cfd959c2add7d74e8ecc699db Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:17:34 -0400 Subject: [PATCH 06/24] Make Plugin Names Consistent --- src/equicordplugins/emojiDumper/index.tsx | 2 ++ src/equicordplugins/noAppsAllowed/index.tsx | 4 +++- src/plugins/oneko/index.ts | 7 ++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/equicordplugins/emojiDumper/index.tsx b/src/equicordplugins/emojiDumper/index.tsx index 6c6b390e..9569ad95 100644 --- a/src/equicordplugins/emojiDumper/index.tsx +++ b/src/equicordplugins/emojiDumper/index.tsx @@ -5,6 +5,7 @@ */ import { addContextMenuPatch, findGroupChildrenByChildId, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; +import { migratePluginSettings } from "@api/Settings"; import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Menu } from "@webpack/common"; @@ -22,6 +23,7 @@ const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; } }; +migratePluginSettings("EmojiDumper", "emojiDumper"); export default definePlugin({ name: "EmojiDumper", description: "Context menu to dump and download a server's emojis.", diff --git a/src/equicordplugins/noAppsAllowed/index.tsx b/src/equicordplugins/noAppsAllowed/index.tsx index dbedeab8..00eb4729 100644 --- a/src/equicordplugins/noAppsAllowed/index.tsx +++ b/src/equicordplugins/noAppsAllowed/index.tsx @@ -4,11 +4,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { migratePluginSettings } from "@api/Settings"; import { EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; +migratePluginSettings("NoAppsAllowed", "noAppsAllowed"); export default definePlugin({ - name: "noAppsAllowed", + name: "NoAppsAllowed", description: "returns the bot's tag :skulk:", authors: [EquicordDevs.kvba], diff --git a/src/plugins/oneko/index.ts b/src/plugins/oneko/index.ts index ad35268f..32c7e917 100644 --- a/src/plugins/oneko/index.ts +++ b/src/plugins/oneko/index.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings, Settings } from "@api/Settings"; +import { definePluginSettings, migratePluginSettings, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -31,7 +31,7 @@ const settings = definePluginSettings({ }, onChange: () => { // note: cant call the start() function from here. so i just copy pasted it (This was pointed out in the last commit i made. So this is to just clear stuff up for any future devs that work on this :D ) - if (Settings.plugins.oneko.enabled) { + if (Settings.plugins.Oneko.enabled) { document.getElementById("oneko")?.remove(); fetch("https://raw.githubusercontent.com/adryd325/oneko.js/8fa8a1864aa71cd7a794d58bc139e755e96a236c/oneko.js") .then(x => x.text()) @@ -45,8 +45,9 @@ const settings = definePluginSettings({ } }); +migratePluginSettings("Oneko", "oneko"); export default definePlugin({ - name: "oneko", + name: "Oneko", description: "cat follow mouse (real)", // Listing adryd here because this literally just evals her script authors: [Devs.Ven, Devs.adryd], From e59763c9d2bd644101bcfdbd67856ce38cf617f9 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:20:57 -0400 Subject: [PATCH 07/24] feat(ConsoleJanitor): NoNitroUpsell Logger Predicate --- src/plugins/consoleJanitor/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 1e8bb132..8f7e54f5 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings } from "@api/Settings"; +import { definePluginSettings, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -105,6 +105,7 @@ export default definePlugin({ }, { find: "ProductCatalog", + predicate: () => Settings.plugins.NoNitroUpsell.enabled, replacement: { match: /\i\.warn\("Cannot find the corresponding SKU to the user's premium type "\.concat\(\i\.premiumType\)\),/, replace: "" From 1e369724fb2d6a4c784208a68241797ae392cd9c Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:23:43 -0400 Subject: [PATCH 08/24] Remove Predicate for NoNitroUpsell I forgot it logs it when its off --- src/plugins/consoleJanitor/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 8f7e54f5..1e8bb132 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings, Settings } from "@api/Settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -105,7 +105,6 @@ export default definePlugin({ }, { find: "ProductCatalog", - predicate: () => Settings.plugins.NoNitroUpsell.enabled, replacement: { match: /\i\.warn\("Cannot find the corresponding SKU to the user's premium type "\.concat\(\i\.premiumType\)\),/, replace: "" From 526133e43d6bbd7ec4bbada672f967e97ed4f825 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:56:25 -0400 Subject: [PATCH 09/24] StickerBlocker --- src/equicordplugins/stickerBlocker/index.tsx | 131 +++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/equicordplugins/stickerBlocker/index.tsx diff --git a/src/equicordplugins/stickerBlocker/index.tsx b/src/equicordplugins/stickerBlocker/index.tsx new file mode 100644 index 00000000..50402c87 --- /dev/null +++ b/src/equicordplugins/stickerBlocker/index.tsx @@ -0,0 +1,131 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { addContextMenuPatch, findGroupChildrenByChildId, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; +import { DataStore } from "@api/index"; +import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; +import { Button, Menu } from "@webpack/common"; +import React, { ReactNode } from "react"; + +const settings = definePluginSettings({ + showGif: { + type: OptionType.BOOLEAN, + description: "Whether to show a snazzy cat gif", + default: true, + restartNeeded: true + }, + showMessage: { + type: OptionType.BOOLEAN, + description: "Whether to show a message detailing which id was blocked", + default: false, + restartNeeded: true + }, + showButton: { + type: OptionType.BOOLEAN, + description: "Whether to show a button to unblock the gif", + default: true, + restartNeeded: true + }, + blockedStickers: { + type: OptionType.STRING, + description: "The list of blocked sticker IDs (don't edit unless you know what you're doing)", + default: "" + } +}); + +export default definePlugin({ + name: "StickerBlocker", + description: "Allows you to block stickers from being displayed.", + authors: [Devs.Samwich], + patches: [ + { + find: "l.Z.STICKER_MESSAGE", + replacement: { + match: /}\),\(null!=\i\?\i:(\i)\)\.name]}\);/, + replace: "$& if(Vencord.Settings.plugins.StickerBlocker.blockedStickers.split(\", \").includes($1.id)) { return($self.blockedComponent($1)) }" + } + } + ], + start() { + addContextMenuPatch("message", messageContextMenuPatch); + DataStore.createStore("StickerBlocker", "data"); + }, + stop() { + removeContextMenuPatch("message", messageContextMenuPatch); + }, + blockedComponent: ErrorBoundary.wrap(blockedComponentRender, { fallback: () =>

Failed to render :(

}), + settings, +}); + +function blockedComponentRender(sticker) { + const { showGif, showMessage, showButton } = settings.store; + const elements = [] as ReactNode[]; + + if (showGif) { + elements.push( + + ); + } + + if (showMessage) { + elements.push( +
Blocked Sticker. ID: {sticker.id}, NAME: {sticker.name}
+ ); + } + + if (showButton) { + elements.push( + + ); + } + + return <>{elements}; +} + + +const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { + const { favoriteableType, favoriteableId } = props ?? {}; + if (favoriteableType !== "sticker") { return; } + if (favoriteableId === null) { return; } + const group = findGroupChildrenByChildId("reply", children); + if (!group) return; + + group.splice(group.findIndex(c => c?.props?.id === "reply") + 1, 0, buttonThingy(favoriteableId)); +}; + +function buttonThingy(name) { + return ( + toggleBlock(name)} + /> + ); +} + +function toggleBlock(name) { + if (settings.store.blockedStickers === undefined || settings.store.blockedStickers == null) { + return; + } + const excepted = isStickerBlocked(name); + if (excepted) { + settings.store.blockedStickers = settings.store.blockedStickers.split(", ").filter(item => item !== name).join(", "); + } else { + settings.store.blockedStickers = settings.store.blockedStickers.split(", ").concat(name).join(", "); + } +} + + +function isStickerBlocked(name) { + if (settings.store.blockedStickers === undefined || settings.store.blockedStickers == null) { + return; + } + return settings.store.blockedStickers.split(", ").includes(name); +} From 8e1140f26dc4e662222a0567beddc0c855d76117 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:58:41 -0400 Subject: [PATCH 10/24] regex find --- src/equicordplugins/stickerBlocker/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/stickerBlocker/index.tsx b/src/equicordplugins/stickerBlocker/index.tsx index 50402c87..f10c761b 100644 --- a/src/equicordplugins/stickerBlocker/index.tsx +++ b/src/equicordplugins/stickerBlocker/index.tsx @@ -45,7 +45,7 @@ export default definePlugin({ authors: [Devs.Samwich], patches: [ { - find: "l.Z.STICKER_MESSAGE", + find: /\i\.\i\.STICKER_MESSAGE/, replacement: { match: /}\),\(null!=\i\?\i:(\i)\)\.name]}\);/, replace: "$& if(Vencord.Settings.plugins.StickerBlocker.blockedStickers.split(\", \").includes($1.id)) { return($self.blockedComponent($1)) }" From 3ae17018487ee6589e81ec3e0582c899850e6f82 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 02:15:30 -0400 Subject: [PATCH 11/24] Fix StickerBlocker contextmenu --- src/equicordplugins/stickerBlocker/index.tsx | 86 ++++++++++++-------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/src/equicordplugins/stickerBlocker/index.tsx b/src/equicordplugins/stickerBlocker/index.tsx index f10c761b..d6bda559 100644 --- a/src/equicordplugins/stickerBlocker/index.tsx +++ b/src/equicordplugins/stickerBlocker/index.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { addContextMenuPatch, findGroupChildrenByChildId, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu"; +import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { DataStore } from "@api/index"; import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; @@ -39,30 +39,6 @@ const settings = definePluginSettings({ } }); -export default definePlugin({ - name: "StickerBlocker", - description: "Allows you to block stickers from being displayed.", - authors: [Devs.Samwich], - patches: [ - { - find: /\i\.\i\.STICKER_MESSAGE/, - replacement: { - match: /}\),\(null!=\i\?\i:(\i)\)\.name]}\);/, - replace: "$& if(Vencord.Settings.plugins.StickerBlocker.blockedStickers.split(\", \").includes($1.id)) { return($self.blockedComponent($1)) }" - } - } - ], - start() { - addContextMenuPatch("message", messageContextMenuPatch); - DataStore.createStore("StickerBlocker", "data"); - }, - stop() { - removeContextMenuPatch("message", messageContextMenuPatch); - }, - blockedComponent: ErrorBoundary.wrap(blockedComponentRender, { fallback: () =>

Failed to render :(

}), - settings, -}); - function blockedComponentRender(sticker) { const { showGif, showMessage, showButton } = settings.store; const elements = [] as ReactNode[]; @@ -89,22 +65,40 @@ function blockedComponentRender(sticker) { } -const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => { - const { favoriteableType, favoriteableId } = props ?? {}; - if (favoriteableType !== "sticker") { return; } - if (favoriteableId === null) { return; } - const group = findGroupChildrenByChildId("reply", children); - if (!group) return; +const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => { + const { favoriteableId, favoriteableType } = props ?? {}; - group.splice(group.findIndex(c => c?.props?.id === "reply") + 1, 0, buttonThingy(favoriteableId)); + if (!favoriteableId) return; + + const menuItem = (() => { + switch (favoriteableType) { + case "sticker": + const sticker = props.message.stickerItems.find(s => s.id === favoriteableId); + if (sticker?.format_type === 3 /* LOTTIE */) return; + + return buildMenuItem(favoriteableId); + } + })(); + + if (menuItem) + findGroupChildrenByChildId("copy-link", children)?.push(menuItem); }; -function buttonThingy(name) { +const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => { + const { id, type } = props?.target?.dataset ?? {}; + if (!id) return; + + if (type === "sticker" && !props.target.className?.includes("lottieCanvas")) { + children.push(buildMenuItem(id)); + } +}; + +function buildMenuItem(name) { return ( toggleBlock(name)} /> ); @@ -129,3 +123,27 @@ function isStickerBlocked(name) { } return settings.store.blockedStickers.split(", ").includes(name); } + +export default definePlugin({ + name: "StickerBlocker", + description: "Allows you to block stickers from being displayed.", + authors: [Devs.Samwich], + patches: [ + { + find: /\i\.\i\.STICKER_MESSAGE/, + replacement: { + match: /}\),\(null!=\i\?\i:(\i)\)\.name]}\);/, + replace: "$& if(Vencord.Settings.plugins.StickerBlocker.blockedStickers.split(\", \").includes($1.id)) { return($self.blockedComponent($1)) }" + } + } + ], + contextMenus: { + "message": messageContextMenuPatch, + "expression-picker": expressionPickerPatch, + }, + start() { + DataStore.createStore("StickerBlocker", "data"); + }, + blockedComponent: ErrorBoundary.wrap(blockedComponentRender, { fallback: () =>

Failed to render :(

}), + settings, +}); From e3ed8240db92a85f49c7de269639fd33e8d473b7 Mon Sep 17 00:00:00 2001 From: thororen <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 05:17:27 -0400 Subject: [PATCH 12/24] FakeProfileThemes Fix --- src/plugins/fakeProfileThemes/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index 0f8c6bb5..54585032 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -57,7 +57,7 @@ function decode(bio: string): Array | null { if (bio == null) return null; const colorString = bio.match( - /\u{e005b}\u{e0023}([\u{e0061}-\u{e0066}\u{e0041}-\u{e0046}\u{e0030}-\u{e0039}]{6})\u{e002c}\u{e0023}([\u{e0061}-\u{e0066}\u{e0041}-\u{e0046}\u{e0030}-\u{e0039}]{6})\u{e005d}/u, + /\u{e005b}\u{e0023}([\u{e0061}-\u{e0066}\u{e0041}-\u{e0046}\u{e0030}-\u{e0039}]{1,6})\u{e002c}\u{e0023}([\u{e0061}-\u{e0066}\u{e0041}-\u{e0046}\u{e0030}-\u{e0039}]{1,6})\u{e005d}/u, ); if (colorString != null) { const parsed = [...colorString[0]] From cf9fd117c850c982cfe5baf6a93221c08de8acb2 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 07:11:14 -0400 Subject: [PATCH 13/24] Fix ViewIcons --- src/plugins/viewIcons/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/viewIcons/index.tsx b/src/plugins/viewIcons/index.tsx index 6bde04be..927a974f 100644 --- a/src/plugins/viewIcons/index.tsx +++ b/src/plugins/viewIcons/index.tsx @@ -189,7 +189,8 @@ export default definePlugin({ replacement: { match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",{...\2,/, replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openImage($1)}," - } + }, + all: true }, // Old Profiles Modal pfp { From 8c26116ffaacac0690796de25661ff52f756078a Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 25 Jul 2024 07:16:18 -0400 Subject: [PATCH 14/24] Change to a different CustomAppIcons --- .../customAppIcons/AppIconModal.tsx | 104 ------------- src/equicordplugins/customAppIcons/index.tsx | 147 +++++++++--------- src/utils/constants.ts | 4 + 3 files changed, 74 insertions(+), 181 deletions(-) delete mode 100644 src/equicordplugins/customAppIcons/AppIconModal.tsx diff --git a/src/equicordplugins/customAppIcons/AppIconModal.tsx b/src/equicordplugins/customAppIcons/AppIconModal.tsx deleted file mode 100644 index c8883a96..00000000 --- a/src/equicordplugins/customAppIcons/AppIconModal.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { localStorage } from "@utils/localStorage"; -import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal"; -import { findByProps } from "@webpack"; -import { Button, FluxDispatcher, Forms, React, showToast, Text, TextInput, Toasts, useState } from "@webpack/common"; - - -interface AppIcon { - id: string, - iconSource: string, - name: string, - isPremium: boolean; -} -function AppIconModal(props: ModalProps) { - const [name, setName] = useState(""); - const [imageUrl, setimageUrl] = useState(""); - - function addAppIcon(name, url) { - const appIcons = JSON.parse(localStorage.getItem("vc_app_icons") ?? "[]"); - const id = `${name.replaceAll(" ", "")}_${Date.now()}`; // avoid crashing if repeated name - const icon = { - "id": id, - "iconSource": url, - "isPremium": false, - "name": name - } as AppIcon; - - - appIcons.push(icon); - findByProps("M9", "UZ", "QA").UZ.push(icon); - findByProps("M9", "UZ", "QA").QA[icon.id] = icon; - showToast("Added custom app icon!", Toasts.Type.SUCCESS); - props.onClose(); - const oldIcon = findByProps("getCurrentDesktopIcon").getCurrentDesktopIcon(); - - let random_icon = Object.keys(findByProps("UZ")).filter(icon => icon !== oldIcon) as []; - random_icon = random_icon[Math.floor(Math.random() * random_icon.length)]; - - FluxDispatcher.dispatch({ - type: "APP_ICON_UPDATED", - id: random_icon - }); - FluxDispatcher.dispatch({ - type: "APP_ICON_UPDATED", - id: oldIcon - }); - localStorage.setItem("vc_app_icons", JSON.stringify(appIcons)); - } - - return - - Add a custom app icon: - - - -
- - - This name will be shown in the App Icons list. - - - -
- - - Paste here your image URL to upload your icon (.webp, .jpg, .jpeg, .png, .gif, .ico and Discord Icons, Emojis, PFPs, etc.). - - - -
- - - - -
; -} - -export default AppIconModal; diff --git a/src/equicordplugins/customAppIcons/index.tsx b/src/equicordplugins/customAppIcons/index.tsx index 7fc75f9a..0339c688 100644 --- a/src/equicordplugins/customAppIcons/index.tsx +++ b/src/equicordplugins/customAppIcons/index.tsx @@ -4,95 +4,88 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Link } from "@components/Link"; +import { definePluginSettings } from "@api/Settings"; +import { CodeBlock } from "@components/CodeBlock"; import { Devs, EquicordDevs } from "@utils/constants"; -import { localStorage } from "@utils/localStorage"; -import { closeAllModals, openModal } from "@utils/modal"; -import definePlugin from "@utils/types"; -import { findByProps } from "@webpack"; -import { Button, FluxDispatcher, Forms, React, showToast, Toasts } from "@webpack/common"; +import definePlugin, { OptionType, PluginSettingComponentDef } from "@utils/types"; +import { Forms, React, TextArea } from "@webpack/common"; -import AppIconModal from "./AppIconModal"; +type Icon = { + id: string, + iconSource: string, + isPremium: boolean, + name: string, +}; -function removeAppIcon() { - const current_icon = findByProps("getCurrentDesktopIcon").getCurrentDesktopIcon(); - let icons = JSON.parse(localStorage.getItem("vc_app_icons") || "[]"); - const index = icons.findIndex(icon => current_icon === icon.id); - if (index !== -1) { - icons = icons.filter(e => e.id !== current_icon); - delete findByProps("M9", "UZ", "QA").QA[current_icon]; - delete findByProps("M9", "UZ", "QA").UZ[findByProps("M9", "UZ", "QA").UZ.findIndex((icon => current_icon === icon?.id))]; - localStorage.setItem("vc_app_icons", JSON.stringify(icons)); - showToast("Icon successfully deleted!", Toasts.Type.SUCCESS); - FluxDispatcher.dispatch({ - type: "APP_ICON_UPDATED", - id: "AppIcon" - }); - } else { - showToast("Cannot delete native App Icons!", Toasts.Type.FAILURE); - return; +const settings = definePluginSettings({ + icons: { + description: "Icons to add", + type: OptionType.COMPONENT, + restartNeeded: true, + component: iconSettingsComponent + } +}); + +function iconSettingsComponent(props: Parameters[0]) { + const [state, setState] = React.useState(settings.store.icons ?? ""); + + function handleChange(newValue: string) { + setState(newValue); + props.setValue(newValue); } + return + Icons + The icons you want to add. + +