UNPKG

uppy

Version:

Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:

386 lines (314 loc) 12.6 kB
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _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; }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise; var _require = require('preact'), h = _require.h; var Plugin = require('../../core/Plugin'); var Translator = require('../../core/Translator'); var _require2 = require('../../core/Utils'), getFileTypeExtension = _require2.getFileTypeExtension, canvasToBlob = _require2.canvasToBlob; var supportsMediaRecorder = require('./supportsMediaRecorder'); var WebcamIcon = require('./WebcamIcon'); var CameraScreen = require('./CameraScreen'); var PermissionsScreen = require('./PermissionsScreen'); // Setup getUserMedia, with polyfill for older browsers // Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia function getMediaDevices() { if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { return navigator.mediaDevices; } var _getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia; if (!_getUserMedia) { return null; } return { getUserMedia: function getUserMedia(opts) { return new _Promise(function (resolve, reject) { _getUserMedia.call(navigator, opts, resolve, reject); }); } }; } /** * Webcam */ module.exports = function (_Plugin) { _inherits(Webcam, _Plugin); function Webcam(uppy, opts) { _classCallCheck(this, Webcam); var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts)); _this.mediaDevices = getMediaDevices(); _this.supportsUserMedia = !!_this.mediaDevices; _this.protocol = location.protocol.match(/https/i) ? 'https' : 'http'; _this.id = _this.opts.id || 'Webcam'; _this.title = 'Webcam'; _this.type = 'acquirer'; _this.icon = WebcamIcon; var defaultLocale = { strings: { smile: 'Smile!' } // set default options };var defaultOptions = { onBeforeSnapshot: function onBeforeSnapshot() { return _Promise.resolve(); }, countdown: false, locale: defaultLocale, modes: ['video-audio', 'video-only', 'audio-only', 'picture'], mirror: true, facingMode: 'user' // merge default options with the ones set by user };_this.opts = _extends({}, defaultOptions, opts); _this.locale = _extends({}, defaultLocale, _this.opts.locale); _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings); // i18n _this.translator = new Translator({ locale: _this.locale }); _this.i18n = _this.translator.translate.bind(_this.translator); _this.install = _this.install.bind(_this); _this.setPluginState = _this.setPluginState.bind(_this); _this.render = _this.render.bind(_this); // 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.webcamActive = false; if (_this.opts.countdown) { _this.opts.onBeforeSnapshot = _this.oneTwoThreeSmile; } return _this; } Webcam.prototype.isSupported = function isSupported() { return !!this.mediaDevices; }; Webcam.prototype.getConstraints = function getConstraints() { var acceptsAudio = this.opts.modes.indexOf('video-audio') !== -1 || this.opts.modes.indexOf('audio-only') !== -1; var acceptsVideo = this.opts.modes.indexOf('video-audio') !== -1 || this.opts.modes.indexOf('video-only') !== -1 || this.opts.modes.indexOf('picture') !== -1; return { audio: acceptsAudio, video: acceptsVideo ? { facingMode: this.opts.facingMode } : false }; }; Webcam.prototype.start = function start() { var _this2 = this; if (!this.isSupported()) { return _Promise.reject(new Error('Webcam access not supported')); } this.webcamActive = true; var constraints = this.getConstraints(); // ask user for access to their camera return this.mediaDevices.getUserMedia(constraints).then(function (stream) { _this2.stream = stream; // this.streamSrc = URL.createObjectURL(this.stream) _this2.setPluginState({ cameraReady: true }); }).catch(function (err) { _this2.setPluginState({ cameraError: err }); }); }; Webcam.prototype.startRecording = function startRecording() { var _this3 = this; // TODO We can check here if any of the mime types listed in the // mimeToExtensions map in Utils.js are supported, and prefer to use one of // those. // Right now we let the browser pick a type that it deems appropriate. this.recorder = new MediaRecorder(this.stream); this.recordingChunks = []; this.recorder.addEventListener('dataavailable', function (event) { _this3.recordingChunks.push(event.data); }); this.recorder.start(); this.setPluginState({ isRecording: true }); }; Webcam.prototype.stopRecording = function stopRecording() { var _this4 = this; var stopped = new _Promise(function (resolve, reject) { _this4.recorder.addEventListener('stop', function () { resolve(); }); _this4.recorder.stop(); }); return stopped.then(function () { _this4.setPluginState({ isRecording: false }); return _this4.getVideo(); }).then(function (file) { return _this4.uppy.addFile(file); }).then(function () { _this4.recordingChunks = null; _this4.recorder = null; var dashboard = _this4.uppy.getPlugin('Dashboard'); if (dashboard) dashboard.hideAllPanels(); }, function (error) { _this4.recordingChunks = null; _this4.recorder = null; throw error; }); }; Webcam.prototype.stop = function stop() { this.stream.getAudioTracks().forEach(function (track) { track.stop(); }); this.stream.getVideoTracks().forEach(function (track) { track.stop(); }); this.webcamActive = false; this.stream = null; }; Webcam.prototype.getVideoElement = function getVideoElement() { return this.el.querySelector('.uppy-Webcam-video'); }; Webcam.prototype.oneTwoThreeSmile = function oneTwoThreeSmile() { var _this5 = this; return new _Promise(function (resolve, reject) { var count = _this5.opts.countdown; var countDown = setInterval(function () { if (!_this5.webcamActive) { clearInterval(countDown); _this5.captureInProgress = false; return reject(new Error('Webcam is not active')); } if (count > 0) { _this5.uppy.info(count + '...', 'warning', 800); count--; } else { clearInterval(countDown); _this5.uppy.info(_this5.i18n('smile'), 'success', 1500); setTimeout(function () { return resolve(); }, 1500); } }, 1000); }); }; Webcam.prototype.takeSnapshot = function takeSnapshot() { var _this6 = this; if (this.captureInProgress) return; this.captureInProgress = true; this.opts.onBeforeSnapshot().catch(function (err) { var message = (typeof err === 'undefined' ? 'undefined' : _typeof(err)) === 'object' ? err.message : err; _this6.uppy.info(message, 'error', 5000); return _Promise.reject(new Error('onBeforeSnapshot: ' + message)); }).then(function () { return _this6.getImage(); }).then(function (tagFile) { _this6.captureInProgress = false; var dashboard = _this6.uppy.getPlugin('Dashboard'); if (dashboard) dashboard.hideAllPanels(); return _this6.uppy.addFile(tagFile).catch(function () { // Ignore }); }, function (error) { _this6.captureInProgress = false; throw error; }); }; Webcam.prototype.getImage = function getImage() { var _this7 = this; var video = this.getVideoElement(); if (!video) { return _Promise.reject(new Error('No video element found, likely due to the Webcam tab being closed.')); } var name = 'webcam-' + Date.now() + '.jpg'; var mimeType = 'image/jpeg'; var width = video.videoWidth; var height = video.videoHeight; // const scaleH = this.opts.mirror ? -1 : 1 // Set horizontal scale to -1 if flip horizontal // const scaleV = 1 // const posX = this.opts.mirror ? width * -1 : 0 // Set x position to -100% if flip horizontal // const posY = 0 var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; var ctx = canvas.getContext('2d'); ctx.drawImage(video, 0, 0); // ctx.save() // Save the current state // ctx.scale(scaleH, scaleV) // Set scale to flip the image // ctx.drawImage(video, posX, posY, width, height) // draw the image // ctx.restore() // Restore the last saved state return canvasToBlob(canvas, mimeType).then(function (blob) { return { source: _this7.id, name: name, data: new File([blob], name, { type: mimeType }), type: mimeType }; }); }; Webcam.prototype.getVideo = function getVideo() { var mimeType = this.recordingChunks[0].type; var fileExtension = getFileTypeExtension(mimeType); if (!fileExtension) { return _Promise.reject(new Error('Could not retrieve recording: Unsupported media type "' + mimeType + '"')); } var name = 'webcam-' + Date.now() + '.' + fileExtension; var blob = new Blob(this.recordingChunks, { type: mimeType }); var file = { source: this.id, name: name, data: new File([blob], name, { type: mimeType }), type: mimeType }; return _Promise.resolve(file); }; Webcam.prototype.focus = function focus() { var _this8 = this; if (this.opts.countdown) return; setTimeout(function () { _this8.uppy.info(_this8.i18n('smile'), 'success', 1500); }, 1000); }; Webcam.prototype.render = function render(state) { if (!this.webcamActive) { this.start(); } var webcamState = this.getPluginState(); if (!webcamState.cameraReady) { return PermissionsScreen(webcamState); } return h(CameraScreen, _extends({}, webcamState, { onSnapshot: this.takeSnapshot, onStartRecording: this.startRecording, onStopRecording: this.stopRecording, onFocus: this.focus, onStop: this.stop, modes: this.opts.modes, supportsRecording: supportsMediaRecorder(), recording: webcamState.isRecording, mirror: this.opts.mirror, src: this.stream })); }; Webcam.prototype.install = function install() { this.setPluginState({ cameraReady: false }); var target = this.opts.target; if (target) { this.mount(target, this); } }; Webcam.prototype.uninstall = function uninstall() { if (this.stream) { this.stop(); } this.unmount(); }; return Webcam; }(Plugin); //# sourceMappingURL=index.js.map