fix
This commit is contained in:
parent
4be4bdc160
commit
8f5c20beeb
|
|
@ -5,38 +5,32 @@ export const SyncActionDefinition = {
|
||||||
"load": "2"
|
"load": "2"
|
||||||
},
|
},
|
||||||
"comp": {
|
"comp": {
|
||||||
"undo": "3",
|
"list": "3",
|
||||||
"redo": "4",
|
"group": "4",
|
||||||
"list": "5",
|
"load": "5"
|
||||||
"group": "6",
|
|
||||||
"load": "7"
|
|
||||||
},
|
},
|
||||||
"page": {
|
"page": {
|
||||||
"undo": "8",
|
"list": "6",
|
||||||
"redo": "9",
|
"load": "7"
|
||||||
"list": "10",
|
|
||||||
"load": "11"
|
|
||||||
},
|
},
|
||||||
"yjs": {
|
"yjs": {
|
||||||
"sv_local": "12",
|
"um": "8",
|
||||||
"diff_local": "13",
|
"sv_local": "9",
|
||||||
"sv_remote": "14"
|
"diff_local": "10",
|
||||||
|
"sv_remote": "11"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const SyncActionPaths = {
|
export const SyncActionPaths = {
|
||||||
"0": "site.list",
|
"0": "site.list",
|
||||||
"1": "site.group",
|
"1": "site.group",
|
||||||
"2": "site.load",
|
"2": "site.load",
|
||||||
"3": "comp.undo",
|
"3": "comp.list",
|
||||||
"4": "comp.redo",
|
"4": "comp.group",
|
||||||
"5": "comp.list",
|
"5": "comp.load",
|
||||||
"6": "comp.group",
|
"6": "page.list",
|
||||||
"7": "comp.load",
|
"7": "page.load",
|
||||||
"8": "page.undo",
|
"8": "yjs.um",
|
||||||
"9": "page.redo",
|
"9": "yjs.sv_local",
|
||||||
"10": "page.list",
|
"10": "yjs.diff_local",
|
||||||
"11": "page.load",
|
"11": "yjs.sv_remote"
|
||||||
"12": "yjs.sv_local",
|
|
||||||
"13": "yjs.diff_local",
|
|
||||||
"14": "yjs.sv_remote"
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,29 +22,33 @@ export const SyncActions = {
|
||||||
load: async (id: string) => ({}) as ESite | void,
|
load: async (id: string) => ({}) as ESite | void,
|
||||||
},
|
},
|
||||||
comp: {
|
comp: {
|
||||||
undo: async (id_comp: string) => {},
|
|
||||||
redo: async (id_comp: string) => {},
|
|
||||||
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
|
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
|
||||||
group: () => ({}) as Record<string, string[]>,
|
group: () => ({}) as Record<string, string[]>,
|
||||||
load: async (id: string) => ({}) as EComp | void,
|
load: async (id: string) => ({}) as EComp | void,
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
undo: async (id_page: string) => {},
|
|
||||||
redo: async (id_page: string) => {},
|
|
||||||
list: (id_site: string) =>
|
list: (id_site: string) =>
|
||||||
({}) as Record<string, Exclude<page, "content_tree">>,
|
({}) as Record<string, Exclude<page, "content_tree">>,
|
||||||
load: async (id: string) => ({}) as EPage | void,
|
load: async (id: string) => ({}) as EPage | void,
|
||||||
},
|
},
|
||||||
yjs: {
|
yjs: {
|
||||||
sv_local: async (mode: "page" | "comp", id: string, bin: Uint8Array) =>
|
um: async (
|
||||||
({}) as { diff: Uint8Array; sv: Uint8Array } | void,
|
mode: "page" | "comp" | "site",
|
||||||
|
action: "undo" | "redo",
|
||||||
|
id: string
|
||||||
|
) => {},
|
||||||
|
sv_local: async (
|
||||||
|
mode: "page" | "comp" | "site",
|
||||||
|
id: string,
|
||||||
|
bin: Uint8Array
|
||||||
|
) => ({}) as { diff: Uint8Array; sv: Uint8Array } | void,
|
||||||
diff_local: async (
|
diff_local: async (
|
||||||
mode: "page" | "comp",
|
mode: "page" | "comp" | "site",
|
||||||
id: string,
|
id: string,
|
||||||
bin: Uint8Array
|
bin: Uint8Array
|
||||||
) => {},
|
) => {},
|
||||||
sv_remote: async (
|
sv_remote: async (
|
||||||
mode: "page" | "comp",
|
mode: "page" | "comp" | "site",
|
||||||
id: string,
|
id: string,
|
||||||
sv: Uint8Array,
|
sv: Uint8Array,
|
||||||
diff: Uint8Array
|
diff: Uint8Array
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
import { SyncConnection } from "../type";
|
|
||||||
|
|
||||||
export const comp_redo = async function (this: SyncConnection, id: string) {};
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
import { SyncConnection } from "../type";
|
|
||||||
|
|
||||||
export const comp_undo = async function (this: SyncConnection, id: string) {};
|
|
||||||
|
|
@ -2,10 +2,7 @@ export * from "./site_load";
|
||||||
export * from "./site_group";
|
export * from "./site_group";
|
||||||
export * from "./page_load";
|
export * from "./page_load";
|
||||||
export * from "./comp_load";
|
export * from "./comp_load";
|
||||||
export * from "./page_undo";
|
export * from "./yjs_um";
|
||||||
export * from "./page_redo";
|
|
||||||
export * from "./comp_undo";
|
|
||||||
export * from "./comp_redo";
|
|
||||||
export * from "./yjs_sv_local";
|
export * from "./yjs_sv_local";
|
||||||
export * from "./yjs_diff_local";
|
export * from "./yjs_diff_local";
|
||||||
export * from "./yjs_sv_remote";
|
export * from "./yjs_sv_remote";
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { syncronize } from "y-pojo";
|
import { syncronize } from "y-pojo";
|
||||||
import { SAction } from "../actions";
|
import { SAction } from "../actions";
|
||||||
|
import { conns } from "../entity/conn";
|
||||||
import { Y, docs } from "../entity/docs";
|
import { Y, docs } from "../entity/docs";
|
||||||
import { snapshot } from "../entity/snapshot";
|
import { snapshot } from "../entity/snapshot";
|
||||||
import { user } from "../entity/user";
|
import { user } from "../entity/user";
|
||||||
import { gzipAsync } from "../entity/zlib";
|
import { gzipAsync } from "../entity/zlib";
|
||||||
import { SyncConnection, SyncType } from "../type";
|
|
||||||
import { conns } from "../entity/conn";
|
|
||||||
import { sendWS } from "../sync-handler";
|
import { sendWS } from "../sync-handler";
|
||||||
|
import { SyncConnection, SyncType } from "../type";
|
||||||
|
|
||||||
export const page_load: SAction["page"]["load"] = async function (
|
export const page_load: SAction["page"]["load"] = async function (
|
||||||
this: SyncConnection,
|
this: SyncConnection,
|
||||||
|
|
@ -17,27 +17,34 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
|
|
||||||
if (this.conf) this.conf.page_id = id;
|
if (this.conf) this.conf.page_id = id;
|
||||||
|
|
||||||
const createUndoManager = (root: Y.Map<any>) => {
|
const createUndoManager = async (root: Y.Map<any>) => {
|
||||||
const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: false });
|
const um = new Y.UndoManager(root, {
|
||||||
|
ignoreRemoteMapChanges: true,
|
||||||
|
});
|
||||||
|
|
||||||
return um;
|
return um;
|
||||||
};
|
};
|
||||||
|
|
||||||
const attachOnUpdate = (doc: Y.Doc, um: Y.UndoManager) => {
|
const attachOnUpdate = async (doc: Y.Doc, um: Y.UndoManager) => {
|
||||||
|
snapshot.set("page", id, "id_doc", um.doc.clientID);
|
||||||
|
|
||||||
doc.on("update", async (update: Uint8Array, origin: any) => {
|
doc.on("update", async (update: Uint8Array, origin: any) => {
|
||||||
if (origin === um) {
|
const bin = Y.encodeStateAsUpdate(doc);
|
||||||
} else {
|
snapshot.set("page", id, "bin", bin);
|
||||||
const sv_local = await gzipAsync(update);
|
|
||||||
user.active.findAll({ page_id: id }).map((e) => {
|
const sv_local = await gzipAsync(update);
|
||||||
|
user.active.findAll({ page_id: id }).map((e) => {
|
||||||
|
if (origin !== um) {
|
||||||
if (e.client_id === origin) return;
|
if (e.client_id === origin) return;
|
||||||
const ws = conns.get(e.client_id)?.ws;
|
}
|
||||||
if (ws)
|
const ws = conns.get(e.client_id)?.ws;
|
||||||
sendWS(ws, {
|
if (ws)
|
||||||
type: SyncType.Event,
|
sendWS(ws, {
|
||||||
event: "remote_svlocal",
|
type: SyncType.Event,
|
||||||
data: { type: "page", sv_local, id },
|
event: "remote_svlocal",
|
||||||
});
|
data: { type: "page", sv_local, id },
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -52,7 +59,7 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
let root = doc.getMap("map");
|
let root = doc.getMap("map");
|
||||||
syncronize(root, { id, root: page.content_tree });
|
syncronize(root, { id, root: page.content_tree });
|
||||||
|
|
||||||
const um = createUndoManager(root);
|
const um = await createUndoManager(root);
|
||||||
docs.page[id] = {
|
docs.page[id] = {
|
||||||
doc: doc as any,
|
doc: doc as any,
|
||||||
id,
|
id,
|
||||||
|
|
@ -60,7 +67,7 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
};
|
};
|
||||||
|
|
||||||
const bin = Y.encodeStateAsUpdate(doc);
|
const bin = Y.encodeStateAsUpdate(doc);
|
||||||
attachOnUpdate(doc, um);
|
await attachOnUpdate(doc, um);
|
||||||
|
|
||||||
snapshot.update({
|
snapshot.update({
|
||||||
bin,
|
bin,
|
||||||
|
|
@ -69,6 +76,7 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
name: page.name,
|
name: page.name,
|
||||||
ts: Date.now(),
|
ts: Date.now(),
|
||||||
url: page.url,
|
url: page.url,
|
||||||
|
id_doc: doc.clientID,
|
||||||
id_site: page.id_site,
|
id_site: page.id_site,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -89,11 +97,12 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
}
|
}
|
||||||
} else if (snap && !ydoc) {
|
} else if (snap && !ydoc) {
|
||||||
const doc = new Y.Doc();
|
const doc = new Y.Doc();
|
||||||
|
snapshot.set("page", id, "id_doc", doc.clientID);
|
||||||
Y.applyUpdate(doc, snap.bin);
|
Y.applyUpdate(doc, snap.bin);
|
||||||
let root = doc.getMap("map");
|
let root = doc.getMap("map");
|
||||||
|
|
||||||
const um = createUndoManager(root);
|
const um = await createUndoManager(root);
|
||||||
attachOnUpdate(doc, um);
|
await attachOnUpdate(doc, um);
|
||||||
|
|
||||||
docs.page[id] = {
|
docs.page[id] = {
|
||||||
doc: doc as any,
|
doc: doc as any,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
import { docs } from "../entity/docs";
|
|
||||||
import { SyncConnection } from "../type";
|
|
||||||
|
|
||||||
export const page_redo = async function (this: SyncConnection, id: string) {
|
|
||||||
if (!docs.page[id]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const um = docs.page[id].um;
|
|
||||||
if (um.canRedo()) {
|
|
||||||
console.log("redoing");
|
|
||||||
um.redo();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import { docs } from "../entity/docs";
|
|
||||||
import { SyncConnection } from "../type";
|
|
||||||
|
|
||||||
export const page_undo = async function (this: SyncConnection, id: string) {
|
|
||||||
if (!docs.page[id]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const um = docs.page[id].um;
|
|
||||||
if (um.canUndo()) {
|
|
||||||
console.log("undoing");
|
|
||||||
|
|
||||||
um.undo();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -19,7 +19,4 @@ export const yjs_diff_local: SAction["yjs"]["diff_local"] = async function (
|
||||||
const um = docs[mode][id].um;
|
const um = docs[mode][id].um;
|
||||||
um.addTrackedOrigin(this.client_id);
|
um.addTrackedOrigin(this.client_id);
|
||||||
Y.applyUpdate(doc, diff, this.client_id);
|
Y.applyUpdate(doc, diff, this.client_id);
|
||||||
|
|
||||||
const save = Y.encodeStateAsUpdate(doc);
|
|
||||||
snapshot.set(mode, id, "bin", save);
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { SAction } from "../actions";
|
||||||
|
import { docs } from "../entity/docs";
|
||||||
|
import { SyncConnection } from "../type";
|
||||||
|
|
||||||
|
export const yjs_um: SAction["yjs"]["um"] = async function (
|
||||||
|
this: SyncConnection,
|
||||||
|
mode,
|
||||||
|
action,
|
||||||
|
id
|
||||||
|
) {
|
||||||
|
if (!docs[mode][id]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const um = docs[mode][id].um;
|
||||||
|
if (action === "redo") {
|
||||||
|
if (um.canRedo()) {
|
||||||
|
um.redo();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (um.undoStack.length > 1) {
|
||||||
|
if (um.canUndo()) {
|
||||||
|
um.undo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -5,6 +5,14 @@ import { DPage } from "../../../../web/src/utils/types/root";
|
||||||
export * as Y from "yjs";
|
export * as Y from "yjs";
|
||||||
|
|
||||||
export const docs = {
|
export const docs = {
|
||||||
|
site: {} as Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
doc: DPage;
|
||||||
|
um: Y.UndoManager;
|
||||||
|
}
|
||||||
|
>,
|
||||||
page: {} as Record<
|
page: {} as Record<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ import { RootDatabase, open } from "lmdb";
|
||||||
import { g } from "utils/global";
|
import { g } from "utils/global";
|
||||||
|
|
||||||
const emptySnapshot = {
|
const emptySnapshot = {
|
||||||
type: "" as "" | "comp" | "page",
|
type: "" as "" | "comp" | "page" | "site",
|
||||||
id: "",
|
id: "",
|
||||||
bin: new Uint8Array(),
|
bin: new Uint8Array(),
|
||||||
|
id_doc: 0,
|
||||||
name: "",
|
name: "",
|
||||||
ts: Date.now(),
|
ts: Date.now(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,20 @@
|
||||||
import { NodeModel } from "@minoru/react-dnd-treeview";
|
import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||||
|
import { ReactElement } from "react";
|
||||||
import { clientStartSync } from "../../../utils/sync/ws-client";
|
import { clientStartSync } from "../../../utils/sync/ws-client";
|
||||||
import { IContent, MContent } from "../../../utils/types/general";
|
|
||||||
import { IItem, MItem } from "../../../utils/types/item";
|
import { IItem, MItem } from "../../../utils/types/item";
|
||||||
import { DComp, DPage, IRoot } from "../../../utils/types/root";
|
import { DComp, DPage, IRoot } from "../../../utils/types/root";
|
||||||
import { ISection } from "../../../utils/types/section";
|
import { ISection } from "../../../utils/types/section";
|
||||||
import { IText, MText } from "../../../utils/types/text";
|
import { IText, MText } from "../../../utils/types/text";
|
||||||
import { ReactElement } from "react";
|
|
||||||
|
|
||||||
const EmptySite = {
|
const EmptySite = {
|
||||||
id: "",
|
id: "",
|
||||||
name: "",
|
name: "",
|
||||||
domain: "",
|
domain: "",
|
||||||
js: "",
|
|
||||||
js_compiled: "",
|
|
||||||
config: { api_url: "" },
|
config: { api_url: "" },
|
||||||
|
snapshot: null as null | Uint8Array,
|
||||||
|
|
||||||
|
// js: "",
|
||||||
|
// js_compiled: "",
|
||||||
};
|
};
|
||||||
export type ESite = typeof EmptySite;
|
export type ESite = typeof EmptySite;
|
||||||
export type EPage = typeof EmptyPage;
|
export type EPage = typeof EmptyPage;
|
||||||
|
|
@ -95,7 +96,14 @@ export const EDGlobal = {
|
||||||
open: {} as Record<string, string[]>,
|
open: {} as Record<string, string[]>,
|
||||||
},
|
},
|
||||||
popup: {
|
popup: {
|
||||||
comp: null as null | ((comp_id: string) => void | Promise<void>),
|
comp: null as null | true | ((comp_id: string) => void | Promise<void>),
|
||||||
|
compGroup: null as
|
||||||
|
| null
|
||||||
|
| true
|
||||||
|
| {
|
||||||
|
event: React.MouseEvent<HTMLElement, MouseEvent>;
|
||||||
|
pick: (group_id: string) => void | Promise<void>;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ export const edUndoManager = async (p: PG) => {
|
||||||
!evt.shiftKey
|
!evt.shiftKey
|
||||||
) {
|
) {
|
||||||
if (p.comp.cur.id) {
|
if (p.comp.cur.id) {
|
||||||
p.sync.comp.redo(p.comp.cur.id);
|
p.sync.yjs.um("comp", "redo", p.comp.cur.id);
|
||||||
} else {
|
} else {
|
||||||
p.sync.page.redo(p.page.cur.id);
|
p.sync.yjs.um("page", "redo", p.page.cur.id);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -32,11 +32,10 @@ export const edUndoManager = async (p: PG) => {
|
||||||
evt.shiftKey
|
evt.shiftKey
|
||||||
) {
|
) {
|
||||||
if (p.comp.cur.id) {
|
if (p.comp.cur.id) {
|
||||||
p.sync.comp.redo(p.comp.cur.id);
|
p.sync.yjs.um("comp", "redo", p.comp.cur.id);
|
||||||
} else {
|
} else {
|
||||||
p.sync.page.redo(p.page.cur.id);
|
p.sync.yjs.um("page", "redo", p.page.cur.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,9 +45,9 @@ export const edUndoManager = async (p: PG) => {
|
||||||
!evt.shiftKey
|
!evt.shiftKey
|
||||||
) {
|
) {
|
||||||
if (p.comp.cur.id) {
|
if (p.comp.cur.id) {
|
||||||
p.sync.comp.undo(p.comp.cur.id);
|
p.sync.yjs.um("comp", "undo", p.comp.cur.id);
|
||||||
} else {
|
} else {
|
||||||
p.sync.page.undo(p.page.cur.id);
|
p.sync.yjs.um("page", "undo", p.page.cur.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,22 @@
|
||||||
import { IContent } from "../../../../../../../utils/types/general";
|
import { syncronize } from "y-pojo";
|
||||||
|
import { IContent, MContent } from "../../../../../../../utils/types/general";
|
||||||
|
import { fillID } from "../../../../../../editor/tools/fill-id";
|
||||||
import { PG } from "../../../../../logic/ed-global";
|
import { PG } from "../../../../../logic/ed-global";
|
||||||
|
import { treeRebuild } from "../../../../../logic/tree/build";
|
||||||
|
|
||||||
export const edActionClone = (p: PG, item: IContent) => {
|
export const edActionClone = (p: PG, item: IContent) => {
|
||||||
const mitem = p.page.meta[item.id].mitem;
|
const mitem = p.page.meta[item.id].mitem;
|
||||||
if (mitem) {
|
if (mitem) {
|
||||||
|
mitem.doc?.transact(() => {
|
||||||
|
mitem.parent.forEach((e: MContent, idx) => {
|
||||||
|
if (e.get("id") === mitem.get("id")) {
|
||||||
|
const json = e.toJSON() as IContent;
|
||||||
|
const map = new Y.Map();
|
||||||
|
syncronize(map, fillID(json));
|
||||||
|
mitem.parent.insert(idx, [map]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
treeRebuild(p, { note: "clone" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export const EdTreeCtxMenu = ({
|
||||||
onClick={() => edActionDetach(p, item)}
|
onClick={() => edActionDetach(p, item)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{type === "item" && comp?.id && (
|
{type === "item" && !comp?.id && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
label="Create Component"
|
label="Create Component"
|
||||||
onClick={() => edActionNewComp(p, item)}
|
onClick={() => edActionNewComp(p, item)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue