ErrorBoundary improvements, StickerCreator logging/resiliency
This commit is contained in:
parent
0fb45f045d
commit
6dd6a64d6c
8 changed files with 67 additions and 19 deletions
|
@ -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],
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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}>
|
||||
<ErrorBoundary
|
||||
name="createConversationView"
|
||||
closeView={() => {
|
||||
window.reduxActions.conversations.showConversation({
|
||||
conversationId: undefined,
|
||||
messageId: undefined,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<SmartConversationView {...props} />
|
||||
</ErrorBoundary>
|
||||
</Provider>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue