169169 </transition >
170170
171171 <div class =" box-footer" >
172+ <div class =" icon-textarea-left" v-if =" showAudio" >
173+ <div class =" svg-button" @click =" recordAudio" >
174+ <slot
175+ v-if =" recorder.state === 'recording'"
176+ name =" microphone-off-icon"
177+ >
178+ <svg-icon name =" microphone-off" />
179+ </slot >
180+ <slot v-else name =" microphone-icon" >
181+ <svg-icon name =" microphone" />
182+ </slot >
183+ </div >
184+ </div >
185+
172186 <div
173187 class =" image-container"
174188 :class =" { 'image-container-right': textareaAction }"
202216 </div >
203217 </div >
204218
205- <div class =" icon-textarea-left" v-if =" textareaAction" >
206- <div class =" svg-button" @click =" textareaActionHandler" >
207- <slot name =" custom-action-icon" >
208- <svg-icon name =" microphone" />
209- </slot >
210- </div >
211- </div >
212-
213219 <textarea
214220 v-show =" !file || imageFile"
215221 ref =" roomTextarea"
@@ -324,6 +330,7 @@ export default {
324330 messageActions: { type: Array , required: true },
325331 showSendIcon: { type: Boolean , required: true },
326332 showFiles: { type: Boolean , required: true },
333+ showAudio: { type: Boolean , required: true },
327334 showEmojis: { type: Boolean , required: true },
328335 showReactionEmojis: { type: Boolean , required: true },
329336 showNewMessagesDivider: { type: Boolean , required: true },
@@ -349,7 +356,10 @@ export default {
349356 emojisList: {},
350357 hideOptions: true ,
351358 scrollIcon: false ,
352- newMessages: []
359+ newMessages: [],
360+ recorderStream: {},
361+ recorder: {},
362+ recordedChunks: []
353363 }
354364 },
355365
@@ -501,6 +511,48 @@ export default {
501511 },
502512
503513 methods: {
514+ async recordAudio () {
515+ if (this .recorder .state === ' recording' ) {
516+ this .recorder .stop ()
517+ } else {
518+ this .recordedChunk = await this .startRecording ()
519+ }
520+ },
521+ async startRecording () {
522+ const stream = await navigator .mediaDevices .getUserMedia ({
523+ audio: true ,
524+ video: false
525+ })
526+
527+ this .recorder = new MediaRecorder (stream)
528+
529+ this .recorder .ondataavailable = e => this .recordedChunks .push (e .data )
530+ this .recorder .start ()
531+
532+ const stopped = new Promise ((resolve , reject ) => {
533+ this .recorder .onstop = resolve
534+ this .recorder .onerror = event => reject (event .name )
535+ })
536+
537+ stopped .then (() => {
538+ stream .getTracks ().forEach (track => track .stop ())
539+
540+ const recordedBlob = new Blob (this .recordedChunks , {
541+ type: ' audio/ogg; codecs="opus"'
542+ })
543+
544+ this .file = {
545+ blob: recordedBlob,
546+ name: ' audio' ,
547+ size: recordedBlob .size ,
548+ type: recordedBlob .type ,
549+ audio: true ,
550+ localUrl: URL .createObjectURL (recordedBlob)
551+ }
552+
553+ this .message = ' audio'
554+ })
555+ },
504556 addNewMessage (message ) {
505557 this .newMessages .push (message)
506558 },
0 commit comments