Adds ErrorBoundary around stories

This commit is contained in:
Josh Perez 2022-07-28 20:10:07 -04:00 committed by GitHub
parent 37f9346f57
commit d7ec2e9d82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 3 deletions

View File

@ -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"

View 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;
}
}

View File

@ -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} />;
}

View File

@ -4,6 +4,7 @@
import { useBoundActions } from '../../hooks/useBoundActions';
export enum ToastType {
Error = 'Error',
MessageBodyTooLong = 'MessageBodyTooLong',
StoryReact = 'StoryReact',
StoryReply = 'StoryReply',

View File

@ -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,