diff --git a/client/ui/preference/PreferenceStore.ts b/client/ui/preference/PreferenceStore.ts index a51cea1..f4e14b5 100644 --- a/client/ui/preference/PreferenceStore.ts +++ b/client/ui/preference/PreferenceStore.ts @@ -1,26 +1,26 @@ import React from 'react' export default class PreferenceStore { - declare value: T - declare setter: React.Dispatch> - declare onUpdate: (value: unknown) => void + declare onUpdate: (value: T) => void + declare state: T + declare setState: React.Dispatch> constructor() { - const _ = React.useState({} as T) - this.value = _[0] - this.setter = _[1] + const _ = React.useState({} as T) + this.state = _[0] + this.setState = _[1] } - // 创建一个用于子选项的更新函数 - updater(key: string) { - return (value: unknown) => { - const newValue = JSON.parse(JSON.stringify({ - ...this.value, + + createUpdater() { + return (key: string, value: unknown) => { + const newValue = { + ...this.state, [key]: value, - })) - this.setter(newValue) + } + this.setState(newValue) this.onUpdate?.(newValue) } } - setOnUpdate(onUpdate: (value: unknown) => void) { + setOnUpdate(onUpdate: (value: T) => void) { this.onUpdate = onUpdate } } diff --git a/client/ui/preference/PreferenceUpdater.ts b/client/ui/preference/PreferenceUpdater.ts new file mode 100644 index 0000000..70b30c2 --- /dev/null +++ b/client/ui/preference/PreferenceUpdater.ts @@ -0,0 +1,6 @@ +import React from 'react' + +// deno-lint-ignore no-explicit-any +const PreferenceUpdater = React.createContext<(key: string, value: unknown) => void>(null as any) + +export default PreferenceUpdater diff --git a/client/ui/preference/SelectPreference.tsx b/client/ui/preference/SelectPreference.tsx index 5cdb36a..05722a6 100644 --- a/client/ui/preference/SelectPreference.tsx +++ b/client/ui/preference/SelectPreference.tsx @@ -1,18 +1,19 @@ import React from 'react' import { Dropdown } from 'mdui' import useEventListener from '../useEventListener.ts' +import PreferenceUpdater from "./PreferenceUpdater.ts" interface Args extends React.HTMLAttributes { title: string icon: string + id: string disabled?: boolean - updater: (value: unknown) => void selections: { [id: string]: string } - defaultCheckedId: string + state: string } -export default function SelectPreference({ title, icon, updater, selections, defaultCheckedId, disabled }: Args) { - const [checkedId, setCheckedId] = React.useState(defaultCheckedId) +export default function SelectPreference({ title, icon, id: preferenceId, selections, state, disabled }: Args) { + const updater = React.useContext(PreferenceUpdater) const dropDownRef = React.useRef(null) const [isDropDownOpen, setDropDownOpen] = React.useState(false) @@ -30,14 +31,13 @@ export default function SelectPreference({ title, icon, updater, selections, def { Object.keys(selections).map((id) => // @ts-ignore: selected 确实存在, 但是并不对外公开使用 - { - setCheckedId(id) - updater(id) + { + updater(preferenceId, id) }}>{selections[id]} ) } - {selections[checkedId]} + {selections[state]} } \ No newline at end of file diff --git a/client/ui/preference/SwitchPreference.tsx b/client/ui/preference/SwitchPreference.tsx index 98d0002..2d072d4 100644 --- a/client/ui/preference/SwitchPreference.tsx +++ b/client/ui/preference/SwitchPreference.tsx @@ -1,25 +1,27 @@ import { Switch } from 'mdui' import React from 'react' +import PreferenceUpdater from "./PreferenceUpdater.ts" interface Args extends React.HTMLAttributes { title: string + id: string description?: string icon: string - updater: (value: unknown) => void - defaultState: boolean + state: boolean disabled?: boolean } -export default function SwitchPreference({ title, icon, updater, disabled, description, defaultState }: Args) { +export default function SwitchPreference({ title, icon, id, disabled, description, state }: Args) { + const updater = React.useContext(PreferenceUpdater) + const switchRef = React.useRef(null) React.useEffect(() => { - switchRef.current!.checked = defaultState - }, [defaultState]) + switchRef.current!.checked = state + }, [state]) return { - switchRef.current!.checked = !switchRef.current!.checked - updater(switchRef.current!.checked) + updater(id, !state) }}> {title} {description && {description}} diff --git a/client/ui/preference/TextFieldPreference.tsx b/client/ui/preference/TextFieldPreference.tsx index d01fb1d..424be9b 100644 --- a/client/ui/preference/TextFieldPreference.tsx +++ b/client/ui/preference/TextFieldPreference.tsx @@ -1,17 +1,18 @@ import React from 'react' import { prompt } from 'mdui' +import PreferenceUpdater from "./PreferenceUpdater.ts" interface Args extends React.HTMLAttributes { title: string description?: string icon: string - updater: (value: unknown) => void - defaultState: string + id: string + state: string disabled?: boolean } -export default function TextFieldPreference({ title, icon, description, updater, defaultState, disabled }: Args) { - const [ text, setText ] = React.useState(defaultState) +export default function TextFieldPreference({ title, icon, description, id, state, disabled }: Args) { + const updater = React.useContext(PreferenceUpdater) return { prompt({ @@ -19,13 +20,12 @@ export default function TextFieldPreference({ title, icon, description, updater, confirmText: "确定", cancelText: "取消", onConfirm: (value) => { - setText(value) - updater(value) + updater(id, value) }, onCancel: () => {}, textFieldOptions: { label: description, - value: text, + value: state, }, }) }}>