Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen1234 2025-02-07 02:43:07 -05:00
commit 77fc5bfd84
12 changed files with 564 additions and 351 deletions

View file

@ -17,16 +17,22 @@
*/
import { Button } from "@webpack/common";
import { ButtonProps } from "@webpack/types";
import { Heart } from "./Heart";
export default function DonateButton(props: any) {
export default function DonateButton({
look = Button.Looks.LINK,
color = Button.Colors.TRANSPARENT,
...props
}: Partial<ButtonProps>) {
return (
<Button
{...props}
look={Button.Looks.LINK}
color={Button.Colors.TRANSPARENT}
look={look}
color={color}
onClick={() => VencordNative.native.openExternal("https://github.com/sponsors/verticalsync")}
innerClassName="vc-donate-button"
>
<Heart />
Donate

View file

@ -16,14 +16,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export function Heart() {
import { classes } from "@utils/misc";
import { SVGProps } from "react";
export function Heart(props: SVGProps<SVGSVGElement>) {
return (
<svg
aria-hidden="true"
height="16"
viewBox="0 0 16 16"
height="16"
width="16"
style={{ marginRight: "0.5em", transform: "translateY(2px)" }}
{...props}
className={classes("vc-heart-icon", props.className)}
>
<path
fill="#db61a2"

View file

@ -0,0 +1,77 @@
/*
* 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 "./specialCard.css";
import { classNameFactory } from "@api/Styles";
import { Card, Clickable, Forms, React } from "@webpack/common";
import type { PropsWithChildren } from "react";
const cl = classNameFactory("vc-special-");
interface StyledCardProps {
title: string;
subtitle?: string;
description: string;
cardImage?: string;
backgroundImage?: string;
backgroundColor?: string;
buttonTitle?: string;
buttonOnClick?: () => void;
}
export function SpecialCard({ title, subtitle, description, cardImage, backgroundImage, backgroundColor, buttonTitle, buttonOnClick: onClick, children }: PropsWithChildren<StyledCardProps>) {
const cardStyle: React.CSSProperties = {
backgroundColor: backgroundColor || "#9c85ef",
backgroundImage: `url(${backgroundImage || ""})`,
};
return (
<Card className={cl("card", "card-special")} style={cardStyle}>
<div className={cl("card-flex")}>
<div className={cl("card-flex-main")}>
<Forms.FormTitle className={cl("title")} tag="h5">{title}</Forms.FormTitle>
<Forms.FormText className={cl("subtitle")}>{subtitle}</Forms.FormText>
<Forms.FormText className={cl("text")}>{description}</Forms.FormText>
{children}
</div>
{cardImage && (
<div className={cl("image-container")}>
<img
role="presentation"
src={cardImage}
alt=""
className={cl("image")}
/>
</div>
)}
</div>
{buttonTitle && (
<>
<Forms.FormDivider className={cl("seperator")} />
<Clickable onClick={onClick} className={cl("hyperlink")}>
<Forms.FormText className={cl("hyperlink-text")}>
{buttonTitle}
</Forms.FormText>
</Clickable>
</>
)}
</Card>
);
}

View file

@ -9,56 +9,47 @@ import "./VencordTab.css";
import { openNotificationLogModal } from "@api/Notifications/notificationLog";
import { useSettings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import DonateButton from "@components/DonateButton";
import { openContributorModal } from "@components/PluginSettings/ContributorModal";
import { openPluginModal } from "@components/PluginSettings/PluginModal";
import { gitRemote } from "@shared/vencordUserAgent";
import { openInviteModal } from "@utils/discord";
import { DONOR_ROLE_ID, GUILD_ID, VC_DONOR_ROLE_ID, VC_GUILD_ID } from "@utils/constants";
import { Margins } from "@utils/margins";
import { identity } from "@utils/misc";
import { identity, isEquicordPluginDev, isPluginDev } from "@utils/misc";
import { relaunch, showItemInFolder } from "@utils/native";
import { useAwaiter } from "@utils/react";
import {
Button,
Card,
Forms,
React,
Select,
showToast,
Switch,
} from "@webpack/common";
import { Button, Forms, GuildMemberStore, React, Select, Switch, UserStore } from "@webpack/common";
import {
Flex,
FolderIcon,
GithubIcon,
Heart,
LogIcon,
PaintbrushIcon,
RestartIcon,
} from "..";
import BadgeAPI from "../../plugins/_api/badges";
import { Flex, FolderIcon, GithubIcon, LogIcon, PaintbrushIcon, RestartIcon } from "..";
import { openNotificationSettingsModal } from "./NotificationSettings";
import { QuickAction, QuickActionCard } from "./quickActions";
import { SettingsTab, wrapTab } from "./shared";
import { SpecialCard } from "./SpecialCard";
const cl = classNameFactory("vc-settings-");
const DEFAULT_DONATE_IMAGE =
"https://cdn.discordapp.com/emojis/1026533090627174460.png";
const DEFAULT_DONATE_IMAGE = "https://cdn.discordapp.com/emojis/1026533090627174460.png";
const SHIGGY_DONATE_IMAGE = "https://i.imgur.com/57ATLZu.png";
const VENNIE_DONATOR_IMAGE = "https://cdn.discordapp.com/emojis/1238120638020063377.png";
const COZY_CONTRIB_IMAGE = "https://cdn.discordapp.com/emojis/1026533070955872337.png";
const DONOR_BACKGROUND_IMAGE = "https://media.discordapp.net/stickers/1311070116305436712.png?size=2048";
const CONTRIB_BACKGROUND_IMAGE = "https://media.discordapp.net/stickers/1311070166481895484.png?size=2048";
type KeysOfType<Object, Type> = {
[K in keyof Object]: Object[K] extends Type ? K : never;
}[keyof Object];
function EquicordSettings() {
const [settingsDir, , settingsDirPending] = useAwaiter(
VencordNative.settings.getSettingsDir,
{
fallbackValue: "Loading...",
},
);
const [settingsDir, , settingsDirPending] = useAwaiter(VencordNative.settings.getSettingsDir, {
fallbackValue: "Loading..."
});
const settings = useSettings();
const discordInvite = "bFp57wxCkv";
const vcDiscordInvite = "https://discord.gg/KGgvd6jPFu";
const donateImage = React.useMemo(
() => (Math.random() > 0.5 ? DEFAULT_DONATE_IMAGE : SHIGGY_DONATE_IMAGE),
[],
@ -68,13 +59,13 @@ function EquicordSettings() {
const isMac = navigator.platform.toLowerCase().startsWith("mac");
const needsVibrancySettings = IS_DISCORD_DESKTOP && isMac;
const Switches: Array<
| false
| {
const user = UserStore.getCurrentUser();
const Switches: Array<false | {
key: KeysOfType<typeof settings, boolean>;
title: string;
note: string;
warning: { enabled: boolean; message?: string };
warning: { enabled: boolean; message?: string; };
}
> = [
{
@ -131,7 +122,46 @@ function EquicordSettings() {
return (
<SettingsTab title="Equicord Settings">
<DiscordInviteCard invite={discordInvite} image={donateImage} />
{(isDonor(user?.id) || isVCDonor(user?.id)) ? (
<SpecialCard
title="Donations"
subtitle="Thank you for donating!"
description={
isDonor(user?.id) && isVCDonor(user?.id)
? "All Vencord users can see your Vencord donor badge, and Equicord users can see your Equicord donor badge. To change your Vencord donor badge, contact @vending.machine. For your Equicord donor badge, make a ticket in Equicord's server."
: isVCDonor(user?.id)
? "All Vencord users can see your badge! You can change it at any time by messaging @vending.machine."
: "All Equicord users can see your badge! You can change it at any time by making a ticket in Equicord's server."
}
cardImage={VENNIE_DONATOR_IMAGE}
backgroundImage={DONOR_BACKGROUND_IMAGE}
backgroundColor="#ED87A9"
>
<DonateButtonComponent />
</SpecialCard>
) : (
<SpecialCard
title="Support the Project"
description="Please consider supporting the development of Equicord by donating!"
cardImage={donateImage}
backgroundImage={DONOR_BACKGROUND_IMAGE}
backgroundColor="#c3a3ce"
>
<DonateButtonComponent />
</SpecialCard>
)}
{isPluginDev(user?.id) || isEquicordPluginDev(user?.id) && (
<SpecialCard
title="Contributions"
subtitle="Thank you for contributing!"
description="Since you've contributed to Equicord you now have a cool new badge!"
cardImage={COZY_CONTRIB_IMAGE}
backgroundImage={CONTRIB_BACKGROUND_IMAGE}
backgroundColor="#EDCC87"
buttonTitle="See what you've contributed to"
buttonOnClick={() => openContributorModal(user)}
/>
)}
<Forms.FormSection title="Quick Actions">
<QuickActionCard>
<QuickAction
@ -302,61 +332,24 @@ function EquicordSettings() {
);
}
interface DiscordInviteProps {
invite: string;
image: string;
function DonateButtonComponent() {
return (
<DonateButton
look={Button.Looks.FILLED}
color={Button.Colors.TRANSPARENT}
style={{ marginTop: "1em" }}
/>
);
}
function DiscordInviteCard({ invite, image }: DiscordInviteProps) {
return (
<Card className={cl("card", "discordinvite")}>
<div>
<Forms.FormTitle tag="h5">Join the discord!</Forms.FormTitle>
<Forms.FormText>
Please consider joining the discord for any news on breaking changes,
or new bigger updates!
</Forms.FormText>
<Forms.FormText>
<Heart />
You can also donate to me if you'd like to support this project.
</Forms.FormText>
function isVCDonor(userId: string): boolean {
const donorBadges = BadgeAPI.getDonorBadges(userId);
return GuildMemberStore.getMember(VC_GUILD_ID, userId)?.roles.includes(VC_DONOR_ROLE_ID) || !!donorBadges;
}
<div className={cl("card-buttons")}>
<Button
className="vc-joindiscordbutton vc-settingbuttons"
onClick={async e => {
e.preventDefault();
openInviteModal(invite).catch(() =>
showToast("Invalid or expired invite"),
);
}}
>
Join
</Button>
<Button
className="vc-donatebutton vc-settingbuttons"
onClick={() => {
VencordNative.native.openExternal(
"https://github.com/sponsors/verticalsync",
);
}}
>
Donate
</Button>
</div>
</div>
<img
role="presentation"
src={image}
alt=""
height={128}
style={{
marginLeft: "auto",
}}
/>
</Card>
);
function isDonor(userId: string): boolean {
const donorBadges = BadgeAPI.getDonorBadges(userId);
return GuildMemberStore.getMember(GUILD_ID, userId)?.roles.includes(DONOR_ROLE_ID) || !!donorBadges;
}
export default wrapTab(EquicordSettings, "Equicord Settings");

View file

@ -1,12 +1,17 @@
.vc-settings-quickActions-card {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, max-content));
grid-template-columns: repeat(3, 1fr);
gap: 0.5em;
justify-content: center;
padding: 0.5em 0;
padding: 0.5em;
margin-bottom: 1em;
}
@media (width <=1040px) {
.vc-settings-quickActions-card {
grid-template-columns: repeat(2, 1fr);
}
}
.vc-settings-quickActions-pill {
all: unset;
background: var(--background-secondary);
@ -14,12 +19,16 @@
display: flex;
align-items: center;
gap: 0.5em;
padding: 8px 12px;
border-radius: 9999px;
padding: 8px 9px;
border-radius: 8px;
transition: 0.1s ease-out;
box-sizing: border-box;
}
.vc-settings-quickActions-pill:hover {
background: var(--background-secondary-alt);
transform: translateY(-1px);
box-shadow: var(--elevation-high);
}
.vc-settings-quickActions-pill:focus-visible {

View file

@ -0,0 +1,92 @@
.vc-donate-button {
overflow: visible !important;
}
.vc-donate-button .vc-heart-icon {
transition: transform 0.3s;
}
.vc-donate-button:hover .vc-heart-icon {
transform: scale(1.1);
z-index: 10;
position: relative;
}
.vc-settings-card {
padding: 1em;
margin-bottom: 1em;
}
.vc-special-card-special {
padding: 1em 1.5em;
margin-bottom: 1em;
background-size: cover;
background-position: center;
}
.vc-special-card-flex {
display: flex;
flex-direction: row;
}
.vc-special-card-flex-main {
width: 100%;
}
.vc-special-title {
color: black;
}
.vc-special-subtitle {
color: black;
font-size: 1.2em;
font-weight: bold;
margin-top: 0.5em;
}
.vc-special-text {
color: black;
font-size: 1em;
margin-top: .75em;
white-space: pre-line;
}
.vc-special-seperator {
margin-top: .75em;
border-top: 1px solid white;
opacity: 0.4;
}
.vc-special-hyperlink {
margin-top: 1em;
cursor: pointer;
.vc-special-hyperlink-text {
color: black;
font-size: 1em;
font-weight: bold;
text-align: center;
transition: text-decoration 0.5s;
cursor: pointer;
}
&:hover .vc-special-hyperlink-text {
text-decoration: underline;
}
}
.vc-special-image-container {
display: flex;
justify-content: center;
align-items: center;
margin-left: 1em;
flex-shrink: 0;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: white;
}
.vc-special-image {
width: 65%;
}

View file

@ -5,3 +5,8 @@
.vc-owner-crown-icon {
color: var(--text-warning);
}
.vc-heart-icon {
margin-right: 0.5em;
translate: 0 2px;
}

View file

@ -22,7 +22,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
import { Flex } from "@components/Flex";
import { Link } from "@components/Link";
import { openUpdaterModal } from "@components/VencordSettings/UpdaterTab";
import { Devs, GUILD_ID, SUPPORT_CHANNEL_ID, SUPPORT_CHANNEL_IDS, VC_GUILD_ID, VC_SUPPORT_CHANNEL_ID } from "@utils/constants";
import { CONTRIB_ROLE_ID, Devs, DONOR_ROLE_ID, EQUIBOP_CONTRIB_ROLE_ID, EQUICORD_TEAM, GUILD_ID, SUPPORT_CHANNEL_ID, SUPPORT_CHANNEL_IDS, VC_CONTRIB_ROLE_ID, VC_DONOR_ROLE_ID, VC_KNOWN_ISSUES_CHANNEL_ID, VC_REGULAR_ROLE_ID, VC_SUPPORT_CHANNEL_ID, VENBOT_USER_ID, VENCORD_CONTRIB_ROLE_ID } from "@utils/constants";
import { sendMessage } from "@utils/discord";
import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins";
@ -40,18 +40,17 @@ import plugins, { PluginMeta } from "~plugins";
import SettingsPlugin from "./settings";
const VENBOT_USER_ID = "1017176847865352332";
const KNOWN_ISSUES_CHANNEL_ID = "1222936386626129920";
const CodeBlockRe = /```js\n(.+?)```/s;
const TrustedRolesIds = [
"1026534353167208489", // contributor
"1026504932959977532", // regular
"1042507929485586532", // donor
"1173520023239786538", // Equicord Team
"1222677964760682556", // Equicord Contributor
"1287079931645263968", // Equibop Contributor
"1173343399470964856", // Vencord Contributor
VC_CONTRIB_ROLE_ID, // Vencord Contributor
VC_REGULAR_ROLE_ID, // Vencord Regular
VC_DONOR_ROLE_ID, // Vencord Donor
EQUICORD_TEAM, // Equicord Team
DONOR_ROLE_ID, // Equicord Donor
CONTRIB_ROLE_ID, // Equicord Contributor
EQUIBOP_CONTRIB_ROLE_ID, // Equibop Contributor
VENCORD_CONTRIB_ROLE_ID, // Vencord Contributor
];
const AsyncFunction = async function () { }.constructor;
@ -261,8 +260,8 @@ export default definePlugin({
const shouldAddUpdateButton =
!IS_UPDATER_DISABLED
&& (
(props.channel.id === KNOWN_ISSUES_CHANNEL_ID) ||
(props.channel.id === SUPPORT_CHANNEL_ID && props.message.author.id === VENBOT_USER_ID)
(props.channel.id === VC_KNOWN_ISSUES_CHANNEL_ID) ||
(props.channel.id === VC_SUPPORT_CHANNEL_ID && props.message.author.id === VENBOT_USER_ID)
)
&& props.message.content?.includes("update");

View file

@ -18,12 +18,29 @@
export const WEBPACK_CHUNK = "webpackChunkdiscord_app";
export const REACT_GLOBAL = "Vencord.Webpack.Common.React";
// Equicord
export const SUPPORT_CHANNEL_ID = "1297590739911573585";
export const VC_SUPPORT_CHANNEL_ID = "1026515880080842772";
export const SUPPORT_CHANNEL_IDS = [SUPPORT_CHANNEL_ID, VC_SUPPORT_CHANNEL_ID];
export const GUILD_ID = "1173279886065029291";
export const DONOR_ROLE_ID = "1173316879083896912";
export const CONTRIB_ROLE_ID = "1222677964760682556";
export const EQUICORD_TEAM = "1173520023239786538";
export const EQUIBOP_CONTRIB_ROLE_ID = "1287079931645263968";
export const VENCORD_CONTRIB_ROLE_ID = "1173343399470964856";
// Vencord
export const VC_SUPPORT_CHANNEL_ID = "1026515880080842772";
export const VC_GUILD_ID = "1015060230222131221";
export const VENBOT_USER_ID = "1017176847865352332";
export const VC_DONOR_ROLE_ID = "1042507929485586532";
export const VC_CONTRIB_ROLE_ID = "1026534353167208489";
export const VC_REGULAR_ROLE_ID = "1026504932959977532";
export const VC_KNOWN_ISSUES_CHANNEL_ID = "1222936386626129920";
export const GUILD_IDS = [GUILD_ID, VC_GUILD_ID];
export const SUPPORT_CHANNEL_IDS = [SUPPORT_CHANNEL_ID, VC_SUPPORT_CHANNEL_ID];
export const DONOR_ROLE_IDS = [DONOR_ROLE_ID, VC_DONOR_ROLE_ID];
export const CONTRIB_ROLE_IDS = [CONTRIB_ROLE_ID, EQUIBOP_CONTRIB_ROLE_ID, VENCORD_CONTRIB_ROLE_ID, VC_CONTRIB_ROLE_ID];
export interface Dev {
name: string;
@ -584,6 +601,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "jamesbt365",
id: 158567567487795200n,
},
samsam: {
name: "samsam",
id: 836452332387565589n,
},
} satisfies Record<string, Dev>);
export const EquicordDevs = Object.freeze({

View file

@ -60,7 +60,7 @@ export async function downloadSettingsBackup() {
}
}
const toast = (type: number, message: string) =>
const toast = (type: string, message: string) =>
Toasts.show({
type,
message,

View file

@ -152,7 +152,7 @@ export type ComboboxPopout = ComponentType<PropsWithChildren<{
}>>;
export type Button = ComponentType<PropsWithChildren<Omit<HTMLProps<HTMLButtonElement>, "size"> & {
export interface ButtonProps extends PropsWithChildren<Omit<HTMLProps<HTMLButtonElement>, "size">> {
/** Button.Looks.FILLED */
look?: string;
/** Button.Colors.BRAND */
@ -172,7 +172,9 @@ export type Button = ComponentType<PropsWithChildren<Omit<HTMLProps<HTMLButtonEl
submittingStartedLabel?: string;
submittingFinishedLabel?: string;
}>> & {
}
export type Button = ComponentType<ButtonProps> & {
BorderColors: Record<"BLACK" | "BRAND" | "BRAND_NEW" | "GREEN" | "LINK" | "PRIMARY" | "RED" | "TRANSPARENT" | "WHITE" | "YELLOW", string>;
Colors: Record<"BRAND" | "RED" | "GREEN" | "YELLOW" | "PRIMARY" | "LINK" | "WHITE" | "BLACK" | "TRANSPARENT" | "BRAND_NEW" | "CUSTOM", string>;
Hovers: Record<"DEFAULT" | "BRAND" | "RED" | "GREEN" | "YELLOW" | "PRIMARY" | "LINK" | "WHITE" | "BLACK" | "TRANSPARENT", string>;

View file

@ -74,10 +74,15 @@ export let Alerts: t.Alerts;
waitFor(["show", "close"], m => Alerts = m);
const ToastType = {
MESSAGE: 0,
SUCCESS: 1,
FAILURE: 2,
CUSTOM: 3
MESSAGE: "message",
SUCCESS: "success",
FAILURE: "failure",
CUSTOM: "custom",
CLIP: "clip",
LINK: "link",
FORWARD: "forward",
BOOKMARK: "bookmark",
CLOCK: "clock"
};
const ToastPosition = {
TOP: 0,
@ -90,7 +95,7 @@ export interface ToastData {
/**
* Toasts.Type
*/
type: number,
type: string,
options?: ToastOptions;
}
@ -113,7 +118,7 @@ export const Toasts = {
...{} as {
show(data: ToastData): void;
pop(): void;
create(message: string, type: number, options?: ToastOptions): ToastData;
create(message: string, type: string, options?: ToastOptions): ToastData;
}
};