UNPKG

ng7-pica

Version:

Angular module to resize images files in browser

327 lines (326 loc) 36.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; import { NgxPicaErrorType } from './ngx-pica-error.interface'; import { NgxPicaExifService } from './ngx-pica-exif.service'; import Pica from 'pica'; export class NgxPicaService { /** * @param {?} _ngxPicaExifService */ constructor(_ngxPicaExifService) { this._ngxPicaExifService = _ngxPicaExifService; this.picaResizer = new Pica(); this.MAX_STEPS = 20; if (!this.picaResizer || !this.picaResizer.resize) { this.picaResizer = new window.Pica(); } } /** * @param {?} files * @param {?} width * @param {?} height * @param {?=} options * @return {?} */ resizeImages(files, width, height, options) { /** @type {?} */ const resizedImage = new Subject(); /** @type {?} */ const totalFiles = files.length; if (totalFiles > 0) { /** @type {?} */ const nextFile = new Subject(); /** @type {?} */ let index = 0; /** @type {?} */ const subscription = nextFile.subscribe((file) => { this.resizeImage(file, width, height, options).subscribe(imageResized => { index++; resizedImage.next(imageResized); if (index < totalFiles) { nextFile.next(files[index]); } else { resizedImage.complete(); subscription.unsubscribe(); } }, (err) => { /** @type {?} */ const ngxPicaError = { file: file, err: err }; resizedImage.error(ngxPicaError); }); }); nextFile.next(files[index]); } else { /** @type {?} */ const ngxPicaError = { err: NgxPicaErrorType.NO_FILES_RECEIVED }; resizedImage.error(ngxPicaError); resizedImage.complete(); } return resizedImage.asObservable(); } /** * @param {?} file * @param {?} width * @param {?} height * @param {?=} options * @return {?} */ resizeImage(file, width, height, options) { /** @type {?} */ const resizedImage = new Subject(); /** @type {?} */ const originCanvas = document.createElement('canvas'); /** @type {?} */ const ctx = originCanvas.getContext('2d'); /** @type {?} */ const img = new Image(); if (ctx) { img.onload = () => { this._ngxPicaExifService.getExifOrientedImage(img).then(orientedImage => { window.URL.revokeObjectURL(img.src); originCanvas.width = orientedImage.width; originCanvas.height = orientedImage.height; ctx.drawImage(orientedImage, 0, 0); /** @type {?} */ const imageData = ctx.getImageData(0, 0, orientedImage.width, orientedImage.height); if (options && options.aspectRatio && options.aspectRatio.keepAspectRatio) { /** @type {?} */ let ratio = 0; if (options.aspectRatio.forceMinDimensions) { ratio = Math.max(width / imageData.width, height / imageData.height); } else { ratio = Math.min(width / imageData.width, height / imageData.height); } width = Math.round(imageData.width * ratio); height = Math.round(imageData.height * ratio); } /** @type {?} */ const destinationCanvas = document.createElement('canvas'); destinationCanvas.width = width; destinationCanvas.height = height; this.picaResize(file, originCanvas, destinationCanvas, options) .catch((err) => resizedImage.error(err)) .then((imgResized) => { resizedImage.next(imgResized); }); }); }; img.src = window.URL.createObjectURL(file); } else { resizedImage.error(NgxPicaErrorType.CANVAS_CONTEXT_IDENTIFIER_NOT_SUPPORTED); } return resizedImage.asObservable(); } /** * @param {?} files * @param {?} sizeInMB * @return {?} */ compressImages(files, sizeInMB) { /** @type {?} */ const compressedImage = new Subject(); /** @type {?} */ const totalFiles = files.length; if (totalFiles > 0) { /** @type {?} */ const nextFile = new Subject(); /** @type {?} */ let index = 0; /** @type {?} */ const subscription = nextFile.subscribe((file) => { this.compressImage(file, sizeInMB).subscribe(imageCompressed => { index++; compressedImage.next(imageCompressed); if (index < totalFiles) { nextFile.next(files[index]); } else { compressedImage.complete(); subscription.unsubscribe(); } }, (err) => { /** @type {?} */ const ngxPicaError = { file: file, err: err }; compressedImage.error(ngxPicaError); }); }); nextFile.next(files[index]); } else { /** @type {?} */ const ngxPicaError = { err: NgxPicaErrorType.NO_FILES_RECEIVED }; compressedImage.error(ngxPicaError); compressedImage.complete(); } return compressedImage.asObservable(); } /** * @param {?} file * @param {?} sizeInMB * @return {?} */ compressImage(file, sizeInMB) { /** @type {?} */ const compressedImage = new Subject(); /** @type {?} */ const originCanvas = document.createElement('canvas'); /** @type {?} */ const ctx = originCanvas.getContext('2d'); /** @type {?} */ const img = new Image(); if (ctx) { img.onload = () => { this._ngxPicaExifService.getExifOrientedImage(img).then(orientedImage => { window.URL.revokeObjectURL(img.src); originCanvas.width = orientedImage.width; originCanvas.height = orientedImage.height; ctx.drawImage(orientedImage, 0, 0); if (this.bytesToMB(file.size) <= sizeInMB) { this.picaResizer.toBlob(originCanvas, file.type, 1) .catch((err) => compressedImage.error(err)) .then((blob) => { /** @type {?} */ const imgCompressed = this.blobToFile(blob, file.name, file.type, new Date().getTime()); compressedImage.next(imgCompressed); }); } else { this.getCompressedImage(originCanvas, file.type, 1, sizeInMB, 0) .catch((err) => compressedImage.error(err)) .then((blob) => { /** @type {?} */ const imgCompressed = this.blobToFile(blob, file.name, file.type, new Date().getTime()); compressedImage.next(imgCompressed); }); } }); }; img.src = window.URL.createObjectURL(file); } else { compressedImage.error(NgxPicaErrorType.CANVAS_CONTEXT_IDENTIFIER_NOT_SUPPORTED); } return compressedImage.asObservable(); } /** * @param {?} canvas * @param {?} type * @param {?} quality * @param {?} sizeInMB * @param {?} step * @return {?} */ getCompressedImage(canvas, type, quality, sizeInMB, step) { return new Promise((resolve, reject) => { this.picaResizer.toBlob(canvas, type, quality) .catch((err) => reject(err)) .then((blob) => { this.checkCompressedImageSize(canvas, blob, quality, sizeInMB, step) .catch((err) => reject(err)) .then((compressedBlob) => { resolve(compressedBlob); }); }); }); } /** * @param {?} canvas * @param {?} blob * @param {?} quality * @param {?} sizeInMB * @param {?} step * @return {?} */ checkCompressedImageSize(canvas, blob, quality, sizeInMB, step) { return new Promise((resolve, reject) => { if (step > this.MAX_STEPS) { reject(NgxPicaErrorType.NOT_BE_ABLE_TO_COMPRESS_ENOUGH); } else if (this.bytesToMB(blob.size) < sizeInMB) { resolve(blob); } else { /** @type {?} */ const newQuality = quality - (quality * 0.1); /** @type {?} */ const newStep = step + 1; // recursively compression resolve(this.getCompressedImage(canvas, blob.type, newQuality, sizeInMB, newStep)); } }); } /** * @param {?} file * @param {?} from * @param {?} to * @param {?} options * @return {?} */ picaResize(file, from, to, options) { return new Promise((resolve, reject) => { this.picaResizer.resize(from, to, options) .catch((err) => reject(err)) .then((resizedCanvas) => this.picaResizer.toBlob(resizedCanvas, file.type)) .then((blob) => { /** @type {?} */ const fileResized = this.blobToFile(blob, file.name, file.type, new Date().getTime()); resolve(fileResized); }); }); } /** * @param {?} blob * @param {?} name * @param {?} type * @param {?} lastModified * @return {?} */ blobToFile(blob, name, type, lastModified) { /** @type {?} */ let file = /** @type {?} */ (new Blob([blob], { type: type })); file.name = name; file.lastModifiedDate = lastModified; return /** @type {?} */ (file); } /** * @param {?} bytes * @return {?} */ bytesToMB(bytes) { return bytes / 1048576; } } NgxPicaService.decorators = [ { type: Injectable } ]; /** @nocollapse */ NgxPicaService.ctorParameters = () => [ { type: NgxPicaExifService } ]; if (false) { /** @type {?} */ NgxPicaService.prototype.picaResizer; /** @type {?} */ NgxPicaService.prototype.MAX_STEPS; /** @type {?} */ NgxPicaService.prototype._ngxPicaExifService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXBpY2Euc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nNy1waWNhLyIsInNvdXJjZXMiOlsibGliL25neC1waWNhLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFDLE9BQU8sRUFBMkIsTUFBTSxNQUFNLENBQUM7QUFDdkQsT0FBTyxFQUF3QixnQkFBZ0IsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBRW5GLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBQzNELE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQU14QixNQUFNLE9BQU8sY0FBYzs7OztJQUl2QixZQUFvQixtQkFBdUM7UUFBdkMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFvQjsyQkFIckMsSUFBSSxJQUFJLEVBQUU7eUJBQ1osRUFBRTtRQUdsQixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFO1lBQy9DLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEM7S0FDSjs7Ozs7Ozs7SUFFTSxZQUFZLENBQUMsS0FBYSxFQUFFLEtBQWEsRUFBRSxNQUFjLEVBQUUsT0FBdUM7O1FBQ3JHLE1BQU0sWUFBWSxHQUFrQixJQUFJLE9BQU8sRUFBRSxDQUFDOztRQUNsRCxNQUFNLFVBQVUsR0FBVyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBRXhDLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTs7WUFDaEIsTUFBTSxRQUFRLEdBQWtCLElBQUksT0FBTyxFQUFFLENBQUM7O1lBQzlDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQzs7WUFFZCxNQUFNLFlBQVksR0FBaUIsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQVUsRUFBRSxFQUFFO2dC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QUFnQixHQUFHLFlBQVksQ0FBQztRQUNyQyx5QkFBTyxJQUFZLEVBQUE7Ozs7OztJQUdmLFNBQVMsQ0FBQyxLQUFhO1FBQzNCLE9BQU8sS0FBSyxHQUFHLE9BQU8sQ0FBQzs7OztZQXpQOUIsVUFBVTs7OztZQU5ILGtCQUFrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1N1YmplY3QsIE9ic2VydmFibGUsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge05neFBpY2FFcnJvckludGVyZmFjZSwgTmd4UGljYUVycm9yVHlwZX0gZnJvbSAnLi9uZ3gtcGljYS1lcnJvci5pbnRlcmZhY2UnO1xuaW1wb3J0IHtOZ3hQaWNhUmVzaXplT3B0aW9uc0ludGVyZmFjZX0gZnJvbSAnLi9uZ3gtcGljYS1yZXNpemUtb3B0aW9ucy5pbnRlcmZhY2UnO1xuaW1wb3J0IHtOZ3hQaWNhRXhpZlNlcnZpY2V9IGZyb20gJy4vbmd4LXBpY2EtZXhpZi5zZXJ2aWNlJztcbmltcG9ydCBQaWNhIGZyb20gJ3BpY2EnO1xuXG5cbmRlY2xhcmUgbGV0IHdpbmRvdzogYW55O1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTmd4UGljYVNlcnZpY2Uge1xuICAgIHByaXZhdGUgcGljYVJlc2l6ZXIgPSBuZXcgUGljYSgpO1xuICAgIHByaXZhdGUgTUFYX1NURVBTID0gMjA7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9uZ3hQaWNhRXhpZlNlcnZpY2U6IE5neFBpY2FFeGlmU2VydmljZSkge1xuICAgICAgICBpZiAoIXRoaXMucGljYVJlc2l6ZXIgfHwgIXRoaXMucGljYVJlc2l6ZXIucmVzaXplKSB7XG4gICAgICAgICAgICB0aGlzLnBpY2FSZXNpemVyID0gbmV3IHdpbmRvdy5QaWNhKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgcmVzaXplSW1hZ2VzKGZpbGVzOiBGaWxlW10sIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBvcHRpb25zPzogTmd4UGljYVJlc2l6ZU9wdGlvbnNJbnRlcmZhY2UpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgcmVzaXplZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcbiAgICAgICAgY29uc3QgdG90YWxGaWxlczogbnVtYmVyID0gZmlsZXMubGVuZ3RoO1xuXG4gICAgICAgIGlmICh0b3RhbEZpbGVzID4gMCkge1xuICAgICAgICAgICAgY29uc3QgbmV4dEZpbGU6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcblxuICAgICAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXh0RmlsZS5zdWJzY3JpYmUoKGZpbGU6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZUltYWdlKGZpbGUsIHdpZHRoLCBoZWlnaHQsIG9wdGlvbnMpLnN1YnNjcmliZShpbWFnZVJlc2l6ZWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UubmV4dChpbWFnZVJlc2l6ZWQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCA8IHRvdGFsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRGaWxlLm5leHQoZmlsZXNbaW5kZXhdKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzaXplZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgbmd4UGljYUVycm9yOiBOZ3hQaWNhRXJyb3JJbnRlcmZhY2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlOiBmaWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyOiBlcnJcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UuZXJyb3Iobmd4UGljYUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBuZXh0RmlsZS5uZXh0KGZpbGVzW2luZGV4XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBuZ3hQaWNhRXJyb3I6IE5neFBpY2FFcnJvckludGVyZmFjZSA9IHtcbiAgICAgICAgICAgICAgICBlcnI6IE5neFBpY2FFcnJvclR5cGUuTk9fRklMRVNfUkVDRUlWRURcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJlc2l6ZWRJbWFnZS5lcnJvcihuZ3hQaWNhRXJyb3IpO1xuICAgICAgICAgICAgcmVzaXplZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzaXplZEltYWdlLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZXNpemVJbWFnZShmaWxlOiBGaWxlLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgb3B0aW9ucz86IE5neFBpY2FSZXNpemVPcHRpb25zSW50ZXJmYWNlKTogT2JzZXJ2YWJsZTxGaWxlPiB7XG4gICAgICAgIGNvbnN0IHJlc2l6ZWRJbWFnZTogU3ViamVjdDxGaWxlPiA9IG5ldyBTdWJqZWN0KCk7XG4gICAgICAgIGNvbnN0IG9yaWdpbkNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgY29uc3QgY3R4ID0gb3JpZ2luQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuXG4gICAgICAgIGlmIChjdHgpIHtcbiAgICAgICAgICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbmd4UGljYUV4aWZTZXJ2aWNlLmdldEV4aWZPcmllbnRlZEltYWdlKGltZykudGhlbihvcmllbnRlZEltYWdlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwoaW1nLnNyYyk7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbkNhbnZhcy53aWR0aCA9IG9yaWVudGVkSW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbkNhbnZhcy5oZWlnaHQgPSBvcmllbnRlZEltYWdlLmhlaWdodDtcblxuICAgICAgICAgICAgICAgICAgICBjdHguZHJhd0ltYWdlKG9yaWVudGVkSW1hZ2UsIDAsIDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltYWdlRGF0YSA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgb3JpZW50ZWRJbWFnZS53aWR0aCwgb3JpZW50ZWRJbWFnZS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmFzcGVjdFJhdGlvICYmIG9wdGlvbnMuYXNwZWN0UmF0aW8ua2VlcEFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgcmF0aW8gPSAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5hc3BlY3RSYXRpby5mb3JjZU1pbkRpbWVuc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXRpbyA9IE1hdGgubWF4KHdpZHRoIC8gaW1hZ2VEYXRhLndpZHRoLCBoZWlnaHQgLyBpbWFnZURhdGEuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF0aW8gPSBNYXRoLm1pbih3aWR0aCAvIGltYWdlRGF0YS53aWR0aCwgaGVpZ2h0IC8gaW1hZ2VEYXRhLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gTWF0aC5yb3VuZChpbWFnZURhdGEud2lkdGggKiByYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSBNYXRoLnJvdW5kKGltYWdlRGF0YS5oZWlnaHQgKiByYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZXN0aW5hdGlvbkNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgICAgICAgICAgZGVzdGluYXRpb25DYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgZGVzdGluYXRpb25DYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGljYVJlc2l6ZShmaWxlLCBvcmlnaW5DYW52YXMsIGRlc3RpbmF0aW9uQ2FudmFzLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHJlc2l6ZWRJbWFnZS5lcnJvcihlcnIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKGltZ1Jlc2l6ZWQ6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UubmV4dChpbWdSZXNpemVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaW1nLnNyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGZpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzaXplZEltYWdlLmVycm9yKE5neFBpY2FFcnJvclR5cGUuQ0FOVkFTX0NPTlRFWFRfSURFTlRJRklFUl9OT1RfU1VQUE9SVEVEKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNpemVkSW1hZ2UuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXByZXNzSW1hZ2VzKGZpbGVzOiBGaWxlW10sIHNpemVJbk1COiBudW1iZXIpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgY29tcHJlc3NlZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcbiAgICAgICAgY29uc3QgdG90YWxGaWxlczogbnVtYmVyID0gZmlsZXMubGVuZ3RoO1xuXG4gICAgICAgIGlmICh0b3RhbEZpbGVzID4gMCkge1xuICAgICAgICAgICAgY29uc3QgbmV4dEZpbGU6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcblxuICAgICAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXh0RmlsZS5zdWJzY3JpYmUoKGZpbGU6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXByZXNzSW1hZ2UoZmlsZSwgc2l6ZUluTUIpLnN1YnNjcmliZShpbWFnZUNvbXByZXNzZWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UubmV4dChpbWFnZUNvbXByZXNzZWQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCA8IHRvdGFsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRGaWxlLm5leHQoZmlsZXNbaW5kZXhdKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgbmd4UGljYUVycm9yOiBOZ3hQaWNhRXJyb3JJbnRlcmZhY2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlOiBmaWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyOiBlcnJcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UuZXJyb3Iobmd4UGljYUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBuZXh0RmlsZS5uZXh0KGZpbGVzW2luZGV4XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBuZ3hQaWNhRXJyb3I6IE5neFBpY2FFcnJvckludGVyZmFjZSA9IHtcbiAgICAgICAgICAgICAgICBlcnI6IE5neFBpY2FFcnJvclR5cGUuTk9fRklMRVNfUkVDRUlWRURcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5lcnJvcihuZ3hQaWNhRXJyb3IpO1xuICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcHJlc3NlZEltYWdlLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wcmVzc0ltYWdlKGZpbGU6IEZpbGUsIHNpemVJbk1COiBudW1iZXIpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgY29tcHJlc3NlZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcblxuICAgICAgICBjb25zdCBvcmlnaW5DYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgIGNvbnN0IGN0eCA9IG9yaWdpbkNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcblxuICAgICAgICBpZiAoY3R4KSB7XG4gICAgICAgICAgICBpbWcub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX25neFBpY2FFeGlmU2VydmljZS5nZXRFeGlmT3JpZW50ZWRJbWFnZShpbWcpLnRoZW4ob3JpZW50ZWRJbWFnZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKGltZy5zcmMpO1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5DYW52YXMud2lkdGggPSBvcmllbnRlZEltYWdlLndpZHRoO1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5DYW52YXMuaGVpZ2h0ID0gb3JpZW50ZWRJbWFnZS5oZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShvcmllbnRlZEltYWdlLCAwLCAwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5ieXRlc1RvTUIoZmlsZS5zaXplKSA8PSBzaXplSW5NQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5waWNhUmVzaXplci50b0Jsb2Iob3JpZ2luQ2FudmFzLCBmaWxlLnR5cGUsIDEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IGNvbXByZXNzZWRJbWFnZS5lcnJvcihlcnIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ0NvbXByZXNzZWQ6IEZpbGUgPSB0aGlzLmJsb2JUb0ZpbGUoYmxvYiwgZmlsZS5uYW1lLCBmaWxlLnR5cGUsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLm5leHQoaW1nQ29tcHJlc3NlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldENvbXByZXNzZWRJbWFnZShvcmlnaW5DYW52YXMsIGZpbGUudHlwZSwgMSwgc2l6ZUluTUIsIDApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IGNvbXByZXNzZWRJbWFnZS5lcnJvcihlcnIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ0NvbXByZXNzZWQ6IEZpbGUgPSB0aGlzLmJsb2JUb0ZpbGUoYmxvYiwgZmlsZS5uYW1lLCBmaWxlLnR5cGUsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UubmV4dChpbWdDb21wcmVzc2VkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaW1nLnNyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGZpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLmVycm9yKE5neFBpY2FFcnJvclR5cGUuQ0FOVkFTX0NPTlRFWFRfSURFTlRJRklFUl9OT1RfU1VQUE9SVEVEKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb21wcmVzc2VkSW1hZ2UuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb21wcmVzc2VkSW1hZ2UoY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCwgdHlwZTogc3RyaW5nLCBxdWFsaXR5OiBudW1iZXIsIHNpemVJbk1COiBudW1iZXIsIHN0ZXA6IG51bWJlcik6IFByb21pc2U8QmxvYj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8QmxvYj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5waWNhUmVzaXplci50b0Jsb2IoY2FudmFzLCB0eXBlLCBxdWFsaXR5KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiByZWplY3QoZXJyKSlcbiAgICAgICAgICAgICAgICAudGhlbigoYmxvYjogQmxvYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNoZWNrQ29tcHJlc3NlZEltYWdlU2l6ZShjYW52YXMsIGJsb2IsIHF1YWxpdHksIHNpemVJbk1CLCBzdGVwKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHJlamVjdChlcnIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKGNvbXByZXNzZWRCbG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY29tcHJlc3NlZEJsb2IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2hlY2tDb21wcmVzc2VkSW1hZ2VTaXplKFxuICAgICAgICBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LFxuICAgICAgICBibG9iOiBCbG9iLFxuICAgICAgICBxdWFsaXR5OiBudW1iZXIsXG4gICAgICAgIHNpemVJbk1COiBudW1iZXIsXG4gICAgICAgIHN0ZXA6IG51bWJlclxuICAgICk6IFByb21pc2U8QmxvYj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8QmxvYj4oKHJlc29sdmUsXG4gICAgICAgICAgICByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKHN0ZXAgPiB0aGlzLk1BWF9TVEVQUykge1xuICAgICAgICAgICAgICAgIHJlamVjdChOZ3hQaWNhRXJyb3JUeXBlLk5PVF9CRV9BQkxFX1RPX0NPTVBSRVNTX0VOT1VHSCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuYnl0ZXNUb01CKGJsb2Iuc2l6ZSkgPCBzaXplSW5NQikge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoYmxvYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1F1YWxpdHk6IG51bWJlciA9IHF1YWxpdHkgLSAocXVhbGl0eSAqIDAuMSk7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3U3RlcDogbnVtYmVyID0gc3RlcCArIDE7XG5cbiAgICAgICAgICAgICAgICAvLyByZWN1cnNpdmVseSBjb21wcmVzc2lvblxuICAgICAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRDb21wcmVzc2VkSW1hZ2UoY2FudmFzLCBibG9iLnR5cGUsIG5ld1F1YWxpdHksIHNpemVJbk1CLCBuZXdTdGVwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcGljYVJlc2l6ZShmaWxlOiBGaWxlLCBmcm9tOiBIVE1MQ2FudmFzRWxlbWVudCwgdG86IEhUTUxDYW52YXNFbGVtZW50LCBvcHRpb25zOiBhbnkpOiBQcm9taXNlPEZpbGU+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPEZpbGU+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGljYVJlc2l6ZXIucmVzaXplKGZyb20sIHRvLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiByZWplY3QoZXJyKSlcbiAgICAgICAgICAgICAgICAudGhlbigocmVzaXplZENhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpID0+IHRoaXMucGljYVJlc2l6ZXIudG9CbG9iKHJlc2l6ZWRDYW52YXMsIGZpbGUudHlwZSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKGJsb2I6IEJsb2IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsZVJlc2l6ZWQ6IEZpbGUgPSB0aGlzLmJsb2JUb0ZpbGUoYmxvYiwgZmlsZS5uYW1lLCBmaWxlLnR5cGUsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShmaWxlUmVzaXplZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYmxvYlRvRmlsZShibG9iOiBCbG9iLCBuYW1lOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgbGFzdE1vZGlmaWVkOiBudW1iZXIpOiBGaWxlIHtcbiAgICAgICAgLy8gcmV0dXJuIG5ldyBGaWxlKFtibG9iXSwgbmFtZSwge3R5cGU6IHR5cGUsIGxhc3RNb2RpZmllZDogbGFzdE1vZGlmaWVkfSk7XG4gICAgICAgIGxldCBmaWxlID0gbmV3IEJsb2IoW2Jsb2JdLCB7dHlwZSA6IHR5cGV9KSBhcyBhbnk7XG4gICAgICAgIGZpbGUubmFtZSA9IG5hbWU7XG4gICAgICAgIGZpbGUubGFzdE1vZGlmaWVkRGF0ZSA9IGxhc3RNb2RpZmllZDtcbiAgICAgICAgcmV0dXJuIGZpbGUgYXMgRmlsZVxuICAgIH1cblxuICAgIHByaXZhdGUgYnl0ZXNUb01CKGJ5dGVzOiBudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIGJ5dGVzIC8gMTA0ODU3NjtcbiAgICB9XG59XG4iXX0=