spee.ch/react/containers/PublishThumbnailInput/view.jsx

141 lines
4.4 KiB
React
Raw Normal View History

2018-01-04 23:14:03 +01:00
import React from 'react';
2018-03-02 05:09:22 +01:00
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
let byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i++) {
2018-03-02 05:09:22 +01:00
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type: mimeString});
}
2018-01-17 19:49:57 +01:00
class PublishThumbnailInput extends React.Component {
2018-01-11 02:41:17 +01:00
constructor (props) {
super(props);
this.state = {
2018-03-01 06:25:51 +01:00
videoSource : null,
error : null,
sliderMinRange: 1,
sliderMaxRange: null,
sliderValue : null,
2018-03-01 02:28:47 +01:00
};
2018-03-01 06:25:51 +01:00
this.handleVideoLoadedData = this.handleVideoLoadedData.bind(this);
this.handleSliderChange = this.handleSliderChange.bind(this);
this.createThumbnail = this.createThumbnail.bind(this);
2018-01-11 02:41:17 +01:00
}
2018-02-06 03:14:12 +01:00
componentDidMount () {
const { file } = this.props;
this.setVideoSource(file);
2018-02-06 03:14:12 +01:00
}
componentWillReceiveProps (nextProps) {
// if file changes
if (nextProps.file && nextProps.file !== this.props.file) {
const { file } = nextProps;
this.setVideoSource(file);
};
2018-01-17 21:54:26 +01:00
}
setVideoSource (file) {
2018-03-01 06:25:51 +01:00
const previewReader = new FileReader();
previewReader.readAsDataURL(file);
previewReader.onloadend = () => {
const dataUri = previewReader.result;
const blob = dataURItoBlob(dataUri);
const videoSource = URL.createObjectURL(blob);
this.setState({ videoSource });
2018-03-01 06:25:51 +01:00
};
2018-01-11 02:41:17 +01:00
}
2018-03-01 06:25:51 +01:00
handleVideoLoadedData (event) {
const duration = event.target.duration;
2018-03-06 07:45:39 +01:00
const totalMinutes = Math.floor(duration / 60);
const totalSeconds = Math.floor(duration % 60);
2018-03-01 06:25:51 +01:00
// set the slider
this.setState({
sliderMaxRange: duration * 100,
sliderValue : duration * 100 / 2,
2018-03-06 07:45:39 +01:00
totalMinutes,
totalSeconds,
2018-01-11 02:41:17 +01:00
});
2018-03-01 06:25:51 +01:00
// update the current time of the video
let video = document.getElementById('video-thumb-player');
video.currentTime = duration / 2;
2018-01-11 02:41:17 +01:00
}
2018-03-01 06:25:51 +01:00
handleSliderChange (event) {
const value = parseInt(event.target.value);
// update the slider value
this.setState({
sliderValue: value,
});
// update the current time of the video
let video = document.getElementById('video-thumb-player');
video.currentTime = value / 100;
2018-02-06 03:14:12 +01:00
}
createThumbnail () {
2018-03-01 06:25:51 +01:00
// take a snapshot
let video = document.getElementById('video-thumb-player');
let canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
const dataUrl = canvas.toDataURL();
const blob = dataURItoBlob(dataUrl);
const snapshot = new File([blob], `thumbnail.png`, {
type: 'image/png',
});
// set the thumbnail in redux store
if (snapshot) {
this.props.onNewThumbnail(snapshot);
}
2018-01-11 02:41:17 +01:00
}
2018-01-04 23:14:03 +01:00
render () {
2018-03-06 07:45:39 +01:00
const { error, videoSource, sliderMinRange, sliderMaxRange, sliderValue, totalMinutes, totalSeconds } = this.state;
2018-01-04 23:14:03 +01:00
return (
2018-01-11 21:51:38 +01:00
<div>
2018-03-06 07:45:39 +01:00
<label className='label'>Thumbnail:</label>
<video
id='video-thumb-player'
preload='metadata'
muted
style={{display: 'none'}}
playsInline
onLoadedData={this.handleVideoLoadedData}
src={videoSource}
onSeeked={this.createThumbnail}
/>
{
sliderValue ? (
<div>
<div className='flex-container--row flex-container--space-between-center' style={{width: '100%'}}>
<span className='info-message'>0'00"</span>
<span className='info-message'>{totalMinutes}'{totalSeconds}"</span>
</div>
<div>
2018-03-01 06:25:51 +01:00
<input
type='range'
min={sliderMinRange}
max={sliderMaxRange}
value={sliderValue}
className='slider'
onChange={this.handleSliderChange}
/>
</div>
2018-03-06 07:45:39 +01:00
</div>
) : (
<p className='info-message' >loading... </p>
)
}
{ error ? (
<p className='info-message--failure'>{error}</p>
) : (
<p className='info-message'>Use slider to set thumbnail</p>
)}
2018-01-04 23:14:03 +01:00
</div>
);
}
}
2018-01-17 19:49:57 +01:00
export default PublishThumbnailInput;