Skip to content

Instantly share code, notes, and snippets.

@kkkrist
Created August 23, 2018 08:55
Show Gist options
  • Save kkkrist/6f985ee0f3e6d7c206fd399786262643 to your computer and use it in GitHub Desktop.
Save kkkrist/6f985ee0f3e6d7c206fd399786262643 to your computer and use it in GitHub Desktop.
Alternate UI for react-mic
import PropTypes from 'prop-types'
import React from 'react'
import { MicrophoneRecorder } from 'react-mic/lib/libs/MicrophoneRecorder'
import app from '../app'
import translate from '../../modules/translate'
import uploadAttachment from '../../modules/upload-attachment'
import Icon from './icon'
const uploadsService = app.service('uploads/:filename')
export default class AudioRecorder extends React.Component {
static propTypes = {
addModal: PropTypes.func.isRequired,
id: PropTypes.string.isRequired,
handleChange: PropTypes.func.isRequired,
url: PropTypes.string
}
constructor (props) {
super()
this.state = {
current: props.url,
library: props.url ? [props.url] : [],
recording: false,
uploading: false
}
if (window.MediaRecorder) {
this.microphoneRecorder = new MicrophoneRecorder(
this.handleStart,
this.handleStop,
{
audioBitsPerSecond: 128000,
mimeType: 'audio/webm;codecs=opus'
}
)
}
}
componentWillUnmount () {
this.cleanup(this.state.current)
}
cleanup = keep => {
this.state.library.map(url => {
if (url !== keep) {
uploadsService
.remove(url.slice(9).replace(/\/.*$/, ''))
.catch(console.error)
}
})
this.setState({
current: keep,
library: [keep]
})
}
handleDelete = () => {
this.props.handleChange({ correctionAudioUrl: null })
this.setState({
blobURL: null
})
}
handleRecording = () => {
if (this.state.recording) {
this.microphoneRecorder.stopRecording()
} else {
this.microphoneRecorder.startRecording()
}
}
handleStart = () => {
this.setState({ recording: true })
}
handleStop = file => {
file.blob.name = 'audio.ogg'
this.setState({ blobURL: file.blobURL, recording: false, uploading: true })
this.storeUpload(file.blob, this.props.id)
}
storeUpload = (result, id) => {
const { addModal, handleChange } = this.props
uploadAttachment(
{
file: result,
onError: error => {
addModal({
title: 'Fehler' + (error.code ? ' ' + error.code : ''),
body:
'Fehler beim Hochladen der Datei' +
(error.message ? `: ${translate(error.message)}` : '.'),
icon: 'faExclamationCircle',
cssClass: 'is-danger'
})
},
setAttributes: attributes => {
handleChange({ correctionAudioUrl: attributes.url })
this.setState(({ library }) => ({
library: library.concat([attributes.url]),
uploading: false
}))
}
},
id
)
}
render () {
const { url } = this.props
const { blobURL, recording, uploading } = this.state
if (!this.microphoneRecorder) {
return (
<div className='audio-recorder'>
<button className='button is-outlined' disabled type='button'>
<span className='icon'>
<Icon icon='faMicrophone' props={{ fixedWidth: true }} />
</span>
</button>
<span
className='help has-text-grey'
style={{ display: 'inline', marginLeft: '1em' }}
>
Audio-Kommentare sind z.Zt. leider nur mit Chrome oder Firefox
möglich.
</span>
</div>
)
} else {
return (
<div className='audio-recorder columns buttons has-addons'>
<div className='column is-narrow'>
<button
className={`button ${
recording ? 'is-danger is-breathing' : 'is-outlined'
}`}
disabled={!this.microphoneRecorder}
onClick={this.handleRecording}
type='button'
>
<span className='icon'>
<Icon
icon={uploading ? 'faSpinner' : 'faMicrophone'}
props={{ fixedWidth: true, pulse: uploading }}
/>
</span>
</button>
{(blobURL || (url && blobURL !== null)) && (
<button
className='button is-outlined'
disabled={recording || uploading}
onClick={this.handleDelete}
type='button'
>
<span className='icon'>
<Icon
icon='faTrash'
props={{ color: 'var(--color-danger)', fixedWidth: true }}
/>
</span>
</button>
)}
</div>
<div className='column is-narrow'>
{!recording &&
(blobURL || (url && blobURL !== null)) && (
<audio controls src={blobURL || url} />
)}
</div>
</div>
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment