This commit is contained in:
Rizky 2023-12-11 23:24:24 +07:00
parent 4e2fa56cd9
commit 0c22d2cdef
12 changed files with 225 additions and 39 deletions

View File

@ -146,9 +146,9 @@ export const EDGlobal = {
on_update?: (bin: Uint8Array, origin: any) => Promise<void>;
}
>,
scope: {} as IScope,
building: false,
meta: {} as Record<string, IMeta>,
smeta: {} as Record<string, ISimpleMeta>,
entry: [] as string[],
tree: [] as NodeModel<IMeta>[],
render: () => {},

View File

@ -56,6 +56,7 @@ export const reloadPage = async (p: PG, page_id: string, note: string) => {
}
p.page.entry = remotePage.entry;
p.page.smeta = remotePage.meta;
p.page.cur = remotePage;
if (remotePage.snapshot) {

View File

@ -1,7 +1,6 @@
import { IItem, MItem } from "../../../../utils/types/item";
import { viEvalComp } from "../../../vi/render/comp";
import { ViRender } from "../../../vi/render/render";
import { ViScript } from "../../../vi/render/script";
import { viEvalProps } from "../../../vi/render/comp";
import { viEvalScript } from "../../../vi/render/script";
import { genMeta } from "../../../view/logic/meta/meta";
import { PG, active } from "../ed-global";
import { pushTreeNode } from "./build/push-tree";
@ -34,29 +33,27 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
for (const mitem of mitems) {
const item = mitem.toJSON() as IItem;
if (item) {
p.page;
genMeta(
{
comps: p.comp.loaded,
meta,
on: !is_layout
? {
visit(meta) {
smeta: p.page.smeta,
on: {
async visit(meta) {
if (!is_layout) {
pushTreeNode(p, meta);
if (!meta.item.adv?.js && !meta.item.component?.id) {
meta.fc = ViRender;
} else {
if (meta.item.component?.id) {
viEvalComp(meta);
if (meta.item.component?.props) {
viEvalProps({ meta: p.page.meta, tick: 0 }, meta);
}
if (meta.item.adv?.js) {
meta.fc = ViScript;
if (meta.item.adv?.jsBuilt) {
viEvalScript({ meta: p.page.meta, tick: 0 }, meta);
}
}
},
}
: undefined,
},
},
{ item, mitem }
);

View File

@ -1,16 +1,11 @@
import { ReactNode, useEffect } from "react";
import { useGlobal, useLocal } from "web-utils";
import { Loading } from "../../../../utils/ui/loading";
import { View } from "../../../view/view";
import { EDGlobal, active } from "../../logic/ed-global";
import { getMetaById } from "../../logic/tree/build";
import { loadComponent } from "../../logic/tree/sync-walk";
import { code } from "../popup/code/code";
import { IMeta } from "../../../view/logic/meta/types";
import { useGlobal } from "web-utils";
import { Vi } from "../../../vi/vi";
import { EDGlobal } from "../../logic/ed-global";
export const EdMain = () => {
return <div className="flex-1"></div>;
// const p = useGlobal(EDGlobal, "EDITOR");
const p = useGlobal(EDGlobal, "EDITOR");
return <Vi ctx={{ meta: p.page.meta }} entry={p.page.entry} />;
// const local = useLocal({
// el: null as ReactNode,
// });

View File

@ -1,3 +1,9 @@
import { IMeta } from "../../ed/logic/ed-global";
import { ViContext } from "./parts";
export const viEvalComp = (meta: IMeta) => {};
export const viEvalProps = async (ctx: ViContext, meta: IMeta) => {
if (meta.item.component?.props) {
for (const [k, v] of Object.entries(meta.item.component.props)) {
}
}
};

View File

@ -0,0 +1,39 @@
import { produceCSS } from "../../../utils/css/gen";
import { IContent } from "../../../utils/types/general";
import { IMeta } from "../../ed/logic/ed-global";
export type ViContext = {
meta: Record<string, IMeta>;
tick: number;
};
export type ViParts = {
mode: "mobile" | "desktop";
hover?: boolean;
active?: boolean;
};
export const viParts = (meta: IMeta, arg?: ViParts) => {
const item = meta.item;
const content = meta.item as unknown as IContent;
const props: React.DetailedHTMLProps<
React.HTMLAttributes<HTMLDivElement>,
HTMLDivElement
> = {};
let shouldRenderChild = true;
if (content.type === "text") {
props.dangerouslySetInnerHTML = { __html: item.html || "" };
shouldRenderChild = false;
}
return {
className: produceCSS(item, {
mode: arg?.mode || "desktop",
hover: arg?.hover,
active: arg?.active,
}),
shouldRenderChild,
props,
};
};

View File

@ -1,6 +1,35 @@
import { FC } from "react";
import { FC, ReactNode } from "react";
import { IMeta } from "../../ed/logic/ed-global";
import { ViContext, viParts } from "./parts";
import { ViScript } from "./script";
export const ViRender: FC<{ meta: IMeta }> = () => {
return <div></div>;
export const ViRender: FC<{
ctx: ViContext;
meta: IMeta;
children?: ReactNode;
}> = ({ meta, children, ctx }) => {
if (!meta) return null;
if (meta.item.adv?.js || meta.item.component?.id) {
return <ViScript ctx={ctx} meta={meta} />;
}
const parts = viParts(meta);
let renderChild = undefined;
if (parts.shouldRenderChild) {
renderChild = children
? children
: meta.item.childs?.map((item) => {
if (!item) return null;
const { id } = item;
return <ViRender key={id} ctx={ctx} meta={ctx.meta[id]} />;
});
}
return (
<div {...parts.props} className={parts.className}>
{renderChild}
</div>
);
};

View File

@ -1,6 +1,29 @@
import { FC } from "react";
import { IMeta } from "../../ed/logic/ed-global";
import { ViContext, viParts } from "./parts";
import { ViRender } from "./render";
export const ViScript: FC<{ meta: IMeta }> = () => {
return <div></div>;
export const ViScript: FC<{ ctx: ViContext; meta: IMeta }> = ({
ctx,
meta,
}) => {
const childs = meta.item.childs;
const parts = viParts(meta);
let renderChild = undefined;
if (parts.shouldRenderChild) {
renderChild =
Array.isArray(childs) &&
childs.map(({ id }) => {
return <ViRender key={id} ctx={ctx} meta={ctx.meta[id]} />;
});
}
return (
<div {...parts.props} className={parts.className}>
{renderChild}
</div>
);
};
export const viEvalScript = async (ctx: ViContext, meta: IMeta) => {};

View File

@ -0,0 +1,26 @@
import { FC } from "react";
import { ViContext } from "./render/parts";
import { ViRender } from "./render/render";
import { useLocal } from "web-utils";
export const ViRoot: FC<{
ctx: ViContext;
entry: string[];
}> = ({ ctx, entry }) => {
const local = useLocal({ tick: Date.now() });
ctx.tick = local.tick;
return (
<div className="flex flex-1 flex-col relative">
{entry.map((id) => {
const meta = ctx.meta[id];
if (meta) {
if (Element) {
return <ViRender key={meta.item.id} ctx={ctx} meta={meta} />;
}
}
return null;
})}
</div>
);
};

View File

@ -0,0 +1,56 @@
import { useErrorBoundary, withErrorBoundary } from "react-use-error-boundary";
import { useLocal } from "web-utils";
import { IMeta } from "../../ed/logic/ed-global";
export const ErrorBox = withErrorBoundary(
({
children,
meta,
id,
silent,
}: {
children: any;
meta?: IMeta;
id?: string;
silent?: boolean;
}) => {
const local = useLocal({ retrying: false });
const [error, resetError] = useErrorBoundary((error, errorInfo) => {
if (silent !== true) console.warn(error);
});
let _meta = meta;
if (error) {
return (
<div className="bg-red-100 border border-red-300 rounded-sm text-xs flex flex-col items-center">
<div className="text-[10px] font-bold text-red-900 self-stretch px-1">
ERROR {_meta?.item.name ? "[" + _meta.item.name + "]:" : ""}
</div>
<p className="border-b border-red-300 px-1 pb-1 min-w-[100px]">
{!local.retrying ? <>{(error as any).message}</> : <>Retrying...</>}
</p>
<div className="p-1">
<button
onClick={() => {
local.retrying = true;
local.render();
setTimeout(() => {
local.retrying = false;
local.render();
resetError();
}, 100);
}}
className="bg-white border border-white hover:border-red-400 hover:bg-red-50 rounded px-2"
>
Try again
</button>
</div>
</div>
);
}
return children;
}
);

View File

@ -0,0 +1,13 @@
import { Suspense } from "react";
import { ViRoot } from "./root";
import { ErrorBox } from "./utils/error-box";
export const Vi: typeof ViRoot = (props) => {
return (
<ErrorBox>
<Suspense>
<ViRoot {...props} />
</Suspense>
</ErrorBox>
);
};

View File

@ -1,6 +1,8 @@
import { FC } from "react";
import { FC, ReactNode } from "react";
import { IContent, MContent } from "../../../../utils/types/general";
import { IItem, MItem } from "../../../../utils/types/item";
import { ViContext } from "../../../vi/render/parts";
import { ViRender } from "../../../vi/render/render";
export type GenMetaP = {
meta: Record<string, IMeta>;
@ -59,7 +61,6 @@ export type IMeta = {
name: string;
is_root: boolean;
};
fc?: FC<{ meta: IMeta }>;
scope: {
val?: any;
def?: {