From 31d1f25b186b74063013935165dfba9e34e0ae38 Mon Sep 17 00:00:00 2001
From: Josh Perez <60019601+josh-signal@users.noreply.github.com>
Date: Thu, 30 Sep 2021 16:13:47 -0400
Subject: [PATCH] Adds error dialog when voice recorder cannot start
---
_locales/en/messages.json | 4 ++
ts/components/ToastVoiceNoteError.tsx | 18 ++++++
ts/components/conversation/AudioCapture.tsx | 64 +++++++++++++--------
ts/services/audioRecorder.ts | 6 +-
ts/state/ducks/audioRecorder.ts | 15 ++++-
5 files changed, 80 insertions(+), 27 deletions(-)
create mode 100644 ts/components/ToastVoiceNoteError.tsx
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 1df758d9288..898e5395528 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -937,6 +937,10 @@
"message": "A voice message must have only one attachment.",
"description": "Shown in toast if tries to record a voice note with any staged attachments"
},
+ "voiceNoteError": {
+ "message": "There was an error with the voice recorder.",
+ "description": "Shown in a dialog to inform user that we experienced an unrecoverable error"
+ },
"attachmentSaved": {
"message": "Attachment saved. Click to show in folder.",
"description": "Shown after user selects to save to downloads",
diff --git a/ts/components/ToastVoiceNoteError.tsx b/ts/components/ToastVoiceNoteError.tsx
new file mode 100644
index 00000000000..b7eca40009e
--- /dev/null
+++ b/ts/components/ToastVoiceNoteError.tsx
@@ -0,0 +1,18 @@
+// Copyright 2021 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import React from 'react';
+import { LocalizerType } from '../types/Util';
+import { Toast } from './Toast';
+
+type PropsType = {
+ i18n: LocalizerType;
+ onClose: () => unknown;
+};
+
+export const ToastVoiceNoteLimit = ({
+ i18n,
+ onClose,
+}: PropsType): JSX.Element => {
+ return {i18n('voiceNoteError')};
+};
diff --git a/ts/components/conversation/AudioCapture.tsx b/ts/components/conversation/AudioCapture.tsx
index bdc781c4cf5..83450c8a841 100644
--- a/ts/components/conversation/AudioCapture.tsx
+++ b/ts/components/conversation/AudioCapture.tsx
@@ -147,16 +147,50 @@ export const AudioCapture = ({
);
}
- let confirmationDialogText: string | undefined;
- if (errorDialogAudioRecorderType === ErrorDialogAudioRecorderType.Blur) {
- confirmationDialogText = i18n('voiceRecordingInterruptedBlur');
- } else if (
+ let confirmationDialog: JSX.Element | undefined;
+ if (
+ errorDialogAudioRecorderType === ErrorDialogAudioRecorderType.Blur ||
errorDialogAudioRecorderType === ErrorDialogAudioRecorderType.Timeout
) {
- confirmationDialogText = i18n('voiceRecordingInterruptedMax');
+ const confirmationDialogText =
+ errorDialogAudioRecorderType === ErrorDialogAudioRecorderType.Blur
+ ? i18n('voiceRecordingInterruptedBlur')
+ : i18n('voiceRecordingInterruptedMax');
+
+ confirmationDialog = (
+
+ {confirmationDialogText}
+
+ );
+ } else if (
+ errorDialogAudioRecorderType === ErrorDialogAudioRecorderType.ErrorRecording
+ ) {
+ confirmationDialog = (
+
+ {i18n('voiceNoteError')}
+
+ );
}
- if (isRecording && !confirmationDialogText) {
+ if (isRecording && !confirmationDialog) {
return (
<>
@@ -203,23 +237,7 @@ export const AudioCapture = ({
title={i18n('voiceRecording--start')}
type="button"
/>
- {confirmationDialogText ? (
-
- {confirmationDialogText}
-
- ) : null}
+ {confirmationDialog}
{toastElement}
>
diff --git a/ts/services/audioRecorder.ts b/ts/services/audioRecorder.ts
index b770403a130..d6c29169e0e 100644
--- a/ts/services/audioRecorder.ts
+++ b/ts/services/audioRecorder.ts
@@ -68,8 +68,12 @@ export class RecorderClass {
this.source = this.context.createMediaStreamSource(stream);
this.source.connect(this.input);
} catch (err) {
- log.error('Recorder.onGetUserMediaError:', err);
+ log.error(
+ 'Recorder.onGetUserMediaError:',
+ err && err.stack ? err.stack : err
+ );
this.clear();
+ throw err;
}
if (this.recorder) {
diff --git a/ts/state/ducks/audioRecorder.ts b/ts/state/ducks/audioRecorder.ts
index 31ba18eaac6..73b0eaaad46 100644
--- a/ts/state/ducks/audioRecorder.ts
+++ b/ts/state/ducks/audioRecorder.ts
@@ -14,6 +14,7 @@ import { useBoundActions } from '../../hooks/useBoundActions';
export enum ErrorDialogAudioRecorderType {
Blur,
+ ErrorRecording,
Timeout,
}
@@ -69,14 +70,22 @@ function startRecording(): ThunkAction<
void,
RootStateType,
unknown,
- StartRecordingAction
+ StartRecordingAction | ErrorRecordingAction
> {
- return (dispatch, getState) => {
+ return async (dispatch, getState) => {
if (getState().composer.attachments.length) {
return;
}
- recorder.start();
+ try {
+ await recorder.start();
+ } catch (err) {
+ dispatch({
+ type: ERROR_RECORDING,
+ payload: ErrorDialogAudioRecorderType.ErrorRecording,
+ });
+ return;
+ }
dispatch({
type: START_RECORDING,