Equicord/src/equicordplugins/hideServers/index.tsx

141 lines
4.3 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
// additional thanks to mwittrien/DevilBro and nexpid for their server hiding plugins, which served as inspiration
import {
findGroupChildrenByChildId,
NavContextMenuPatchCallback,
} from "@api/ContextMenu";
import {
addServerListElement,
removeServerListElement,
ServerListRenderPosition,
} from "@api/ServerList";
import { EquicordDevs } from "@utils/constants";
import definePlugin from "@utils/types";
import { Menu, React, useStateFromStores } from "@webpack/common";
import { Guild } from "discord-types/general";
import hiddenServersButton from "./components/HiddenServersButton";
import { HiddenServersStore } from "./HiddenServersStore";
import settings from "./settings";
type guildsNode = {
type: "guild" | "folder";
id: number | string;
children: guildsNode[];
};
type qsResult = {
type: "GUILD" | string;
record?: {
id?: string;
guild_id?: string;
};
};
const Patch: NavContextMenuPatchCallback = (
children,
{ guild }: { guild: Guild; }
) => {
const group = findGroupChildrenByChildId("privacy", children);
group?.push(
<Menu.MenuItem
id="vc-hide-server"
label="Hide Server"
action={() => HiddenServersStore.addHidden(guild)}
/>
);
};
export function addIndicator() {
addServerListElement(ServerListRenderPosition.Below, hiddenServersButton);
}
export function removeIndicator() {
removeServerListElement(ServerListRenderPosition.Below, hiddenServersButton);
}
export default definePlugin({
name: "HideServers",
description: "Allows you to hide servers from the guild list and quick switcher by right clicking them",
authors: [EquicordDevs.bep],
tags: ["guild", "server", "hide"],
dependencies: ["ServerListAPI"],
contextMenus: {
"guild-context": Patch,
"guild-header-popout": Patch,
},
patches: [
{
find: '("guildsnav")',
replacement: [
{
match: /(?<=Messages\.SERVERS,children:.{0,300}?)(\i)(\)?\.map\(\i\))/,
replace: "$self.useFilteredGuilds($1)$2",
},
// despite my best efforts, the above doesnt trigger a rerender
{
match: /let{disableAppDownload.{0,10}isPlatformEmbedded/,
replace: "$self.useStore();$&",
}
]
},
{
find: "QUICKSWITCHER_PROTIP.format",
replacement: {
match: /(?<=renderResults\(\){)let{query/,
replace: "this.props.results = $self.filteredGuildResults(this.props.results);$&",
},
},
],
settings,
useStore: () => { useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuilds, undefined, (old, newer) => old.size === newer.size); },
async start() {
if (settings.store.showIndicator) {
addIndicator();
}
await HiddenServersStore.load();
},
async stop() {
removeIndicator();
HiddenServersStore.unload();
},
useFilteredGuilds(guilds: guildsNode[]): guildsNode[] {
const hiddenGuilds = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuilds, undefined, (old, newer) => old.size === newer.size);
return guilds.flatMap(guild => {
if (hiddenGuilds.has(guild.id.toString())) {
return [];
}
const newGuild = Object.assign({}, guild);
newGuild.children = guild.children.filter(
child => !hiddenGuilds.has(child.id.toString())
);
return [newGuild];
});
},
filteredGuildResults(results: qsResult[]): qsResult[] {
// not used in a component so no useStateFromStore
const { hiddenGuilds } = HiddenServersStore;
return results.filter(result => {
if (result?.record?.guild_id && hiddenGuilds.has(result.record.guild_id)) {
return false;
}
if (result.type === "GUILD" && hiddenGuilds.has(result.record!.id!)) {
return false;
}
return true;
});
},
});