2022-01-11 20:02:46 +00:00
|
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
import type { ReadonlyDeep } from 'type-fest';
|
2024-01-29 20:09:54 +00:00
|
|
|
import type { ThunkAction } from 'redux-thunk';
|
|
|
|
|
2022-01-11 20:02:46 +00:00
|
|
|
import * as log from '../../logging/log';
|
|
|
|
import * as Errors from '../../types/errors';
|
2024-01-29 20:09:54 +00:00
|
|
|
import { ToastType } from '../../types/Toast';
|
|
|
|
import type { StateType as RootStateType } from '../reducer';
|
|
|
|
import { showToast } from './toast';
|
|
|
|
import type { ShowToastActionType } from './toast';
|
2022-10-18 17:12:02 +00:00
|
|
|
import type { PromiseAction } from '../util';
|
2024-03-13 20:44:13 +00:00
|
|
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
|
|
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
2022-01-11 20:02:46 +00:00
|
|
|
|
|
|
|
// State
|
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
export type CrashReportsStateType = ReadonlyDeep<{
|
2022-01-11 20:02:46 +00:00
|
|
|
count: number;
|
|
|
|
isPending: boolean;
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2022-01-11 20:02:46 +00:00
|
|
|
|
|
|
|
// Actions
|
|
|
|
|
|
|
|
const SET_COUNT = 'crashReports/SET_COUNT';
|
2024-02-13 21:41:48 +00:00
|
|
|
const WRITE_TO_LOG = 'crashReports/WRITE_TO_LOG';
|
2022-01-11 20:02:46 +00:00
|
|
|
const ERASE = 'crashReports/ERASE';
|
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
type SetCrashReportCountActionType = ReadonlyDeep<{
|
2022-01-11 20:02:46 +00:00
|
|
|
type: typeof SET_COUNT;
|
|
|
|
payload: number;
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2022-01-11 20:02:46 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
type CrashReportsActionType = ReadonlyDeep<
|
2022-01-11 20:02:46 +00:00
|
|
|
| SetCrashReportCountActionType
|
2024-02-13 21:41:48 +00:00
|
|
|
| PromiseAction<typeof WRITE_TO_LOG>
|
2023-01-13 20:07:26 +00:00
|
|
|
| PromiseAction<typeof ERASE>
|
|
|
|
>;
|
2022-01-11 20:02:46 +00:00
|
|
|
|
|
|
|
// Action Creators
|
|
|
|
|
|
|
|
export const actions = {
|
|
|
|
setCrashReportCount,
|
2024-02-13 21:41:48 +00:00
|
|
|
writeCrashReportsToLog,
|
2022-01-11 20:02:46 +00:00
|
|
|
eraseCrashReports,
|
|
|
|
};
|
|
|
|
|
2024-03-13 20:44:13 +00:00
|
|
|
export const useCrashReportsActions = (): BoundActionCreatorsMapObject<
|
|
|
|
typeof actions
|
|
|
|
> => useBoundActions(actions);
|
|
|
|
|
2022-01-11 20:02:46 +00:00
|
|
|
function setCrashReportCount(count: number): SetCrashReportCountActionType {
|
|
|
|
return { type: SET_COUNT, payload: count };
|
|
|
|
}
|
|
|
|
|
2024-02-13 21:41:48 +00:00
|
|
|
function writeCrashReportsToLog(): ThunkAction<
|
2024-01-29 20:09:54 +00:00
|
|
|
void,
|
|
|
|
RootStateType,
|
|
|
|
unknown,
|
2024-02-13 21:41:48 +00:00
|
|
|
PromiseAction<typeof WRITE_TO_LOG> | ShowToastActionType
|
2024-01-29 20:09:54 +00:00
|
|
|
> {
|
|
|
|
return dispatch => {
|
|
|
|
async function run() {
|
|
|
|
try {
|
2024-02-13 21:41:48 +00:00
|
|
|
await window.IPC.crashReports.writeToLog();
|
2024-01-29 20:09:54 +00:00
|
|
|
} catch (error) {
|
|
|
|
dispatch(showToast({ toastType: ToastType.DebugLogError }));
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
2024-02-13 21:41:48 +00:00
|
|
|
dispatch({ type: WRITE_TO_LOG, payload: run() });
|
2024-01-29 20:09:54 +00:00
|
|
|
};
|
2022-01-11 20:02:46 +00:00
|
|
|
}
|
|
|
|
|
2024-01-29 20:09:54 +00:00
|
|
|
function eraseCrashReports(): ThunkAction<
|
|
|
|
void,
|
|
|
|
RootStateType,
|
|
|
|
unknown,
|
|
|
|
PromiseAction<typeof ERASE> | ShowToastActionType
|
|
|
|
> {
|
|
|
|
return dispatch => {
|
|
|
|
async function run() {
|
|
|
|
try {
|
|
|
|
await window.IPC.crashReports.erase();
|
|
|
|
} catch (error) {
|
|
|
|
dispatch(showToast({ toastType: ToastType.DebugLogError }));
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dispatch({ type: ERASE, payload: run() });
|
|
|
|
};
|
2022-01-11 20:02:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 (
|
2024-02-13 21:41:48 +00:00
|
|
|
action.type === `${WRITE_TO_LOG}_PENDING` ||
|
2022-01-11 20:02:46 +00:00
|
|
|
action.type === `${ERASE}_PENDING`
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
isPending: true,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
2024-02-13 21:41:48 +00:00
|
|
|
action.type === `${WRITE_TO_LOG}_FULFILLED` ||
|
2022-01-11 20:02:46 +00:00
|
|
|
action.type === `${ERASE}_FULFILLED`
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
count: 0,
|
|
|
|
isPending: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
2024-02-13 21:41:48 +00:00
|
|
|
action.type === (`${WRITE_TO_LOG}_REJECTED` as const) ||
|
2022-01-11 20:02:46 +00:00
|
|
|
action.type === (`${ERASE}_REJECTED` as const)
|
|
|
|
) {
|
|
|
|
const { error } = action;
|
|
|
|
|
|
|
|
log.error(
|
2024-02-13 21:41:48 +00:00
|
|
|
`Failed to write crash report due to error ${Errors.toLogFormat(error)}`
|
2022-01-11 20:02:46 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
count: 0,
|
|
|
|
isPending: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|