feat: undo/redo

This commit is contained in:
cha0s 2022-04-08 17:15:23 -05:00
parent 025ecb72c6
commit 71d53095fb
4 changed files with 77 additions and 18 deletions

View File

@ -51,8 +51,8 @@
show: false
quitOnClosed: false
window:
- '@persea/core'
- '...'
- '@persea/core'
'@flecks/governor': {}
'@flecks/react':
providers:

View File

@ -1,4 +1,9 @@
import {patchJsonResource, replaceResource} from '@avocado/resource/persea';
import {
patchJsonResource,
redo,
replaceResource,
undo,
} from '@avocado/resource/persea';
import {Hooks} from '@flecks/core';
import Persea from './components/persea';
@ -17,14 +22,23 @@ export default {
'@flecks/react.roots': () => Persea,
'@flecks/redux.effects': (flecks) => {
const withSocket = (fn) => (...args) => fn(...args.concat(flecks.get('$flecks/socket.socket')));
return {
[patchJsonResource]: withSocket((store, action, socket) => {
socket.send(['Action', action]);
}),
[replaceResource]: withSocket((store, action, socket) => {
socket.send(['Action', action]);
}),
};
return Object.fromEntries(
[
patchJsonResource,
redo,
replaceResource,
undo,
]
.map((action) => [
action,
withSocket((store, action, socket) => {
if (action.meta?.isRemote) {
return;
}
socket.send(['Action', action]);
}),
]),
);
},
'@flecks/redux.slices': () => ({
project,

View File

@ -1,4 +1,13 @@
import {patchJsonResource, replaceResource} from '@avocado/resource/persea';
import {readFile, writeFile} from 'fs/promises';
import {join} from 'path';
import {
patchJsonResource,
redo,
replaceResource,
undo,
} from '@avocado/resource/persea';
import {applyPatch, compare} from 'fast-json-patch';
export default (Action, flecks) => class ProjectAction extends Action {
@ -9,10 +18,44 @@ export default (Action, flecks) => class ProjectAction extends Action {
flecks.get('$persea/core.patches').push(payload);
break;
}
case redo.toString(): {
const {project, uri} = payload;
const path = join(process.cwd(), 'projects', project, uri);
const {toBuffer, fromBuffer} = flecks.get('$avocado/resource/persea.controllers')
.find(({matcher}) => uri.match(matcher));
const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks);
if (json.history?.redo?.length) {
const patch = json.history.redo[json.history.redo.length - 1];
socket.send(['Action', patchJsonResource({patch, project, uri}, true)]);
applyPatch(json, patch);
json.history.undo.push(compare(json, fromBuffer(buffer, flecks)));
json.history.redo.pop();
await writeFile(path, toBuffer(json, flecks));
}
break;
}
case replaceResource.toString(): {
flecks.get('$persea/core.replacements').push(payload);
break;
}
case undo.toString(): {
const {project, uri} = payload;
const path = join(process.cwd(), 'projects', project, uri);
const {toBuffer, fromBuffer} = flecks.get('$avocado/resource/persea.controllers')
.find(({matcher}) => uri.match(matcher));
const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks);
if (json.history?.undo?.length) {
const patch = json.history.undo[json.history.undo.length - 1];
socket.send(['Action', patchJsonResource({patch, project, uri}, true)]);
applyPatch(json, patch);
json.history.redo.push(compare(json, fromBuffer(buffer, flecks)));
json.history.undo.pop();
await writeFile(path, toBuffer(json, flecks));
}
break;
}
default:
}
return super.respond(packet, socket);

View File

@ -1,11 +1,7 @@
import fs from 'fs';
import {readFile, writeFile} from 'fs/promises';
import {join} from 'path';
import {promisify} from 'util';
import {applyPatch} from 'fast-json-patch';
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
import {applyPatch, compare} from 'fast-json-patch';
const startFlush = (flecks) => {
const flushPatches = async () => {
@ -21,6 +17,7 @@ const startFlush = (flecks) => {
patching[path] = new Promise((resolve) => {
readFile(path).then((buffer) => {
resolve({
fromBuffer,
toBuffer,
json: fromBuffer(buffer, flecks),
});
@ -34,7 +31,12 @@ const startFlush = (flecks) => {
await Promise.all(
Object.entries(patching)
.map(async ([path, promise]) => {
const {toBuffer, json} = await promise;
const {fromBuffer, toBuffer, json} = await promise;
const buffer = await readFile(path);
const undo = compare(json, fromBuffer(buffer, flecks));
json.history = json.history || {redo: [], undo: []};
json.history.redo = [];
json.history.undo.push(undo);
return writeFile(path, toBuffer(json, flecks));
}),
);