@uppy/webcam
Advanced tools
Comparing version 1.8.8 to 1.8.9
@@ -0,1 +1,3 @@ | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } | ||
@@ -5,2 +7,3 @@ | ||
/* eslint-disable jsx-a11y/media-has-caption */ | ||
var _require = require('preact'), | ||
@@ -18,2 +21,6 @@ h = _require.h, | ||
var SubmitButton = require('./SubmitButton'); | ||
var DiscardButton = require('./DiscardButton'); | ||
function isModeAvailable(modes, mode) { | ||
@@ -33,14 +40,54 @@ return modes.indexOf(mode) !== -1; | ||
_proto.componentDidMount = function componentDidMount() { | ||
this.props.onFocus(); | ||
var onFocus = this.props.onFocus; | ||
onFocus(); | ||
}; | ||
_proto.componentWillUnmount = function componentWillUnmount() { | ||
this.props.onStop(); | ||
var onStop = this.props.onStop; | ||
onStop(); | ||
}; | ||
_proto.render = function render() { | ||
var shouldShowRecordButton = this.props.supportsRecording && (isModeAvailable(this.props.modes, 'video-only') || isModeAvailable(this.props.modes, 'audio-only') || isModeAvailable(this.props.modes, 'video-audio')); | ||
var shouldShowSnapshotButton = isModeAvailable(this.props.modes, 'picture'); | ||
var shouldShowRecordingLength = this.props.supportsRecording && this.props.showRecordingLength; | ||
var shouldShowVideoSourceDropdown = this.props.showVideoSourceDropdown && this.props.videoSources && this.props.videoSources.length > 1; | ||
var _this = this; | ||
var _this$props = this.props, | ||
src = _this$props.src, | ||
recordedVideo = _this$props.recordedVideo, | ||
recording = _this$props.recording, | ||
modes = _this$props.modes, | ||
supportsRecording = _this$props.supportsRecording, | ||
videoSources = _this$props.videoSources, | ||
showVideoSourceDropdown = _this$props.showVideoSourceDropdown, | ||
showRecordingLength = _this$props.showRecordingLength, | ||
onSubmit = _this$props.onSubmit, | ||
i18n = _this$props.i18n, | ||
mirror = _this$props.mirror, | ||
onSnapshot = _this$props.onSnapshot, | ||
onStartRecording = _this$props.onStartRecording, | ||
onStopRecording = _this$props.onStopRecording, | ||
onDiscardRecordedVideo = _this$props.onDiscardRecordedVideo, | ||
recordingLengthSeconds = _this$props.recordingLengthSeconds; | ||
var hasRecordedVideo = !!recordedVideo; | ||
var shouldShowRecordButton = !hasRecordedVideo && supportsRecording && (isModeAvailable(modes, 'video-only') || isModeAvailable(modes, 'audio-only') || isModeAvailable(modes, 'video-audio')); | ||
var shouldShowSnapshotButton = !hasRecordedVideo && isModeAvailable(modes, 'picture'); | ||
var shouldShowRecordingLength = supportsRecording && showRecordingLength; | ||
var shouldShowVideoSourceDropdown = showVideoSourceDropdown && videoSources && videoSources.length > 1; | ||
var videoProps = { | ||
playsinline: true | ||
}; | ||
if (recordedVideo) { | ||
videoProps.muted = false; | ||
videoProps.controls = true; | ||
videoProps.src = recordedVideo; // reset srcObject in dom. If not resetted, stream sticks in element | ||
if (this.videoElement) { | ||
this.videoElement.srcObject = undefined; | ||
} | ||
} else { | ||
videoProps.muted = true; | ||
videoProps.autoplay = true; | ||
videoProps.srcObject = src; | ||
} | ||
return h("div", { | ||
@@ -50,9 +97,11 @@ className: "uppy uppy-Webcam-container" | ||
className: "uppy-Webcam-videoContainer" | ||
}, h("video", { | ||
className: "uppy-Webcam-video " + (this.props.mirror ? 'uppy-Webcam-video--mirrored' : ''), | ||
autoPlay: true, | ||
muted: true, | ||
playsinline: true, | ||
srcObject: this.props.src || '' | ||
})), h("div", { | ||
}, h("video", _extends({ | ||
/* eslint-disable-next-line no-return-assign */ | ||
ref: function ref(videoElement) { | ||
return _this.videoElement = videoElement; | ||
}, | ||
className: "uppy-Webcam-video " + (mirror ? 'uppy-Webcam-video--mirrored' : '') | ||
/* eslint-disable-next-line react/jsx-props-no-spreading */ | ||
}, videoProps))), h("div", { | ||
className: "uppy-Webcam-footer" | ||
@@ -63,5 +112,22 @@ }, h("div", { | ||
className: "uppy-Webcam-buttonContainer" | ||
}, shouldShowSnapshotButton ? SnapshotButton(this.props) : null, ' ', shouldShowRecordButton ? RecordButton(this.props) : null), h("div", { | ||
}, shouldShowSnapshotButton && h(SnapshotButton, { | ||
onSnapshot: onSnapshot, | ||
i18n: i18n | ||
}), shouldShowRecordButton && h(RecordButton, { | ||
recording: recording, | ||
onStartRecording: onStartRecording, | ||
onStopRecording: onStopRecording, | ||
i18n: i18n | ||
}), hasRecordedVideo && h(SubmitButton, { | ||
onSubmit: onSubmit, | ||
i18n: i18n | ||
}), hasRecordedVideo && h(DiscardButton, { | ||
onDiscard: onDiscardRecordedVideo, | ||
i18n: i18n | ||
})), shouldShowRecordingLength && h("div", { | ||
className: "uppy-Webcam-recordingLength" | ||
}, shouldShowRecordingLength ? RecordingLength(this.props) : null))); | ||
}, h(RecordingLength, { | ||
recordingLengthSeconds: recordingLengthSeconds, | ||
i18n: i18n | ||
})))); | ||
}; | ||
@@ -68,0 +134,0 @@ |
153
lib/index.js
@@ -32,2 +32,4 @@ var _class, _temp; | ||
var PermissionsScreen = require('./PermissionsScreen'); | ||
var packageJsonVersion = "1.8.9"; | ||
/** | ||
@@ -40,3 +42,2 @@ * Normalize a MIME type or file extension into a MIME type. | ||
function toMimeType(fileType) { | ||
@@ -111,3 +112,4 @@ if (fileType[0] === '.') { | ||
_this.mediaDevices = getMediaDevices(); | ||
_this.supportsUserMedia = !!_this.mediaDevices; | ||
_this.supportsUserMedia = !!_this.mediaDevices; // eslint-disable-next-line no-restricted-globals | ||
_this.protocol = location.protocol.match(/https/i) ? 'https' : 'http'; | ||
@@ -117,2 +119,3 @@ _this.id = _this.opts.id || 'Webcam'; | ||
_this.type = 'acquirer'; | ||
_this.capturedMediaFile = null; | ||
@@ -153,3 +156,5 @@ _this.icon = function () { | ||
recordingStoppedMaxSize: 'Recording stopped because the file size is about to exceed the limit', | ||
recordingLength: 'Recording length %{recording_length}' | ||
recordingLength: 'Recording length %{recording_length}', | ||
submitRecordedFile: 'Submit recorded file', | ||
discardRecordedFile: 'Discard recorded file' | ||
} | ||
@@ -179,14 +184,16 @@ }; // set default options | ||
_this._start = _this._start.bind(_assertThisInitialized(_this)); | ||
_this._stop = _this._stop.bind(_assertThisInitialized(_this)); | ||
_this._takeSnapshot = _this._takeSnapshot.bind(_assertThisInitialized(_this)); | ||
_this._startRecording = _this._startRecording.bind(_assertThisInitialized(_this)); | ||
_this._stopRecording = _this._stopRecording.bind(_assertThisInitialized(_this)); | ||
_this._oneTwoThreeSmile = _this._oneTwoThreeSmile.bind(_assertThisInitialized(_this)); | ||
_this._focus = _this._focus.bind(_assertThisInitialized(_this)); | ||
_this._changeVideoSource = _this._changeVideoSource.bind(_assertThisInitialized(_this)); | ||
_this.start = _this.start.bind(_assertThisInitialized(_this)); | ||
_this.stop = _this.stop.bind(_assertThisInitialized(_this)); | ||
_this.takeSnapshot = _this.takeSnapshot.bind(_assertThisInitialized(_this)); | ||
_this.startRecording = _this.startRecording.bind(_assertThisInitialized(_this)); | ||
_this.stopRecording = _this.stopRecording.bind(_assertThisInitialized(_this)); | ||
_this.discardRecordedVideo = _this.discardRecordedVideo.bind(_assertThisInitialized(_this)); | ||
_this.submit = _this.submit.bind(_assertThisInitialized(_this)); | ||
_this.oneTwoThreeSmile = _this.oneTwoThreeSmile.bind(_assertThisInitialized(_this)); | ||
_this.focus = _this.focus.bind(_assertThisInitialized(_this)); | ||
_this.changeVideoSource = _this.changeVideoSource.bind(_assertThisInitialized(_this)); | ||
_this.webcamActive = false; | ||
if (_this.opts.countdown) { | ||
_this.opts.onBeforeSnapshot = _this._oneTwoThreeSmile; | ||
_this.opts.onBeforeSnapshot = _this.oneTwoThreeSmile; | ||
} | ||
@@ -260,5 +267,6 @@ | ||
}; | ||
}; | ||
} // eslint-disable-next-line consistent-return | ||
; | ||
_proto._start = function _start(options) { | ||
_proto.start = function start(options) { | ||
var _this2 = this; | ||
@@ -275,2 +283,3 @@ | ||
this.webcamActive = true; | ||
this.opts.mirror = true; | ||
var constraints = this.getConstraints(options && options.deviceId ? options.deviceId : null); | ||
@@ -320,3 +329,3 @@ this.hasCameraCheck().then(function (hasCamera) { | ||
_proto._getMediaRecorderOptions = function _getMediaRecorderOptions() { | ||
_proto.getMediaRecorderOptions = function getMediaRecorderOptions() { | ||
var options = {}; // Try to use the `opts.preferredVideoMimeType` or one of the `allowedFileTypes` for the recording. | ||
@@ -336,7 +345,10 @@ // If the browser doesn't support it, we'll fall back to the browser default instead. | ||
var acceptableMimeTypes = preferredVideoMimeTypes.filter(function (candidateType) { | ||
var filterSupportedTypes = function filterSupportedTypes(candidateType) { | ||
return MediaRecorder.isTypeSupported(candidateType) && getFileTypeExtension(candidateType); | ||
}); | ||
}; | ||
var acceptableMimeTypes = preferredVideoMimeTypes.filter(filterSupportedTypes); | ||
if (acceptableMimeTypes.length > 0) { | ||
// eslint-disable-next-line prefer-destructuring | ||
options.mimeType = acceptableMimeTypes[0]; | ||
@@ -349,3 +361,3 @@ } | ||
_proto._startRecording = function _startRecording() { | ||
_proto.startRecording = function startRecording() { | ||
var _this3 = this; | ||
@@ -355,3 +367,3 @@ | ||
// eslint-disable-next-line compat/compat | ||
this.recorder = new MediaRecorder(this.stream, this._getMediaRecorderOptions()); | ||
this.recorder = new MediaRecorder(this.stream, this.getMediaRecorderOptions()); | ||
this.recordingChunks = []; | ||
@@ -379,3 +391,3 @@ var stoppingBecauseOfMaxSize = false; | ||
_this3._stopRecording(); | ||
_this3.stopRecording(); | ||
} | ||
@@ -404,6 +416,6 @@ } | ||
_proto._stopRecording = function _stopRecording() { | ||
_proto.stopRecording = function stopRecording() { | ||
var _this4 = this; | ||
var stopped = new Promise(function (resolve, reject) { | ||
var stopped = new Promise(function (resolve) { | ||
_this4.recorder.addEventListener('stop', function () { | ||
@@ -432,3 +444,10 @@ resolve(); | ||
try { | ||
_this4.uppy.addFile(file); | ||
_this4.capturedMediaFile = file; // create object url for capture result preview | ||
_this4.setPluginState({ | ||
// eslint-disable-next-line compat/compat | ||
recordedVideo: URL.createObjectURL(file.data) | ||
}); | ||
_this4.opts.mirror = false; | ||
} catch (err) { | ||
@@ -450,3 +469,24 @@ // Logging the error, exept restrictions, which is handled in Core | ||
_proto._stop = function _stop() { | ||
_proto.discardRecordedVideo = function discardRecordedVideo() { | ||
this.setPluginState({ | ||
recordedVideo: null | ||
}); | ||
this.opts.mirror = true; | ||
this.capturedMediaFile = null; | ||
}; | ||
_proto.submit = function submit() { | ||
try { | ||
if (this.capturedMediaFile) { | ||
this.uppy.addFile(this.capturedMediaFile); | ||
} | ||
} catch (err) { | ||
// Logging the error, exept restrictions, which is handled in Core | ||
if (!err.isRestriction) { | ||
this.uppy.log(err, 'error'); | ||
} | ||
} | ||
}; | ||
_proto.stop = function stop() { | ||
if (this.stream) { | ||
@@ -463,13 +503,17 @@ this.stream.getAudioTracks().forEach(function (track) { | ||
this.stream = null; | ||
this.setPluginState({ | ||
recordedVideo: null | ||
}); | ||
}; | ||
_proto._getVideoElement = function _getVideoElement() { | ||
_proto.getVideoElement = function getVideoElement() { | ||
return this.el.querySelector('.uppy-Webcam-video'); | ||
}; | ||
_proto._oneTwoThreeSmile = function _oneTwoThreeSmile() { | ||
_proto.oneTwoThreeSmile = function oneTwoThreeSmile() { | ||
var _this5 = this; | ||
return new Promise(function (resolve, reject) { | ||
var count = _this5.opts.countdown; | ||
var count = _this5.opts.countdown; // eslint-disable-next-line consistent-return | ||
var countDown = setInterval(function () { | ||
@@ -499,3 +543,3 @@ if (!_this5.webcamActive) { | ||
_proto._takeSnapshot = function _takeSnapshot() { | ||
_proto.takeSnapshot = function takeSnapshot() { | ||
var _this6 = this; | ||
@@ -512,3 +556,3 @@ | ||
}).then(function () { | ||
return _this6._getImage(); | ||
return _this6.getImage(); | ||
}).then(function (tagFile) { | ||
@@ -531,6 +575,6 @@ _this6.captureInProgress = false; | ||
_proto._getImage = function _getImage() { | ||
_proto.getImage = function getImage() { | ||
var _this7 = this; | ||
var video = this._getVideoElement(); | ||
var video = this.getVideoElement(); | ||
@@ -573,3 +617,10 @@ if (!video) { | ||
_proto.getVideo = function getVideo() { | ||
var mimeType = this.recordingChunks[0].type; | ||
// Sometimes in iOS Safari, Blobs (especially the first Blob in the recordingChunks Array) | ||
// have empty 'type' attributes (e.g. '') so we need to find a Blob that has a defined 'type' | ||
// attribute in order to determine the correct MIME type. | ||
var mimeType = this.recordingChunks.find(function (blob) { | ||
var _blob$type; | ||
return ((_blob$type = blob.type) == null ? void 0 : _blob$type.length) > 0; | ||
}).type; | ||
var fileExtension = getFileTypeExtension(mimeType); | ||
@@ -596,3 +647,3 @@ | ||
_proto._focus = function _focus() { | ||
_proto.focus = function focus() { | ||
var _this8 = this; | ||
@@ -606,6 +657,5 @@ | ||
_proto._changeVideoSource = function _changeVideoSource(deviceId) { | ||
this._stop(); | ||
this._start({ | ||
_proto.changeVideoSource = function changeVideoSource(deviceId) { | ||
this.stop(); | ||
this.start({ | ||
deviceId: deviceId | ||
@@ -629,3 +679,3 @@ }); | ||
if (!this.webcamActive) { | ||
this._start(); | ||
this.start(); | ||
} | ||
@@ -643,9 +693,12 @@ | ||
return h(CameraScreen, _extends({}, webcamState, { | ||
onChangeVideoSource: this._changeVideoSource, | ||
onSnapshot: this._takeSnapshot, | ||
onStartRecording: this._startRecording, | ||
onStopRecording: this._stopRecording, | ||
onFocus: this._focus, | ||
onStop: this._stop, | ||
return h(CameraScreen // eslint-disable-next-line react/jsx-props-no-spreading | ||
, _extends({}, webcamState, { | ||
onChangeVideoSource: this.changeVideoSource, | ||
onSnapshot: this.takeSnapshot, | ||
onStartRecording: this.startRecording, | ||
onStopRecording: this.stopRecording, | ||
onDiscardRecordedVideo: this.discardRecordedVideo, | ||
onSubmit: this.submit, | ||
onFocus: this.focus, | ||
onStop: this.stop, | ||
i18n: this.i18n, | ||
@@ -678,3 +731,3 @@ modes: this.opts.modes, | ||
this.mediaDevices.ondevicechange = function (event) { | ||
this.mediaDevices.ondevicechange = function () { | ||
_this10.updateVideoSources(); | ||
@@ -696,5 +749,5 @@ | ||
if (restartStream) { | ||
_this10._stop(); | ||
_this10.stop(); | ||
_this10._start(); | ||
_this10.start(); | ||
} | ||
@@ -708,3 +761,3 @@ } | ||
if (this.stream) { | ||
this._stop(); | ||
this.stop(); | ||
} | ||
@@ -716,2 +769,2 @@ | ||
return Webcam; | ||
}(Plugin), _class.VERSION = "1.8.8", _temp); | ||
}(Plugin), _class.VERSION = packageJsonVersion, _temp); |
@@ -12,3 +12,3 @@ var _require = require('preact'), | ||
return h("button", { | ||
className: "uppy-u-reset uppy-c-btn uppy-Webcam-button uppy-Webcam-button--video", | ||
className: "uppy-u-reset uppy-c-btn uppy-Webcam-button", | ||
type: "button", | ||
@@ -35,3 +35,3 @@ title: i18n('stopRecording'), | ||
return h("button", { | ||
className: "uppy-u-reset uppy-c-btn uppy-Webcam-button uppy-Webcam-button--video", | ||
className: "uppy-u-reset uppy-c-btn uppy-Webcam-button", | ||
type: "button", | ||
@@ -38,0 +38,0 @@ title: i18n('startRecording'), |
{ | ||
"name": "@uppy/webcam", | ||
"description": "Uppy plugin that takes photos or records videos using the device's camera.", | ||
"version": "1.8.8", | ||
"version": "1.8.9", | ||
"license": "MIT", | ||
@@ -35,3 +35,3 @@ "main": "lib/index.js", | ||
}, | ||
"gitHead": "6771545fe70134088a5441ef5c2f7b872e32d812" | ||
"gitHead": "209a0079d3ced4e20c5ef3e44582c2d82ad2e60c" | ||
} |
@@ -0,1 +1,2 @@ | ||
/* eslint-disable jsx-a11y/media-has-caption */ | ||
const { h, Component } = require('preact') | ||
@@ -6,2 +7,4 @@ const SnapshotButton = require('./SnapshotButton') | ||
const VideoSourceSelect = require('./VideoSourceSelect') | ||
const SubmitButton = require('./SubmitButton') | ||
const DiscardButton = require('./DiscardButton') | ||
@@ -14,36 +17,99 @@ function isModeAvailable (modes, mode) { | ||
componentDidMount () { | ||
this.props.onFocus() | ||
const { onFocus } = this.props | ||
onFocus() | ||
} | ||
componentWillUnmount () { | ||
this.props.onStop() | ||
const { onStop } = this.props | ||
onStop() | ||
} | ||
render () { | ||
const shouldShowRecordButton = this.props.supportsRecording && ( | ||
isModeAvailable(this.props.modes, 'video-only') | ||
|| isModeAvailable(this.props.modes, 'audio-only') | ||
|| isModeAvailable(this.props.modes, 'video-audio') | ||
const { | ||
src, | ||
recordedVideo, | ||
recording, | ||
modes, | ||
supportsRecording, | ||
videoSources, | ||
showVideoSourceDropdown, | ||
showRecordingLength, | ||
onSubmit, | ||
i18n, | ||
mirror, | ||
onSnapshot, | ||
onStartRecording, | ||
onStopRecording, | ||
onDiscardRecordedVideo, | ||
recordingLengthSeconds, | ||
} = this.props | ||
const hasRecordedVideo = !!recordedVideo | ||
const shouldShowRecordButton = !hasRecordedVideo && supportsRecording && ( | ||
isModeAvailable(modes, 'video-only') | ||
|| isModeAvailable(modes, 'audio-only') | ||
|| isModeAvailable(modes, 'video-audio') | ||
) | ||
const shouldShowSnapshotButton = isModeAvailable(this.props.modes, 'picture') | ||
const shouldShowRecordingLength = this.props.supportsRecording && this.props.showRecordingLength | ||
const shouldShowVideoSourceDropdown = this.props.showVideoSourceDropdown && this.props.videoSources && this.props.videoSources.length > 1 | ||
const shouldShowSnapshotButton = !hasRecordedVideo && isModeAvailable(modes, 'picture') | ||
const shouldShowRecordingLength = supportsRecording && showRecordingLength | ||
const shouldShowVideoSourceDropdown = showVideoSourceDropdown && videoSources && videoSources.length > 1 | ||
const videoProps = { | ||
playsinline: true, | ||
} | ||
if (recordedVideo) { | ||
videoProps.muted = false | ||
videoProps.controls = true | ||
videoProps.src = recordedVideo | ||
// reset srcObject in dom. If not resetted, stream sticks in element | ||
if (this.videoElement) { | ||
this.videoElement.srcObject = undefined | ||
} | ||
} else { | ||
videoProps.muted = true | ||
videoProps.autoplay = true | ||
videoProps.srcObject = src | ||
} | ||
return ( | ||
<div className="uppy uppy-Webcam-container"> | ||
<div className="uppy-Webcam-videoContainer"> | ||
<video className={`uppy-Webcam-video ${this.props.mirror ? 'uppy-Webcam-video--mirrored' : ''}`} autoPlay muted playsinline srcObject={this.props.src || ''} /> | ||
<video | ||
/* eslint-disable-next-line no-return-assign */ | ||
ref={(videoElement) => (this.videoElement = videoElement)} | ||
className={`uppy-Webcam-video ${mirror ? 'uppy-Webcam-video--mirrored' : ''}`} | ||
/* eslint-disable-next-line react/jsx-props-no-spreading */ | ||
{...videoProps} | ||
/> | ||
</div> | ||
<div className="uppy-Webcam-footer"> | ||
<div className="uppy-Webcam-videoSourceContainer"> | ||
{shouldShowVideoSourceDropdown ? VideoSourceSelect(this.props) : null} | ||
{shouldShowVideoSourceDropdown | ||
? VideoSourceSelect(this.props) | ||
: null} | ||
</div> | ||
<div className="uppy-Webcam-buttonContainer"> | ||
{shouldShowSnapshotButton ? SnapshotButton(this.props) : null} | ||
{' '} | ||
{shouldShowRecordButton ? RecordButton(this.props) : null} | ||
{shouldShowSnapshotButton && <SnapshotButton onSnapshot={onSnapshot} i18n={i18n} />} | ||
{shouldShowRecordButton && ( | ||
<RecordButton | ||
recording={recording} | ||
onStartRecording={onStartRecording} | ||
onStopRecording={onStopRecording} | ||
i18n={i18n} | ||
/> | ||
)} | ||
{hasRecordedVideo && <SubmitButton onSubmit={onSubmit} i18n={i18n} />} | ||
{hasRecordedVideo && <DiscardButton onDiscard={onDiscardRecordedVideo} i18n={i18n} />} | ||
</div> | ||
<div className="uppy-Webcam-recordingLength"> | ||
{shouldShowRecordingLength ? RecordingLength(this.props) : null} | ||
</div> | ||
{shouldShowRecordingLength && ( | ||
<div className="uppy-Webcam-recordingLength"> | ||
<RecordingLength recordingLengthSeconds={recordingLengthSeconds} i18n={i18n} /> | ||
</div> | ||
)} | ||
</div> | ||
@@ -50,0 +116,0 @@ </div> |
135
src/index.js
@@ -11,2 +11,3 @@ const { h } = require('preact') | ||
const PermissionsScreen = require('./PermissionsScreen') | ||
const packageJsonVersion = require('../package.json').version | ||
@@ -74,3 +75,3 @@ /** | ||
module.exports = class Webcam extends Plugin { | ||
static VERSION = require('../package.json').version | ||
static VERSION = packageJsonVersion | ||
@@ -81,2 +82,3 @@ constructor (uppy, opts) { | ||
this.supportsUserMedia = !!this.mediaDevices | ||
// eslint-disable-next-line no-restricted-globals | ||
this.protocol = location.protocol.match(/https/i) ? 'https' : 'http' | ||
@@ -86,2 +88,3 @@ this.id = this.opts.id || 'Webcam' | ||
this.type = 'acquirer' | ||
this.capturedMediaFile = null | ||
this.icon = () => ( | ||
@@ -108,2 +111,4 @@ <svg aria-hidden="true" focusable="false" width="32" height="32" viewBox="0 0 32 32"> | ||
recordingLength: 'Recording length %{recording_length}', | ||
submitRecordedFile: 'Submit recorded file', | ||
discardRecordedFile: 'Discard recorded file', | ||
}, | ||
@@ -140,10 +145,12 @@ } | ||
// Camera controls | ||
this._start = this._start.bind(this) | ||
this._stop = this._stop.bind(this) | ||
this._takeSnapshot = this._takeSnapshot.bind(this) | ||
this._startRecording = this._startRecording.bind(this) | ||
this._stopRecording = this._stopRecording.bind(this) | ||
this._oneTwoThreeSmile = this._oneTwoThreeSmile.bind(this) | ||
this._focus = this._focus.bind(this) | ||
this._changeVideoSource = this._changeVideoSource.bind(this) | ||
this.start = this.start.bind(this) | ||
this.stop = this.stop.bind(this) | ||
this.takeSnapshot = this.takeSnapshot.bind(this) | ||
this.startRecording = this.startRecording.bind(this) | ||
this.stopRecording = this.stopRecording.bind(this) | ||
this.discardRecordedVideo = this.discardRecordedVideo.bind(this) | ||
this.submit = this.submit.bind(this) | ||
this.oneTwoThreeSmile = this.oneTwoThreeSmile.bind(this) | ||
this.focus = this.focus.bind(this) | ||
this.changeVideoSource = this.changeVideoSource.bind(this) | ||
@@ -153,3 +160,3 @@ this.webcamActive = false | ||
if (this.opts.countdown) { | ||
this.opts.onBeforeSnapshot = this._oneTwoThreeSmile | ||
this.opts.onBeforeSnapshot = this.oneTwoThreeSmile | ||
} | ||
@@ -222,3 +229,4 @@ | ||
_start (options = null) { | ||
// eslint-disable-next-line consistent-return | ||
start (options = null) { | ||
if (!this.supportsUserMedia) { | ||
@@ -229,2 +237,3 @@ return Promise.reject(new Error('Webcam access not supported')) | ||
this.webcamActive = true | ||
this.opts.mirror = true | ||
@@ -277,3 +286,3 @@ const constraints = this.getConstraints(options && options.deviceId ? options.deviceId : null) | ||
*/ | ||
_getMediaRecorderOptions () { | ||
getMediaRecorderOptions () { | ||
const options = {} | ||
@@ -293,5 +302,8 @@ | ||
const acceptableMimeTypes = preferredVideoMimeTypes.filter((candidateType) => MediaRecorder.isTypeSupported(candidateType) | ||
&& getFileTypeExtension(candidateType)) | ||
const filterSupportedTypes = (candidateType) => MediaRecorder.isTypeSupported(candidateType) | ||
&& getFileTypeExtension(candidateType) | ||
const acceptableMimeTypes = preferredVideoMimeTypes.filter(filterSupportedTypes) | ||
if (acceptableMimeTypes.length > 0) { | ||
// eslint-disable-next-line prefer-destructuring | ||
options.mimeType = acceptableMimeTypes[0] | ||
@@ -304,6 +316,6 @@ } | ||
_startRecording () { | ||
startRecording () { | ||
// only used if supportsMediaRecorder() returned true | ||
// eslint-disable-next-line compat/compat | ||
this.recorder = new MediaRecorder(this.stream, this._getMediaRecorderOptions()) | ||
this.recorder = new MediaRecorder(this.stream, this.getMediaRecorderOptions()) | ||
this.recordingChunks = [] | ||
@@ -327,3 +339,3 @@ let stoppingBecauseOfMaxSize = false | ||
this.uppy.info(this.i18n('recordingStoppedMaxSize'), 'warning', 4000) | ||
this._stopRecording() | ||
this.stopRecording() | ||
} | ||
@@ -350,4 +362,4 @@ } | ||
_stopRecording () { | ||
const stopped = new Promise((resolve, reject) => { | ||
stopRecording () { | ||
const stopped = new Promise((resolve) => { | ||
this.recorder.addEventListener('stop', () => { | ||
@@ -372,3 +384,9 @@ resolve() | ||
try { | ||
this.uppy.addFile(file) | ||
this.capturedMediaFile = file | ||
// create object url for capture result preview | ||
this.setPluginState({ | ||
// eslint-disable-next-line compat/compat | ||
recordedVideo: URL.createObjectURL(file.data), | ||
}) | ||
this.opts.mirror = false | ||
} catch (err) { | ||
@@ -390,3 +408,22 @@ // Logging the error, exept restrictions, which is handled in Core | ||
_stop () { | ||
discardRecordedVideo () { | ||
this.setPluginState({ recordedVideo: null }) | ||
this.opts.mirror = true | ||
this.capturedMediaFile = null | ||
} | ||
submit () { | ||
try { | ||
if (this.capturedMediaFile) { | ||
this.uppy.addFile(this.capturedMediaFile) | ||
} | ||
} catch (err) { | ||
// Logging the error, exept restrictions, which is handled in Core | ||
if (!err.isRestriction) { | ||
this.uppy.log(err, 'error') | ||
} | ||
} | ||
} | ||
stop () { | ||
if (this.stream) { | ||
@@ -402,12 +439,16 @@ this.stream.getAudioTracks().forEach((track) => { | ||
this.stream = null | ||
this.setPluginState({ | ||
recordedVideo: null, | ||
}) | ||
} | ||
_getVideoElement () { | ||
getVideoElement () { | ||
return this.el.querySelector('.uppy-Webcam-video') | ||
} | ||
_oneTwoThreeSmile () { | ||
oneTwoThreeSmile () { | ||
return new Promise((resolve, reject) => { | ||
let count = this.opts.countdown | ||
// eslint-disable-next-line consistent-return | ||
const countDown = setInterval(() => { | ||
@@ -432,4 +473,5 @@ if (!this.webcamActive) { | ||
_takeSnapshot () { | ||
takeSnapshot () { | ||
if (this.captureInProgress) return | ||
this.captureInProgress = true | ||
@@ -442,3 +484,3 @@ | ||
}).then(() => { | ||
return this._getImage() | ||
return this.getImage() | ||
}).then((tagFile) => { | ||
@@ -460,4 +502,4 @@ this.captureInProgress = false | ||
_getImage () { | ||
const video = this._getVideoElement() | ||
getImage () { | ||
const video = this.getVideoElement() | ||
if (!video) { | ||
@@ -499,3 +541,7 @@ return Promise.reject(new Error('No video element found, likely due to the Webcam tab being closed.')) | ||
getVideo () { | ||
const mimeType = this.recordingChunks[0].type | ||
// Sometimes in iOS Safari, Blobs (especially the first Blob in the recordingChunks Array) | ||
// have empty 'type' attributes (e.g. '') so we need to find a Blob that has a defined 'type' | ||
// attribute in order to determine the correct MIME type. | ||
const mimeType = this.recordingChunks.find(blob => blob.type?.length > 0).type | ||
const fileExtension = getFileTypeExtension(mimeType) | ||
@@ -519,3 +565,3 @@ | ||
_focus () { | ||
focus () { | ||
if (!this.opts.countdown) return | ||
@@ -527,5 +573,5 @@ setTimeout(() => { | ||
_changeVideoSource (deviceId) { | ||
this._stop() | ||
this._start({ deviceId }) | ||
changeVideoSource (deviceId) { | ||
this.stop() | ||
this.start({ deviceId }) | ||
} | ||
@@ -543,3 +589,3 @@ | ||
if (!this.webcamActive) { | ||
this._start() | ||
this.start() | ||
} | ||
@@ -561,9 +607,12 @@ | ||
<CameraScreen | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...webcamState} | ||
onChangeVideoSource={this._changeVideoSource} | ||
onSnapshot={this._takeSnapshot} | ||
onStartRecording={this._startRecording} | ||
onStopRecording={this._stopRecording} | ||
onFocus={this._focus} | ||
onStop={this._stop} | ||
onChangeVideoSource={this.changeVideoSource} | ||
onSnapshot={this.takeSnapshot} | ||
onStartRecording={this.startRecording} | ||
onStopRecording={this.stopRecording} | ||
onDiscardRecordedVideo={this.discardRecordedVideo} | ||
onSubmit={this.submit} | ||
onFocus={this.focus} | ||
onStop={this.stop} | ||
i18n={this.i18n} | ||
@@ -595,3 +644,3 @@ modes={this.opts.modes} | ||
this.mediaDevices.ondevicechange = (event) => { | ||
this.mediaDevices.ondevicechange = () => { | ||
this.updateVideoSources() | ||
@@ -611,4 +660,4 @@ | ||
if (restartStream) { | ||
this._stop() | ||
this._start() | ||
this.stop() | ||
this.start() | ||
} | ||
@@ -622,3 +671,3 @@ } | ||
if (this.stream) { | ||
this._stop() | ||
this.stop() | ||
} | ||
@@ -625,0 +674,0 @@ |
@@ -13,3 +13,3 @@ const Uppy = require('@uppy/core') | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).not.toBeDefined() | ||
@@ -25,3 +25,3 @@ }) | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).toEqual('video/webm') | ||
@@ -37,3 +37,3 @@ }) | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).not.toBeDefined() | ||
@@ -51,3 +51,3 @@ }) | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).toEqual('video/mp4') | ||
@@ -65,3 +65,3 @@ }) | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).toEqual('video/webm') | ||
@@ -80,3 +80,3 @@ }) | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).toEqual('video/webm') | ||
@@ -94,3 +94,3 @@ }) | ||
expect( | ||
uppy.getPlugin('Webcam')._getMediaRecorderOptions().mimeType | ||
uppy.getPlugin('Webcam').getMediaRecorderOptions().mimeType | ||
).toEqual(undefined) | ||
@@ -97,0 +97,0 @@ }) |
@@ -7,3 +7,3 @@ const { h } = require('preact') | ||
<button | ||
className="uppy-u-reset uppy-c-btn uppy-Webcam-button uppy-Webcam-button--video" | ||
className="uppy-u-reset uppy-c-btn uppy-Webcam-button" | ||
type="button" | ||
@@ -24,3 +24,3 @@ title={i18n('stopRecording')} | ||
<button | ||
className="uppy-u-reset uppy-c-btn uppy-Webcam-button uppy-Webcam-button--video" | ||
className="uppy-u-reset uppy-c-btn uppy-Webcam-button" | ||
type="button" | ||
@@ -27,0 +27,0 @@ title={i18n('startRecording')} |
@@ -14,4 +14,6 @@ import Uppy = require('@uppy/core') | ||
| 'recordingLength' | ||
| 'submitRecordedFile' | ||
| 'discardRecordedFile' | ||
> | ||
export = WebcamLocale |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
148598
48
2108