From 65c38f7b05b0e61bec174bfe1909054766f20a5c Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 8 Jul 2020 16:15:27 +0200 Subject: [PATCH] Implement restoring selection on undo/redo (not yet for cursor) --- src/JSONEditor.svelte | 83 ++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/src/JSONEditor.svelte b/src/JSONEditor.svelte index f3562f0..96998aa 100644 --- a/src/JSONEditor.svelte +++ b/src/JSONEditor.svelte @@ -78,8 +78,13 @@ history.clear() } - export function patch(operations) { + /** + * @param {JSONPatchDocument} operations + * @param {Selection} [newSelection] + */ + export function patch(operations, newSelection) { const prevState = state + const prevSelection = selection console.log('operations', operations) @@ -89,12 +94,17 @@ doc = documentPatchResult.json state = patchProps(statePatchResult.json, operations) + if (newSelection) { + selection = newSelection + } history.add({ undo: documentPatchResult.revert, redo: operations, - prevState: prevState, - state: state + prevState, + state, + prevSelection, + selection: newSelection }) return { @@ -140,12 +150,15 @@ if (selection && clipboard) { console.log('paste', { clipboard, selection }) - function selectAddOperations (operations) { - handleSelect({ - paths: operations - .filter(operation => operation.op === 'add') - .map(operation => parseJSONPointer(operation.path)) - }) + function createNewSelection (operations) { + const paths = operations + .filter(operation => operation.op === 'add') + .map(operation => parseJSONPointer(operation.path)) + + return { + paths, + pathsMap: createPathsMap(paths) + } } if (selection.beforePath) { @@ -154,14 +167,14 @@ const props = getIn(state, parentPath.concat(STATE_PROPS)) const nextKeys = getNextKeys(props, parentPath, beforeKey, true) const operations = insertBefore(doc, selection.beforePath, clipboard, nextKeys) + const newSelection = createNewSelection(operations) - handlePatch(operations) - selectAddOperations(operations) + handlePatch(operations, newSelection) } else if (selection.appendPath) { const operations = append(doc, selection.appendPath, clipboard) + const newSelection = createNewSelection(operations) - handlePatch(operations) - selectAddOperations(operations) + handlePatch(operations, newSelection) } else if (selection.paths) { const lastPath = last(selection.paths) // FIXME: here we assume selection.paths is sorted correctly, that's a dangerous assumption const parentPath = initial(lastPath) @@ -169,9 +182,9 @@ const props = getIn(state, parentPath.concat(STATE_PROPS)) const nextKeys = getNextKeys(props, parentPath, beforeKey, true) const operations = replace(doc, selection.paths, clipboard, nextKeys) + const newSelection = createNewSelection(operations) - handlePatch(operations) - selectAddOperations(operations) + handlePatch(operations, newSelection) } } } @@ -187,8 +200,9 @@ if (item) { doc = immutableJSONPatch(doc, item.undo).json state = item.prevState + selection = item.prevSelection - console.log('undo', { item, doc, state }) + console.log('undo', { item, doc, state, selection }) emitOnChange() } @@ -201,8 +215,9 @@ if (item) { doc = immutableJSONPatch(doc, item.redo).json state = item.state + selection = item.selection - console.log('redo', { item, doc, state }) + console.log('redo', { item, doc, state, selection }) emitOnChange() } @@ -280,11 +295,12 @@ /** * @param {JSONPatchDocument} operations + * @param {Selection} [newSelection] */ - function handlePatch(operations) { + function handlePatch(operations, newSelection) { // console.log('handlePatch', operations) - const patchResult = patch(operations) + const patchResult = patch(operations, newSelection) emitOnChange() @@ -333,17 +349,7 @@ if (newSelection) { const { paths, anchorPath, focusPath, beforePath, appendPath } = newSelection - if (paths) { - const pathsMap = {} - paths.forEach(path => { - pathsMap[compileJSONPointer(path)] = true - }) - - selection = { - paths, - pathsMap - } - } else if (beforePath) { + if (beforePath) { selection = { beforePath } @@ -355,14 +361,9 @@ // TODO: move expandSelection to JSONNode? (must change expandSelection to support relative path) const paths = expandSelection(doc, state, anchorPath, focusPath) - const pathsMap = {} - paths.forEach(path => { - pathsMap[compileJSONPointer(path)] = true - }) - selection = { paths, - pathsMap + pathsMap: createPathsMap(paths) } } else { console.error('Unknown type of selection', newSelection) @@ -375,6 +376,16 @@ } } + function createPathsMap (paths) { + const pathsMap = {} + + paths.forEach(path => { + pathsMap[compileJSONPointer(path)] = true + }) + + return pathsMap + } + /** * Expand all nodes on given path * @param {Path} path