Improve UI around Voice Message limits
This commit is contained in:
parent
148aedeeb4
commit
2138395bcb
4 changed files with 48 additions and 2 deletions
|
@ -777,6 +777,18 @@
|
|||
"message": "Original message found, but not loaded. Scroll up to load it.",
|
||||
"description": "Shown in toast if user clicks on quote references messages not loaded in view, but in database"
|
||||
},
|
||||
"voiceRecordingInterruptedMax": {
|
||||
"message": "Voice message recording stopped because the maximum time limit was reached.",
|
||||
"description": "Confirmation dialog message for when the voice recording is interrupted due to max time limit"
|
||||
},
|
||||
"voiceRecordingInterruptedBlur": {
|
||||
"message": "Voice message recording stopped because you switched to another app.",
|
||||
"description": "Confirmation dialog message for when the voice recording is interrupted due to app losing focus"
|
||||
},
|
||||
"voiceNoteLimit": {
|
||||
"message": "Voice messages are limited to five minutes. Recording will stop if you switch to another app.",
|
||||
"description": "Shown in toast to warn user about limited time and that window must be in focus"
|
||||
},
|
||||
"voiceNoteMustBeOnlyAttachment": {
|
||||
"message": "A voice message must have only one attachment.",
|
||||
"description": "Shown in toast if tries to record a voice note with any staged attachments"
|
||||
|
@ -863,6 +875,9 @@
|
|||
"cancel": {
|
||||
"message": "Cancel"
|
||||
},
|
||||
"discard": {
|
||||
"message": "Discard"
|
||||
},
|
||||
"failedToSend": {
|
||||
"message": "Failed to send to some recipients. Check your network connection."
|
||||
},
|
||||
|
|
|
@ -75,6 +75,11 @@
|
|||
return { toastMessage: i18n('messageFoundButNotLoaded') };
|
||||
},
|
||||
});
|
||||
Whisper.VoiceNoteLimit = Whisper.ToastView.extend({
|
||||
render_attributes() {
|
||||
return { toastMessage: i18n('voiceNoteLimit') };
|
||||
},
|
||||
});
|
||||
Whisper.VoiceNoteMustBeOnlyAttachmentToast = Whisper.ToastView.extend({
|
||||
render_attributes() {
|
||||
return { toastMessage: i18n('voiceNoteMustBeOnlyAttachment') };
|
||||
|
@ -1650,6 +1655,8 @@
|
|||
return;
|
||||
}
|
||||
|
||||
this.showToast(Whisper.VoiceNoteLimit);
|
||||
|
||||
// Note - clicking anywhere will close the audio capture panel, due to
|
||||
// the onClick handler in InboxView, which calls its closeRecording method.
|
||||
|
||||
|
@ -1663,6 +1670,7 @@
|
|||
const view = this.captureAudioView;
|
||||
view.render();
|
||||
view.on('send', this.handleAudioCapture.bind(this));
|
||||
view.on('confirm', this.handleAudioConfirm.bind(this));
|
||||
view.on('closed', this.endCaptureAudio.bind(this));
|
||||
view.$el.appendTo(this.$('.capture-audio'));
|
||||
view.$('.finish').focus();
|
||||
|
@ -1671,6 +1679,19 @@
|
|||
this.disableMessageField();
|
||||
this.$('.microphone').hide();
|
||||
},
|
||||
handleAudioConfirm(blob, lostFocus) {
|
||||
const dialog = new Whisper.ConfirmationDialogView({
|
||||
cancelText: i18n('discard'),
|
||||
message: lostFocus ? i18n('voiceRecordingInterruptedBlur') : i18n('voiceRecordingInterruptedMax'),
|
||||
okText: i18n('sendAnyway'),
|
||||
resolve: async () => {
|
||||
await this.handleAudioCapture(blob);
|
||||
},
|
||||
});
|
||||
|
||||
this.$el.prepend(dialog.el);
|
||||
dialog.focusCancel();
|
||||
},
|
||||
async handleAudioCapture(blob) {
|
||||
if (this.hasFiles()) {
|
||||
throw new Error('A voice note cannot be sent with other attachments');
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
close: 'close',
|
||||
},
|
||||
onSwitchAway() {
|
||||
this.lostFocus = true;
|
||||
this.recorder.finishRecording();
|
||||
this.close();
|
||||
},
|
||||
handleKeyDown(event) {
|
||||
|
@ -89,11 +91,14 @@
|
|||
handleBlob(recorder, blob) {
|
||||
if (blob && this.clickedFinish) {
|
||||
this.trigger('send', blob);
|
||||
} else if (blob) {
|
||||
this.trigger('confirm', blob, this.lostFocus);
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
start() {
|
||||
this.lostFocus = false;
|
||||
this.clickedFinish = false;
|
||||
this.context = new AudioContext();
|
||||
this.input = this.context.createGain();
|
||||
|
@ -103,6 +108,7 @@
|
|||
});
|
||||
this.recorder.onComplete = this.handleBlob.bind(this);
|
||||
this.recorder.onError = this.onError.bind(this);
|
||||
this.recorder.onTimeout = this.onTimeout.bind(this);
|
||||
navigator.webkitGetUserMedia(
|
||||
{ audio: true },
|
||||
stream => {
|
||||
|
@ -113,6 +119,10 @@
|
|||
);
|
||||
this.recorder.startRecording();
|
||||
},
|
||||
onTimeout() {
|
||||
this.recorder.finishRecording();
|
||||
this.close();
|
||||
},
|
||||
onError(error) {
|
||||
// Protect against out-of-band errors, which can happen if the user revokes media
|
||||
// permissions after successfully accessing the microphone.
|
||||
|
|
|
@ -793,7 +793,7 @@
|
|||
"rule": "jQuery-$(",
|
||||
"path": "js/views/recorder_view.js",
|
||||
"line": " this.$('.time').text(`${minutes}:${seconds}`);",
|
||||
"lineNumber": 49,
|
||||
"lineNumber": 50,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2018-09-19T21:59:32.770Z",
|
||||
"reasonDetail": "Protected from arbitrary input"
|
||||
|
@ -802,7 +802,7 @@
|
|||
"rule": "jQuery-$(",
|
||||
"path": "js/views/recorder_view.js",
|
||||
"line": " $(window).off('blur', this.onSwitchAwayBound);",
|
||||
"lineNumber": 80,
|
||||
"lineNumber": 81,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2018-10-11T19:22:47.331Z",
|
||||
"reasonDetail": "Operating on already-existing DOM elements"
|
||||
|
|
Loading…
Reference in a new issue