Update settings page

This commit is contained in:
2023-05-27 11:15:04 +08:00
parent 7ef2014fec
commit 21a17dd9d7
5 changed files with 187 additions and 28 deletions

View File

@@ -4,26 +4,40 @@ import { ConfigType } from "../config.ts";
import TextField from "preact-material-components/TextField";
import { Ref, StateUpdater, useRef } from "preact/hooks";
export type SettingsTextProps = {
value: string;
interface TextType {
text: string;
password: string;
number: number;
}
interface DataType {
text: never;
password: never;
number: number;
}
export type SettingsTextProps<T extends keyof TextType> = {
value: TextType[T];
name: keyof ConfigType;
description: string;
type: T;
label?: string;
helpertext?: string;
textarea?: boolean;
fullwidth?: boolean;
disabled?: boolean;
children?: ComponentChildren;
set_value?: StateUpdater<string>;
ignore_update_value?: boolean;
set_value?: StateUpdater<TextType[T]>;
min?: DataType[T];
max?: DataType[T];
};
export default class SettingsText
extends Component<SettingsTextProps, unknown> {
export default class SettingsText<T extends keyof TextType>
extends Component<SettingsTextProps<T>, unknown> {
static contextType = SettingsCtx;
ref: Ref<TextField | undefined> | undefined;
declare context: ContextType<typeof SettingsCtx>;
update(value: string) {
update(value: TextType[T]) {
const e = this.ref?.current;
if (e) {
const b = e.base;
@@ -31,7 +45,11 @@ export default class SettingsText
const t = b as HTMLElement;
const d = t.querySelector("input");
if (d) {
d.value = value;
const type = this.props.type;
// @ts-ignore Checked
if (type === "text" || type === "password") d.value = value;
// @ts-ignore Checked
else d.valueAsNumber = value;
}
}
}
@@ -44,7 +62,7 @@ export default class SettingsText
});
}
}
set_text(value: string) {
set_value(value: TextType[T]) {
if (this.props.set_value) {
this.props.set_value(value);
this.set_changed();
@@ -60,14 +78,21 @@ export default class SettingsText
}
}
componentDidMount() {
if (!this.props.ignore_update_value) this.update(this.props.value);
this.update(this.props.value);
}
componentWillUpdate(
nextProps: Readonly<SettingsTextProps>,
nextProps: Readonly<SettingsTextProps<T>>,
_nextState: Readonly<unknown>,
_nextContext: unknown,
) {
if (!this.props.ignore_update_value) this.update(nextProps.value);
this.update(nextProps.value);
}
get_value(e: HTMLInputElement): TextType[T] {
const type = this.props.type;
// @ts-ignore Checked
if (type === "text" || type === "password") return e.value;
// @ts-ignore Checked
return e.valueAsNumber;
}
render() {
this.ref = useRef<TextField>();
@@ -78,7 +103,7 @@ export default class SettingsText
<TextField
fullwidth={this.props.fullwidth}
textarea={this.props.textarea}
type="text"
type={this.props.type}
disabled={this.props.disabled}
helperText={this.props.helpertext}
label={this.props.label}
@@ -86,9 +111,11 @@ export default class SettingsText
onInput={(ev: InputEvent) => {
if (ev.target) {
const e = ev.target as HTMLInputElement;
this.set_text(e.value);
this.set_value(this.get_value(e));
}
}}
min={this.props.min}
max={this.props.max}
/>
{this.props.children}
</div>