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