import DiffMatchPatch from 'diff-match-patch'; import moduleTemplate from './moduleTemplate'; import empty from '../data/emptyContent'; import utils from '../services/utils'; import cledit from '../services/cledit'; const diffMatchPatch = new DiffMatchPatch(); const module = moduleTemplate(empty); module.state = { ...module.state, revisionContent: null, }; module.mutations = { ...module.mutations, setRevisionContent: (state, value) => { if (value) { state.revisionContent = { ...empty(), ...value, id: utils.uid(), hash: Date.now(), }; } else { state.revisionContent = null; } }, }; module.getters = { ...module.getters, current: (state, getters, rootState, rootGetters) => { if (state.revisionContent) { return state.revisionContent; } return state.itemMap[`${rootGetters['file/current'].id}/content`] || empty(); }, currentChangeTrigger: (state, getters) => { const { current } = getters; return utils.serializeObject([ current.id, current.text, current.hash, ]); }, currentProperties: (state, getters) => utils.computeProperties(getters.current.properties), isCurrentEditable: (state, getters, rootState, rootGetters) => !state.revisionContent && getters.current.id && rootGetters['layout/styles'].showEditor, }; module.actions = { ...module.actions, patchCurrent({ state, getters, commit }, value) { const { id } = getters.current; if (id && !state.revisionContent) { commit('patchItem', { ...value, id, }); } }, setRevisionContent({ state, rootGetters, commit }, value) { const currentFile = rootGetters['file/current']; const currentContent = state.itemMap[`${currentFile.id}/content`]; if (currentContent) { const diffs = diffMatchPatch.diff_main(currentContent.text, value.text); diffMatchPatch.diff_cleanupSemantic(diffs); commit('setRevisionContent', { text: diffs.map(([, text]) => text).join(''), diffs, originalText: value.text, }); } }, restoreRevision({ state, getters, commit, dispatch, }) { const { revisionContent } = state; if (revisionContent) { dispatch('modal/fileRestoration', null, { root: true }) .then(() => { // Close revision commit('setRevisionContent'); const currentContent = utils.deepCopy(getters.current); if (currentContent) { // Restore text and move discussions const diffs = diffMatchPatch .diff_main(currentContent.text, revisionContent.originalText); diffMatchPatch.diff_cleanupSemantic(diffs); Object.entries(currentContent.discussions).forEach(([, discussion]) => { const adjustOffset = (offsetName) => { const marker = new cledit.Marker(discussion[offsetName], offsetName === 'end'); marker.adjustOffset(diffs); discussion[offsetName] = marker.offset; }; adjustOffset('start'); adjustOffset('end'); }); dispatch('patchCurrent', { ...currentContent, text: revisionContent.originalText, }); } }); } }, }; export default module;