Online Themes: fix & improve ui

This commit is contained in:
Vendicated 2025-07-10 01:37:13 +02:00 committed by dorkbutt
parent c2fbcec3bd
commit c2d7b68950
No known key found for this signature in database
8 changed files with 26 additions and 81 deletions

View file

@ -62,7 +62,7 @@ function showErrorToast(message: string) {
function ReloadRequiredCard({ required }: { required: boolean; }) { function ReloadRequiredCard({ required }: { required: boolean; }) {
return ( return (
<Card className={cl("info-card", { "restart-card": required })}> <Card className={classes(cl("info-card"), required && "vc-warning-card")}>
{required ? ( {required ? (
<> <>
<Forms.FormTitle tag="h5">Restart required!</Forms.FormTitle> <Forms.FormTitle tag="h5">Restart required!</Forms.FormTitle>

View file

@ -66,13 +66,6 @@
gap: 0.25em; gap: 0.25em;
} }
.vc-plugins-restart-card {
padding: 1em;
background: var(--info-warning-background);
border: 1px solid var(--info-warning-foreground);
color: var(--info-warning-foreground);
}
.vc-plugins-restart-button { .vc-plugins-restart-button {
margin-top: 0.5em; margin-top: 0.5em;
background: var(--info-warning-foreground) !important; background: var(--info-warning-foreground) !important;

View file

@ -29,7 +29,7 @@ import { openInviteModal } from "@utils/discord";
import { Margins } from "@utils/margins"; import { Margins } from "@utils/margins";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import { relaunch } from "@utils/native"; import { relaunch } from "@utils/native";
import { useAwaiter, useForceUpdater } from "@utils/react"; import { useForceUpdater } from "@utils/react";
import { getStylusWebStoreUrl } from "@utils/web"; import { getStylusWebStoreUrl } from "@utils/web";
import { findLazy } from "@webpack"; import { findLazy } from "@webpack";
import { Alerts, Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common"; import { Alerts, Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
@ -52,62 +52,6 @@ const FileInput: FileInput = findLazy(m => m.prototype?.activateUploadDialogue &
const cl = classNameFactory("vc-settings-theme-"); const cl = classNameFactory("vc-settings-theme-");
function Validator({ link }: { link: string; }) {
const [res, err, pending] = useAwaiter(() => fetch(link).then(res => {
if (res.status > 300) throw `${res.status} ${res.statusText}`;
const contentType = res.headers.get("Content-Type");
if (!contentType?.startsWith("text/css") && !contentType?.startsWith("text/plain"))
throw "Not a CSS file. Remember to use the raw link!";
return "Okay!";
}));
const text = pending
? "Checking..."
: err
? `Error: ${err instanceof Error ? err.message : String(err)}`
: "Valid!";
return <Forms.FormText style={{
color: pending ? "var(--text-muted)" : err ? "var(--text-danger)" : "var(--status-positive)"
}}>{text}</Forms.FormText>;
}
function Validators({ themeLinks }: { themeLinks: string[]; }) {
if (!themeLinks.length) return null;
return (
<>
<Forms.FormTitle className={Margins.top20} tag="h5">Validator</Forms.FormTitle>
<Forms.FormText>This section will tell you whether your themes can successfully be loaded</Forms.FormText>
<div>
{themeLinks.map(rawLink => {
const { label, link } = (() => {
const match = /^@(light|dark) (.*)/.exec(rawLink);
if (!match) return { label: rawLink, link: rawLink };
const [, mode, link] = match;
return { label: `[${mode} mode only] ${link}`, link };
})();
return <Card style={{
padding: ".5em",
marginBottom: ".5em",
marginTop: ".5em"
}} key={link}>
<Forms.FormTitle tag="h5" style={{
overflowWrap: "break-word"
}}>
{label}
</Forms.FormTitle>
<Validator link={link} />
</Card>;
})}
</div>
</>
);
}
interface ThemeCardProps { interface ThemeCardProps {
theme: UserThemeHeader; theme: UserThemeHeader;
enabled: boolean; enabled: boolean;
@ -309,6 +253,12 @@ function ThemesTab() {
function renderOnlineThemes() { function renderOnlineThemes() {
return ( return (
<> <>
<Card className={classes("vc-warning-card", Margins.bottom16)}>
<Forms.FormText>
This section is for advanced users. If you are having difficulties using it, use the
Local Themes tab instead.
</Forms.FormText>
</Card>
<Card className="vc-settings-card"> <Card className="vc-settings-card">
<Forms.FormTitle tag="h5">Paste links to css files here</Forms.FormTitle> <Forms.FormTitle tag="h5">Paste links to css files here</Forms.FormTitle>
<Forms.FormText>One link per line</Forms.FormText> <Forms.FormText>One link per line</Forms.FormText>
@ -321,12 +271,11 @@ function ThemesTab() {
value={themeText} value={themeText}
onChange={setThemeText} onChange={setThemeText}
className={"vc-settings-theme-links"} className={"vc-settings-theme-links"}
placeholder="Theme Links" placeholder="Enter Theme Links..."
spellCheck={false} spellCheck={false}
onBlur={onBlur} onBlur={onBlur}
rows={10} rows={10}
/> />
<Validators themeLinks={settings.themeLinks} />
</Forms.FormSection> </Forms.FormSection>
</> </>
); );

View file

@ -1,7 +1,7 @@
.vc-settings-tab-bar { .vc-settings-tab-bar {
margin-top: 20px; margin-top: 20px;
margin-bottom: 10px; margin-bottom: 10px;
border-bottom: 2px solid var(--background-modifier-accent); border-bottom: 1px solid var(--border-subtle);
} }
.vc-settings-tab-bar-item { .vc-settings-tab-bar-item {
@ -20,6 +20,13 @@
margin-bottom: 1em; margin-bottom: 1em;
} }
.vc-warning-card {
padding: 1em;
background: var(--info-warning-background);
border: 1px solid var(--info-warning-foreground);
color: var(--info-warning-foreground);
}
.vc-backup-restore-card { .vc-backup-restore-card {
background-color: var(--info-warning-background); background-color: var(--info-warning-background);
border-color: var(--info-warning-foreground); border-color: var(--info-warning-foreground);
@ -30,19 +37,20 @@
/* Needed to fix bad themes that hide certain textarea elements for whatever eldritch reason */ /* Needed to fix bad themes that hide certain textarea elements for whatever eldritch reason */
display: inline-block !important; display: inline-block !important;
color: var(--text-default) !important; color: var(--text-default) !important;
padding: 0.5em; padding: 0.5em 1em;
border: 1px solid var(--background-modifier-accent); border: 1px solid var(--input-border);
max-height: unset; max-height: unset;
background-color: transparent; background-color: transparent;
box-sizing: border-box; box-sizing: border-box;
font-size: 12px;
line-height: 14px;
resize: none; resize: none;
width: 100%; width: 100%;
font-size: 1em;
line-height: 2em;
white-space: nowrap;
} }
.vc-settings-theme-links::placeholder { .vc-settings-theme-links::placeholder {
color: var(--header-secondary); color: var(--text-muted) !important;
} }
.vc-settings-theme-links:focus { .vc-settings-theme-links:focus {

View file

@ -12,11 +12,6 @@
position: relative; position: relative;
} }
.vc-settings-card {
padding: 1em;
margin-bottom: 1em;
}
.vc-special-card-special { .vc-special-card-special {
padding: 1em 1.5em; padding: 1em 1.5em;
margin-bottom: 1em; margin-bottom: 1em;

View file

@ -318,7 +318,7 @@ export default definePlugin({
if (RelationshipStore.isFriend(userId) || isPluginDev(UserStore.getCurrentUser()?.id)) return null; if (RelationshipStore.isFriend(userId) || isPluginDev(UserStore.getCurrentUser()?.id)) return null;
return ( return (
<Card className={`vc-plugins-restart-card ${Margins.top8}`}> <Card className={`vc-warning-card ${Margins.top8}`}>
Please do not private message Vencord plugin developers for support! Please do not private message Vencord plugin developers for support!
<br /> <br />
Instead, use the Vencord support channel: {Parser.parse("https://discord.com/channels/1015060230222131221/1026515880080842772")} Instead, use the Vencord support channel: {Parser.parse("https://discord.com/channels/1015060230222131221/1026515880080842772")}

View file

@ -219,7 +219,7 @@ function Modal({ modalProps }: { modalProps: ModalProps; }) {
/> />
{isUnsupportedFormat && ( {isUnsupportedFormat && (
<Card className={`vc-plugins-restart-card ${Margins.top16}`}> <Card className={`vc-warning-card ${Margins.top16}`}>
<Forms.FormText>Voice Messages have to be OggOpus to be playable on iOS. This file is <code>{blob.type}</code> so it will not be playable on iOS.</Forms.FormText> <Forms.FormText>Voice Messages have to be OggOpus to be playable on iOS. This file is <code>{blob.type}</code> so it will not be playable on iOS.</Forms.FormText>
<Forms.FormText className={Margins.top8}> <Forms.FormText className={Margins.top8}>

View file

@ -8,7 +8,7 @@ import { useLayoutEffect } from "@webpack/common";
import { useForceUpdater } from "./react"; import { useForceUpdater } from "./react";
const cssRelevantDirectives = ["style-src", "img-src", "font-src"] as const; const cssRelevantDirectives = ["style-src", "style-src-elem", "img-src", "font-src"] as const;
export const CspBlockedUrls = new Set<string>(); export const CspBlockedUrls = new Set<string>();
const CspErrorListeners = new Set<() => void>(); const CspErrorListeners = new Set<() => void>();