import { toRaw } from "vue" ; import { enablePatches , enableMapSet , Immer } from "immer" ; import { enablePatches as enablePatchesImpl } from "immer/src/plugins/patches" ; import { enableMapSet as enableMapSetImpl } from "immer/src/plugins/mapset" ; import { getPlugin } from "immer/src/utils/plugins" ; import { Command , CommandActions , CommandGetters , CommandMutations , CommandStoreState , VoiceVoxStoreOptions , } from "./type" ; import { Mutation , MutationsBase , MutationTree } from "@/store/vuex" ; enablePatches ( ) ; enableMapSet ( ) ; enablePatchesImpl ( ) ; enableMapSetImpl ( ) ; const applyPatchesImpl = getPlugin ( "Patches" ) . applyPatches_ ; const immer = new Immer ( ) ; immer . setAutoFreeze ( false ) ; export type PayloadRecipe < S , P > = ( draft : S , payload : P ) => void ; export type PayloadRecipeTree < S , M > = { [ K in keyof M ] : PayloadRecipe < S , M [ K ] > ; } ; interface UndoRedoState { undoCommands : Command [ ] ; redoCommands : Command [ ] ; } param payloadRecipeTree returns export const createCommandMutationTree = < S extends UndoRedoState , M extends MutationsBase > ( payloadRecipeTree ) : MutationTree < S , M > => Object . fromEntries ( Object . entries ( payloadRecipeTree ) . map ( ( [ key , val ] ) => [ key , createCommandMutation ( val ) , ] ) ) as MutationTree < S , M > ; param payloadRecipe returns export const createCommandMutation = < S extends UndoRedoState , P > ( payloadRecipe ) : Mutation < S , P > => ( state , payload ) : void => { const command = recordPatches ( payloadRecipe ) ( state , payload ) ; applyPatchesImpl ( state , command . redoPatches ) ; state . undoCommands . push ( command ) ; state . redoCommands . splice ( 0 ) ; } ; param recipe returns const recordPatches = < S , P > ( recipe ) => ( state , payload ) : Command => { const [ , doPatches , undoPatches ] = immer . produceWithPatches ( toRaw ( state ) as S , ( draft ) => recipe ( draft , payload ) ) ; return { unixMillisec : new Date ( ) . getTime ( ) , redoPatches : doPatches , undoPatches : undoPatches , } ; } ; export const commandStoreState = { undoCommands : [ ] , redoCommands : [ ] , } ; export const commandStore = { getters : { CAN_UNDO ( state ) { return state . undoCommands . length > 0 ; } , CAN_REDO ( state ) { return state . redoCommands . length > 0 ; } , LAST_COMMAND_UNIX_MILLISEC ( state ) { if ( state . undoCommands . length === 0 ) { return null ; } else { return state . undoCommands [ state . undoCommands . length - 1 ] . unixMillisec ; } } , } , mutations : { UNDO ( state ) { const command = state . undoCommands . pop ( ) ; if ( command != null ) { state . redoCommands . push ( command ) ; applyPatchesImpl ( state , command . undoPatches ) ; } } , REDO ( state ) { const command = state . redoCommands . pop ( ) ; if ( command != null ) { state . undoCommands . push ( command ) ; applyPatchesImpl ( state , command . redoPatches ) ; } } , CLEAR_COMMANDS ( state ) { state . redoCommands . splice ( 0 ) ; state . undoCommands . splice ( 0 ) ; } , } , actions : { UNDO ( { commit } ) { commit ( "UNDO" ) ; } , REDO ( { commit } ) { commit ( "REDO" ) ; } , } , } ;