ErrorBoundary improvements, StickerCreator logging/resiliency

This commit is contained in:
Scott Nonnenberg 2022-08-19 11:35:40 -07:00 committed by GitHub
parent 0fb45f045d
commit 6dd6a64d6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 67 additions and 19 deletions

View File

@ -12,6 +12,7 @@ import { Button } from '../../elements/Button';
import { stickersDuck } from '../../store';
import { encryptAndUpload } from '../../util/preload';
import { useI18n } from '../../util/i18n';
import * as Errors from '../../../ts/types/errors';
const handleCancel = () => {
history.push('/add-meta');
@ -42,7 +43,10 @@ export const UploadStage: React.ComponentType = () => {
actions.setPackMeta(packMeta);
history.push('/share');
} catch (e) {
window.SignalContext.log.error('Error uploading image:', e);
window.SignalContext.log.error(
'Error uploading pack:',
Errors.toLogFormat(e)
);
actions.addToast({
key: 'StickerCreator--Toasts--errorUploading',
subs: [e.message],

View File

@ -185,16 +185,25 @@ window.encryptAndUpload = async (
return s;
});
const coverStickerId =
uniqueStickers.length === stickers.length ? 0 : uniqueStickers.length - 1;
const coverStickerId = 0;
const coverStickerData = stickers[coverStickerId];
if (!coverStickerData) {
window.SignalContext.log.warn(
'encryptAndUpload: No coverStickerData with ' +
`index ${coverStickerId} and ${stickers.length} total stickers`
);
}
const coverSticker = new Proto.StickerPack.Sticker();
coverSticker.id = coverStickerId;
if (coverStickerData.emoji) {
if (coverStickerData?.emoji && coverSticker) {
coverSticker.emoji = coverStickerData.emoji;
} else {
coverSticker.emoji = '';
}
manifestProto.cover = coverSticker;
const encryptedManifest = await encrypt(

View File

@ -10,6 +10,7 @@ import type { ExecuteMenuRoleType } from './TitleBarContainer';
import type { LocaleMessagesType } from '../types/I18N';
import type { MenuOptionsType, MenuActionType } from '../types/menu';
import type { ToastType } from '../state/ducks/toast';
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
import { AppViewType } from '../state/ducks/app';
import { Inbox } from './Inbox';
import { SmartInstallScreen } from '../state/smart/InstallScreen';
@ -28,9 +29,9 @@ type PropsType = {
renderCallManager: () => JSX.Element;
renderGlobalModalContainer: () => JSX.Element;
isShowingStoriesView: boolean;
renderStories: () => JSX.Element;
renderStories: (closeView: () => unknown) => JSX.Element;
hasSelectedStoryData: boolean;
renderStoryViewer: () => JSX.Element;
renderStoryViewer: (closeView: () => unknown) => JSX.Element;
requestVerification: (
type: 'sms' | 'voice',
number: string,
@ -48,6 +49,8 @@ type PropsType = {
titleBarDoubleClick: () => void;
toastType?: ToastType;
hideToast: () => unknown;
toggleStoriesView: () => unknown;
viewStory: ViewStoryActionCreatorType;
} & ComponentProps<typeof Inbox>;
export const App = ({
@ -82,6 +85,8 @@ export const App = ({
theme,
titleBarDoubleClick,
toastType,
toggleStoriesView,
viewStory,
}: PropsType): JSX.Element => {
let contents;
@ -168,8 +173,9 @@ export const App = ({
<ToastManager hideToast={hideToast} i18n={i18n} toastType={toastType} />
{renderGlobalModalContainer()}
{renderCallManager()}
{isShowingStoriesView && renderStories()}
{hasSelectedStoryData && renderStoryViewer()}
{isShowingStoriesView && renderStories(toggleStoriesView)}
{hasSelectedStoryData &&
renderStoryViewer(() => viewStory({ closeViewer: true }))}
{contents}
</div>
</TitleBarContainer>

View File

@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { ReactNode } from 'react';
import type { ReactNode, ErrorInfo } from 'react';
import React from 'react';
import * as Errors from '../types/errors';
@ -10,6 +10,8 @@ import { ToastType } from '../state/ducks/toast';
export type Props = {
children: ReactNode;
name: string;
closeView?: () => unknown;
};
export type State = {
@ -24,14 +26,23 @@ export class ErrorBoundary extends React.PureComponent<Props, State> {
}
public static getDerivedStateFromError(error: Error): State {
return { error };
}
public override componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
const { closeView, name } = this.props;
log.error(
'ErrorBoundary: captured rendering error',
Errors.toLogFormat(error)
`ErrorBoundary/${name}: ` +
`captured rendering error ${Errors.toLogFormat(error)}` +
`\nerrorInfo: ${errorInfo.componentStack}`
);
if (window.reduxActions) {
window.reduxActions.toast.showToast(ToastType.Error);
}
return { error };
if (closeView) {
closeView();
}
}
public override render(): ReactNode {

View File

@ -972,7 +972,10 @@ export class Message extends React.PureComponent<Props, State> {
);
}
if (isImage(attachments) || isVideo(attachments)) {
if (
isImage(attachments) ||
(isVideo(attachments) && hasVideoScreenshot(attachments))
) {
const bottomOverlay = !isSticker && !collapseMetadata;
// We only want users to tab into this if there's more than one
const tabIndex = attachments.length > 1 ? 0 : -1;

View File

@ -4633,13 +4633,17 @@ function extractDiffs({
Boolean(current.expireTimer) &&
old.expireTimer !== current.expireTimer)
) {
const expireTimer = current.expireTimer || 0;
log.info(
`extractDiffs/${logId}: generating change notifcation for new ${expireTimer} timer`
);
timerNotification = {
...generateBasicMessage(),
type: 'timer-notification',
sourceUuid,
flags: Proto.DataMessage.Flags.EXPIRATION_TIMER_UPDATE,
expirationTimerUpdate: {
expireTimer: current.expireTimer || 0,
expireTimer,
sourceUuid,
},
};

View File

@ -5,6 +5,7 @@ import React from 'react';
import { Provider } from 'react-redux';
import type { Store } from 'redux';
import { ErrorBoundary } from '../../components/ErrorBoundary';
import type { PropsType } from '../smart/ConversationView';
import { SmartConversationView } from '../smart/ConversationView';
@ -14,6 +15,16 @@ export const createConversationView = (
props: PropsType
): React.ReactElement => (
<Provider store={store}>
<SmartConversationView {...props} />
<ErrorBoundary
name="createConversationView"
closeView={() => {
window.reduxActions.conversations.showConversation({
conversationId: undefined,
messageId: undefined,
});
}}
>
<SmartConversationView {...props} />
</ErrorBoundary>
</Provider>
);

View File

@ -51,14 +51,14 @@ const mapStateToProps = (state: StateType) => {
renderGlobalModalContainer: () => <SmartGlobalModalContainer />,
renderLeftPane: () => <SmartLeftPane />,
isShowingStoriesView: shouldShowStoriesView(state),
renderStories: () => (
<ErrorBoundary>
renderStories: (closeView: () => unknown) => (
<ErrorBoundary name="App/renderStories" closeView={closeView}>
<SmartStories />
</ErrorBoundary>
),
hasSelectedStoryData: hasSelectedStoryData(state),
renderStoryViewer: () => (
<ErrorBoundary>
renderStoryViewer: (closeView: () => unknown) => (
<ErrorBoundary name="App/renderStoryViewer" closeView={closeView}>
<SmartStoryViewer />
</ErrorBoundary>
),