mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
fix(component): image preview fallback (#3058)
This commit is contained in:
@@ -16,10 +16,13 @@ import {
|
|||||||
} from '@blocksuite/icons';
|
} from '@blocksuite/icons';
|
||||||
import type { Workspace } from '@blocksuite/store';
|
import type { Workspace } from '@blocksuite/store';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { useErrorBoundary } from 'foxact/use-error-boundary';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import type { ReactElement } from 'react';
|
import type { PropsWithChildren, ReactElement } from 'react';
|
||||||
import { Suspense, useCallback } from 'react';
|
import { Suspense, useCallback } from 'react';
|
||||||
import { useEffect, useRef, useState } 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 useSWR from 'swr';
|
||||||
|
|
||||||
import { useZoomControls } from './hooks/use-zoom';
|
import { useZoomControls } from './hooks/use-zoom';
|
||||||
@@ -252,21 +255,28 @@ const ImagePreviewModalImpl = (
|
|||||||
assertExists(block);
|
assertExists(block);
|
||||||
setCaption(block?.caption);
|
setCaption(block?.caption);
|
||||||
}, [props.blockId, props.pageId, props.workspace]);
|
}, [props.blockId, props.pageId, props.workspace]);
|
||||||
const { data } = useSWR(['workspace', 'image', props.pageId, props.blockId], {
|
const { data, error } = useSWR(
|
||||||
fetcher: ([_, __, pageId, blockId]) => {
|
['workspace', 'image', props.pageId, props.blockId],
|
||||||
const page = props.workspace.getPage(pageId);
|
{
|
||||||
assertExists(page);
|
fetcher: ([_, __, pageId, blockId]) => {
|
||||||
const block = page.getBlockById(blockId) as ImageBlockModel;
|
const page = props.workspace.getPage(pageId);
|
||||||
assertExists(block);
|
assertExists(page);
|
||||||
return props.workspace.blobs.get(block?.sourceId);
|
const block = page.getBlockById(blockId) as ImageBlockModel;
|
||||||
},
|
assertExists(block);
|
||||||
suspense: true,
|
return props.workspace.blobs.get(block?.sourceId);
|
||||||
});
|
},
|
||||||
|
suspense: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
useErrorBoundary(error);
|
||||||
|
|
||||||
const [prevData, setPrevData] = useState<string | null>(() => data);
|
const [prevData, setPrevData] = useState<string | null>(() => data);
|
||||||
const [url, setUrl] = useState<string | null>(null);
|
const [url, setUrl] = useState<string | null>(null);
|
||||||
|
|
||||||
if (prevData !== data) {
|
if (data === null) {
|
||||||
|
return null;
|
||||||
|
} else if (prevData !== data) {
|
||||||
if (url) {
|
if (url) {
|
||||||
URL.revokeObjectURL(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 = (
|
export const ImagePreviewModal = (
|
||||||
props: ImagePreviewModalProps
|
props: ImagePreviewModalProps
|
||||||
): ReactElement | null => {
|
): ReactElement | null => {
|
||||||
@@ -530,39 +555,43 @@ export const ImagePreviewModal = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<ImagePreviewErrorBoundary>
|
||||||
data-testid="image-preview-modal"
|
<div
|
||||||
className={`${imagePreviewBackgroundStyle} ${isOpen ? loaded : unloaded}`}
|
data-testid="image-preview-modal"
|
||||||
>
|
className={`${imagePreviewBackgroundStyle} ${
|
||||||
<Suspense fallback={<div />}>
|
isOpen ? loaded : unloaded
|
||||||
<ImagePreviewModalImpl
|
}`}
|
||||||
{...props}
|
|
||||||
blockId={blockId}
|
|
||||||
onClose={() => setBlockId(null)}
|
|
||||||
/>
|
|
||||||
</Suspense>
|
|
||||||
<button
|
|
||||||
data-testid="image-preview-close-button"
|
|
||||||
onClick={() => {
|
|
||||||
setBlockId(null);
|
|
||||||
}}
|
|
||||||
className={imagePreviewModalCloseButtonStyle}
|
|
||||||
>
|
>
|
||||||
<svg
|
<Suspense>
|
||||||
width="10"
|
<ImagePreviewModalImpl
|
||||||
height="10"
|
{...props}
|
||||||
viewBox="0 0 10 10"
|
blockId={blockId}
|
||||||
fill="none"
|
onClose={() => setBlockId(null)}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M0.286086 0.285964C0.530163 0.0418858 0.925891 0.0418858 1.16997 0.285964L5.00013 4.11613L8.83029 0.285964C9.07437 0.0418858 9.4701 0.0418858 9.71418 0.285964C9.95825 0.530041 9.95825 0.925769 9.71418 1.16985L5.88401 5.00001L9.71418 8.83017C9.95825 9.07425 9.95825 9.46998 9.71418 9.71405C9.4701 9.95813 9.07437 9.95813 8.83029 9.71405L5.00013 5.88389L1.16997 9.71405C0.925891 9.95813 0.530163 9.95813 0.286086 9.71405C0.0420079 9.46998 0.0420079 9.07425 0.286086 8.83017L4.11625 5.00001L0.286086 1.16985C0.0420079 0.925769 0.0420079 0.530041 0.286086 0.285964Z"
|
|
||||||
fill="#77757D"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</Suspense>
|
||||||
</button>
|
<button
|
||||||
</div>
|
data-testid="image-preview-close-button"
|
||||||
|
onClick={() => {
|
||||||
|
setBlockId(null);
|
||||||
|
}}
|
||||||
|
className={imagePreviewModalCloseButtonStyle}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="10"
|
||||||
|
height="10"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M0.286086 0.285964C0.530163 0.0418858 0.925891 0.0418858 1.16997 0.285964L5.00013 4.11613L8.83029 0.285964C9.07437 0.0418858 9.4701 0.0418858 9.71418 0.285964C9.95825 0.530041 9.95825 0.925769 9.71418 1.16985L5.88401 5.00001L9.71418 8.83017C9.95825 9.07425 9.95825 9.46998 9.71418 9.71405C9.4701 9.95813 9.07437 9.95813 8.83029 9.71405L5.00013 5.88389L1.16997 9.71405C0.925891 9.95813 0.530163 9.95813 0.286086 9.71405C0.0420079 9.46998 0.0420079 9.07425 0.286086 8.83017L4.11625 5.00001L0.286086 1.16985C0.0420079 0.925769 0.0420079 0.530041 0.286086 0.285964Z"
|
||||||
|
fill="#77757D"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ImagePreviewErrorBoundary>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user