diff --git a/src/equicordplugins/hideServers/HiddenServersStore.ts b/src/equicordplugins/hideServers/HiddenServersStore.ts index 7bf946c53..af3d4ec9a 100644 --- a/src/equicordplugins/hideServers/HiddenServersStore.ts +++ b/src/equicordplugins/hideServers/HiddenServersStore.ts @@ -15,38 +15,58 @@ export const HiddenServersStore = proxyLazyWebpack(() => { const SortedGuildStore = findStoreLazy("SortedGuildStore"); const DB_KEY = "HideServers_servers"; - class HiddenServersStore extends Store { public _hiddenGuilds: Set = new Set(); - public get hiddenGuilds() { - return this._hiddenGuilds; - } - // id try to use .initialize() but i dont know how it works + + public get hiddenGuilds() { return this._hiddenGuilds; } + public async load() { const data = await DataStore.get(DB_KEY); if (data && data instanceof Set) { this._hiddenGuilds = data; } } + public unload() { this._hiddenGuilds.clear(); } - public addHidden(guild: Guild) { - this._hiddenGuilds.add(guild.id); + private save() { DataStore.set(DB_KEY, this._hiddenGuilds); + } + + public addHiddenGuild(id: string) { + this._hiddenGuilds.add(id); + this.save(); this.emitChange(); } - public removeHidden(id: string) { + + public removeHiddenGuild(id: string) { this._hiddenGuilds.delete(id); - DataStore.set(DB_KEY, this._hiddenGuilds); + this.save(); this.emitChange(); } + + public addHiddenFolder(id: string, guildIds: string[]) { + this._hiddenGuilds.add(`folder-${id}`); + guildIds.forEach(gid => this._hiddenGuilds.add(gid)); + this.save(); + this.emitChange(); + } + + public removeHiddenFolder(id: string, guildIds: string[]) { + this._hiddenGuilds.delete(`folder-${id}`); + guildIds.forEach(gid => this._hiddenGuilds.delete(gid)); + this.save(); + this.emitChange(); + } + public clearHidden() { this._hiddenGuilds.clear(); DataStore.del(DB_KEY); this.emitChange(); } + public hiddenGuildsDetail(): Guild[] { const sortedGuildIds = SortedGuildStore.getFlattenedGuildIds() as string[]; // otherwise the list is in order of increasing id number which is confusing diff --git a/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx b/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx index 07be64d0f..0d6a444ec 100644 --- a/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx +++ b/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx @@ -21,6 +21,7 @@ import { Guild } from "@vencord/discord-types"; import { findByPropsLazy } from "@webpack"; import { Button, Forms, IconUtils, Text, useStateFromStores } from "@webpack/common"; +import { SortedGuildStore } from ".."; import { HiddenServersStore } from "../HiddenServersStore"; const cl = classNameFactory("vc-hideservers-"); @@ -44,50 +45,121 @@ function HiddenServersModal({ modalProps, close }: { modalProps: ModalProps; clo ); } -export function HiddenServersMenu({ guilds }: { guilds: Guild[]; }) { - return
- {guilds.length > 0 ? ( - guilds.map(guild => ( -
-
- {guild.icon - ? - :
- {getGuildAcronym(guild)} -
- } -
- - {guild.name} - - + {getGuildAcronym(guild)} +
+ )} +
+ + {guild.name} + + + + ); +} + +export function HiddenServersMenu({ guilds }: { guilds: Guild[]; }) { + const hiddenGuilds = guilds.filter(g => isGuildHidden(g, SortedGuildStore)); + const folders: Record = {}; + const guildsWithoutFolder: Guild[] = []; + + hiddenGuilds.forEach(guild => { + const folder = getFolderForGuild(SortedGuildStore, guild.id); + if (folder) { + if (!folders[folder.folderId]) folders[folder.folderId] = []; + folders[folder.folderId].push(guild); + } else { + guildsWithoutFolder.push(guild); + } + }); + + return
+ {Object.entries(folders).map(([folderId, folderGuilds]) => { + const folder = SortedGuildStore.getGuildFolders().find(f => f.folderId === Number(folderId)); + if (!folder) return null; + + return ( +
+
+ {folder.folderName || "Folder"} + +
+ {folderGuilds.map(guild => ( + + ))}
- )) - ) : ( - - No hidden servers - - )} + ); + })} + + Guilds + {guildsWithoutFolder.map(guild => ( + + ))} + + {hiddenGuilds.length === 0 && No hidden servers}
; } diff --git a/src/equicordplugins/hideServers/components/style.css b/src/equicordplugins/hideServers/components/style.css index 760a26f66..b636ee53f 100644 --- a/src/equicordplugins/hideServers/components/style.css +++ b/src/equicordplugins/hideServers/components/style.css @@ -45,3 +45,10 @@ .vc-hideservers-row-button { margin-left: auto; } + +.vc-hideservers-folder-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-right: 20px; +} \ No newline at end of file diff --git a/src/equicordplugins/hideServers/index.tsx b/src/equicordplugins/hideServers/index.tsx index 6f4d4af3f..054c9ecac 100644 --- a/src/equicordplugins/hideServers/index.tsx +++ b/src/equicordplugins/hideServers/index.tsx @@ -18,6 +18,7 @@ import { import { EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Guild } from "@vencord/discord-types"; +import { findStoreLazy } from "@webpack"; import { Menu, React, useStateFromStores } from "@webpack/common"; import hiddenServersButton from "./components/HiddenServersButton"; @@ -38,17 +39,28 @@ type qsResult = { }; }; +export const SortedGuildStore = findStoreLazy("SortedGuildStore"); + const Patch: NavContextMenuPatchCallback = ( children, { guild }: { guild: Guild; } ) => { const group = findGroupChildrenByChildId("privacy", children); + if (!group) return; - group?.push( + const isHidden = HiddenServersStore.hiddenGuilds.has(guild.id.toString()); + + group.push( HiddenServersStore.addHidden(guild)} + label={isHidden ? "Unhide Server" : "Hide Server"} + action={() => { + if (isHidden) { + HiddenServersStore.removeHiddenGuild(guild.id); + } else { + HiddenServersStore.addHiddenGuild(guild.id); + } + }} /> ); }; @@ -65,12 +77,37 @@ 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"], + tags: ["guild", "server", "hide", "folder"], dependencies: ["ServerListAPI"], contextMenus: { - "guild-context": Patch, "guild-header-popout": Patch, + "guild-context": (menuItems, props: any) => { + if ("guild" in props) { + Patch(menuItems, props); + } + + if ("folderId" in props) { + const { folderId } = props; + const folder = SortedGuildStore.getGuildFolderById(folderId); + const { guildIds } = folder; + const isHidden = guildIds.every(id => HiddenServersStore.hiddenGuilds.has(id)); + + menuItems.push( + { + if (isHidden) { + HiddenServersStore.removeHiddenFolder(folderId, guildIds); + } else { + HiddenServersStore.addHiddenFolder(folderId, guildIds); + } + }} + /> + ); + } + }, }, patches: [ { @@ -80,7 +117,6 @@ export default definePlugin({ match: /(\i)(\.map\(.{0,30}\}\),\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();$&", @@ -111,15 +147,28 @@ export default definePlugin({ }, useFilteredGuilds(guilds: guildsNode[]): guildsNode[] { - const hiddenGuilds = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuilds, undefined, (old, newer) => old.size === newer.size); + const hiddenGuilds = useStateFromStores( + [HiddenServersStore], + () => HiddenServersStore.hiddenGuilds, + undefined, + (old, newer) => old.size === newer.size + ); + return guilds.flatMap(guild => { if (!(hiddenGuilds instanceof Set)) return [guild]; - if (hiddenGuilds.has(guild.id.toString())) { + if (guild.type === "guild" && hiddenGuilds.has(guild.id.toString())) { return []; } + + if (guild.type === "folder" && hiddenGuilds.has("folder-" + guild.id.toString())) { + return []; + } + const newGuild = Object.assign({}, guild); newGuild.children = guild.children.filter( - child => !hiddenGuilds.has(child.id.toString()) + child => + !hiddenGuilds.has(child.id.toString()) && + !(child.type === "folder" && hiddenGuilds.has("folder-" + child.id.toString())) ); return [newGuild]; @@ -127,7 +176,6 @@ export default definePlugin({ }, 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)) {