This commit is contained in:
Rizky 2023-10-24 09:18:22 +07:00
parent 4be4bdc160
commit 8f5c20beeb
16 changed files with 134 additions and 111 deletions

View File

@ -5,38 +5,32 @@ export const SyncActionDefinition = {
"load": "2"
},
"comp": {
"undo": "3",
"redo": "4",
"list": "5",
"group": "6",
"load": "7"
"list": "3",
"group": "4",
"load": "5"
},
"page": {
"undo": "8",
"redo": "9",
"list": "10",
"load": "11"
"list": "6",
"load": "7"
},
"yjs": {
"sv_local": "12",
"diff_local": "13",
"sv_remote": "14"
"um": "8",
"sv_local": "9",
"diff_local": "10",
"sv_remote": "11"
}
};
export const SyncActionPaths = {
"0": "site.list",
"1": "site.group",
"2": "site.load",
"3": "comp.undo",
"4": "comp.redo",
"5": "comp.list",
"6": "comp.group",
"7": "comp.load",
"8": "page.undo",
"9": "page.redo",
"10": "page.list",
"11": "page.load",
"12": "yjs.sv_local",
"13": "yjs.diff_local",
"14": "yjs.sv_remote"
"3": "comp.list",
"4": "comp.group",
"5": "comp.load",
"6": "page.list",
"7": "page.load",
"8": "yjs.um",
"9": "yjs.sv_local",
"10": "yjs.diff_local",
"11": "yjs.sv_remote"
};

View File

@ -22,29 +22,33 @@ export const SyncActions = {
load: async (id: string) => ({}) as ESite | void,
},
comp: {
undo: async (id_comp: string) => {},
redo: async (id_comp: string) => {},
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
group: () => ({}) as Record<string, string[]>,
load: async (id: string) => ({}) as EComp | void,
},
page: {
undo: async (id_page: string) => {},
redo: async (id_page: string) => {},
list: (id_site: string) =>
({}) as Record<string, Exclude<page, "content_tree">>,
load: async (id: string) => ({}) as EPage | void,
},
yjs: {
sv_local: async (mode: "page" | "comp", id: string, bin: Uint8Array) =>
({}) as { diff: Uint8Array; sv: Uint8Array } | void,
um: async (
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 (
mode: "page" | "comp",
mode: "page" | "comp" | "site",
id: string,
bin: Uint8Array
) => {},
sv_remote: async (
mode: "page" | "comp",
mode: "page" | "comp" | "site",
id: string,
sv: Uint8Array,
diff: Uint8Array

View File

@ -1,3 +0,0 @@
import { SyncConnection } from "../type";
export const comp_redo = async function (this: SyncConnection, id: string) {};

View File

@ -1,3 +0,0 @@
import { SyncConnection } from "../type";
export const comp_undo = async function (this: SyncConnection, id: string) {};

View File

@ -2,10 +2,7 @@ export * from "./site_load";
export * from "./site_group";
export * from "./page_load";
export * from "./comp_load";
export * from "./page_undo";
export * from "./page_redo";
export * from "./comp_undo";
export * from "./comp_redo";
export * from "./yjs_um";
export * from "./yjs_sv_local";
export * from "./yjs_diff_local";
export * from "./yjs_sv_remote";

View File

@ -1,12 +1,12 @@
import { syncronize } from "y-pojo";
import { SAction } from "../actions";
import { conns } from "../entity/conn";
import { Y, docs } from "../entity/docs";
import { snapshot } from "../entity/snapshot";
import { user } from "../entity/user";
import { gzipAsync } from "../entity/zlib";
import { SyncConnection, SyncType } from "../type";
import { conns } from "../entity/conn";
import { sendWS } from "../sync-handler";
import { SyncConnection, SyncType } from "../type";
export const page_load: SAction["page"]["load"] = async function (
this: SyncConnection,
@ -17,18 +17,26 @@ export const page_load: SAction["page"]["load"] = async function (
if (this.conf) this.conf.page_id = id;
const createUndoManager = (root: Y.Map<any>) => {
const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: false });
const createUndoManager = async (root: Y.Map<any>) => {
const um = new Y.UndoManager(root, {
ignoreRemoteMapChanges: true,
});
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) => {
if (origin === um) {
} else {
const bin = Y.encodeStateAsUpdate(doc);
snapshot.set("page", id, "bin", bin);
const sv_local = await gzipAsync(update);
user.active.findAll({ page_id: id }).map((e) => {
if (origin !== um) {
if (e.client_id === origin) return;
}
const ws = conns.get(e.client_id)?.ws;
if (ws)
sendWS(ws, {
@ -37,7 +45,6 @@ export const page_load: SAction["page"]["load"] = async function (
data: { type: "page", sv_local, id },
});
});
}
});
};
@ -52,7 +59,7 @@ export const page_load: SAction["page"]["load"] = async function (
let root = doc.getMap("map");
syncronize(root, { id, root: page.content_tree });
const um = createUndoManager(root);
const um = await createUndoManager(root);
docs.page[id] = {
doc: doc as any,
id,
@ -60,7 +67,7 @@ export const page_load: SAction["page"]["load"] = async function (
};
const bin = Y.encodeStateAsUpdate(doc);
attachOnUpdate(doc, um);
await attachOnUpdate(doc, um);
snapshot.update({
bin,
@ -69,6 +76,7 @@ export const page_load: SAction["page"]["load"] = async function (
name: page.name,
ts: Date.now(),
url: page.url,
id_doc: doc.clientID,
id_site: page.id_site,
});
@ -89,11 +97,12 @@ export const page_load: SAction["page"]["load"] = async function (
}
} else if (snap && !ydoc) {
const doc = new Y.Doc();
snapshot.set("page", id, "id_doc", doc.clientID);
Y.applyUpdate(doc, snap.bin);
let root = doc.getMap("map");
const um = createUndoManager(root);
attachOnUpdate(doc, um);
const um = await createUndoManager(root);
await attachOnUpdate(doc, um);
docs.page[id] = {
doc: doc as any,

View File

@ -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();
}
};

View File

@ -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();
}
};

View File

@ -19,7 +19,4 @@ export const yjs_diff_local: SAction["yjs"]["diff_local"] = async function (
const um = docs[mode][id].um;
um.addTrackedOrigin(this.client_id);
Y.applyUpdate(doc, diff, this.client_id);
const save = Y.encodeStateAsUpdate(doc);
snapshot.set(mode, id, "bin", save);
};

View File

@ -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();
}
}
}
};

View File

@ -5,6 +5,14 @@ import { DPage } from "../../../../web/src/utils/types/root";
export * as Y from "yjs";
export const docs = {
site: {} as Record<
string,
{
id: string;
doc: DPage;
um: Y.UndoManager;
}
>,
page: {} as Record<
string,
{

View File

@ -3,9 +3,10 @@ import { RootDatabase, open } from "lmdb";
import { g } from "utils/global";
const emptySnapshot = {
type: "" as "" | "comp" | "page",
type: "" as "" | "comp" | "page" | "site",
id: "",
bin: new Uint8Array(),
id_doc: 0,
name: "",
ts: Date.now(),
};

View File

@ -1,19 +1,20 @@
import { NodeModel } from "@minoru/react-dnd-treeview";
import { ReactElement } from "react";
import { clientStartSync } from "../../../utils/sync/ws-client";
import { IContent, MContent } from "../../../utils/types/general";
import { IItem, MItem } from "../../../utils/types/item";
import { DComp, DPage, IRoot } from "../../../utils/types/root";
import { ISection } from "../../../utils/types/section";
import { IText, MText } from "../../../utils/types/text";
import { ReactElement } from "react";
const EmptySite = {
id: "",
name: "",
domain: "",
js: "",
js_compiled: "",
config: { api_url: "" },
snapshot: null as null | Uint8Array,
// js: "",
// js_compiled: "",
};
export type ESite = typeof EmptySite;
export type EPage = typeof EmptyPage;
@ -95,7 +96,14 @@ export const EDGlobal = {
open: {} as Record<string, string[]>,
},
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>;
},
},
},
};

View File

@ -19,9 +19,9 @@ export const edUndoManager = async (p: PG) => {
!evt.shiftKey
) {
if (p.comp.cur.id) {
p.sync.comp.redo(p.comp.cur.id);
p.sync.yjs.um("comp", "redo", p.comp.cur.id);
} else {
p.sync.page.redo(p.page.cur.id);
p.sync.yjs.um("page", "redo", p.page.cur.id);
}
return;
}
@ -32,11 +32,10 @@ export const edUndoManager = async (p: PG) => {
evt.shiftKey
) {
if (p.comp.cur.id) {
p.sync.comp.redo(p.comp.cur.id);
p.sync.yjs.um("comp", "redo", p.comp.cur.id);
} else {
p.sync.page.redo(p.page.cur.id);
p.sync.yjs.um("page", "redo", p.page.cur.id);
}
return;
}
@ -46,9 +45,9 @@ export const edUndoManager = async (p: PG) => {
!evt.shiftKey
) {
if (p.comp.cur.id) {
p.sync.comp.undo(p.comp.cur.id);
p.sync.yjs.um("comp", "undo", p.comp.cur.id);
} else {
p.sync.page.undo(p.page.cur.id);
p.sync.yjs.um("page", "undo", p.page.cur.id);
}
}

View File

@ -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 { treeRebuild } from "../../../../../logic/tree/build";
export const edActionClone = (p: PG, item: IContent) => {
const mitem = p.page.meta[item.id].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" });
}
};

View File

@ -76,7 +76,7 @@ export const EdTreeCtxMenu = ({
onClick={() => edActionDetach(p, item)}
/>
)}
{type === "item" && comp?.id && (
{type === "item" && !comp?.id && (
<MenuItem
label="Create Component"
onClick={() => edActionNewComp(p, item)}