new plugin: server profile
This commit is contained in:
parent
c165725297
commit
49bc6b8fd6
117
src/plugins/serverProfile/GuildProfileModal.tsx
Normal file
117
src/plugins/serverProfile/GuildProfileModal.tsx
Normal file
@ -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;
|
||||||
|
}
|
38
src/plugins/serverProfile/index.tsx
Normal file
38
src/plugins/serverProfile/index.tsx
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
});
|
38
src/plugins/serverProfile/styles.css
Normal file
38
src/plugins/serverProfile/styles.css
Normal file
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user