Merge branch 'main' into dev

This commit is contained in:
thororen1234 2026-04-16 13:44:24 -04:00
commit e9fd57a4c2
No known key found for this signature in database
397 changed files with 981 additions and 3396 deletions

View file

@ -1,7 +1,7 @@
{
"name": "equicord",
"private": "true",
"version": "1.14.7.0",
"version": "1.14.6.2",
"description": "The other cutest Discord client mod",
"homepage": "https://github.com/Equicord/Equicord#readme",
"bugs": {
@ -54,47 +54,47 @@
"gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
"idb": "8.0.3",
"jsqr": "1.4.0",
"monaco-editor": "^0.55.1",
"monaco-editor": "^0.54.0",
"nanoid": "^5.1.6",
"native-file-system-adapter": "^3.0.1",
"usercss-meta": "^0.12.0",
"virtual-merge": "^1.0.1",
"yaml-js": "^0.3.1"
"virtual-merge": "^1.0.1"
},
"devDependencies": {
"@electron/asar": "^4.2.0",
"@stylistic/eslint-plugin": "^5.10.0",
"@types/chrome": "^0.1.40",
"@types/lodash": "^4.17.24",
"@types/node": "^25.6.0",
"@electron/asar": "^4.0.1",
"@stylistic/eslint-plugin": "^5.6.0",
"@types/adm-zip": "^0.5.7",
"@types/chrome": "^0.1.30",
"@types/diff": "^7.0.2",
"@types/lodash": "^4.17.20",
"@types/node": "^24.10.1",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@types/yazl": "^3.3.1",
"@types/yazl": "^3.3.0",
"@vencord/discord-types": "link:packages/discord-types",
"diff": "^9.0.0",
"esbuild": "^0.28.0",
"eslint": "10.2.0",
"diff": "^8.0.2",
"esbuild": "^0.27.0",
"eslint": "9.39.1",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-simple-header": "^1.2.1",
"eslint-plugin-simple-import-sort": "^13.0.0",
"eslint-plugin-unused-imports": "^4.4.1",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^4.3.0",
"highlight.js": "11.11.1",
"html-minifier-terser": "^7.2.0",
"moment": "^2.22.2",
"p-limit": "^7.3.0",
"puppeteer-core": "^24.41.0",
"standalone-electron-types": "^41.2.1",
"stylelint": "^17.8.0",
"stylelint-config-standard": "^40.0.0",
"svgo": "^4.0.1",
"puppeteer-core": "^24.30.0",
"standalone-electron-types": "^34.2.0",
"stylelint": "^16.25.0",
"stylelint-config-standard": "^39.0.1",
"ts-patch": "^3.3.0",
"ts-pattern": "^5.9.0",
"tsx": "^4.21.0",
"type-fest": "^5.5.0",
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.2",
"typescript-transform-paths": "^3.5.6",
"ts-pattern": "^5.6.0",
"tsx": "^4.20.6",
"type-fest": "^5.2.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0",
"typescript-transform-paths": "^3.5.5",
"zip-local": "^0.3.5"
},
"packageManager": "pnpm@10.33.0",

1857
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,6 @@ export interface PluginData {
name: string;
description: string;
tags: string[];
searchTerms: string[];
authors: Dev[];
dependencies: string[];
hasPatches: boolean;
@ -153,8 +152,7 @@ export async function parseFile(fileName: string) {
enabledByDefault: false,
required: false,
isModified: false,
tags: [] as string[],
searchTerms: [] as string[],
tags: [] as string[]
} as PluginData;
for (const prop of pluginObj.properties) {
@ -210,10 +208,9 @@ export async function parseFile(fileName: string) {
});
break;
case "tags":
case "searchTerms":
if (!isArrayLiteralExpression(value)) throw fail(`${key} is not an array literal`);
data[key] = value.elements.map(e => {
if (!isStringLiteral(e)) throw fail(`${key} array contains non-string literals`);
if (!isArrayLiteralExpression(value)) throw fail("tags is not an array literal");
data.tags = value.elements.map(e => {
if (!isStringLiteral(e)) throw fail("tags array contains non-string literals");
return e.text;
});
break;

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { findByCodeLazy, findLazy } from "@webpack";
import { findByCodeLazy, findLazy } from "webpack";
let defaultSounds: null | string[] = null;
const findDefaultSounds = findLazy(module => module.resolve && module.id && module.keys().some(key => key.endsWith(".mp3")), false);

View file

@ -28,7 +28,6 @@ import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/Messag
import { addNicknameIcon, removeNicknameIcon } from "@api/NicknameIcons";
import { Settings, SettingsStore } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
import { traceFunction } from "@debug/Tracer";
import { Logger } from "@utils/Logger";
import { onlyOnce } from "@utils/onlyOnce";
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
@ -40,6 +39,7 @@ import { patches } from "@webpack/patcher";
import Plugins from "~plugins";
export { Plugins as plugins };
import { traceFunction } from "../debug/Tracer";
import { addAudioProcessor, removeAudioProcessor } from "./AudioPlayer";
import { addChannelToolbarButton, addHeaderBarButton, removeChannelToolbarButton, removeHeaderBarButton } from "./HeaderBar";
import { addProfileCollection, removeProfileCollection } from "./ProfileCollections";

View file

@ -16,13 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { React, TextInput, useState } from "@webpack/common";
import { React, TextInput } from "@webpack/common";
interface TextInputProps {
/**
* WARNING: Changing this between renders will have no effect!
*/
initialValue: string;
value: string;
/**
* This will only be called if the new value passed validate()
*/
@ -41,15 +41,13 @@ interface TextInputProps {
* A very simple wrapper around Discord's TextInput that validates input and shows
* the user an error message and only calls your onChange when the input is valid
*/
export function CheckedTextInput({ initialValue, onChange, validate, placeholder }: TextInputProps) {
const [value, setValue] = useState(initialValue);
const [error, setError] = useState<string>();
export function CheckedTextInput({ value: initialValue, onChange, validate, placeholder }: TextInputProps) {
const [value, setValue] = React.useState(initialValue);
const [error, setError] = React.useState<string>();
function handleChange(v: string) {
setValue(v);
const res = validate(v);
if (res === true) {
setError(void 0);
onChange(v);

View file

@ -9,7 +9,6 @@ import "./colorStyles.css";
import { classNameFactory } from "@utils/css";
import { findByCodeLazy } from "@webpack";
import { ColorPicker, useMemo } from "@webpack/common";
import type tinycolor from "tinycolor2";
// TinyColor is completely unmangled and it's duplicated in two modules! Fun!
const TinyColor: tinycolor.Constructor = findByCodeLazy("this._gradientType=");

View file

@ -6,13 +6,13 @@
import { showNotice } from "@api/Notices";
import { isPluginEnabled, pluginRequiresRestart, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager";
import { Settings } from "@api/Settings";
import { CogWheel, InfoIcon } from "@components/Icons";
import { AddonCard } from "@components/settings/AddonCard";
import { classNameFactory } from "@utils/css";
import { Logger } from "@utils/Logger";
import { OptionType, Plugin } from "@utils/types";
import { React, showToast, Toasts } from "@webpack/common";
import { Settings } from "Vencord";
import { PluginMeta } from "~plugins";

View file

@ -60,25 +60,5 @@
}
.vc-plugin-modal-info {
display: flex;
gap: 1em;
justify-content: space-between;
align-items: start;
}
.vc-plugin-modal-tags {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-block: 8px 16px;
}
.vc-plugin-modal-tag {
align-items: center;
border: 1px solid var(--border-normal);
border-radius: 9999px;
display: flex;
justify-content: center;
padding: 6px 12px;
color: var(--text-default);
}

View file

@ -32,7 +32,7 @@ import { proxyLazy } from "@utils/lazy";
import { Margins } from "@utils/margins";
import { classes, isObjectEmpty } from "@utils/misc";
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { OptionType, Plugin, PluginTag } from "@utils/types";
import { OptionType, Plugin } from "@utils/types";
import { User } from "@vencord/discord-types";
import { findComponentByCodeLazy, findCssClassesLazy } from "@webpack";
import { Clickable, FluxDispatcher, React, Toasts, Tooltip, useEffect, useMemo, UserStore, UserSummaryItem, UserUtils, useState } from "@webpack/common";
@ -74,16 +74,6 @@ export function makeDummyUser(user: { username: string; id?: string; avatar?: st
return newUser;
}
function PluginTags({ tags }: { tags: PluginTag[]; }) {
return (
<div className={cl("tags")}>
{tags.map(tag => (
<div key={tag} className={cl("tag")}>{tag}</div>
))}
</div>
);
}
export default function PluginModal({ plugin, onRestartNeeded, onClose, transitionState }: PluginModalProps) {
const pluginSettings = useSettings([`plugins.${plugin.name}.*`]).plugins[plugin.name];
const hasSettings = Boolean(pluginSettings && plugin.options && !isObjectEmpty(plugin.options));
@ -177,7 +167,6 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
<div className={cl("header-content")}>
<BaseText size="lg" weight="semibold" className={cl("title")}>{plugin.name}</BaseText>
<BaseText size="sm" className={cl("description")}>{plugin.description}</BaseText>
{!!plugin.tags?.length && <PluginTags tags={plugin.tags} />}
{!!plugin.settingsAboutComponent && (
<div className={Margins.top8}>
<ErrorBoundary message="An error occurred while rendering this plugin's custom Info Component">

View file

@ -36,8 +36,7 @@ import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins";
import { classes } from "@utils/misc";
import { useAwaiter, useIntersection } from "@utils/react";
import { PluginTag, PluginTags } from "@utils/types";
import { Alerts, lodash, Parser, React, SearchableSelect, Select, TextInput, Toasts, Tooltip, useCallback, useMemo, useRef, useState } from "@webpack/common";
import { Alerts, lodash, Parser, React, Select, TextInput, Toasts, Tooltip, useCallback, useMemo, useState } from "@webpack/common";
import { JSX } from "react";
import Plugins, { ExcludedPlugins, PluginMeta } from "~plugins";
@ -144,8 +143,7 @@ function ExcludedPluginsList({ search }: { search: string; }) {
export default function PluginSettings() {
const settings = useSettings();
const changeRef = useRef<ChangeList<string>>(null);
const changes = changeRef.current ??= new ChangeList<string>();
const changes = React.useMemo(() => new ChangeList<string>(), []);
React.useEffect(() => {
return () => {
@ -196,13 +194,25 @@ export default function PluginSettings() {
const hasUserPlugins = useMemo(() => !IS_STANDALONE && Object.values(PluginMeta).some(m => m.userPlugin), []);
const [searchValue, setSearchValue] = useState({ value: "", tags: [] as PluginTag[], status: SearchStatus.ALL });
const [searchValue, setSearchValue] = useState({ value: "", status: SearchStatus.ALL });
const [searchInput, setSearchInput] = useState("");
const debouncedSetSearch = useMemo(
() => debounce((query: string) => setSearchValue(prev => ({ ...prev, value: query })), 150),
[]
);
const search = searchValue.value.toLowerCase();
const onSearch = (query: string) => setSearchValue(prev => ({ ...prev, value: query }));
const onSearch = useCallback((query: string) => {
setSearchInput(query);
debouncedSetSearch(query);
}, [debouncedSetSearch]);
const onStatusChange = useCallback((status: SearchStatus) => {
setSearchValue(prev => ({ ...prev, status }));
}, []);
const pluginFilter = useCallback((plugin: typeof Plugins[keyof typeof Plugins], newPluginsSet: Set<string> | null) => {
const { status, tags } = searchValue;
const { status } = searchValue;
const enabled = isPluginEnabled(plugin.name);
switch (status) {
@ -229,14 +239,12 @@ export default function PluginSettings() {
break;
}
if (tags.length && tags.some(t => !plugin.tags?.includes(t))) return false;
if (!search.length) return true;
return (
plugin.name.toLowerCase().includes(search.replace(/\s+/g, "")) ||
plugin.description.toLowerCase().includes(search) ||
plugin.searchTerms?.some(t => t.toLowerCase().includes(search))
plugin.tags?.some(t => t.toLowerCase().includes(search))
);
}, [searchValue, search]);
@ -398,45 +406,31 @@ export default function PluginSettings() {
Filters
</HeadingTertiary>
<ErrorBoundary noop>
<TextInput
inputClassName={cl("filter-control")}
placeholder="Search for a plugin..."
value={searchValue.value}
onChange={onSearch}
autoFocus
/>
</ErrorBoundary>
<ErrorBoundary noop>
<div className={classes(Margins.bottom20, Margins.top8, cl("filter-controls"))}>
<Select
options={[
{ label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: SearchStatus.DISABLED },
{ label: "Show Equicord", value: SearchStatus.EQUICORD },
{ label: "Show Vencord", value: SearchStatus.VENCORD },
{ label: "Show New", value: SearchStatus.NEW },
hasUserPlugins && { label: "Show UserPlugins", value: SearchStatus.USER_PLUGINS },
{ label: "Show API Plugins", value: SearchStatus.API_PLUGINS },
].filter(isTruthy)}
serialize={String}
select={status => setSearchValue(prev => ({ ...prev, status }))}
isSelected={v => v === searchValue.status}
closeOnSelect={true}
placeholder="Filter by Type"
/>
<SearchableSelect
options={PluginTags.map(tag => ({ label: tag, value: tag }))}
value={searchValue.tags}
onChange={tags => setSearchValue(prev => ({ ...prev, tags }))}
closeOnSelect={false}
placeholder="Filter by Tags"
multi
/>
<div className={classes(Margins.bottom20, cl("filter-controls"))}>
<ErrorBoundary noop>
<TextInput autoFocus value={searchInput} placeholder="Search for a plugin..." onChange={onSearch} />
</ErrorBoundary>
<div>
<ErrorBoundary noop>
<Select
options={[
{ label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: SearchStatus.DISABLED },
{ label: "Show Equicord", value: SearchStatus.EQUICORD },
{ label: "Show Vencord", value: SearchStatus.VENCORD },
{ label: "Show New", value: SearchStatus.NEW },
hasUserPlugins && { label: "Show UserPlugins", value: SearchStatus.USER_PLUGINS },
{ label: "Show API Plugins", value: SearchStatus.API_PLUGINS },
].filter(isTruthy)}
serialize={String}
select={onStatusChange}
isSelected={v => v === searchValue.status}
closeOnSelect={true}
/>
</ErrorBoundary>
</div>
</ErrorBoundary>
</div>
<HeadingTertiary className={Margins.top20}>Plugins</HeadingTertiary>
@ -462,7 +456,6 @@ export default function PluginSettings() {
<HeadingTertiary className={classes(Margins.top20, Margins.bottom8)}>
Required Plugins
</HeadingTertiary>
<div className={cl("grid")}>
{requiredPlugins.length
? requiredPlugins

View file

@ -45,12 +45,7 @@
display: grid;
height: 40px;
gap: 10px;
grid-template-columns: 1fr 1fr;
align-items: center;
}
.vc-plugins-filter-control {
height: 40px;
grid-template-columns: 1fr 150px;
}
.vc-plugins-dep-name {

View file

@ -137,7 +137,7 @@ function CloudTab() {
<div style={{ flex: 1 }}>
<CheckedTextInput
key={`backendUrl-${inputKey}`}
initialValue={cloud.url}
value={cloud.url}
onChange={async v => {
cloud.url = v;
cloud.authenticated = false;

View file

@ -20,7 +20,6 @@ import { Paragraph } from "@components/Paragraph";
import { openContributorModal, openPluginModal, SettingsTab, wrapTab } from "@components/settings";
import { QuickAction, QuickActionCard } from "@components/settings/QuickAction";
import { SpecialCard } from "@components/settings/SpecialCard";
import BadgeAPI from "@plugins/_api/badges";
import { gitRemote } from "@shared/vencordUserAgent";
import { DONOR_ROLE_ID, GUILD_ID, IS_MAC, IS_WINDOWS, VC_DONOR_ROLE_ID, VC_GUILD_ID } from "@utils/constants";
import { classNameFactory } from "@utils/css";
@ -28,6 +27,7 @@ import { Margins } from "@utils/margins";
import { identity, isAnyPluginDev } from "@utils/misc";
import { relaunch } from "@utils/native";
import { GuildMemberStore, React, Select, UserStore } from "@webpack/common";
import BadgeAPI from "plugins/_api/badges";
import { DonateButtonComponent } from "./DonateButton";
import { openNotificationSettingsModal } from "./NotificationSettings";

View file

@ -9,8 +9,8 @@ import { canonicalizeMatch } from "@utils/patches";
import { ModuleFactory } from "@vencord/discord-types/webpack";
import * as Webpack from "@webpack";
import { wreq } from "@webpack";
import { AnyModuleFactory } from "@webpack/types";
import pLimit from "p-limit";
import { AnyModuleFactory } from "webpack";
function getWebpackChunkMap() {
const sym = Symbol();

View file

@ -26,7 +26,6 @@ export interface ReporterData {
};
failedWebpack: Record<TypeWebpackSearchHistory, string[][]>;
}
export const reporterData: ReporterData = {
failedPatches: {
foundNoModule: [],

View file

@ -10,7 +10,6 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "AltKrispSwitch",
description: "Makes the Noise Suppression Popout switch between None and Krisp instead of Krisp and Standard",
tags: ["Customisation", "Voice"],
authors: [Devs.newwares],
patches: [
{

View file

@ -11,7 +11,6 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "AlwaysExpandProfiles",
description: "Always expands profile popouts to the full modal",
tags: ["Appearance", "Utility"],
authors: [Devs.thororen],
patches: [
{

View file

@ -193,7 +193,6 @@ async function playSound(buffer: AudioBuffer, volume: number) {
export default definePlugin({
name: "Animalese",
description: "Plays animal crossing animalese for every message sent (they yap a lot)",
tags: ["Customisation", "Fun"],
authors: [EquicordDevs.ryanamay, EquicordDevs.Mocha],
settings,

View file

@ -13,7 +13,6 @@ export default definePlugin({
name: "AtSomeone",
authors: [Devs.Joona],
description: "Mention someone randomly",
tags: ["Chat", "Fun"],
patches: [
{
find: ".LAUNCHABLE_APPLICATIONS;",

View file

@ -209,7 +209,6 @@ function handlePaste(event: ClipboardEvent) {
export default definePlugin({
name: "AutoZipper",
description: "Automatically zips specified file types and folders before uploading to Discord",
tags: ["Chat", "Organisation"],
authors: [EquicordDevs.SSnowly],
settings,

View file

@ -44,7 +44,6 @@ const DATASTORE_KEY = "bannersEverywhere";
export default definePlugin({
name: "BannersEverywhere",
description: "Displays banners in the member list ",
tags: ["Appearance", "Customisation"],
authors: [Devs.ImLvna, Devs.AutumnVN],
settings,
patches: [

View file

@ -107,8 +107,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "DecodeBase64",
description: "Decode base64 content of any message and copy the decoded content.",
dependencies: ["MessagePopoverAPI"],
tags: ["Appearance", "Customisation", "Chat"],
authors: [EquicordDevs.ThePirateStoner],
settings,
messagePopoverButton: {

View file

@ -20,7 +20,7 @@ export default definePlugin({
name: "BetterActivities",
description: "Shows activity icons in the member list and allows showing all activities",
authors: [Devs.D3SOX, Devs.Arjix, Devs.AutumnVN, Devs.thororen],
tags: ["Activity"],
tags: ["activity"],
settings,
patchActivityList,
showAllActivitiesComponent,

View file

@ -274,7 +274,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "BetterAudioPlayer",
description: "Adds a spectrograph and oscilloscope visualizer to audio attachment players.",
tags: ["Appearance", "Media", "Voice"],
authors: [EquicordDevs.creations],
settings,

View file

@ -74,7 +74,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "BetterBanReasons",
description: "Create custom reasons to use in the Discord ban modal, and/or show a text input by default instead of the options.",
tags: ["Appearance", "Customisation"],
authors: [Devs.Inbestigator],
patches: [
{

View file

@ -17,7 +17,6 @@ let updateFunc = (v: any) => { };
export default definePlugin({
name: "BetterBlockedUsers",
description: "Allows you to search in blocked users list and makes names selectable in settings.",
tags: ["Appearance", "Shortcuts"],
authors: [EquicordDevs.TheArmagan],
patches: [
{

View file

@ -33,8 +33,6 @@ function fetchIndex(target: object) {
export default definePlugin({
name: "BetterCommands",
description: "Enhances the command system with miscellaneous improvements.",
dependencies: ["CommandsAPI"],
tags: ["Appearance", "Commands", "Shortcuts"],
authors: [Devs.thororen],
settings,
patches: [

View file

@ -34,7 +34,6 @@ function lurk(id: string) {
export default definePlugin({
name: "BetterInvites",
description: "See invites expiration date, view inviter profile and preview servers before joining by clicking the name",
tags: ["Appearance", "Customisation", "Chat", "Servers"],
authors: [EquicordDevs.iamme, Devs.thororen],
patches: [
{

View file

@ -12,7 +12,6 @@ export default definePlugin({
name: "BetterPlusReacts",
authors: [Devs.Joona],
description: "The amount of plus before :emoji: is the message to add it to",
tags: ["Chat", "Emotes"],
patches: [
{
find: ".SLASH_COMMAND_USED,",

View file

@ -70,7 +70,6 @@ export function containsBlockedKeywords(message: Message) {
export default definePlugin({
name: "BlockKeywords",
description: "Blocks messages containing specific user-defined keywords, as if the user sending them was blocked.",
tags: ["Appearance", "Customisation", "Privacy"],
authors: [EquicordDevs.catcraft],
patches: [
{

View file

@ -10,7 +10,6 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "BlockKrisp",
description: "Prevent Krisp from loading",
tags: ["Privacy", "Utility", "Voice"],
authors: [Devs.D3SOX],
patches: [
// Block loading modules on Desktop

View file

@ -10,7 +10,6 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "BypassPinPrompt",
description: "Bypass the pin prompt when using the pin functions",
tags: ["Shortcuts"],
authors: [Devs.thororen],
patches: [
...[

View file

@ -157,7 +157,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "BypassStatus",
description: "Still get notifications from specific sources when in do not disturb mode. Right-click on users/channels/guilds to set them to bypass do not disturb mode.",
tags: ["Activity", "Customisation", "Notifications", "Servers"],
authors: [Devs.Inbestigator],
dependencies: ["AudioPlayerAPI"],
flux: {

View file

@ -32,7 +32,6 @@ function renderBadge(id: number, title: string) {
export default definePlugin({
name: "ChannelBadges",
description: "Adds badges to channels based on their type",
tags: ["Appearance", "Customisation", "Servers"],
authors: [EquicordDevs.creations, Devs.thororen],
settings,
patches: [

View file

@ -15,8 +15,8 @@ import { ChannelStore, Menu } from "@webpack/common";
import { JSX } from "react";
import ChannelsTabsContainer from "./components/ChannelTabsContainer";
import * as ChannelTabsUtils from "./util";
import { BasicChannelTabsProps, createTab, handleChannelSwitch, settings } from "./util";
import * as ChannelTabsUtils from "./util";
const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channel: Channel, messageId?: string; }) => {
const { channel, messageId } = props;
@ -47,7 +47,6 @@ const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channe
export default definePlugin({
name: "ChannelTabs",
description: "Group your commonly visited channels in tabs, like a browser",
tags: ["Appearance", "Customisation", "Organisation", "Servers"],
authors: [Devs.TheSun, Devs.TheKodeToad, EquicordDevs.keifufu, Devs.Nickyux, EquicordDevs.DiabeloDEV, EquicordDevs.justjxke],
dependencies: ["ContextMenuAPI"],
contextMenus: {

View file

@ -12,7 +12,6 @@ export default definePlugin({
name: "CleanChannelName",
authors: [Devs.AutumnVN],
description: "remove all emoji and decor shit from channel names",
tags: ["Appearance", "Customisation", "Chat", "Emotes", "Servers"],
patches: [
{
find: "loadAllGuildAndPrivateChannelsFromDisk(){",

View file

@ -10,7 +10,6 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "CleanerChannelGroups",
description: "Hides all channels in collapsed categories, even if they have unread messages.",
tags: ["Appearance", "Customisation", "Chat", "Organisation", "Servers"],
authors: [EquicordDevs.justjxke],
patches: [
{

View file

@ -146,7 +146,6 @@ const WrappedClickableRole = ErrorBoundary.wrap(ClickableRole, { noop: true });
export default definePlugin({
name: "ClickableRoles",
description: "Click on roles in user profiles and the member list to see which members have them.",
tags: ["Appearance", "Roles"],
authors: [Devs.prism],
patches: [

View file

@ -142,8 +142,7 @@ function activeNowView(cards) {
export default definePlugin({
name: "ClientSideBlock",
description: "Allows you to locally hide almost all content from any user",
tags: ["Utility"],
searchTerms: ["blocked", "block", "hide", "hidden", "noblockedmessages"],
tags: ["blocked", "block", "hide", "hidden", "noblockedmessages"],
authors: [Devs.Samwich, EquicordDevs.KamiRu],
settings,
activeNowView,

View file

@ -72,7 +72,6 @@ migratePluginSettings("ClipsEnhancements", "TimelessClips");
export default definePlugin({
name: "ClipsEnhancements",
description: "Add more Clip FPS and duration options, custom clip length, RPC tagging and more",
tags: ["Activity", "Media", "Utility"],
authors: [Devs.niko, Devs.Joona, EquicordDevs.keircn],
settings,
patches: [

View file

@ -108,10 +108,8 @@ const ChatButtonsRow = ErrorBoundary.wrap(({ buttons }: { buttons: ReactNode[];
export default definePlugin({
name: "CollapsibleUI",
description: "Native collapsible channel, member, chat button, and user area surfaces.",
tags: ["Appearance", "Customisation", "Chat", "Servers"],
dependencies: ["HeaderBarAPI"],
authors: [EquicordDevs.benjii],
searchTerms: ["ui", "sidebar", "layout"],
tags: ["ui", "sidebar", "layout"],
managedStyle,
settings,

View file

@ -201,7 +201,6 @@ function hotkeyUsesModifiers() {
export default definePlugin({
name: "CommandPalette",
description: "Quickly run actions through a searchable command palette",
tags: ["Appearance", "Customisation", "Commands", "Shortcuts"],
authors: [EquicordDevs.justjxke],
settings,
patches: [

View file

@ -18,7 +18,6 @@ import ComponentsTab from "./components/ComponentsTab";
export default definePlugin({
name: "Components",
description: "Adds a new tab to settings to browse Discord components.",
tags: ["Appearance", "Customisation", "Console", "Developers", "Organisation"],
authors: [Devs.prism],
dependencies: ["Settings"],
startAt: StartAt.WebpackReady,

View file

@ -152,7 +152,6 @@ export default definePlugin({
name: "ContentWarning",
authors: [EquicordDevs.camila314],
description: "Allows you to specify certain trigger words that will be blurred by default. Hovering/Clicking on the blurred content will reveal it.",
tags: ["Appearance", "Utility"],
settings,
patches: [
{

View file

@ -90,7 +90,6 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }) =
export default definePlugin({
name: "CopyProfileColors",
description: "A plugin to copy people's profile gradient colors to clipboard.",
tags: ["Appearance", "Customisation"],
authors: [EquicordDevs.Crxa, EquicordDevs.Cortex],
contextMenus: {
"user-context": userContextMenuPatch,

View file

@ -23,7 +23,6 @@ const getMetadataFromApi: (activity: any, userId: string) => Promise<any> = find
export default definePlugin({
name: "CopyStatusUrls",
description: "Copy the users status url when you right-click it",
tags: ["Activity", "Utility"],
authors: [Devs.sadan],
patches: [

View file

@ -48,7 +48,6 @@ export default definePlugin({
name: "CopyUserMention",
authors: [EquicordDevs.Cortex, Devs.castdrian],
description: "Adds a button to copy user's mention on the user context menu, works best with ValidUser.",
tags: ["Chat", "Utility"],
contextMenus: {
"user-context": UserContextMenuPatch
}

View file

@ -235,9 +235,8 @@ migratePluginSettings("CursorBuddy", "Oneko", "oneko");
export default definePlugin({
name: "CursorBuddy",
description: "Adds a sprite that follows your cursor.",
tags: ["Appearance", "Customisation", "Fun"],
authors: [Devs.Ven, Devs.adryd, EquicordDevs.nexpid, EquicordDevs.ZcraftElite],
searchTerms: ["Oneko", "FatassHorse", "Pet"],
tags: ["Oneko", "FatassHorse", "Pet"],
settings,
isModified: true,

View file

@ -14,7 +14,6 @@ import { folderProp, int2rgba } from "./util";
export default definePlugin({
name: "CustomFolderIcons",
description: "Customize folder icons with any png",
tags: ["Appearance", "Customisation", "Organisation"],
authors: [EquicordDevs.sadan],
settings,
patches: [

View file

@ -393,8 +393,6 @@ export function findOverride(id: string): SoundOverride | null {
export default definePlugin({
name: "CustomSounds",
description: "Customize Discord's sounds.",
dependencies: ["AudioPlayerAPI"],
tags: ["Customisation", "Notifications", "Voice"],
authors: [Devs.ScattrdBlade, Devs.TheKodeToad],
settings,
startAt: StartAt.Init,

View file

@ -54,7 +54,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "CustomStatusTimeouts",
description: "Adds configurable timeout presets to the status (presence) menu.",
tags: ["Activity", "Utility"],
authors: [EquicordDevs.Kiri, EquicordDevs.thororen],
settings,
patches: [

View file

@ -125,7 +125,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "CustomTimestamps",
description: "Custom timestamps on messages and tooltips",
tags: ["Appearance", "Customisation"],
authors: [Devs.Rini, EquicordDevs.nvhhr, EquicordDevs.Suffocate, Devs.Obsidian],
settings,
settingsAboutComponent: () => (

View file

@ -100,7 +100,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "CustomUserColors",
description: "Lets you add a custom color to any user, anywhere! Highly recommend to use with typingTweaks and roleColorEverywhere",
tags: ["Appearance", "Customisation", "Chat"],
authors: [EquicordDevs.mochienya],
contextMenus: {
"user-context": userContextMenuPatch,

View file

@ -141,7 +141,6 @@ function SectionSeparator(title: string) {
export default definePlugin({
name: "Declutter",
description: "Cleans up Discord by removing non-essential UI elements like profile effects, shop tabs, boosts, and more.",
tags: ["Appearance", "Customisation"],
authors: [EquicordDevs.Leon135, Devs.prism, Devs.Kyuuhachi],
settings,
patches: [

View file

@ -10,7 +10,6 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "DisableCameras",
description: "Disables cameras in a call by default",
tags: ["Appearance", "Customisation", "Media", "Privacy"],
authors: [Devs.Joona],
patches: [
{

View file

@ -4,10 +4,10 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import SettingsPlugin from "@plugins/_core/settings";
import { detectClient } from "@plugins/_core/supportHelper";
import { gitHashShort } from "@shared/vencordUserAgent";
import { React } from "@webpack/common";
import SettingsPlugin from "plugins/_core/settings";
import { JSX } from "react";
import { ChromiumIcon, ClientIcon, DevBannerIcon, DiscordIcon, ElectronIcon, EquicordIcon, names, settings } from ".";

View file

@ -14,7 +14,6 @@ import { makeDevBanner, settings } from "./components";
export default definePlugin({
name: "DiscordDevBanner",
description: "Enables the Discord developer banner, in which displays the build-ID",
tags: ["Appearance", "Console", "Developers"],
authors: [EquicordDevs.KrystalSkull, Devs.thororen],
settings,
patches: [

View file

@ -45,7 +45,6 @@ export default definePlugin({
name: "DragFavoriteEmotes",
authors: [EquicordDevs.PWall],
description: "Adds the ability to change the order of your favourite emotes",
tags: ["Customisation", "Chat", "Emotes"],
patches: [
{
find: "#{intl::EMOJI_FAVORITE_TOOLTIP}",

View file

@ -149,7 +149,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "Dragify",
description: "Drop users, channels, or servers into chat to insert mentions or invites.",
tags: ["Chat", "Servers", "Utility", "Voice"],
authors: [EquicordDevs.justjxke],
settings,

View file

@ -449,7 +449,6 @@ function onToggle(e: KeyboardEvent) {
export default definePlugin({
name: "ElementHighlighter",
description: "Highlight and inspect elements easily.",
tags: ["Developers"],
authors: [Devs.prism],
settings,

View file

@ -89,7 +89,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "EquibopStreamFixes",
description: "Tries to fix stream quality on Equibop by patching Discord's encoder and quality restrictions.",
tags: ["Voice"],
authors: [EquicordDevs.creations],
settings,

View file

@ -133,8 +133,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "EquicordHelper",
description: "Used to provide support, fix discord caused crashes, and other misc features.",
tags: ["Appearance", "Commands", "Utility"],
dependencies: ["CommandsAPI", "HeaderBarAPI", "MessageAccessoriesAPI"],
authors: [
Devs.thororen,
EquicordDevs.nyx,

View file

@ -77,10 +77,11 @@ migratePluginSettings("EquicordToolbox", "VencordToolbox");
export default definePlugin({
name: "EquicordToolbox",
description: "Adds a button next to the inbox button in the channel header that houses Equicord quick actions",
tags: ["Voice", "Accessibility"],
authors: [Devs.Ven, Devs.AutumnVN],
dependencies: ["HeaderBarAPI"],
settings,
headerBarButton: {
icon: Icon,
render: VencordPopoutButton,

View file

@ -33,7 +33,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "Equissant",
description: "Crossant every specified amount of clicks :trolley:",
tags: ["Fun"],
authors: [EquicordDevs.SomeAspy, Devs.thororen],
dependencies: ["AudioPlayerAPI"],
settings,

View file

@ -104,7 +104,6 @@ let original: typeof ChannelActions.selectVoiceChannel;
export default definePlugin({
name: "ExitSounds",
description: "Play soundboard sounds when you disconnect from voice.",
tags: ["Fun", "Voice"],
authors: [Devs.prism],
dependencies: ["AudioPlayerAPI"],
settings,

View file

@ -129,7 +129,6 @@ function getUsernames(contacts: ContactsList[], type: number): string[] {
export default definePlugin({
name: "ExportMessages",
description: "Allows you to export any message to a file",
tags: ["Chat", "Utility"],
authors: [EquicordDevs.veygax, EquicordDevs.dat_insanity],
settings,
contextMenus: {

View file

@ -74,7 +74,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "FastDeleteChannels",
description: "Adds a trash icon to delete channels",
tags: ["Servers", "Utility"],
authors: [Devs.thororen],
settings,
patches: [

View file

@ -25,9 +25,8 @@ export const AttachmentContext = proxyLazyWebpack(() => React.createContext<null
export default definePlugin({
name: "FavouriteAnything",
description: "Favourite any image, video, or file attachment",
tags: ["Chat", "Media"],
authors: [Devs.nin0dev, EquicordDevs.davri],
searchTerms: ["favorite"],
tags: ["favorite"],
managedStyle,
patches: [
// EMBEDS

View file

@ -44,7 +44,7 @@ interface Uint8ArrayConstructorExtended extends Uint8ArrayConstructor {
): Uint8ArrayExtended<ArrayBuffer>;
}
function supportsToBase64(array: Uint8Array<ArrayBufferLike>): boolean {
function supportsToBase64(array: Uint8Array<ArrayBufferLike>): array is Uint8ArrayExtended<ArrayBufferLike> {
return "toBase64" in array && typeof array.toBase64 === "function";
}

View file

@ -216,7 +216,6 @@ const channelAttachMenuPatch: NavContextMenuPatchCallback = (children, props) =>
export default definePlugin({
name: "FileUpload",
description: "Upload images and videos to file hosting services like Zipline and Nest",
tags: ["Media"],
authors: [EquicordDevs.creations, EquicordDevs.keircn, Devs.ScattrdBlade],
settings,
patches: [

View file

@ -89,8 +89,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "FindReply",
description: "Jumps to the earliest reply to a message in a channel (lets you follow past conversations more easily).",
dependencies: ["MessagePopoverAPI"],
tags: ["Chat", "Shortcuts"],
authors: [Devs.newwares],
settings,
messagePopoverButton: {

View file

@ -29,7 +29,6 @@ export default definePlugin({
name: "FixFileExtensions",
authors: [Devs.thororen],
description: "Fixes file extensions by renaming them to a compatible supported format if possible",
tags: ["Media", "Utility"],
reporterTestable: ReporterTestable.None,
patches: [
// Taken from AnonymiseFileNames

View file

@ -74,7 +74,6 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { channel,
export default definePlugin({
name: "FollowVoiceUser",
description: "Follow a friend in voice chat.",
tags: ["Voice"],
authors: [EquicordDevs.TheArmagan],
settings,
settingsAboutComponent: () => (

View file

@ -200,7 +200,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "FontLoader",
description: "Loads any font from Google Fonts",
tags: ["Appearance", "Customisation"],
authors: [EquicordDevs.vmohammad],
settings,

View file

@ -25,7 +25,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "ForwardAnywhere",
description: "If a forward fails send it as a normal message also allows nsfw forwards",
tags: ["Chat", "Utility"],
authors: [Devs.thororen],
settings,
patches: [

View file

@ -37,7 +37,6 @@ function generateSearchResults(query) {
export default definePlugin({
name: "FrequentQuickSwitcher",
description: "Rewrites and filters the quick switcher results to be your most frequent channels",
tags: ["Shortcuts", "Servers"],
authors: [Devs.Samwich],
generateSearchResults: generateSearchResults,
patches: [

View file

@ -12,7 +12,6 @@ import FriendCodesPanel from "./FriendCodesPanel";
export default definePlugin({
name: "FriendCodes",
description: "Generate FriendCodes to easily add friends",
tags: ["Friends", "Utility"],
authors: [Devs.HypedDomi],
patches: [
{

View file

@ -209,7 +209,6 @@ const userPatch: NavContextMenuPatchCallback = (children, { user }) => {
export default definePlugin({
name: "FriendTags",
description: "Allows you to filter by custom tags in the quick switcher by starting a search with &",
tags: ["Shortcuts"],
authors: [Devs.Samwich],
settings,
contextMenus: {

View file

@ -143,7 +143,6 @@ function getBadgesToApply() {
export default definePlugin({
name: "FriendshipRanks",
description: "Adds badges showcasing how long you have been friends with a user for",
tags: ["Friends"],
authors: [Devs.Samwich],
start() {
getBadgesToApply().forEach(b => Badges.addProfileBadge(b));

View file

@ -14,7 +14,6 @@ import style from "./style.css?managed";
export default definePlugin({
name: "FullVCPFP",
description: "Makes avatars take up the entire vc tile",
tags: ["Appearance", "Voice"],
authors: [EquicordDevs.mochienya],
patches: [
{

View file

@ -147,7 +147,6 @@ function makeContextItem(props) {
export default definePlugin({
name: "Ghosted",
description: "A cute ghost will appear if you don't answer their DMs",
tags: ["Chat", "Utility"],
authors: [EquicordDevs.vei, Devs.sadan, EquicordDevs.justjxke, EquicordDevs.iamme],
settings,
dependencies: ["AudioPlayerAPI", "ServerListAPI"],

View file

@ -26,7 +26,6 @@ let oldTrendingCat: Category[] | null = null;
export default definePlugin({
name: "GifCollections",
description: "Allows you to create collections of gifs.",
tags: ["Chat", "Emotes"],
authors: [EquicordDevs.creations],
settings,
contextMenus: {

View file

@ -38,8 +38,6 @@ export const settings = definePluginSettings({
export default definePlugin({
name: "GitHubRepos",
description: "Displays a user's public GitHub repositories in their profile",
dependencies: ["ProfileCollectionsAPI"],
tags: ["Appearance"],
authors: [EquicordDevs.talhakf, EquicordDevs.Panniku, EquicordDevs.benjii],
settings,

View file

@ -25,7 +25,6 @@ migratePluginSetting("GlobalBadges", "showRaincord", "showRa1ncord");
export default definePlugin({
name: "GlobalBadges",
description: "Adds global badges from other client mods",
tags: ["Appearance"],
authors: [Devs.HypedDomi, EquicordDevs.Wolfie, Devs.thororen],
settings,
settingsAboutComponent: () => (

View file

@ -75,10 +75,8 @@ const settings = definePluginSettings({
export default definePlugin({
name: "GoogleThat",
description: "Adds a command to send a internet search link",
dependencies: ["CommandsAPI"],
tags: ["Commands", "Utility"],
authors: [Devs.Samwich, EquicordDevs.KrystalSkull],
searchTerms: ["search", "google", "query", "duckduckgo", "command"],
tags: ["search", "google", "query", "duckduckgo", "command"],
settings,
commands: [
{

View file

@ -95,7 +95,6 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
export default definePlugin({
name: "GuildPickerDumper",
description: "Context menu to dump and download a server's emojis and stickers.",
tags: ["Emotes", "Servers", "Utility"],
authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Synth, Devs.thororen],
contextMenus: {
"guild-context": Patch,

View file

@ -81,7 +81,6 @@ function ButtonsInnerComponent({ buttons }: { buttons: ReactNode; }) {
export default definePlugin({
name: "HideChatButtons",
description: "Able to hide the chat buttons",
tags: ["Chat", "Utility"],
settings: settings,
authors: [EquicordDevs.iamme],
patches: [

View file

@ -49,8 +49,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "HideMessages",
description: "A plugin to temporarily hide messages until you restart.",
dependencies: ["MessagePopoverAPI"],
tags: ["Chat", "Utility"],
authors: [EquicordDevs.yash],
contextMenus: {
"message": messageCtxPatch

View file

@ -76,9 +76,8 @@ export function removeIndicator() {
export default definePlugin({
name: "HideServers",
description: "Allows you to hide servers from the guild list and quick switcher by right clicking them",
tags: ["Servers", "Utility"],
authors: [EquicordDevs.bep],
searchTerms: ["guild", "server", "hide", "folder"],
tags: ["guild", "server", "hide", "folder"],
dependencies: ["ServerListAPI"],
contextMenus: {

View file

@ -72,8 +72,6 @@ function ToolBarHeader() {
export default definePlugin({
name: "HolyNotes",
description: "Save messages as notes to revisit later",
dependencies: ["MessagePopoverAPI", "HeaderBarAPI"],
tags: ["Chat", "Organisation"],
authors: [EquicordDevs.Wolfie],
toolboxActions: {

View file

@ -18,7 +18,6 @@ const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { ge
export default definePlugin({
name: "HomeTyping",
description: "Changes the home button to a typing indicator if someone in your dms is typing",
tags: ["Chat"],
authors: [Devs.Samwich],
TypingIcon() {
return <ThreeDots className={cl("dots")} dotRadius={3} themed={true} />;

View file

@ -32,7 +32,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "HopOn",
description: "Hop on! Opens a configurable URL when a message matches a custom regex in the current channel.",
tags: ["Fun"],
authors: [Devs.ImLvna],
settings,
flux: {

View file

@ -99,8 +99,6 @@ function getEmojiIdThatShouldBeUsed(guildId: string) {
export default definePlugin({
name: "Husk",
description: "Adds Husk button (check settings to change used emoji)",
dependencies: ["MessagePopoverAPI"],
tags: ["Emotes", "Fun"],
authors: [Devs.nin0dev],
settings,
messagePopoverButton: {

View file

@ -19,7 +19,6 @@ import DataUI from "./components/ui";
export default definePlugin({
name: "IRememberYou",
description: "Locally saves everyone you've been communicating with (including servers), in case of lose",
tags: ["Chat", "Servers"],
authors: [EquicordDevs.zoodogood, EquicordDevs.keircn],
dependencies: ["MessageEventsAPI"],

View file

@ -19,7 +19,6 @@ import { SettingsAbout } from "./components/Modals";
export default definePlugin({
name: "IconViewer",
description: "Adds a new tab to settings to preview all icons.",
tags: ["Developers"],
authors: [EquicordDevs.iamme],
dependencies: ["Settings"],
startAt: StartAt.WebpackReady,

View file

@ -36,7 +36,6 @@ function onActivity() {
export default definePlugin({
name: "IdleAutoRestart",
description: "Automatically restarts the client after being idle for a configurable amount of time, but avoids restarting while you are in VC.",
tags: ["Utility"],
authors: [EquicordDevs.SteelTech],
settings,

View file

@ -93,7 +93,6 @@ const settings = definePluginSettings({
export default definePlugin({
name: "IgnoreCalls",
description: "Allows you to ignore calls from specific users or dm groups.",
tags: ["Voice"],
authors: [EquicordDevs.TheArmagan, Devs.thororen],
settings,
patches: [

View file

@ -34,9 +34,8 @@ function getMembersInRole(roleId: string, guildId: string) {
export default definePlugin({
name: "InRole",
description: "Know who is in a role with the role context menu or /inrole command (read plugin info!)",
tags: ["Commands", "Roles"],
authors: [Devs.nin0dev],
dependencies: ["UserSettingsAPI", "CommandsAPI"],
dependencies: ["UserSettingsAPI"],
start() {
// DeveloperMode needs to be enabled for the context menu to be shown
DeveloperMode.updateSetting(true);

View file

@ -146,8 +146,6 @@ function disabledIcon() {
export default definePlugin({
name: "Ingtoninator",
description: "Suffixes 'ington' to a random word in your message",
dependencies: ["ChatInputButtonAPI"],
tags: ["Fun"],
authors: [EquicordDevs.zyqunix, EquicordDevs.BioTomateDE],
settings,
chatBarButton: {

Some files were not shown because too many files have changed in this diff Show more