/* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ import { computed, Reactive, reactive, watch } from 'vue'; function copy(v: T): T { return JSON.parse(JSON.stringify(v)); } function unwrapReactive(v: Reactive): T { return JSON.parse(JSON.stringify(v)); } export function useForm>(initialState: T, save: (newState: T) => Promise) { const currentState = reactive(copy(initialState)); const previousState = reactive(copy(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] = currentState[key] !== previousState[key]; } }, { deep: true }); async function _save() { await save(unwrapReactive(currentState)); for (const key in currentState) { previousState[key] = copy(currentState[key]); } } function discard() { for (const key in currentState) { currentState[key] = copy(previousState[key]); } } return { state: currentState, savedState: previousState, modifiedStates, modified, modifiedCount, save: _save, discard, }; }