fix(component): image preview fallback (#3058)
This commit is contained in:
@@ -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,7 +255,9 @@ const ImagePreviewModalImpl = (
|
||||
assertExists(block);
|
||||
setCaption(block?.caption);
|
||||
}, [props.blockId, props.pageId, props.workspace]);
|
||||
const { data } = useSWR(['workspace', 'image', props.pageId, props.blockId], {
|
||||
const { data, error } = useSWR(
|
||||
['workspace', 'image', props.pageId, props.blockId],
|
||||
{
|
||||
fetcher: ([_, __, pageId, blockId]) => {
|
||||
const page = props.workspace.getPage(pageId);
|
||||
assertExists(page);
|
||||
@@ -261,12 +266,17 @@ const ImagePreviewModalImpl = (
|
||||
return props.workspace.blobs.get(block?.sourceId);
|
||||
},
|
||||
suspense: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
useErrorBoundary(error);
|
||||
|
||||
const [prevData, setPrevData] = useState<string | null>(() => data);
|
||||
const [url, setUrl] = useState<string | null>(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 (
|
||||
<ErrorBoundary fallbackRender={ErrorLogger}>{props.children}</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
export const ImagePreviewModal = (
|
||||
props: ImagePreviewModalProps
|
||||
): ReactElement | null => {
|
||||
@@ -530,11 +555,14 @@ export const ImagePreviewModal = (
|
||||
}
|
||||
|
||||
return (
|
||||
<ImagePreviewErrorBoundary>
|
||||
<div
|
||||
data-testid="image-preview-modal"
|
||||
className={`${imagePreviewBackgroundStyle} ${isOpen ? loaded : unloaded}`}
|
||||
className={`${imagePreviewBackgroundStyle} ${
|
||||
isOpen ? loaded : unloaded
|
||||
}`}
|
||||
>
|
||||
<Suspense fallback={<div />}>
|
||||
<Suspense>
|
||||
<ImagePreviewModalImpl
|
||||
{...props}
|
||||
blockId={blockId}
|
||||
@@ -564,5 +592,6 @@ export const ImagePreviewModal = (
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</ImagePreviewErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user