From 0677d8763d9b92bdef7008060b48b0adcf6cc4f3 Mon Sep 17 00:00:00 2001 From: Pranav Date: Sat, 5 Oct 2024 00:17:11 -0700 Subject: [PATCH] fix: Update the reply box to handle play, pause callbacks from WaveSurfer (#10223) - Implemented custom @play, @pause methods to update the state of the recording. Once the recording is finished the button icon changes from stop button to play/pause button. - Removes the console error undefined hasAudio Fixes https://linear.app/chatwoot/issue/CW-3609/audio-recorder-issue --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> --- .../widgets/WootWriter/AudioRecorder.vue | 16 +++- .../widgets/WootWriter/ReplyBottomPanel.vue | 7 +- .../widgets/conversation/ReplyBox.vue | 92 ++++++++++--------- 3 files changed, 59 insertions(+), 56 deletions(-) diff --git a/app/javascript/dashboard/components/widgets/WootWriter/AudioRecorder.vue b/app/javascript/dashboard/components/widgets/WootWriter/AudioRecorder.vue index 771e6f741..924e72c53 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/AudioRecorder.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/AudioRecorder.vue @@ -13,7 +13,12 @@ const props = defineProps({ }, }); -const emit = defineEmits(['recorderProgressChanged', 'finishRecord']); +const emit = defineEmits([ + 'recorderProgressChanged', + 'finishRecord', + 'pause', + 'play', +]); const waveformContainer = ref(null); const wavesurfer = ref(null); @@ -47,6 +52,9 @@ const initWaveSurfer = () => { ], }); + wavesurfer.value.on('pause', () => emit('pause')); + wavesurfer.value.on('play', () => emit('play')); + record.value = wavesurfer.value.plugins[0]; wavesurfer.value.on('finish', () => { @@ -106,11 +114,9 @@ onUnmounted(() => { } }); -defineExpose({ playPause, stopRecording }); +defineExpose({ playPause, stopRecording, record }); diff --git a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue index c146c0ec2..41491353e 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue @@ -35,7 +35,7 @@ export default { }, recordingAudioDurationText: { type: String, - default: '', + default: '00:00', }, // inbox prop is used in /mixins/inboxMixin, // remove this props when refactoring to composable if not needed @@ -259,7 +259,6 @@ export default { v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_EMOJI_ICON')" :title="$t('CONVERSATION.REPLYBOX.TIP_EMOJI_ICON')" icon="emoji" - emoji="😊" color-scheme="secondary" variant="smooth" size="small" @@ -285,7 +284,6 @@ export default { class-names="button--upload" :title="$t('CONVERSATION.REPLYBOX.TIP_ATTACH_ICON')" icon="attach" - emoji="📎" color-scheme="secondary" variant="smooth" size="small" @@ -295,7 +293,6 @@ export default { v-if="showAudioRecorderButton" v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_ICON')" :icon="!isRecordingAudio ? 'microphone' : 'microphone-off'" - emoji="🎤" :color-scheme="!isRecordingAudio ? 'secondary' : 'alert'" variant="smooth" size="small" @@ -305,7 +302,6 @@ export default { v-if="showEditorToggle" v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_FORMAT_ICON')" icon="quote" - emoji="🖊️" color-scheme="secondary" variant="smooth" size="small" @@ -314,7 +310,6 @@ export default { !file?.isRecordedAudio - ); - }, + toggleEmojiPicker() { this.showEmojiPicker = !this.showEmojiPicker; }, @@ -823,17 +813,18 @@ export default { this.isRecordingAudio = !this.isRecordingAudio; this.isRecorderAudioStopped = !this.isRecordingAudio; if (!this.isRecordingAudio) { - this.clearRecorder(); + this.resetAudioRecorderInput(); } }, toggleAudioRecorderPlayPause() { - if (this.isRecordingAudio) { - if (!this.isRecorderAudioStopped) { - this.isRecorderAudioStopped = true; - this.$refs.audioRecorderInput.stopRecording(); - } else if (this.isRecorderAudioStopped) { - this.$refs.audioRecorderInput.playPause(); - } + if (!this.isRecordingAudio) { + return; + } + if (!this.isRecorderAudioStopped) { + this.isRecorderAudioStopped = true; + this.$refs.audioRecorderInput.stopRecording(); + } else if (this.isRecorderAudioStopped) { + this.$refs.audioRecorderInput.playPause(); } }, hideEmojiPicker() { @@ -860,13 +851,9 @@ export default { onRecordProgressChanged(duration) { this.recordingAudioDurationText = duration; }, - onStateRecorderChanged(state) { - this.recordingAudioState = state; - if (state && 'notallowederror'.includes(state)) { - this.toggleAudioRecorder(); - } - }, onFinishRecorder(file) { + this.recordingAudioState = 'stopped'; + this.hasRecordedAudio = true; // Added a new key isRecordedAudio to the file to find it's and recorded audio // Because to filter and show only non recorded audio and other attachments const autoRecordedFile = { @@ -1067,6 +1054,16 @@ export default { toggleInsertArticle() { this.showArticleSearchPopover = !this.showArticleSearchPopover; }, + resetAudioRecorderInput() { + this.recordingAudioDurationText = '00:00'; + this.isRecordingAudio = false; + this.recordingAudioState = ''; + this.hasRecordedAudio = false; + // Only clear the recorded audio when we click toggle button. + this.attachedFiles = this.attachedFiles.filter( + file => !file?.isRecordedAudio + ); + }, }, }; @@ -1122,13 +1119,14 @@ export default { v-model:bcc-emails="bccEmails" v-model:to-emails="toEmails" /> - -
+