Adds ErrorBoundary around stories
This commit is contained in:
parent
37f9346f57
commit
d7ec2e9d82
5 changed files with 85 additions and 3 deletions
|
@ -2377,6 +2377,14 @@
|
|||
"message": "No conversations found",
|
||||
"description": "Label shown when there are no conversations to compose to"
|
||||
},
|
||||
"Toast--error": {
|
||||
"message": "An error has occurred",
|
||||
"description": "Toast for general errors"
|
||||
},
|
||||
"Toast--error--action": {
|
||||
"message": "Submit log",
|
||||
"description": "Label for the error toast button"
|
||||
},
|
||||
"Toast--failed-to-fetch-username": {
|
||||
"message": "Failed to fetch username. Check your connection and try again.",
|
||||
"description": "Shown if request to Signal servers to find username fails"
|
||||
|
|
47
ts/components/ErrorBoundary.tsx
Normal file
47
ts/components/ErrorBoundary.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
import { ToastType } from '../state/ducks/toast';
|
||||
|
||||
export type Props = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export type State = {
|
||||
error?: Error;
|
||||
};
|
||||
|
||||
export class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = { error: undefined };
|
||||
}
|
||||
|
||||
public static getDerivedStateFromError(error: Error): State {
|
||||
log.error(
|
||||
'ErrorBoundary: captured rendering error',
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
if (window.reduxActions) {
|
||||
window.reduxActions.toast.showToast(ToastType.Error);
|
||||
}
|
||||
return { error };
|
||||
}
|
||||
|
||||
public override render(): ReactNode {
|
||||
const { error } = this.state;
|
||||
const { children } = this.props;
|
||||
|
||||
if (error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,21 @@ export const ToastManager = ({
|
|||
i18n,
|
||||
toastType,
|
||||
}: PropsType): JSX.Element | null => {
|
||||
if (toastType === ToastType.Error) {
|
||||
return (
|
||||
<Toast
|
||||
autoDismissDisabled
|
||||
onClose={hideToast}
|
||||
toastAction={{
|
||||
label: i18n('Toast--error--action'),
|
||||
onClick: () => window.showDebugLog(),
|
||||
}}
|
||||
>
|
||||
{i18n('Toast--error')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.MessageBodyTooLong) {
|
||||
return <ToastMessageBodyTooLong i18n={i18n} onClose={hideToast} />;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||
|
||||
export enum ToastType {
|
||||
Error = 'Error',
|
||||
MessageBodyTooLong = 'MessageBodyTooLong',
|
||||
StoryReact = 'StoryReact',
|
||||
StoryReply = 'StoryReply',
|
||||
|
|
|
@ -33,13 +33,16 @@ import { getConversationsStoppingSend } from '../selectors/conversations';
|
|||
import { getIsCustomizingPreferredReactions } from '../selectors/preferredReactions';
|
||||
import { mapDispatchToProps } from '../actions';
|
||||
import type { SafetyNumberProps } from '../../components/SafetyNumberChangeDialog';
|
||||
import { ErrorBoundary } from '../../components/ErrorBoundary';
|
||||
|
||||
const mapStateToProps = (state: StateType) => {
|
||||
const i18n = getIntl(state);
|
||||
|
||||
return {
|
||||
...state.app,
|
||||
conversationsStoppingSend: getConversationsStoppingSend(state),
|
||||
getPreferredBadge: getPreferredBadgeSelector(state),
|
||||
i18n: getIntl(state),
|
||||
i18n,
|
||||
localeMessages: getLocaleMessages(state),
|
||||
isCustomizingPreferredReactions: getIsCustomizingPreferredReactions(state),
|
||||
isMaximized: getIsMainWindowMaximized(state),
|
||||
|
@ -57,9 +60,17 @@ const mapStateToProps = (state: StateType) => {
|
|||
<SmartSafetyNumberViewer {...props} />
|
||||
),
|
||||
isShowingStoriesView: shouldShowStoriesView(state),
|
||||
renderStories: () => <SmartStories />,
|
||||
renderStories: () => (
|
||||
<ErrorBoundary>
|
||||
<SmartStories />
|
||||
</ErrorBoundary>
|
||||
),
|
||||
selectedStoryData: getSelectedStoryData(state),
|
||||
renderStoryViewer: () => <SmartStoryViewer />,
|
||||
renderStoryViewer: () => (
|
||||
<ErrorBoundary>
|
||||
<SmartStoryViewer />
|
||||
</ErrorBoundary>
|
||||
),
|
||||
requestVerification: (
|
||||
type: 'sms' | 'voice',
|
||||
number: string,
|
||||
|
|
Loading…
Add table
Reference in a new issue