From 766a9767180d040251a82ea9857b824b241c6550 Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 9 Sep 2024 18:19:41 -0700 Subject: [PATCH] errorboundary fallback, errorboundary in block frame header. fix workspace error boundary --- frontend/app/block/blockframe.tsx | 45 ++++++++++++++++++-------- frontend/app/element/errorboundary.tsx | 9 +++++- frontend/app/workspace/workspace.tsx | 2 +- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/frontend/app/block/blockframe.tsx b/frontend/app/block/blockframe.tsx index fcfb65a8..b2794b64 100644 --- a/frontend/app/block/blockframe.tsx +++ b/frontend/app/block/blockframe.tsx @@ -28,6 +28,7 @@ import { } from "@/app/store/global"; import * as services from "@/app/store/services"; import { WshServer } from "@/app/store/wshserver"; +import { ErrorBoundary } from "@/element/errorboundary"; import { IconButton } from "@/element/iconbutton"; import { MagnifyIcon } from "@/element/magnify"; import { NodeModel } from "@/layout/index"; @@ -116,7 +117,7 @@ function computeEndIcons( onContextMenu: (e: React.MouseEvent) => void ): JSX.Element[] { const endIconsElem: JSX.Element[] = []; - const endIconButtons = util.useAtomValueSafe(viewModel.endIconButtons); + const endIconButtons = util.useAtomValueSafe(viewModel?.endIconButtons); const magnified = jotai.useAtomValue(nodeModel.isMagnified); const numLeafs = jotai.useAtomValue(nodeModel.numLeafs); const magnifyDisabled = numLeafs <= 1; @@ -155,15 +156,16 @@ const BlockFrame_Header = ({ preview, connBtnRef, changeConnModalAtom, -}: BlockFrameProps & { changeConnModalAtom: jotai.PrimitiveAtom }) => { + error, +}: BlockFrameProps & { changeConnModalAtom: jotai.PrimitiveAtom; error?: Error }) => { const [blockData] = WOS.useWaveObjectValue(WOS.makeORef("block", nodeModel.blockId)); - const viewName = util.useAtomValueSafe(viewModel.viewName) ?? blockViewToName(blockData?.meta?.view); + const viewName = util.useAtomValueSafe(viewModel?.viewName) ?? blockViewToName(blockData?.meta?.view); const showBlockIds = jotai.useAtomValue(useSettingsKeyAtom("blockheader:showblockids")); - const viewIconUnion = util.useAtomValueSafe(viewModel.viewIcon) ?? blockViewToIcon(blockData?.meta?.view); - const preIconButton = util.useAtomValueSafe(viewModel.preIconButton); - const headerTextUnion = util.useAtomValueSafe(viewModel.viewText); + const viewIconUnion = util.useAtomValueSafe(viewModel?.viewIcon) ?? blockViewToIcon(blockData?.meta?.view); + const preIconButton = util.useAtomValueSafe(viewModel?.preIconButton); + const headerTextUnion = util.useAtomValueSafe(viewModel?.viewText); const magnified = jotai.useAtomValue(nodeModel.isMagnified); - const manageConnection = util.useAtomValueSafe(viewModel.manageConnection); + const manageConnection = util.useAtomValueSafe(viewModel?.manageConnection); const dragHandleRef = preview ? null : nodeModel.dragHandleRef; const onContextMenu = React.useCallback( @@ -193,6 +195,19 @@ const BlockFrame_Header = ({ headerTextElems.push(...renderHeaderElements(headerTextUnion, preview)); } headerTextElems.unshift(); + if (error != null) { + const copyHeaderErr = () => { + navigator.clipboard.writeText(error.message + "\n" + error.stack); + }; + headerTextElems.push( +
+ +
+ ); + } return (
@@ -377,9 +392,9 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => { const { nodeModel, viewModel, blockModel, preview, numBlocksInTab, children } = props; const [blockData] = WOS.useWaveObjectValue(WOS.makeORef("block", nodeModel.blockId)); const isFocused = jotai.useAtomValue(nodeModel.isFocused); - const viewIconUnion = util.useAtomValueSafe(viewModel.viewIcon) ?? blockViewToIcon(blockData?.meta?.view); - const customBg = util.useAtomValueSafe(viewModel.blockBg); - const manageConnection = util.useAtomValueSafe(viewModel.manageConnection); + const viewIconUnion = util.useAtomValueSafe(viewModel?.viewIcon) ?? blockViewToIcon(blockData?.meta?.view); + const customBg = util.useAtomValueSafe(viewModel?.blockBg); + const manageConnection = util.useAtomValueSafe(viewModel?.manageConnection); const changeConnModalAtom = useBlockAtom(nodeModel.blockId, "changeConn", () => { return jotai.atom(false); }) as jotai.PrimitiveAtom; @@ -429,6 +444,10 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => { } } const previewElem =
{viewIconElem}
; + const headerElem = ( + + ); + const headerElemNoView = React.cloneElement(headerElem, { viewModel: null }); return (
{ ref={blockModel?.blockRef} > - {preview ? null : ( + {preview || viewModel == null ? null : ( { /> )}
- + {headerElem} {preview ? previewElem : children}
- {preview || !connModalOpen ? null : ( + {preview || viewModel == null || !connModalOpen ? null : ( { +export class ErrorBoundary extends React.Component< + { children: ReactNode; fallback?: React.ReactElement & { error?: Error } }, + { error: Error } +> { constructor(props) { super(props); this.state = { error: null }; @@ -14,8 +17,12 @@ export class ErrorBoundary extends React.Component<{ children: ReactNode }, { er } render() { + const { fallback } = this.props; const { error } = this.state; if (error) { + if (fallback != null) { + return React.cloneElement(fallback as any, { error }); + } const errorMsg = `Error: ${error?.message}\n\n${error?.stack}`; return
{errorMsg}
; } else { diff --git a/frontend/app/workspace/workspace.tsx b/frontend/app/workspace/workspace.tsx index cb81bc7d..5e669235 100644 --- a/frontend/app/workspace/workspace.tsx +++ b/frontend/app/workspace/workspace.tsx @@ -108,7 +108,7 @@ const WorkspaceElem = React.memo(() => {
- + {activeTabId == "" ? ( No Active Tab ) : (