diff --git a/app/web/src/render/ed/logic/ed-route.ts b/app/web/src/render/ed/logic/ed-route.ts index 762f1270..9ae3a73b 100644 --- a/app/web/src/render/ed/logic/ed-route.ts +++ b/app/web/src/render/ed/logic/ed-route.ts @@ -36,7 +36,7 @@ export const edRoute = async (p: PG) => { const res = await p.sync.yjs.sv_local( "page", p.page.cur.id, - compress(bin) + Buffer.from(compress(bin)) ); if (res) { @@ -48,7 +48,7 @@ export const edRoute = async (p: PG) => { await p.sync.yjs.diff_local( "page", p.page.cur.id, - compress(diff_local) + Buffer.from(compress(diff_local)) ); } }); diff --git a/app/web/src/render/ed/panel/tree/node/item/action/attach.tsx b/app/web/src/render/ed/panel/tree/node/item/action/attach.tsx index 907b91c0..98ace4d7 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/attach.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/attach.tsx @@ -1,5 +1,4 @@ import { IItem } from "../../../../../../../utils/types/item"; -import { MenuItem } from "../../../../../../../utils/ui/context-menu"; import { PG } from "../../../../../logic/ed-global"; export const edActionAttach = (p: PG, item: IItem) => { diff --git a/app/web/src/render/ed/panel/tree/node/item/action/clone.tsx b/app/web/src/render/ed/panel/tree/node/item/action/clone.tsx index db04dbdf..bd3a785b 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/clone.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/clone.tsx @@ -1,4 +1,8 @@ import { IContent } from "../../../../../../../utils/types/general"; import { PG } from "../../../../../logic/ed-global"; -export const edActionClone = (p: PG, item: IContent) => {}; +export const edActionClone = (p: PG, item: IContent) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx b/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx index 4358fd05..fa2d9c68 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx @@ -1,4 +1,8 @@ import { IItem } from "../../../../../../../utils/types/item"; import { PG } from "../../../../../logic/ed-global"; -export const edActionDetach = (p: PG, item: IItem) => {}; +export const edActionDetach = (p: PG, item: IItem) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/hide.tsx b/app/web/src/render/ed/panel/tree/node/item/action/hide.tsx index 5d5a1852..0e96622e 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/hide.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/hide.tsx @@ -1,4 +1,12 @@ import { IContent } from "../../../../../../../utils/types/general"; import { PG } from "../../../../../logic/ed-global"; -export const edActionHide = (p: PG, item: IContent) => {}; +export const edActionHide = (p: PG, item: IContent) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + const hidden = mitem.get("hidden"); + if (!hidden) mitem.set("hidden", "all"); + else if (hidden === "all") mitem.set("hidden", "only-editor"); + else if (hidden === "only-editor") mitem.delete("hidden"); + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx b/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx index 3dfb6aec..b142939a 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx @@ -1,4 +1,8 @@ import { IItem } from "../../../../../../../utils/types/item"; import { PG } from "../../../../../logic/ed-global"; -export const edActionNewComp = (p: PG, item: IItem) => {}; +export const edActionNewComp = (p: PG, item: IItem) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/paste.tsx b/app/web/src/render/ed/panel/tree/node/item/action/paste.tsx index 6ae4f799..e5756493 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/paste.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/paste.tsx @@ -1,4 +1,41 @@ +import { syncronize } from "y-pojo"; import { IContent } from "../../../../../../../utils/types/general"; +import { MItem } from "../../../../../../../utils/types/item"; import { PG } from "../../../../../logic/ed-global"; +import { treeRebuild } from "../../../../../logic/tree/build"; +import { fillID } from "../../../../../../editor/tools/fill-id"; -export const edActionPaste = (p: PG, item: IContent) => {}; +export const edActionPaste = async (p: PG, item: IContent) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + const res = await navigator.clipboard.readText(); + if (typeof res === "string" && res.startsWith("prasi-clipboard:")) { + const clip = JSON.parse( + res.substring("prasi-clipboard:".length) + ) as IContent; + + mitem.doc?.transact(() => { + const mchilds = mitem.get("childs"); + if (mchilds) { + let child: any = { ...clip }; + if (item.type === "section") { + child = { ...clip, type: "item" }; + } else { + if (item.type === "text") { + (mitem as MItem).set("type", "item"); + item.type = "item" as any; + } + + if (clip.type === "section") { + child = { ...clip, type: "item" }; + } + } + const map = new Y.Map(); + syncronize(map, fillID(child)); + mchilds.push([map]); + } + }); + } + treeRebuild(p, { note: "paste" }); + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/unwrap.tsx b/app/web/src/render/ed/panel/tree/node/item/action/unwrap.tsx new file mode 100644 index 00000000..8dbb0aba --- /dev/null +++ b/app/web/src/render/ed/panel/tree/node/item/action/unwrap.tsx @@ -0,0 +1,28 @@ +import { syncronize } from "y-pojo"; +import { IContent, MContent } from "../../../../../../../utils/types/general"; +import { IItem } from "../../../../../../../utils/types/item"; +import { PG } from "../../../../../logic/ed-global"; +import { treeRebuild } from "../../../../../logic/tree/build"; + +export const edActionUnwrap = (p: PG, item: IItem) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + mitem.parent.forEach((e: MContent, idx) => { + if (e.get("id") === mitem.get("id")) { + const json = e.toJSON() as IContent; + if (json.type === "item") { + mitem.parent.delete(idx); + mitem.parent.insert( + idx, + json.childs.map((e) => { + const map = new Y.Map() as MContent; + syncronize(map as any, e); + return map; + }) + ); + treeRebuild(p, { note: "unwrap" }); + } + } + }); + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/wrap.tsx b/app/web/src/render/ed/panel/tree/node/item/action/wrap.tsx new file mode 100644 index 00000000..9161d7b8 --- /dev/null +++ b/app/web/src/render/ed/panel/tree/node/item/action/wrap.tsx @@ -0,0 +1,30 @@ +import { createId } from "@paralleldrive/cuid2"; +import { IContent, MContent } from "../../../../../../../utils/types/general"; +import { IItem } from "../../../../../../../utils/types/item"; +import { IText } from "../../../../../../../utils/types/text"; +import { PG } from "../../../../../logic/ed-global"; +import { syncronize } from "y-pojo"; +import { treeRebuild } from "../../../../../logic/tree/build"; + +export const edActionWrap = (p: PG, item: IText | IItem) => { + const mitem = p.page.meta[item.id].mitem; + if (mitem) { + mitem.parent.forEach((e: MContent, idx) => { + if (e.get("id") === mitem.get("id")) { + const json: IContent = { + id: createId(), + name: `Wrapped`, + type: "item", + childs: [e.toJSON() as IItem | IText], + }; + const map = new Y.Map() as MContent; + if (map) { + syncronize(map as any, json); + mitem.parent.delete(idx); + mitem.parent.insert(idx, [map]); + treeRebuild(p, { note: "wrap" }); + } + } + }); + } +}; diff --git a/app/web/src/render/ed/panel/tree/node/item/ctx-menu.tsx b/app/web/src/render/ed/panel/tree/node/item/ctx-menu.tsx index c46c54e8..d37feaef 100644 --- a/app/web/src/render/ed/panel/tree/node/item/ctx-menu.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/ctx-menu.tsx @@ -12,6 +12,8 @@ import { edActionDetach } from "./action/detach"; import { edActionHide } from "./action/hide"; import { edActionNewComp } from "./action/new-comp"; import { edActionPaste } from "./action/paste"; +import { edActionWrap } from "./action/wrap"; +import { edActionUnwrap } from "./action/unwrap"; export const EdTreeCtxMenu = ({ node, @@ -49,6 +51,7 @@ export const EdTreeCtxMenu = ({ const type = item?.type; const comp = (item as IItem).component as FNComponent | undefined; const rootComp = p.comp.cur; + const isComponent = comp?.id; const isActiveComponent = rootComp && rootComp.id === item?.id && rootComp.id; if (!item) { @@ -85,8 +88,20 @@ export const EdTreeCtxMenu = ({ edActionClone(p, item)} /> edActionCut(p, item)} /> edActionCopy(p, item)} /> - {local.allowCopy && local.allowPaste && ( - edActionPaste(p, item)} /> + {local.allowCopy && + local.allowPaste && + !isComponent && + item.type !== "text" && ( + edActionPaste(p, item)} /> + )} + {["text", "item"].includes(item.type) && ( + edActionWrap(p, item as IItem)} /> + )} + {["item"].includes(item.type) && !isComponent && ( + edActionUnwrap(p, item as IItem)} + /> )} ); diff --git a/app/web/src/render/ed/panel/tree/node/item/indent.tsx b/app/web/src/render/ed/panel/tree/node/item/indent.tsx index ef033831..047a7b89 100644 --- a/app/web/src/render/ed/panel/tree/node/item/indent.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/indent.tsx @@ -50,6 +50,11 @@ export const EdTreeIndent = ({ )} + {item.type === "item" && !isComponent && !prm.hasChild && ( +
+ +
+ )} {isComponent && !prm.hasChild && (