Detect startup after recent crashes
This commit is contained in:
parent
02a732c511
commit
91f1b62bc7
23 changed files with 650 additions and 101 deletions
|
@ -9,6 +9,7 @@ import { actions as badges } from './ducks/badges';
|
|||
import { actions as calling } from './ducks/calling';
|
||||
import { actions as composer } from './ducks/composer';
|
||||
import { actions as conversations } from './ducks/conversations';
|
||||
import { actions as crashReports } from './ducks/crashReports';
|
||||
import { actions as emojis } from './ducks/emojis';
|
||||
import { actions as expiration } from './ducks/expiration';
|
||||
import { actions as globalModals } from './ducks/globalModals';
|
||||
|
@ -31,6 +32,7 @@ export const actionCreators: ReduxActions = {
|
|||
calling,
|
||||
composer,
|
||||
conversations,
|
||||
crashReports,
|
||||
emojis,
|
||||
expiration,
|
||||
globalModals,
|
||||
|
@ -53,6 +55,7 @@ export const mapDispatchToProps = {
|
|||
...calling,
|
||||
...composer,
|
||||
...conversations,
|
||||
...crashReports,
|
||||
...emojis,
|
||||
...expiration,
|
||||
...globalModals,
|
||||
|
|
135
ts/state/ducks/crashReports.ts
Normal file
135
ts/state/ducks/crashReports.ts
Normal file
|
@ -0,0 +1,135 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as log from '../../logging/log';
|
||||
import { showToast } from '../../util/showToast';
|
||||
import * as Errors from '../../types/errors';
|
||||
import { ToastLinkCopied } from '../../components/ToastLinkCopied';
|
||||
import { ToastDebugLogError } from '../../components/ToastDebugLogError';
|
||||
|
||||
// State
|
||||
|
||||
export type CrashReportsStateType = {
|
||||
count: number;
|
||||
isPending: boolean;
|
||||
};
|
||||
|
||||
// Actions
|
||||
|
||||
const SET_COUNT = 'crashReports/SET_COUNT';
|
||||
const UPLOAD = 'crashReports/UPLOAD';
|
||||
const ERASE = 'crashReports/ERASE';
|
||||
|
||||
type SetCrashReportCountActionType = {
|
||||
type: typeof SET_COUNT;
|
||||
payload: number;
|
||||
};
|
||||
|
||||
type PromiseAction<Type extends string, Payload = void> =
|
||||
| {
|
||||
type: Type;
|
||||
payload: Promise<Payload>;
|
||||
}
|
||||
| {
|
||||
type: `${Type}_PENDING`;
|
||||
}
|
||||
| {
|
||||
type: `${Type}_FULFILLED`;
|
||||
payload: Payload;
|
||||
}
|
||||
| {
|
||||
type: `${Type}_REJECTED`;
|
||||
error: true;
|
||||
payload: Error;
|
||||
};
|
||||
|
||||
type CrashReportsActionType =
|
||||
| SetCrashReportCountActionType
|
||||
| PromiseAction<typeof UPLOAD>
|
||||
| PromiseAction<typeof ERASE>;
|
||||
|
||||
// Action Creators
|
||||
|
||||
export const actions = {
|
||||
setCrashReportCount,
|
||||
uploadCrashReports,
|
||||
eraseCrashReports,
|
||||
};
|
||||
|
||||
function setCrashReportCount(count: number): SetCrashReportCountActionType {
|
||||
return { type: SET_COUNT, payload: count };
|
||||
}
|
||||
|
||||
function uploadCrashReports(): PromiseAction<typeof UPLOAD> {
|
||||
return { type: UPLOAD, payload: window.crashReports.upload() };
|
||||
}
|
||||
|
||||
function eraseCrashReports(): PromiseAction<typeof ERASE> {
|
||||
return { type: ERASE, payload: window.crashReports.erase() };
|
||||
}
|
||||
|
||||
// Reducer
|
||||
|
||||
export function getEmptyState(): CrashReportsStateType {
|
||||
return {
|
||||
count: 0,
|
||||
isPending: false,
|
||||
};
|
||||
}
|
||||
|
||||
export function reducer(
|
||||
state: Readonly<CrashReportsStateType> = getEmptyState(),
|
||||
action: Readonly<CrashReportsActionType>
|
||||
): CrashReportsStateType {
|
||||
if (action.type === SET_COUNT) {
|
||||
return {
|
||||
...state,
|
||||
count: action.payload,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
action.type === `${UPLOAD}_PENDING` ||
|
||||
action.type === `${ERASE}_PENDING`
|
||||
) {
|
||||
return {
|
||||
...state,
|
||||
isPending: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
action.type === `${UPLOAD}_FULFILLED` ||
|
||||
action.type === `${ERASE}_FULFILLED`
|
||||
) {
|
||||
if (action.type === `${UPLOAD}_FULFILLED`) {
|
||||
showToast(ToastLinkCopied);
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
count: 0,
|
||||
isPending: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
action.type === (`${UPLOAD}_REJECTED` as const) ||
|
||||
action.type === (`${ERASE}_REJECTED` as const)
|
||||
) {
|
||||
const { error } = action;
|
||||
|
||||
log.error(
|
||||
`Failed to upload crash report due to error ${Errors.toLogFormat(error)}`
|
||||
);
|
||||
|
||||
showToast(ToastDebugLogError);
|
||||
|
||||
return {
|
||||
...state,
|
||||
count: 0,
|
||||
isPending: false,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
|
@ -11,6 +11,7 @@ import { reducer as badges } from './ducks/badges';
|
|||
import { reducer as calling } from './ducks/calling';
|
||||
import { reducer as composer } from './ducks/composer';
|
||||
import { reducer as conversations } from './ducks/conversations';
|
||||
import { reducer as crashReports } from './ducks/crashReports';
|
||||
import { reducer as emojis } from './ducks/emojis';
|
||||
import { reducer as expiration } from './ducks/expiration';
|
||||
import { reducer as globalModals } from './ducks/globalModals';
|
||||
|
@ -33,6 +34,7 @@ export const reducer = combineReducers({
|
|||
calling,
|
||||
composer,
|
||||
conversations,
|
||||
crashReports,
|
||||
emojis,
|
||||
expiration,
|
||||
globalModals,
|
||||
|
|
19
ts/state/smart/CrashReportDialog.tsx
Normal file
19
ts/state/smart/CrashReportDialog.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { mapDispatchToProps } from '../actions';
|
||||
import { CrashReportDialog } from '../../components/CrashReportDialog';
|
||||
import type { StateType } from '../reducer';
|
||||
import { getIntl } from '../selectors/user';
|
||||
|
||||
const mapStateToProps = (state: StateType) => {
|
||||
return {
|
||||
...state.crashReports,
|
||||
i18n: getIntl(state),
|
||||
};
|
||||
};
|
||||
|
||||
const smart = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
export const SmartCrashReportDialog = smart(CrashReportDialog);
|
|
@ -58,6 +58,7 @@ import { SmartNetworkStatus } from './NetworkStatus';
|
|||
import { SmartRelinkDialog } from './RelinkDialog';
|
||||
import { SmartUpdateDialog } from './UpdateDialog';
|
||||
import { SmartCaptchaDialog } from './CaptchaDialog';
|
||||
import { SmartCrashReportDialog } from './CrashReportDialog';
|
||||
|
||||
function renderExpiredBuildDialog(
|
||||
props: Readonly<{ containerWidthBreakpoint: WidthBreakpoint }>
|
||||
|
@ -88,6 +89,9 @@ function renderUpdateDialog(
|
|||
function renderCaptchaDialog({ onSkip }: { onSkip(): void }): JSX.Element {
|
||||
return <SmartCaptchaDialog onSkip={onSkip} />;
|
||||
}
|
||||
function renderCrashReportDialog(): JSX.Element {
|
||||
return <SmartCrashReportDialog />;
|
||||
}
|
||||
|
||||
const getModeSpecificProps = (
|
||||
state: StateType
|
||||
|
@ -185,6 +189,7 @@ const mapStateToProps = (state: StateType) => {
|
|||
i18n: getIntl(state),
|
||||
regionCode: getRegionCode(state),
|
||||
challengeStatus: state.network.challengeStatus,
|
||||
crashReportCount: state.crashReports.count,
|
||||
renderExpiredBuildDialog,
|
||||
renderMainHeader,
|
||||
renderMessageSearchResult,
|
||||
|
@ -192,6 +197,7 @@ const mapStateToProps = (state: StateType) => {
|
|||
renderRelinkDialog,
|
||||
renderUpdateDialog,
|
||||
renderCaptchaDialog,
|
||||
renderCrashReportDialog,
|
||||
theme: getTheme(state),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ import type { actions as badges } from './ducks/badges';
|
|||
import type { actions as calling } from './ducks/calling';
|
||||
import type { actions as composer } from './ducks/composer';
|
||||
import type { actions as conversations } from './ducks/conversations';
|
||||
import type { actions as crashReports } from './ducks/crashReports';
|
||||
import type { actions as emojis } from './ducks/emojis';
|
||||
import type { actions as expiration } from './ducks/expiration';
|
||||
import type { actions as globalModals } from './ducks/globalModals';
|
||||
|
@ -30,6 +31,7 @@ export type ReduxActions = {
|
|||
calling: typeof calling;
|
||||
composer: typeof composer;
|
||||
conversations: typeof conversations;
|
||||
crashReports: typeof crashReports;
|
||||
emojis: typeof emojis;
|
||||
expiration: typeof expiration;
|
||||
globalModals: typeof globalModals;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue