/* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ import { computed, reactive, watch, toRaw } from 'vue'; import { deepEqual } from '@/utility/deep-equal.js'; import { deepClone } from '@/utility/clone.js'; export function useForm>(initialState: T, save: (newState: T) => Promise) { const currentState = reactive(deepClone(initialState)); const previousState = reactive(deepClone(initialState)); const modifiedStates = reactive>({} as any); for (const key in currentState) { modifiedStates[key] = false; } const modified = computed(() => Object.values(modifiedStates).some(v => v)); const modifiedCount = computed(() => Object.values(modifiedStates).filter(v => v).length); watch([currentState, previousState], () => { for (const key in modifiedStates) { modifiedStates[key] = !deepEqual(currentState[key], previousState[key]); } }, { deep: true }); async function _save() { await save(toRaw(currentState) as T); for (const key in currentState) { previousState[key] = deepClone(currentState[key]); } } function discard() { for (const key in currentState) { currentState[key] = deepClone(previousState[key]); } } return { state: currentState, savedState: previousState, modifiedStates, modified, modifiedCount, save: _save, discard, }; }