From ce633642991ebaf2e68a82d9ec76c2c41e38b0aa Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Thu, 6 Jul 2023 17:22:23 +0800 Subject: [PATCH] fix(component): image preview fallback (#3058) --- .../components/image-preview-modal/index.tsx | 117 +++++++++++------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/packages/component/src/components/image-preview-modal/index.tsx b/packages/component/src/components/image-preview-modal/index.tsx index f0fe3a10ba..2078097593 100644 --- a/packages/component/src/components/image-preview-modal/index.tsx +++ b/packages/component/src/components/image-preview-modal/index.tsx @@ -16,10 +16,13 @@ import { } from '@blocksuite/icons'; import type { Workspace } from '@blocksuite/store'; import clsx from 'clsx'; +import { useErrorBoundary } from 'foxact/use-error-boundary'; import { useAtom } from 'jotai'; -import type { ReactElement } from 'react'; +import type { PropsWithChildren, ReactElement } from 'react'; import { Suspense, useCallback } from 'react'; import { useEffect, useRef, useState } from 'react'; +import type { FallbackProps } from 'react-error-boundary'; +import { ErrorBoundary } from 'react-error-boundary'; import useSWR from 'swr'; import { useZoomControls } from './hooks/use-zoom'; @@ -252,21 +255,28 @@ const ImagePreviewModalImpl = ( assertExists(block); setCaption(block?.caption); }, [props.blockId, props.pageId, props.workspace]); - const { data } = useSWR(['workspace', 'image', props.pageId, props.blockId], { - fetcher: ([_, __, pageId, blockId]) => { - const page = props.workspace.getPage(pageId); - assertExists(page); - const block = page.getBlockById(blockId) as ImageBlockModel; - assertExists(block); - return props.workspace.blobs.get(block?.sourceId); - }, - suspense: true, - }); + const { data, error } = useSWR( + ['workspace', 'image', props.pageId, props.blockId], + { + fetcher: ([_, __, pageId, blockId]) => { + const page = props.workspace.getPage(pageId); + assertExists(page); + const block = page.getBlockById(blockId) as ImageBlockModel; + assertExists(block); + return props.workspace.blobs.get(block?.sourceId); + }, + suspense: true, + } + ); + + useErrorBoundary(error); const [prevData, setPrevData] = useState(() => data); const [url, setUrl] = useState(null); - if (prevData !== data) { + if (data === null) { + return null; + } else if (prevData !== data) { if (url) { URL.revokeObjectURL(url); } @@ -461,6 +471,21 @@ const ImagePreviewModalImpl = ( ); }; +const ErrorLogger = (props: FallbackProps) => { + useEffect(() => { + console.error('image preview modal error', props.error); + }, [props.error]); + return null; +}; + +export const ImagePreviewErrorBoundary = ( + props: PropsWithChildren +): ReactElement => { + return ( + {props.children} + ); +}; + export const ImagePreviewModal = ( props: ImagePreviewModalProps ): ReactElement | null => { @@ -530,39 +555,43 @@ export const ImagePreviewModal = ( } return ( -
- }> - setBlockId(null)} - /> - - -
+ + + + ); };