Detect startup after recent crashes
This commit is contained in:
parent
02a732c511
commit
91f1b62bc7
23 changed files with 650 additions and 101 deletions
33
ts/components/CrashReportDialog.stories.tsx
Normal file
33
ts/components/CrashReportDialog.stories.tsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
|
||||
import { CrashReportDialog } from './CrashReportDialog';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import { sleep } from '../util/sleep';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
const story = storiesOf('Components/CrashReportDialog', module);
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
story.add('CrashReportDialog', () => {
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
return (
|
||||
<CrashReportDialog
|
||||
i18n={i18n}
|
||||
isPending={isPending}
|
||||
uploadCrashReports={async () => {
|
||||
setIsPending(true);
|
||||
action('uploadCrashReports')();
|
||||
await sleep(5000);
|
||||
setIsPending(false);
|
||||
}}
|
||||
eraseCrashReports={action('eraseCrashReports')}
|
||||
/>
|
||||
);
|
||||
});
|
68
ts/components/CrashReportDialog.tsx
Normal file
68
ts/components/CrashReportDialog.tsx
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { Modal } from './Modal';
|
||||
import { Spinner } from './Spinner';
|
||||
|
||||
type PropsActionsType = {
|
||||
uploadCrashReports: () => void;
|
||||
eraseCrashReports: () => void;
|
||||
};
|
||||
|
||||
type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
isPending: boolean;
|
||||
} & PropsActionsType;
|
||||
|
||||
export function CrashReportDialog(props: Readonly<PropsType>): JSX.Element {
|
||||
const { i18n, isPending, uploadCrashReports, eraseCrashReports } = props;
|
||||
|
||||
const onEraseClick = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
eraseCrashReports();
|
||||
};
|
||||
|
||||
const onSubmitClick = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
uploadCrashReports();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
moduleClassName="module-Modal--important"
|
||||
i18n={i18n}
|
||||
title={i18n('CrashReportDialog__title')}
|
||||
hasXButton
|
||||
onClose={eraseCrashReports}
|
||||
>
|
||||
<section>{i18n('CrashReportDialog__body')}</section>
|
||||
<Modal.ButtonFooter>
|
||||
<Button
|
||||
disabled={isPending}
|
||||
onClick={onEraseClick}
|
||||
variant={ButtonVariant.Secondary}
|
||||
>
|
||||
{i18n('CrashReportDialog__erase')}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isPending}
|
||||
onClick={onSubmitClick}
|
||||
ref={button => button?.focus()}
|
||||
variant={ButtonVariant.Primary}
|
||||
>
|
||||
{isPending ? (
|
||||
<Spinner size="22px" svgSize="small" />
|
||||
) : (
|
||||
i18n('CrashReportDialog__submit')
|
||||
)}
|
||||
</Button>
|
||||
</Modal.ButtonFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -10,6 +10,7 @@ import { storiesOf } from '@storybook/react';
|
|||
import type { PropsType } from './LeftPane';
|
||||
import { LeftPane, LeftPaneMode } from './LeftPane';
|
||||
import { CaptchaDialog } from './CaptchaDialog';
|
||||
import { CrashReportDialog } from './CrashReportDialog';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import { MessageSearchResult } from './conversationList/MessageSearchResult';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
|
@ -104,6 +105,7 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
['idle', 'required', 'pending'],
|
||||
'idle'
|
||||
),
|
||||
crashReportCount: select('challengeReportCount', [0, 1], 0),
|
||||
setChallengeStatus: action('setChallengeStatus'),
|
||||
renderExpiredBuildDialog: () => <div />,
|
||||
renderMainHeader: () => <div />,
|
||||
|
@ -134,6 +136,14 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
onSkip={action('onCaptchaSkip')}
|
||||
/>
|
||||
),
|
||||
renderCrashReportDialog: () => (
|
||||
<CrashReportDialog
|
||||
i18n={i18n}
|
||||
isPending={false}
|
||||
uploadCrashReports={action('uploadCrashReports')}
|
||||
eraseCrashReports={action('eraseCrashReports')}
|
||||
/>
|
||||
),
|
||||
selectedConversationId: undefined,
|
||||
selectedMessageId: undefined,
|
||||
savePreferredLeftPaneWidth: action('savePreferredLeftPaneWidth'),
|
||||
|
@ -633,6 +643,24 @@ story.add('Captcha dialog: pending', () => (
|
|||
/>
|
||||
));
|
||||
|
||||
// Crash report flow
|
||||
|
||||
story.add('Crash report dialog', () => (
|
||||
<LeftPane
|
||||
{...useProps({
|
||||
modeSpecificProps: {
|
||||
mode: LeftPaneMode.Inbox,
|
||||
pinnedConversations,
|
||||
conversations: defaultConversations,
|
||||
archivedConversations: [],
|
||||
isAboutToSearchInAConversation: false,
|
||||
startSearchCounter: 0,
|
||||
},
|
||||
crashReportCount: 42,
|
||||
})}
|
||||
/>
|
||||
));
|
||||
|
||||
// Set group metadata
|
||||
|
||||
story.add('Group Metadata: No Timer', () => (
|
||||
|
|
|
@ -92,6 +92,7 @@ export type PropsType = {
|
|||
canResizeLeftPane: boolean;
|
||||
challengeStatus: 'idle' | 'required' | 'pending';
|
||||
setChallengeStatus: (status: 'idle') => void;
|
||||
crashReportCount: number;
|
||||
theme: ThemeType;
|
||||
|
||||
// Action Creators
|
||||
|
@ -144,12 +145,14 @@ export type PropsType = {
|
|||
_: Readonly<{ containerWidthBreakpoint: WidthBreakpoint }>
|
||||
) => JSX.Element;
|
||||
renderCaptchaDialog: (props: { onSkip(): void }) => JSX.Element;
|
||||
renderCrashReportDialog: () => JSX.Element;
|
||||
};
|
||||
|
||||
export const LeftPane: React.FC<PropsType> = ({
|
||||
cantAddContactToGroup,
|
||||
canResizeLeftPane,
|
||||
challengeStatus,
|
||||
crashReportCount,
|
||||
clearGroupCreationError,
|
||||
clearSearch,
|
||||
closeCantAddContactToGroupModal,
|
||||
|
@ -165,6 +168,7 @@ export const LeftPane: React.FC<PropsType> = ({
|
|||
openConversationInternal,
|
||||
preferredWidthFromStorage,
|
||||
renderCaptchaDialog,
|
||||
renderCrashReportDialog,
|
||||
renderExpiredBuildDialog,
|
||||
renderMainHeader,
|
||||
renderMessageSearchResult,
|
||||
|
@ -641,6 +645,7 @@ export const LeftPane: React.FC<PropsType> = ({
|
|||
setChallengeStatus('idle');
|
||||
},
|
||||
})}
|
||||
{crashReportCount > 0 && renderCrashReportDialog()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue