From 74f9b1a02280ff5db78e656b8b972cf467cb3c28 Mon Sep 17 00:00:00 2001 From: Lewis Crichton Date: Sun, 10 Sep 2023 14:09:00 +0100 Subject: [PATCH] feat: each settings component handles state, + fix selects again lol --- src/components/ThemeSettings/ThemesTab.tsx | 4 ++- src/components/ThemeSettings/UserCSSModal.tsx | 35 +++++-------------- .../components/SettingBooleanComponent.tsx | 19 +++++++--- .../components/SettingColorComponent.tsx | 17 ++++++--- .../components/SettingNumberComponent.tsx | 17 ++++++--- .../components/SettingRangeComponent.tsx | 19 +++++++--- .../components/SettingSelectComponent.tsx | 17 ++++++--- .../components/SettingTextComponent.tsx | 17 ++++++--- src/utils/themes/usercss/compiler.ts | 5 --- 9 files changed, 88 insertions(+), 62 deletions(-) diff --git a/src/components/ThemeSettings/ThemesTab.tsx b/src/components/ThemeSettings/ThemesTab.tsx index 7dbdba2e7..84017e274 100644 --- a/src/components/ThemeSettings/ThemesTab.tsx +++ b/src/components/ThemeSettings/ThemesTab.tsx @@ -243,9 +243,11 @@ function ThemesTab() { switch (varInfo.type) { case "text": case "color": - case "select": normalizedValue = varInfo.default; break; + case "select": + normalizedValue = varInfo.options.find(v => v.name === varInfo.default)!.value; + break; case "checkbox": normalizedValue = varInfo.default ? "1" : "0"; break; diff --git a/src/components/ThemeSettings/UserCSSModal.tsx b/src/components/ThemeSettings/UserCSSModal.tsx index d041cd847..078934dca 100644 --- a/src/components/ThemeSettings/UserCSSModal.tsx +++ b/src/components/ThemeSettings/UserCSSModal.tsx @@ -7,7 +7,7 @@ import { useSettings } from "@api/Settings"; import { Flex } from "@components/Flex"; import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot } from "@utils/modal"; -import { Text, useState } from "@webpack/common"; +import { Text } from "@webpack/common"; import type { ReactNode } from "react"; import { UserstyleHeader } from "usercss-meta"; @@ -24,98 +24,79 @@ export function UserCSSSettingsModal({ modalProps, theme }: UserCSSSettingsModal const controls: ReactNode[] = []; - function updateSetting(key: string, value: string, setValue: (value: string) => void) { + function updateSetting(key: string, value: string) { 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( updateSetting(name, v, setValue)} + themeSettings={themeSettings} /> ); break; } case "checkbox": { - const [value, setValue] = useState(themeSettings[name]); - controls.push( updateSetting(name, v, setValue)} + themeSettings={themeSettings} /> ); break; } case "color": { - const [value, setValue] = useState(themeSettings[name]); - controls.push( updateSetting(name, v, setValue)} + themeSettings={themeSettings} /> ); break; } case "number": { - const [value, setValue] = useState(themeSettings[name]); - controls.push( updateSetting(name, v, setValue)} + themeSettings={themeSettings} /> ); break; } case "select": { - const [value, setValue] = useState(themeSettings[name]); - controls.push( updateSetting(name, v, setValue)} + themeSettings={themeSettings} /> ); break; } case "range": { - const [value, setValue] = useState(themeSettings[name]); - controls.push( updateSetting(name, v, setValue)} + themeSettings={themeSettings} /> ); break; diff --git a/src/components/ThemeSettings/components/SettingBooleanComponent.tsx b/src/components/ThemeSettings/components/SettingBooleanComponent.tsx index 7a6e822d2..a0d3239b6 100644 --- a/src/components/ThemeSettings/components/SettingBooleanComponent.tsx +++ b/src/components/ThemeSettings/components/SettingBooleanComponent.tsx @@ -4,22 +4,31 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Forms, Switch } from "@webpack/common"; +import { Forms, Switch, useState } from "@webpack/common"; interface Props { label: string; name: string; - value: string; - onChange: (value: string) => void; + themeSettings: Record; } -export function SettingBooleanComponent({ label, name, value, onChange }: Props) { +export function SettingBooleanComponent({ label, name, themeSettings }: Props) { + const [value, setValue] = useState(themeSettings[name]); + + function handleChange(value: boolean) { + const corrected = value ? "1" : "0"; + + setValue(corrected); + + themeSettings[name] = corrected; + } + return ( onChange(v ? "1" : "0")} + onChange={handleChange} hideBorder style={{ marginBottom: "0.5em" }} > diff --git a/src/components/ThemeSettings/components/SettingColorComponent.tsx b/src/components/ThemeSettings/components/SettingColorComponent.tsx index 93e9b720a..9b2befc0a 100644 --- a/src/components/ThemeSettings/components/SettingColorComponent.tsx +++ b/src/components/ThemeSettings/components/SettingColorComponent.tsx @@ -55,11 +55,20 @@ function ColorPicker(props: ColorPickerProps) { interface Props { label: string; name: string; - value: string; - onChange: (value: string) => void; + themeSettings: Record; } -export function SettingColorComponent({ label, name, value, onChange }: Props) { +export function SettingColorComponent({ label, name, themeSettings }: Props) { + const [value, setValue] = useState(themeSettings[name]); + + function handleChange(value: number) { + const corrected = "#" + (value?.toString(16).padStart(6, "0") ?? "000000"); + + setValue(corrected); + + themeSettings[name] = corrected; + } + const normalizedValue = TinyColor(value).toHex(); return ( @@ -68,7 +77,7 @@ export function SettingColorComponent({ label, name, value, onChange }: Props) { onChange("#" + (v?.toString(16).padStart(6, "0") ?? "000000"))} + onChange={handleChange} /> ); diff --git a/src/components/ThemeSettings/components/SettingNumberComponent.tsx b/src/components/ThemeSettings/components/SettingNumberComponent.tsx index 24fc1058a..35f57ed44 100644 --- a/src/components/ThemeSettings/components/SettingNumberComponent.tsx +++ b/src/components/ThemeSettings/components/SettingNumberComponent.tsx @@ -4,16 +4,23 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Forms, TextInput } from "@webpack/common"; +import { Forms, TextInput, useState } from "@webpack/common"; interface Props { label: string; name: string; - value: string; - onChange: (value: string) => void; + themeSettings: Record; } -export function SettingNumberComponent({ label, name, value, onChange }: Props) { +export function SettingNumberComponent({ label, name, themeSettings }: Props) { + const [value, setValue] = useState(themeSettings[name]); + + function handleChange(value: string) { + setValue(value); + + themeSettings[name] = value; + } + return ( {label} @@ -22,7 +29,7 @@ export function SettingNumberComponent({ label, name, value, onChange }: Props) pattern="-?[0-9]+" key={name} value={value} - onChange={onChange} + onChange={handleChange} /> ); diff --git a/src/components/ThemeSettings/components/SettingRangeComponent.tsx b/src/components/ThemeSettings/components/SettingRangeComponent.tsx index c47346256..ac2746824 100644 --- a/src/components/ThemeSettings/components/SettingRangeComponent.tsx +++ b/src/components/ThemeSettings/components/SettingRangeComponent.tsx @@ -4,20 +4,29 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Forms, Slider } from "@webpack/common"; +import { Forms, Slider, useState } from "@webpack/common"; interface Props { label: string; name: string; - value: string; default: number; min?: number; max?: number; step?: number; - onChange: (value: string) => void; + themeSettings: Record; } -export function SettingRangeComponent({ label, name, value, default: def, min, max, step, onChange }: Props) { +export function SettingRangeComponent({ label, name, default: def, min, max, step, themeSettings }: Props) { + const [value, setValue] = useState(themeSettings[name]); + + function handleChange(value: number) { + const corrected = value.toString(); + + setValue(corrected); + + themeSettings[name] = corrected; + } + const markers: number[] = []; // defaults taken from https://github.com/openstyles/stylus/wiki/Writing-UserCSS#default-value @@ -31,7 +40,7 @@ export function SettingRangeComponent({ label, name, value, default: def, min, m onChange(v.toString())} + onValueChange={handleChange} minValue={min} maxValue={max} diff --git a/src/components/ThemeSettings/components/SettingSelectComponent.tsx b/src/components/ThemeSettings/components/SettingSelectComponent.tsx index 2ce5c2a3c..5e20a958b 100644 --- a/src/components/ThemeSettings/components/SettingSelectComponent.tsx +++ b/src/components/ThemeSettings/components/SettingSelectComponent.tsx @@ -5,7 +5,7 @@ */ import { identity } from "@utils/misc"; -import { ComponentTypes, Forms, Select } from "@webpack/common"; +import { ComponentTypes, Forms, Select, useState } from "@webpack/common"; interface Props { label: string; @@ -15,12 +15,19 @@ interface Props { label: string; value: string; }[]; - value: string; default: string; - onChange: (value: string) => void; + themeSettings: Record; } -export function SettingSelectComponent({ label, name, options, value, default: def, onChange }: Props) { +export function SettingSelectComponent({ label, name, options, default: def, themeSettings }: Props) { + const [value, setValue] = useState(themeSettings[name]); + + function handleChange(value: string) { + setValue(value); + + themeSettings[name] = value; + } + const opts = options.map(option => ({ disabled: false, @@ -39,7 +46,7 @@ export function SettingSelectComponent({ label, name, options, value, default: d options={opts} closeOnSelect={true} - select={onChange} + select={handleChange} isSelected={v => v === value} serialize={identity} /> diff --git a/src/components/ThemeSettings/components/SettingTextComponent.tsx b/src/components/ThemeSettings/components/SettingTextComponent.tsx index fb74b036a..a568d6336 100644 --- a/src/components/ThemeSettings/components/SettingTextComponent.tsx +++ b/src/components/ThemeSettings/components/SettingTextComponent.tsx @@ -4,23 +4,30 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Forms, TextInput } from "@webpack/common"; +import { Forms, TextInput, useState } from "@webpack/common"; interface Props { label: string; name: string; - value: string; - onChange: (value: string) => void; + themeSettings: Record; } -export function SettingTextComponent({ label, name, value, onChange }: Props) { +export function SettingTextComponent({ label, name, themeSettings }: Props) { + const [value, setValue] = useState(themeSettings[name]); + + function handleChange(value: string) { + setValue(value); + + themeSettings[name] = value; + } + return ( {label} ); diff --git a/src/utils/themes/usercss/compiler.ts b/src/utils/themes/usercss/compiler.ts index 30cbe9ad4..5acfc805b 100644 --- a/src/utils/themes/usercss/compiler.ts +++ b/src/utils/themes/usercss/compiler.ts @@ -88,11 +88,6 @@ export async function compileUsercss(fileName: string) { varsToPass[k] = `${varsToPass[k]}${v.units ?? "px"}`; break; } - - case "select": { - varsToPass[k] = v.options.find(opt => opt.name === varsToPass[k])!.value; - break; - } } }