Update HideServers & Add Hide Folder functionality (#422)
* Update index.tsx * Lint * bleh --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
parent
134235c1e1
commit
ec91a6b7c0
4 changed files with 208 additions and 61 deletions
|
|
@ -15,38 +15,58 @@ export const HiddenServersStore = proxyLazyWebpack(() => {
|
|||
|
||||
const SortedGuildStore = findStoreLazy("SortedGuildStore");
|
||||
const DB_KEY = "HideServers_servers";
|
||||
|
||||
class HiddenServersStore extends Store {
|
||||
public _hiddenGuilds: Set<string> = 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
|
||||
|
|
|
|||
|
|
@ -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 <div className={cl("list")}>
|
||||
{guilds.length > 0 ? (
|
||||
guilds.map(guild => (
|
||||
<div key={guild.id} className={cl("row")}>
|
||||
<div className={cl("guildicon")}>
|
||||
{guild.icon
|
||||
? <img
|
||||
alt=""
|
||||
height="48"
|
||||
width="48"
|
||||
src={IconUtils.getGuildIconURL({
|
||||
id: guild.id,
|
||||
icon: guild.icon,
|
||||
canAnimate: true,
|
||||
size: 240,
|
||||
})} />
|
||||
: <div
|
||||
aria-hidden
|
||||
className={classes(
|
||||
IconClasses.childWrapper,
|
||||
IconClasses.acronym
|
||||
)}>
|
||||
{getGuildAcronym(guild)}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<Forms.FormTitle className={cl("name")}>
|
||||
{guild.name}
|
||||
</Forms.FormTitle>
|
||||
<Button
|
||||
className={"row-button"}
|
||||
color={Button.Colors.PRIMARY}
|
||||
onClick={() => HiddenServersStore.removeHidden(guild.id)}
|
||||
function isGuildHidden(guild: Guild, SortedGuildStore: any) {
|
||||
const folder = SortedGuildStore.getGuildFolders().find((f: any) => f.guildIds.includes(guild.id));
|
||||
if (folder && HiddenServersStore.hiddenGuilds.has("folder-" + folder.folderId)) return true;
|
||||
return HiddenServersStore.hiddenGuilds.has(guild.id);
|
||||
}
|
||||
|
||||
function getFolderForGuild(SortedGuildStore: any, guildId: string) {
|
||||
return SortedGuildStore.getGuildFolders()
|
||||
.filter((f: any) => f.folderId !== undefined)
|
||||
.find((f: any) => f.guildIds.includes(guildId));
|
||||
}
|
||||
|
||||
function restoreGuild(guild: Guild, SortedGuildStore: any) {
|
||||
HiddenServersStore.removeHiddenGuild(guild.id);
|
||||
|
||||
const folder = getFolderForGuild(SortedGuildStore, guild.id);
|
||||
if (!folder) return;
|
||||
|
||||
HiddenServersStore.removeHiddenGuild("folder-" + folder.folderId);
|
||||
}
|
||||
|
||||
|
||||
function GuildRow({ guild }) {
|
||||
return (
|
||||
<div key={guild.id} className={cl("row")}>
|
||||
<div className={cl("guildicon")}>
|
||||
{guild.icon ? (
|
||||
<img
|
||||
alt=""
|
||||
height="48"
|
||||
width="48"
|
||||
src={IconUtils.getGuildIconURL({
|
||||
id: guild.id,
|
||||
icon: guild.icon,
|
||||
canAnimate: true,
|
||||
size: 240,
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
aria-hidden
|
||||
className={classes(IconClasses.childWrapper, IconClasses.acronym)}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
{getGuildAcronym(guild)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Forms.FormTitle className={cl("name")}>
|
||||
{guild.name}
|
||||
</Forms.FormTitle>
|
||||
<Button
|
||||
className="row-button"
|
||||
color={Button.Colors.PRIMARY}
|
||||
onClick={() => restoreGuild(guild, SortedGuildStore)}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function HiddenServersMenu({ guilds }: { guilds: Guild[]; }) {
|
||||
const hiddenGuilds = guilds.filter(g => isGuildHidden(g, SortedGuildStore));
|
||||
const folders: Record<string, Guild[]> = {};
|
||||
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 <div className={cl("list")}>
|
||||
{Object.entries(folders).map(([folderId, folderGuilds]) => {
|
||||
const folder = SortedGuildStore.getGuildFolders().find(f => f.folderId === Number(folderId));
|
||||
if (!folder) return null;
|
||||
|
||||
return (
|
||||
<div key={folderId} className={cl("folder")}>
|
||||
<div className={cl("folder-header")}>
|
||||
<Text variant="heading-sm/medium">{folder.folderName || "Folder"}</Text>
|
||||
<Button
|
||||
color={Button.Colors.PRIMARY}
|
||||
onClick={() => {
|
||||
folderGuilds.forEach(g => restoreGuild(g, SortedGuildStore));
|
||||
}}
|
||||
size={Button.Sizes.TINY}
|
||||
className={cl("restore-all")}
|
||||
>
|
||||
Remove All
|
||||
</Button>
|
||||
</div>
|
||||
{folderGuilds.map(guild => (
|
||||
<GuildRow
|
||||
key={guild.id}
|
||||
guild={guild}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Text variant="heading-sm/medium">
|
||||
No hidden servers
|
||||
</Text>
|
||||
)}
|
||||
);
|
||||
})}
|
||||
|
||||
<Text variant="heading-sm/medium">Guilds</Text>
|
||||
{guildsWithoutFolder.map(guild => (
|
||||
<GuildRow
|
||||
key={guild.id}
|
||||
guild={guild}
|
||||
/>
|
||||
))}
|
||||
|
||||
{hiddenGuilds.length === 0 && <Text variant="heading-sm/medium">No hidden servers</Text>}
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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(
|
||||
<Menu.MenuItem
|
||||
id="vc-hide-server"
|
||||
label="Hide Server"
|
||||
action={() => 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(
|
||||
<Menu.MenuItem
|
||||
id="vc-hide-folder"
|
||||
label={isHidden ? "Unhide Folder" : "Hide Folder"}
|
||||
action={() => {
|
||||
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)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue