Add HideServers (#36)

* Add HideServers

* HideServers: Add a count indicator and a modal to manage hidden servers

* Dont include servers youve left in the indicator count

* fix(hideServers) for webpack change

* fix(hideServers): update regex

* fix(hideServers): rewrite to use stores

* move hideServers to equicordplugins

* add serverhider to readme

* put myself in equicorddevs

* formatting nit
This commit is contained in:
bep 2024-09-05 17:02:16 -07:00 committed by GitHub
parent 0f9ef9949b
commit f2696a118f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 461 additions and 8 deletions

View file

@ -0,0 +1,36 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./style.css";
import { classNameFactory } from "@api/Styles";
import { Button, ButtonLooks, GuildStore, useStateFromStores } from "@webpack/common";
import { HiddenServersStore } from "../HiddenServersStore";
import { openHiddenServersModal } from "./HiddenServersMenu";
const cl = classNameFactory("vc-hideservers-");
function HiddenServersButton() {
const hiddenGuilds = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuilds, undefined, (old, newer) => old.size === newer.size);
// if youve left a server dont show it in the count
const actuallyHidden = Array.from(hiddenGuilds).filter(x => GuildStore.getGuild(x)).length;
return (
<div className={cl("button-wrapper")}>
{actuallyHidden > 0 ? (
<Button
className={cl("button")}
look={ButtonLooks.BLANK}
size={Button.Sizes.MIN}
onClick={() => openHiddenServersModal()}
>
{actuallyHidden} Hidden
</Button>
) : null}
</div >
);
}
export default () => { return <HiddenServersButton />; };

View file

@ -0,0 +1,105 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { classNameFactory } from "@api/Styles";
import { classes } from "@utils/misc";
import {
closeModal,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalProps,
ModalRoot,
ModalSize,
openModal,
} from "@utils/modal";
import { findByPropsLazy } from "@webpack";
import { Button, Forms, IconUtils, Text, useState, useStateFromStores } from "@webpack/common";
import { Guild } from "discord-types/general";
import { HiddenServersStore } from "../HiddenServersStore";
const cl = classNameFactory("vc-hideservers-");
const IconClasses = findByPropsLazy("icon", "acronym", "childWrapper");
function HiddenServersModal({
modalProps,
close,
}: {
modalProps: ModalProps;
close(): void;
}) {
const servers = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuildsDetail());
return (
<ModalRoot {...modalProps} size={ModalSize.LARGE}>
<ModalHeader>
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>
Hidden Servers
</Text>
<ModalCloseButton onClick={close} />
</ModalHeader>
<ModalContent>
<HiddenServersMenu servers={servers} />
</ModalContent>
</ModalRoot>
);
}
export function HiddenServersMenu({ servers }: { servers: Guild[]; }) {
return <div className={cl("list")}>
{servers.length > 0 ? (
servers.map(server => (
<div key={server.id} className={cl("row")}>
<div className={cl("guildicon")}>
{server.icon
? <img height="48" width="48"
src={IconUtils.getGuildIconURL({
id: server.id,
icon: server.icon,
canAnimate: true,
size: 240,
})} />
: <div
aria-hidden
className={classes(
IconClasses.childWrapper,
IconClasses.acronym
)}>
{server.acronym}
</div>
}
</div>
<Forms.FormTitle className={cl("name")}>
{server.name}
</Forms.FormTitle>
<Button
className={"row-button"}
color={Button.Colors.PRIMARY}
onClick={() => HiddenServersStore.removeHidden(server.id)}
>
Remove
</Button>
</div>
))
) : (
<Text variant="heading-sm/medium">
No hidden servers
</Text>
)}
</div>;
};
export function openHiddenServersModal() {
const key = openModal(modalProps => {
return (
<HiddenServersModal
modalProps={modalProps}
close={() => closeModal(key)}
/>
);
});
}

View file

@ -0,0 +1,47 @@
.vc-hideservers-button-wrapper {
display: flex;
justify-content: center;
margin: 0 0 8px;
}
.vc-hideservers-button {
max-width: 48px;
font-size: 60%;
background-color: var(--background-primary);
color: var(--header-secondary);
}
.vc-hideservers-list {
flex: 1 1 auto;
}
/* copied from blocked row */
.vc-hideservers-row {
height: 62px;
display: flex;
align-items: center;
flex-direction: row;
margin-left: 20px;
margin-right: 20px;
border-top: 1px solid var(--background-modifier-accent);
border-bottom: 1px solid transparent;
justify-content: space-between;
}
.vc-hideservers-guildicon {
display: flex;
align-items: center;
margin-right: 1em;
}
.vc-hideservers-guildicon img {
border-radius: 50%;
}
.vc-hideservers-name {
flex-grow: 1;
}
.vc-hideservers-row-button {
margin-left: auto;
}