new plugin: server profile

This commit is contained in:
V 2023-09-04 23:36:48 +02:00
parent c165725297
commit 49bc6b8fd6
No known key found for this signature in database
GPG Key ID: A1DC0CFB5615D905
3 changed files with 193 additions and 0 deletions

@ -0,0 +1,117 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import "./styles.css";
import { classNameFactory } from "@api/Styles";
import { ModalRoot, ModalSize, openModal } from "@utils/modal";
import { useAwaiter } from "@utils/react";
import { Forms, Parser, SnowflakeUtils, TabBar, UserUtils, useState } from "@webpack/common";
import { Guild } from "discord-types/general";
const cl = classNameFactory("vc-gp-");
export function openGuildProfileModal(guild: Guild) {
openModal(props =>
<ModalRoot {...props} size={ModalSize.LARGE}>
<GuildProfileModal guild={guild} />
</ModalRoot>
);
}
const Tabs = {
ServerInfo: {
label: "Server Info",
component: ServerInfoTab
},
Friends: {
label: "Friends",
component: FriendsTab
},
BlockedUsers: {
label: "Blocked Users",
component: BlockedUsersTab
}
} as const;
type TabKeys = keyof typeof Tabs;
interface GuildProps {
guild: Guild;
}
function GuildProfileModal({ guild }: GuildProps) {
const [currentTab, setCurrentTab] = useState<TabKeys>("ServerInfo");
const Tab = Tabs[currentTab].component;
return (
<div className={cl("root")}>
<TabBar
type="top"
look="brand"
className={cl("tab-bar")}
selectedItem={currentTab}
onItemSelect={setCurrentTab}
>
{Object.entries(Tabs).map(([id, { label }]) =>
<TabBar.Item
className={cl("tab", { selected: currentTab === id })}
id={id}
key={id}
>
{label}
</TabBar.Item>
)}
</TabBar>
<div className={cl("tab-content")}>
<Tab guild={guild} />
</div>
</div>
);
}
const dateFormat = new Intl.DateTimeFormat(void 0, { timeStyle: "short", dateStyle: "medium" });
function renderTimestampFromId(id: string) {
return dateFormat.format(SnowflakeUtils.extractTimestamp(id));
}
function ServerInfoTab({ guild }: GuildProps) {
useAwaiter(() => UserUtils.fetchUser(guild.ownerId), {
deps: [guild.ownerId],
fallbackValue: null
});
const Fields = {
"Server Owner": Parser.parse(`<@${guild.ownerId}>`),
"Created At": renderTimestampFromId(guild.id),
"Joined At": dateFormat.format(guild.joinedAt),
"Vanity Link": guild.vanityURLCode ? Parser.parse(`https://discord.gg/${guild.vanityURLCode}`) : "-",
"Preferred Locale": guild.preferredLocale || "-",
"Verification Level": ["Low", "Medium", "High", "Highest"][guild.verificationLevel] || "?"
};
return (
<div className={cl("server-info")}>
{Object.entries(Fields).map(([name, node]) =>
<div className={cl("server-info-pair")} key={name}>
<Forms.FormTitle tag="h5">{name}</Forms.FormTitle>
{typeof node === "string" ? <span>{node}</span> : node}
</div>
)}
</div>
);
}
function FriendsTab({ guild }: GuildProps) {
return null;
}
function BlockedUsersTab({ guild }: GuildProps) {
return null;
}

@ -0,0 +1,38 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { addContextMenuPatch, NavContextMenuPatchCallback, removeContextMenuPatch } from "@api/ContextMenu";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { Menu } from "@webpack/common";
import { Guild } from "discord-types/general";
import { openGuildProfileModal } from "./GuildProfileModal";
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => () => {
children.splice(-1, 0, (
<Menu.MenuItem
id="vc-server-profile"
label="Server Profile"
action={() => openGuildProfileModal(guild)}
/>
));
};
export default definePlugin({
name: "ServerProfile",
description: "Allows you to view info about a server by right clicking it in the server list",
authors: [Devs.Ven],
tags: ["guild", "info"],
start() {
addContextMenuPatch("guild-context", Patch);
},
stop() {
removeContextMenuPatch("guild-context", Patch);
}
});

@ -0,0 +1,38 @@
.vc-gp-root {
height: 100%;
}
.vc-gp-tab-bar {
border-bottom: 2px solid var(--background-modifier-accent);
margin: 20px 12px 0;
display: flex;
gap: 40px;
align-items: stretch;
flex-direction: row;
}
.vc-gp-tab {
border-bottom: 2px solid transparent;
color: var(--interactive-normal);
cursor: pointer;
height: 39px;
line-height: 14px;
}
.vc-gp-tab-content {
margin: 1em;
}
.vc-gp-tab:where(.vc-gp-selected, :hover, :focus) {
border-bottom-color: var(--interactive-active);
}
.vc-gp-server-info {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1em;
}
.vc-gp-server-info-pair {
color: var(--text-normal);
}