diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/ThemeSettings/ThemesTab.tsx similarity index 68% rename from src/components/VencordSettings/ThemesTab.tsx rename to src/components/ThemeSettings/ThemesTab.tsx index efb061cb..7dbdba2e 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/ThemeSettings/ThemesTab.tsx @@ -16,25 +16,28 @@ * along with this program. If not, see . */ +import "./themesStyles.css"; + import { Settings, useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import { Flex } from "@components/Flex"; import { Link } from "@components/Link"; +import { AddonCard } from "@components/VencordSettings/AddonCard"; +import { SettingsTab, wrapTab } from "@components/VencordSettings/shared"; import { Margins } from "@utils/margins"; -import { classes, identity } from "@utils/misc"; -import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; +import { classes } from "@utils/misc"; +import { openModal } from "@utils/modal"; import { showItemInFolder } from "@utils/native"; -import { LazyComponent, useAwaiter } from "@utils/react"; +import { useAwaiter } from "@utils/react"; import type { ThemeHeader } from "@utils/themes"; import { getThemeInfo, stripBOM, type UserThemeHeader } from "@utils/themes/bd"; import { usercssParse } from "@utils/themes/usercss"; -import { find, findByCodeLazy, findByPropsLazy, findLazy } from "@webpack"; -import { Button, Card, ComponentTypes, FluxDispatcher, Forms, Popout, React, Select, showToast, Slider, Switch, TabBar, Text, TextArea, TextInput, useEffect, useRef, useState } from "@webpack/common"; -import type { ComponentType, ReactNode, Ref, SyntheticEvent } from "react"; +import { findByCodeLazy, findByPropsLazy, findLazy } from "@webpack"; +import { Button, Card, FluxDispatcher, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common"; +import type { ComponentType, Ref, SyntheticEvent } from "react"; import type { UserstyleHeader } from "usercss-meta"; -import { AddonCard } from "./AddonCard"; -import { SettingsTab, wrapTab } from "./shared"; +import { UserCSSSettingsModal } from "./UserCSSModal"; type FileInput = ComponentType<{ ref: Ref; @@ -43,22 +46,13 @@ type FileInput = ComponentType<{ filters?: { name?: string; extensions: string[]; }[]; }>; -interface ColorPickerProps { - value: number | null; - showEyeDropper?: boolean; - onChange(value: number | null): void; - onClose?(): void; -} -const ColorPickerModal = LazyComponent(() => find(m => m?.type?.toString?.().includes(".showEyeDropper"))); const InviteActions = findByPropsLazy("resolveInvite"); const TrashIcon = findByCodeLazy("M5 6.99902V18.999C5 20.101 5.897 20.999"); const CogWheel = findByCodeLazy("18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069"); const FileInput: FileInput = findByCodeLazy("activateUploadDialogue="); -const EditPencil = findByCodeLazy("M19.2929 9.8299L19.9409 9.18278C21.353 7.77064", '["color","height","width"]'); -// TinyColor is completely unmangled and it's duplicated in two modules! Fun! -const TinyColor: tinycolor.Constructor = findByCodeLazy("this._gradientType="); + const TextAreaProps = findLazy(m => typeof m.textarea === "string"); const cl = classNameFactory("vc-settings-theme-"); @@ -112,194 +106,6 @@ function Validators({ themeLinks }: { themeLinks: string[]; }) { ); } -function ColorPicker(props: ColorPickerProps) { - const [color, setColor] = useState(props.value); - - const correctedColor = color ? `#${color.toString(16).padStart(6, "0")}` : "#000000"; - - return ( - ( - { setColor(value); props.onChange(value); }} showEyeDropper={props.showEyeDropper} /> - )} - > - {popoutProps => ( -
- -
- )} -
- ); -} - -interface UserCSSSettingsModalProps { - modalProps: ModalProps; - theme: UserstyleHeader; -} - -function UserCSSSettingsModal({ modalProps, theme }: UserCSSSettingsModalProps) { - // @ts-expect-error UseSettings<> can't determine this is a valid key - const themeSettings = useSettings(["userCssVars"], false).userCssVars[theme.id]; - - const controls: ReactNode[] = []; - - function updateSetting(key: string, value: string, setValue: (value: string) => void) { - themeSettings[key] = value; - setValue(value); - } - - for (const [name, varInfo] of Object.entries(theme.vars)) { - switch (varInfo.type) { - case "text": { - const [value, setValue] = useState(themeSettings[name]); - - controls.push( - - {varInfo.label} - updateSetting(name, v, setValue)} - /> - - ); - break; - } - - case "checkbox": { - const [value, setValue] = useState(themeSettings[name]); - - controls.push( - - updateSetting(name, value ? "1" : "0", setValue)} - hideBorder - style={{ marginBottom: "0.5em" }} - > - {varInfo.label} - - - ); - break; - } - - case "color": { - const [value, setValue] = useState(themeSettings[name]); - - const normalizedValue = TinyColor(value).toHex(); - - controls.push( - - {varInfo.label} - updateSetting(name, "#" + (v?.toString(16).padStart(6, "0") ?? "000000"), setValue)} - /> - - ); - break; - } - - case "number": { - const [value, setValue] = useState(themeSettings[name]); - - controls.push( - - {varInfo.label} - updateSetting(name, v, setValue)} - /> - - ); - break; - } - - case "select": { - const [value, setValue] = useState(themeSettings[name]); - - const options = varInfo.options.map(option => ({ - disabled: false, - - key: option.name, - value: option.value, - default: varInfo.default === option.name, - label: option.label - } as ComponentTypes.SelectOption)); - - controls.push( - - {varInfo.label} - v === value} + serialize={identity} + /> + + ); +} diff --git a/src/components/ThemeSettings/components/SettingTextComponent.tsx b/src/components/ThemeSettings/components/SettingTextComponent.tsx new file mode 100644 index 00000000..fb74b036 --- /dev/null +++ b/src/components/ThemeSettings/components/SettingTextComponent.tsx @@ -0,0 +1,27 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Forms, TextInput } from "@webpack/common"; + +interface Props { + label: string; + name: string; + value: string; + onChange: (value: string) => void; +} + +export function SettingTextComponent({ label, name, value, onChange }: Props) { + return ( + + {label} + + + ); +} diff --git a/src/components/ThemeSettings/components/colorStyles.css b/src/components/ThemeSettings/components/colorStyles.css new file mode 100644 index 00000000..53a88e95 --- /dev/null +++ b/src/components/ThemeSettings/components/colorStyles.css @@ -0,0 +1,20 @@ +.vc-usercss-settings-color-swatch { + display: flex; + align-items: center; + justify-content: center; + width: 69px; + height: 50px; + box-sizing: border-box; + position: relative; + border: 1px solid; + border-radius: 4px; + cursor: pointer; +} + +.vc-usercss-settings-color-swatch-pencil { + position: absolute; + top: 4px; + right: 4px; + width: 14px; + height: 14px; +} diff --git a/src/components/ThemeSettings/components/index.ts b/src/components/ThemeSettings/components/index.ts new file mode 100644 index 00000000..8b9f48cd --- /dev/null +++ b/src/components/ThemeSettings/components/index.ts @@ -0,0 +1,12 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +export * from "./SettingBooleanComponent"; +export * from "./SettingColorComponent"; +export * from "./SettingNumberComponent"; +export * from "./SettingRangeComponent"; +export * from "./SettingSelectComponent"; +export * from "./SettingTextComponent"; diff --git a/src/components/VencordSettings/themesStyles.css b/src/components/ThemeSettings/themesStyles.css similarity index 62% rename from src/components/VencordSettings/themesStyles.css rename to src/components/ThemeSettings/themesStyles.css index 938d8f34..6038274f 100644 --- a/src/components/VencordSettings/themesStyles.css +++ b/src/components/ThemeSettings/themesStyles.css @@ -27,24 +27,3 @@ .vc-settings-theme-author::before { content: "by "; } - -.vc-settings-theme-usercss-swatch { - display: flex; - align-items: center; - justify-content: center; - width: 69px; - height: 50px; - box-sizing: border-box; - position: relative; - border: 1px solid; - border-radius: 4px; - cursor: pointer; -} - -.vc-settings-theme-usercss-swatch-pencil { - position: absolute; - top: 4px; - right: 4px; - width: 14px; - height: 14px; -} diff --git a/src/components/VencordSettings/shared.tsx b/src/components/VencordSettings/shared.tsx index 6dd34c46..0d3910df 100644 --- a/src/components/VencordSettings/shared.tsx +++ b/src/components/VencordSettings/shared.tsx @@ -17,7 +17,6 @@ */ import "./settingsStyles.css"; -import "./themesStyles.css"; import ErrorBoundary from "@components/ErrorBoundary"; import { handleComponentFailed } from "@components/handleComponentFailed"; diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 88ebb578..670e8fcf 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -100,7 +100,7 @@ export default definePlugin({ { section: "VencordThemes", label: "Themes", - element: require("@components/VencordSettings/ThemesTab").default, + element: require("@components/ThemeSettings/ThemesTab").default, className: "vc-themes" }, !IS_UPDATER_DISABLED && {