This commit is contained in:
thororen 2024-05-12 17:43:11 -04:00
parent 992523682d
commit ee8a5a977e
5 changed files with 81 additions and 36 deletions

View file

@ -8,7 +8,7 @@ import { CodeBlock } from "@components/CodeBlock";
import { Heart } from "@components/Heart";
import { openInviteModal } from "@utils/discord";
import { Margins } from "@utils/margins";
import { ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal";
import { ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { findComponentByCodeLazy } from "@webpack";
import { Button, Clipboard, Forms, React, showToast, Toasts } from "@webpack/common";
@ -51,7 +51,7 @@ export const ThemeInfoModal: React.FC<ThemeInfoModalProps> = ({ author, theme, .
<Forms.FormTitle tag="h5" style={{ marginTop: "10px" }}>Source</Forms.FormTitle>
<Forms.FormText>
<Button onClick={() => openModal(modalProps => (
<ModalRoot {...modalProps}>
<ModalRoot {...modalProps} size={ModalSize.LARGE}>
<ModalHeader>
<Forms.FormTitle tag="h4">Theme Source</Forms.FormTitle>
</ModalHeader>

View file

@ -4,17 +4,14 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/* eslint-disable indent */
import "./styles.css";
import { generateId } from "@api/Commands";
import { Settings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import { CodeBlock } from "@components/CodeBlock";
import { OpenExternalIcon } from "@components/Icons";
import { SettingsTab, wrapTab } from "@components/VencordSettings/shared";
import { proxyLazy } from "@utils/lazy";
import { Margins } from "@utils/margins";
@ -35,6 +32,32 @@ const TextAreaProps = findLazy(m => typeof m.textarea === "string");
const API_URL = "https://themes-delta.vercel.app/api";
async function fetchThemes(url: string): Promise<Theme[]> {
const response = await fetch(url);
const data = await response.json();
const themes: Theme[] = Object.values(data);
themes.forEach(theme => {
if (!theme.source) {
theme.source = `${API_URL}/${theme.name}`;
} else {
theme.source = theme.source.replace("?raw=true", "") + "?raw=true";
}
});
return themes.sort((a, b) => new Date(b.release_date).getTime() - new Date(a.release_date).getTime());
}
function API_TYPE(theme, returnAll?: boolean) {
if (!theme) return;
const settings = Settings.plugins.ThemeLibrary.domain ?? false;
if (returnAll) {
const url = settings ? "https://raw.githubusercontent.com/Faf4a/plugins/main/assets/meta.json" : `${API_URL}/themes`;
return fetchThemes(url);
} else {
return settings ? theme.source : `${API_URL}/${theme.name}`;
}
}
async function themeRequest(path: string, options: RequestInit = {}) {
return fetch(API_URL + path, {
...options,
@ -84,7 +107,7 @@ function ThemeTab() {
const onStatusChange = (status: SearchStatus) => setSearchValue(prev => ({ ...prev, status }));
const themeFilter = (theme: Theme) => {
const enabled = themeLinks.includes("https://themes-delta.vercel.app/api/" + theme.name);
const enabled = themeLinks.includes(API_TYPE(theme));
if (enabled && searchValue.status === SearchStatus.DISABLED) return false;
if (!theme.tags.includes("theme") && searchValue.status === SearchStatus.THEME) return false;
if (!theme.tags.includes("snippet") && searchValue.status === SearchStatus.SNIPPET) return false;
@ -103,15 +126,13 @@ function ThemeTab() {
};
useEffect(() => {
themeRequest("/themes", {
method: "GET",
}).then(async (response: Response) => {
const data = await response.json();
const themes: Theme[] = Object.values(data);
themes.sort((a, b) => new Date(b.release_date).getTime() - new Date(a.release_date).getTime());
Promise.resolve(API_TYPE({}, true)).then(themes => {
setThemes(themes);
setFilteredThemes(themes);
setLoading(false);
}).catch(err => {
console.error("Failed to load 'ThemeLibrary'", err);
setLoading(true);
});
}, []);
@ -119,6 +140,7 @@ function ThemeTab() {
setThemeLinks(Vencord.Settings.themeLinks);
}, [Vencord.Settings.themeLinks]);
useEffect(() => {
const filteredThemes = themes.filter(themeFilter);
setFilteredThemes(filteredThemes);
@ -161,7 +183,7 @@ function ThemeTab() {
overflowWrap: "break-word",
marginTop: 8,
}}
className="vce-theme-text">
className="vce-theme-text">
{theme.name}
</Forms.FormTitle>
<Forms.FormText className="vce-theme-text">
@ -182,10 +204,10 @@ function ThemeTab() {
</Forms.FormText>
)}
<div style={{ marginTop: "8px", display: "flex", flexDirection: "row" }}>
{themeLinks.includes("https://themes-delta.vercel.app/api/" + theme.name) ? (
{themeLinks.includes(API_TYPE(theme)) ? (
<Button
onClick={() => {
const onlineThemeLinks = themeLinks.filter(x => x !== "https://themes-delta.vercel.app/api/" + theme.name);
const onlineThemeLinks = themeLinks.filter(x => x !== API_TYPE(theme));
setThemeLinks(onlineThemeLinks);
Vencord.Settings.themeLinks = onlineThemeLinks;
}}
@ -199,7 +221,7 @@ function ThemeTab() {
) : (
<Button
onClick={() => {
const onlineThemeLinks = [...themeLinks, `https://themes-delta.vercel.app/api/${theme.name}`];
const onlineThemeLinks = [...themeLinks, API_TYPE(theme)];
setThemeLinks(onlineThemeLinks);
Vencord.Settings.themeLinks = onlineThemeLinks;
}}
@ -223,12 +245,13 @@ function ThemeTab() {
Theme Info
</Button>
<Button
onClick={() => VencordNative.native.openExternal(`https://themes-delta.vercel.app/api/${theme.name}`)}
onClick={() => VencordNative.native.openExternal(API_TYPE(theme).replace("?raw=true", ""))}
size={Button.Sizes.MEDIUM}
color={Button.Colors.LINK}
look={Button.Looks.LINK}
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}
>
View Source
View Source <OpenExternalIcon height={16} width={16} />
</Button>
</div>
</div>
@ -276,7 +299,7 @@ function ThemeTab() {
overflowWrap: "break-word",
marginTop: 8,
}}
className="vce-theme-text">
className="vce-theme-text">
{theme.name}
</Forms.FormTitle>
<Forms.FormText className="vce-theme-text">
@ -285,7 +308,8 @@ function ThemeTab() {
<img
role="presentation"
src={theme.thumbnail_url}
alt="Theme Preview Image"
loading="lazy"
alt={theme.name}
className="vce-theme-info-preview"
/>
<div className="vce-theme-info">
@ -303,10 +327,10 @@ function ThemeTab() {
</Forms.FormText>
)}
<div style={{ marginTop: "8px", display: "flex", flexDirection: "row" }}>
{themeLinks.includes("https://themes-delta.vercel.app/api/" + theme.name) ? (
{themeLinks.includes(API_TYPE(theme)) ? (
<Button
onClick={() => {
const onlineThemeLinks = themeLinks.filter(x => x !== "https://themes-delta.vercel.app/api/" + theme.name);
const onlineThemeLinks = themeLinks.filter(x => x !== API_TYPE(theme));
setThemeLinks(onlineThemeLinks);
Vencord.Settings.themeLinks = onlineThemeLinks;
}}
@ -320,7 +344,7 @@ function ThemeTab() {
) : (
<Button
onClick={() => {
const onlineThemeLinks = [...themeLinks, `https://themes-delta.vercel.app/api/${theme.name}`];
const onlineThemeLinks = [...themeLinks, API_TYPE(theme)];
setThemeLinks(onlineThemeLinks);
Vencord.Settings.themeLinks = onlineThemeLinks;
}}
@ -344,12 +368,13 @@ function ThemeTab() {
Theme Info
</Button>
<Button
onClick={() => VencordNative.native.openExternal(`https://themes-delta.vercel.app/api/${theme.name}`)}
onClick={() => VencordNative.native.openExternal(API_TYPE(theme).replace("?raw=true", ""))}
size={Button.Sizes.MEDIUM}
color={Button.Colors.LINK}
look={Button.Looks.LINK}
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}
>
View Source
View Source <OpenExternalIcon height={16} width={16} />
</Button>
</div>
</div>

View file

@ -1,5 +1,5 @@
/* stylelint-disable property-no-vendor-prefix */
[data-tab-id="ThemeLibrary"]::before {
/* stylelint-disable-next-line property-no-vendor-prefix */
-webkit-mask: var(--si-widget) center/contain no-repeat !important;
mask: var(--si-widget) center/contain no-repeat !important;
}
@ -23,8 +23,8 @@
}
.vce-theme-info-preview img {
width: 1080px;
height: 1920px;
width: 1080px !important;
height: 1920px !important;
object-fit: cover;
}

View file

@ -4,13 +4,32 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { EquicordDevs } from "@utils/constants";
import definePlugin from "@utils/types";
import { definePluginSettings } from "@api/Settings";
import definePlugin, { OptionType } from "@utils/types";
import { SettingsRouter } from "@webpack/common";
const settings = definePluginSettings({
domain: {
type: OptionType.BOOLEAN,
default: false,
description: "Use Github instead of the default domain for themes",
restartNeeded: false
},
});
export default definePlugin({
name: "Theme Library",
name: "ThemeLibrary",
description: "A library of themes for Vencord.",
authors: [EquicordDevs.Fafa],
authors: [{
name: "Fafa",
id: 428188716641812481n,
}],
settings,
toolboxActions: {
"Open Theme Library": () => {
SettingsRouter.open("ThemeLibrary");
}
},
start() {
const customSettingsSections = (
@ -35,5 +54,5 @@ export default definePlugin({
const i = customSettingsSections.findIndex(section => section({}).id === "ThemeSection");
if (i !== -1) customSettingsSections.splice(i, 1);
}
},
});

View file

@ -33,6 +33,7 @@ export interface Theme {
invite_link: string;
avatar_hash: string;
};
source?: string;
}
export interface ThemeInfoModalProps extends ModalProps {