feat: each settings component handles state, + fix selects again lol

This commit is contained in:
Lewis Crichton 2023-09-10 14:09:00 +01:00
parent 482caf0c5b
commit 74f9b1a022
No known key found for this signature in database
9 changed files with 88 additions and 62 deletions

View file

@ -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;

View file

@ -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(
<SettingTextComponent
label={varInfo.label}
name={name}
value={value}
onChange={v => updateSetting(name, v, setValue)}
themeSettings={themeSettings}
/>
);
break;
}
case "checkbox": {
const [value, setValue] = useState(themeSettings[name]);
controls.push(
<SettingBooleanComponent
label={varInfo.label}
name={name}
value={value}
onChange={v => updateSetting(name, v, setValue)}
themeSettings={themeSettings}
/>
);
break;
}
case "color": {
const [value, setValue] = useState(themeSettings[name]);
controls.push(
<SettingColorComponent
label={varInfo.label}
name={name}
value={value}
onChange={v => updateSetting(name, v, setValue)}
themeSettings={themeSettings}
/>
);
break;
}
case "number": {
const [value, setValue] = useState(themeSettings[name]);
controls.push(
<SettingNumberComponent
label={varInfo.label}
name={name}
value={value}
onChange={v => updateSetting(name, v, setValue)}
themeSettings={themeSettings}
/>
);
break;
}
case "select": {
const [value, setValue] = useState(themeSettings[name]);
controls.push(
<SettingSelectComponent
label={varInfo.label}
name={name}
options={varInfo.options}
value={value}
default={varInfo.default}
onChange={v => updateSetting(name, v, setValue)}
themeSettings={themeSettings}
/>
);
break;
}
case "range": {
const [value, setValue] = useState(themeSettings[name]);
controls.push(
<SettingRangeComponent
label={varInfo.label}
name={name}
value={value}
default={varInfo.default}
min={varInfo.min}
max={varInfo.max}
step={varInfo.step}
onChange={v => updateSetting(name, v, setValue)}
themeSettings={themeSettings}
/>
);
break;

View file

@ -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<string, string>;
}
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 (
<Forms.FormSection>
<Switch
key={name}
value={value === "1"}
onChange={v => onChange(v ? "1" : "0")}
onChange={handleChange}
hideBorder
style={{ marginBottom: "0.5em" }}
>

View file

@ -55,11 +55,20 @@ function ColorPicker(props: ColorPickerProps) {
interface Props {
label: string;
name: string;
value: string;
onChange: (value: string) => void;
themeSettings: Record<string, string>;
}
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) {
<ColorPicker
key={name}
value={parseInt(normalizedValue, 16)}
onChange={v => onChange("#" + (v?.toString(16).padStart(6, "0") ?? "000000"))}
onChange={handleChange}
/>
</Forms.FormSection>
);

View file

@ -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<string, string>;
}
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 (
<Forms.FormSection>
<Forms.FormTitle tag="h5">{label}</Forms.FormTitle>
@ -22,7 +29,7 @@ export function SettingNumberComponent({ label, name, value, onChange }: Props)
pattern="-?[0-9]+"
key={name}
value={value}
onChange={onChange}
onChange={handleChange}
/>
</Forms.FormSection>
);

View file

@ -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<string, string>;
}
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
<Slider
initialValue={parseInt(value, 10)}
defaultValue={def}
onValueChange={v => onChange(v.toString())}
onValueChange={handleChange}
minValue={min}
maxValue={max}

View file

@ -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<string, string>;
}
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}
/>

View file

@ -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<string, string>;
}
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 (
<Forms.FormSection>
<Forms.FormTitle tag="h5">{label}</Forms.FormTitle>
<TextInput
key={name}
value={value}
onChange={onChange}
onChange={handleChange}
/>
</Forms.FormSection>
);

View file

@ -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;
}
}
}