mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-16 13:57:02 +08:00
fix(core): add error boundary for workspace layout (#5014)
https://github.com/toeverything/AFFiNE/assets/3468483/d478bf4f-2be3-4d7d-8d94-aa95c1f74c8e
This commit is contained in:
@@ -15,7 +15,7 @@ export const errorDetailStyle = style({
|
||||
});
|
||||
|
||||
export const errorTitle = style({
|
||||
fontSize: '36px',
|
||||
fontSize: '32px',
|
||||
lineHeight: '44px',
|
||||
fontWeight: 700,
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ import { useLocation, useParams } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
RecoverableError,
|
||||
SessionFetchErrorRightAfterLoginOrSignUp,
|
||||
type SessionFetchErrorRightAfterLoginOrSignUp,
|
||||
} from '../../unexpected-application-state/errors';
|
||||
import {
|
||||
errorDescription,
|
||||
@@ -33,7 +33,9 @@ import {
|
||||
} from './affine-error-boundary.css';
|
||||
import errorBackground from './error-status.assets.svg';
|
||||
|
||||
export type AffineErrorBoundaryProps = React.PropsWithChildren;
|
||||
export type AffineErrorBoundaryProps = React.PropsWithChildren & {
|
||||
height?: number | string;
|
||||
};
|
||||
|
||||
type AffineError =
|
||||
| QueryParamError
|
||||
@@ -81,7 +83,7 @@ export class AffineErrorBoundary extends Component<
|
||||
if (this.state.error.canRetry()) {
|
||||
this.state.error.retry();
|
||||
this.setState({
|
||||
error: this.state.error,
|
||||
error: null,
|
||||
canRetryRecoveredError: this.state.error.canRetry(),
|
||||
});
|
||||
} else {
|
||||
@@ -90,6 +92,10 @@ export class AffineErrorBoundary extends Component<
|
||||
}
|
||||
};
|
||||
|
||||
private readonly handleRefresh = () => {
|
||||
this.setState({ error: null });
|
||||
};
|
||||
|
||||
static getDerivedStateFromError(
|
||||
error: AffineError
|
||||
): AffineErrorBoundaryState {
|
||||
@@ -121,14 +127,14 @@ export class AffineErrorBoundary extends Component<
|
||||
</>
|
||||
</>
|
||||
);
|
||||
} else if (error instanceof SessionFetchErrorRightAfterLoginOrSignUp) {
|
||||
} else if (error instanceof RecoverableError) {
|
||||
const retryButtonDesc = this.state.canRetryRecoveredError
|
||||
? 'Refetch'
|
||||
: 'Reload';
|
||||
errorDetail = (
|
||||
<>
|
||||
<h1 className={errorTitle}>Sorry.. there was an error</h1>
|
||||
<span className={errorDescription}> Fetching session failed </span>
|
||||
<span className={errorDescription}> {error.message} </span>
|
||||
<span className={errorDescription}>
|
||||
If you are still experiencing this issue, please{' '}
|
||||
<a
|
||||
@@ -151,13 +157,22 @@ export class AffineErrorBoundary extends Component<
|
||||
} else {
|
||||
errorDetail = (
|
||||
<>
|
||||
<h1>Sorry.. there was an error</h1>
|
||||
{error.message ?? error.toString()}
|
||||
<h1 className={errorTitle}>Sorry.. there was an error</h1>
|
||||
<code className={errorDescription}>
|
||||
{error.message ?? error.toString()}
|
||||
</code>
|
||||
<Button
|
||||
onClick={this.handleRefresh}
|
||||
className={errorRetryButton}
|
||||
type="primary"
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={errorLayout}>
|
||||
<div className={errorLayout} style={{ height: this.props.height }}>
|
||||
<div className={errorDetailStyle}>{errorDetail}</div>
|
||||
<span className={errorDivider} />
|
||||
<div
|
||||
|
||||
@@ -60,7 +60,7 @@ export function useCurrentUser(): CheckedUser {
|
||||
// login succeed but the session request failed then.
|
||||
// also need a error boundary to handle this error.
|
||||
throw new SessionFetchErrorRightAfterLoginOrSignUp(
|
||||
'First session should not be null',
|
||||
'Fetching session failed',
|
||||
() => {
|
||||
getSession()
|
||||
.then(session => {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import { AffineErrorBoundary } from '../../components/affine/affine-error-boundary';
|
||||
import { WorkspaceLayout } from '../../layouts/workspace-layout';
|
||||
import { performanceLogger, performanceRenderLogger } from '../../shared';
|
||||
|
||||
@@ -82,8 +83,10 @@ export const Component = (): ReactElement => {
|
||||
|
||||
const incompatible = useLoaderData();
|
||||
return (
|
||||
<WorkspaceLayout incompatible={!!incompatible}>
|
||||
<Outlet />
|
||||
</WorkspaceLayout>
|
||||
<AffineErrorBoundary height="100vh">
|
||||
<WorkspaceLayout incompatible={!!incompatible}>
|
||||
<Outlet />
|
||||
</WorkspaceLayout>
|
||||
</AffineErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user