aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/showConnections/index.tsx173
-rw-r--r--src/plugins/showConnections/styles.css5
2 files changed, 178 insertions, 0 deletions
diff --git a/src/plugins/showConnections/index.tsx b/src/plugins/showConnections/index.tsx
new file mode 100644
index 0000000..7c0a46a
--- /dev/null
+++ b/src/plugins/showConnections/index.tsx
@@ -0,0 +1,173 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2023 Vendicated and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+import "./styles.css";
+
+import { definePluginSettings } from "@api/settings";
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Devs } from "@utils/constants";
+import { copyWithToast, LazyComponent } from "@utils/misc";
+import definePlugin, { OptionType } from "@utils/types";
+import { findByCode, findByCodeLazy, findByPropsLazy, findStoreLazy } from "@webpack";
+import { Text, Tooltip } from "@webpack/common";
+import { User } from "discord-types/general";
+
+const Section = LazyComponent(() => findByCode("().lastSection"));
+const UserProfileStore = findStoreLazy("UserProfileStore");
+const ThemeStore = findStoreLazy("ThemeStore");
+const platforms: { get(type: string): ConnectionPlatform; } = findByPropsLazy("isSupported", "getByUrl");
+const getTheme: (user: User, displayProfile: any) => any = findByCodeLazy(',"--profile-gradient-primary-color"');
+
+const enum Spacing {
+ COMPACT,
+ COZY,
+ ROOMY
+}
+const getSpacingPx = (spacing: Spacing | undefined) => (spacing ?? Spacing.COMPACT) * 2 + 4;
+
+const settings = definePluginSettings({
+ iconSize: {
+ type: OptionType.NUMBER,
+ description: "Icon size (px)",
+ default: 32
+ },
+ iconSpacing: {
+ type: OptionType.SELECT,
+ description: "Icon margin",
+ default: Spacing.COZY,
+ options: [
+ { label: "Compact", value: Spacing.COMPACT },
+ { label: "Cozy", value: Spacing.COZY }, // US Spelling :/
+ { label: "Roomy", value: Spacing.ROOMY }
+ ]
+ }
+});
+
+interface Connection {
+ type: string;
+ id: string;
+ name: string;
+ verified: boolean;
+}
+
+interface ConnectionPlatform {
+ getPlatformUserUrl(connection: Connection): string;
+ icon: { lightSVG: string, darkSVG: string; };
+}
+
+const profilePopoutComponent = ErrorBoundary.wrap(e =>
+ <ConnectionsComponent id={e.user.id} theme={getTheme(e.user, e.displayProfile).profileTheme} />
+);
+
+const profilePanelComponent = ErrorBoundary.wrap(e =>
+ <ConnectionsComponent id={e.channel.recipients[0]} theme={ThemeStore.theme} />
+);
+
+function ConnectionsComponent({ id, theme }: { id: string, theme: string; }) {
+ const profile = UserProfileStore.getUserProfile(id);
+ if (!profile)
+ return null;
+
+ const connections: Connection[] = profile.connectedAccounts;
+ if (!connections?.length)
+ return null;
+
+ return (
+ <Section>
+ <Text
+ tag="h2"
+ variant="eyebrow"
+ style={{ color: "var(--header-primary)" }}
+ >
+ Connections
+ </Text>
+ {connections.map(connection => <CompactConnectionComponent connection={connection} theme={theme} />)}
+ </Section>
+ );
+}
+
+function CompactConnectionComponent({ connection, theme }: { connection: Connection, theme: string; }) {
+ const platform = platforms.get(connection.type);
+ const url = platform.getPlatformUserUrl?.(connection);
+
+ const img = (
+ <img
+ aria-label={connection.name}
+ src={theme === "light" ? platform.icon.lightSVG : platform.icon.darkSVG}
+ style={{
+ marginTop: getSpacingPx(settings.store.iconSpacing),
+ marginRight: getSpacingPx(settings.store.iconSpacing),
+ width: settings.store.iconSize,
+ height: settings.store.iconSize
+ }}
+ />
+ );
+
+ return (
+ <Tooltip
+ text={`${connection.name}${!connection.verified ? " (unverified)" : ""} (click to ${url ? "open" : "copy"})`}
+ key={connection.id}
+ >
+ {tooltipProps =>
+ url
+ ? <a
+ {...tooltipProps}
+ className="vc-user-connection"
+ href={url}
+ target="_blank"
+ >
+ {img}
+ </a>
+ : <button
+ {...tooltipProps}
+ className="vc-user-connection"
+ onClick={() => copyWithToast(connection.name)}
+ >
+ {img}
+ </button>
+
+ }
+ </Tooltip>
+ );
+}
+
+export default definePlugin({
+ name: "ShowConnections",
+ description: "Show connected accounts in user popouts",
+ authors: [Devs.TheKodeToad],
+ patches: [
+ {
+ find: ".Messages.BOT_PROFILE_SLASH_COMMANDS",
+ replacement: {
+ match: /,theme:\i\}\)(?=,.{0,100}setNote:)/,
+ replace: "$&,$self.profilePopoutComponent(arguments[0])"
+ }
+ },
+ {
+ find: "\"Profile Panel: user cannot be undefined\"",
+ replacement: {
+ // createElement(Divider, {}), createElement(NoteComponent)
+ match: /\(0,\i\.jsx\)\(\i\.\i,\{\}\).{0,100}setNote:/,
+ replace: "$self.profilePanelComponent(arguments[0]),$&"
+ }
+ }
+ ],
+ settings,
+ profilePopoutComponent,
+ profilePanelComponent
+});
diff --git a/src/plugins/showConnections/styles.css b/src/plugins/showConnections/styles.css
new file mode 100644
index 0000000..71a835b
--- /dev/null
+++ b/src/plugins/showConnections/styles.css
@@ -0,0 +1,5 @@
+.vc-user-connection {
+ all: unset;
+ display: inline-block;
+ cursor: pointer;
+}