prasi-bun/app/web/src/nova/vi/render/render.tsx

122 lines
3.2 KiB
TypeScript

import { FC, Fragment, ReactNode } from "react";
import { useGlobal } from "web-utils";
import { IMeta } from "../../ed/logic/ed-global";
import { ErrorBox } from "../utils/error-box";
import { ViGlobal } from "./global";
import { viParts } from "./parts";
import { ViScript } from "./script";
const MAX_RENDER_IN_SECOND = 70;
export const render_stat = {
enabled: false,
meta: {} as Record<string, { last_render: number; count: number }>,
};
export const ViRender: FC<{
meta: IMeta;
children?: ReactNode;
passprop?: any;
is_layout: boolean;
}> = ({ meta, children, passprop, is_layout }) => {
if (render_stat.enabled) {
const rstat_meta = render_stat.meta;
if (!rstat_meta[meta.item.id]) {
rstat_meta[meta.item.id] = {
last_render: Math.floor(Date.now() / 1000),
count: 1,
};
} else {
if (
rstat_meta[meta.item.id].last_render === Math.floor(Date.now() / 1000)
) {
rstat_meta[meta.item.id].count++;
} else {
rstat_meta[meta.item.id] = {
last_render: Math.floor(Date.now() / 1000),
count: 1,
};
}
}
if (rstat_meta[meta.item.id]?.count > MAX_RENDER_IN_SECOND) {
return (
<div className="bg-orange-100 border border-orange-300 rounded-sm text-xs flex flex-col items-center">
<div className="text-[10px] font-bold text-red-900 self-stretch px-1">
WARNING: Render loop detected in [{meta.item.name}]
</div>
<p className="border-b border-orange-300 px-1 pb-1 min-w-[100px]">
Rendered {rstat_meta[meta.item.id]?.count} times in less than 1
second.
</p>
</div>
);
}
}
if (!meta) return null;
if (meta.item.hidden) return null;
if (meta.item.adv?.js || meta.item.component?.id) {
return (
<ErrorBox meta={meta}>
<ViScript
meta={meta}
is_layout={is_layout}
passprop={passprop}
></ViScript>
</ErrorBox>
);
}
return (
<ErrorBox meta={meta}>
<ViChild meta={meta} passprop={passprop} is_layout={is_layout}></ViChild>
</ErrorBox>
);
};
export const ViChild: FC<{
meta: IMeta;
is_layout: boolean;
passprop?: any;
}> = ({ meta, passprop, is_layout }) => {
const vi = useGlobal(ViGlobal, "VI");
if (is_layout && meta.item.name === "children") {
const childs: ReactNode[] = [];
for (const item_id of vi.entry) {
const meta = vi.meta[item_id];
if (meta.item.adv?.js || meta.item.component?.id) {
childs.push(
<ErrorBox meta={meta}>
<ViScript
meta={meta}
is_layout={false}
passprop={passprop}
></ViScript>
</ErrorBox>
);
} else {
const parts = viParts(vi, meta, false, passprop);
if (vi.visit) vi.visit(meta, parts);
childs.push(<div {...parts.props} />);
}
}
return (
<>
{childs.map((e, idx) => (
<Fragment key={idx}>{e}</Fragment>
))}
</>
);
}
const parts = viParts(vi, meta, is_layout, passprop);
if (vi.visit) vi.visit(meta, parts);
return <div {...parts.props} />;
};