ng-pica
Version:
Angular module to resize images files in browser
446 lines • 40.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,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((/**
* @param {?} file
* @return {?}
*/
(file) => {
this.resizeImage(file, width, height, options).subscribe((/**
* @param {?} imageResized
* @return {?}
*/
imageResized => {
index++;
resizedImage.next(imageResized);
if (index < totalFiles) {
nextFile.next(files[index]);
}
else {
resizedImage.complete();
subscription.unsubscribe();
}
}), (/**
* @param {?} err
* @return {?}
*/
(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 = (/**
* @return {?}
*/
() => {
this._ngxPicaExifService.getExifOrientedImage(img).then((/**
* @param {?} orientedImage
* @return {?}
*/
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((/**
* @param {?} err
* @return {?}
*/
(err) => resizedImage.error(err)))
.then((/**
* @param {?} imgResized
* @return {?}
*/
(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((/**
* @param {?} file
* @return {?}
*/
(file) => {
this.compressImage(file, sizeInMB).subscribe((/**
* @param {?} imageCompressed
* @return {?}
*/
imageCompressed => {
index++;
compressedImage.next(imageCompressed);
if (index < totalFiles) {
nextFile.next(files[index]);
}
else {
compressedImage.complete();
subscription.unsubscribe();
}
}), (/**
* @param {?} err
* @return {?}
*/
(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 = (/**
* @return {?}
*/
() => {
this._ngxPicaExifService.getExifOrientedImage(img).then((/**
* @param {?} orientedImage
* @return {?}
*/
orientedImage => {
window.URL.revokeObjectURL(img.src);
originCanvas.width = orientedImage.width;
originCanvas.height = orientedImage.height;
ctx.drawImage(orientedImage, 0, 0);
this.picaResizer.toBlob(originCanvas, file.type, 1)
.catch((/**
* @param {?} err
* @return {?}
*/
(err) => compressedImage.error(err)))
.then((/**
* @param {?} blob
* @return {?}
*/
(blob) => {
if (this.bytesToMB(blob.size) <= sizeInMB) {
/** @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((/**
* @param {?} err
* @return {?}
*/
(err) => compressedImage.error(err)))
.then((/**
* @param {?} blob
* @return {?}
*/
(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();
}
/**
* @private
* @param {?} canvas
* @param {?} type
* @param {?} quality
* @param {?} sizeInMB
* @param {?} step
* @return {?}
*/
getCompressedImage(canvas, type, quality, sizeInMB, step) {
return new Promise((/**
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
(resolve, reject) => {
this.picaResizer.toBlob(canvas, type, quality)
.catch((/**
* @param {?} err
* @return {?}
*/
(err) => reject(err)))
.then((/**
* @param {?} blob
* @return {?}
*/
(blob) => {
this.checkCompressedImageSize(canvas, blob, quality, sizeInMB, step)
.catch((/**
* @param {?} err
* @return {?}
*/
(err) => reject(err)))
.then((/**
* @param {?} compressedBlob
* @return {?}
*/
(compressedBlob) => {
resolve(compressedBlob);
}));
}));
}));
}
/**
* @private
* @param {?} canvas
* @param {?} blob
* @param {?} quality
* @param {?} sizeInMB
* @param {?} step
* @return {?}
*/
checkCompressedImageSize(canvas, blob, quality, sizeInMB, step) {
return new Promise((/**
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
(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));
}
}));
}
/**
* @private
* @param {?} file
* @param {?} from
* @param {?} to
* @param {?} options
* @return {?}
*/
picaResize(file, from, to, options) {
return new Promise((/**
* @param {?} resolve
* @param {?} reject
* @return {?}
*/
(resolve, reject) => {
this.picaResizer.resize(from, to, options)
.catch((/**
* @param {?} err
* @return {?}
*/
(err) => reject(err)))
.then((/**
* @param {?} resizedCanvas
* @return {?}
*/
(resizedCanvas) => this.picaResizer.toBlob(resizedCanvas, file.type)))
.then((/**
* @param {?} blob
* @return {?}
*/
(blob) => {
/** @type {?} */
const fileResized = this.blobToFile(blob, file.name, file.type, new Date().getTime());
resolve(fileResized);
}));
}));
}
/**
* @private
* @param {?} blob
* @param {?} name
* @param {?} type
* @param {?} lastModified
* @return {?}
*/
blobToFile(blob, name, type, lastModified) {
// return new File([blob], name, {type: type, lastModified: lastModified});
/** @type {?} */
let file = (/** @type {?} */ (new Blob([blob], { type: type })));
file.name = name;
file.lastModifiedDate = lastModified;
return (/** @type {?} */ (file));
}
/**
* @private
* @param {?} bytes
* @return {?}
*/
bytesToMB(bytes) {
return bytes / 1048576;
}
}
NgxPicaService.decorators = [
{ type: Injectable }
];
/** @nocollapse */
NgxPicaService.ctorParameters = () => [
{ type: NgxPicaExifService }
];
if (false) {
/**
* @type {?}
* @private
*/
NgxPicaService.prototype.picaResizer;
/**
* @type {?}
* @private
*/
NgxPicaService.prototype.MAX_STEPS;
/**
* @type {?}
* @private
*/
NgxPicaService.prototype._ngxPicaExifService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXBpY2Euc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLXBpY2EvIiwic291cmNlcyI6WyJsaWIvbmd4LXBpY2Euc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUMsT0FBTyxFQUEyQixNQUFNLE1BQU0sQ0FBQztBQUN2RCxPQUFPLEVBQXdCLGdCQUFnQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFFbkYsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDM0QsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBTXhCLE1BQU0sT0FBTyxjQUFjOzs7O0lBSXZCLFlBQW9CLG1CQUF1QztRQUF2Qyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQW9CO1FBSG5ELGdCQUFXLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN6QixjQUFTLEdBQUcsRUFBRSxDQUFDO1FBR25CLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUU7WUFDL0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUN4QztJQUNMLENBQUM7Ozs7Ozs7O0lBRU0sWUFBWSxDQUFDLEtBQWEsRUFBRSxLQUFhLEVBQUUsTUFBYyxFQUFFLE9BQXVDOztjQUMvRixZQUFZLEdBQWtCLElBQUksT0FBTyxFQUFFOztjQUMzQyxVQUFVLEdBQVcsS0FBSyxDQUFDLE1BQU07UUFFdkMsSUFBSSxVQUFVLEdBQUcsQ0FBQyxFQUFFOztrQkFDVixRQUFRLEdBQWtCLElBQUksT0FBTyxFQUFFOztnQkFDekMsS0FBSyxHQUFHLENBQUM7O2tCQUVQLFlBQVksR0FBaUIsUUFBUSxDQUFDLFNBQVM7Ozs7WUFBQyxDQUFDLElBQVUsRUFBRSxFQUFFO2dCQUNqRSxJ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QUNqQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsWUFBWSxDQUFDO1FBQ3JDLE9BQU8sbUJBQUEsSUFBSSxFQUFRLENBQUE7SUFDdkIsQ0FBQzs7Ozs7O0lBRU8sU0FBUyxDQUFDLEtBQWE7UUFDM0IsT0FBTyxLQUFLLEdBQUcsT0FBTyxDQUFDO0lBQzNCLENBQUM7OztZQTFQSixVQUFVOzs7O1lBTkgsa0JBQWtCOzs7Ozs7O0lBUXRCLHFDQUFpQzs7Ozs7SUFDakMsbUNBQXVCOzs7OztJQUVYLDZDQUErQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1N1YmplY3QsIE9ic2VydmFibGUsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge05neFBpY2FFcnJvckludGVyZmFjZSwgTmd4UGljYUVycm9yVHlwZX0gZnJvbSAnLi9uZ3gtcGljYS1lcnJvci5pbnRlcmZhY2UnO1xuaW1wb3J0IHtOZ3hQaWNhUmVzaXplT3B0aW9uc0ludGVyZmFjZX0gZnJvbSAnLi9uZ3gtcGljYS1yZXNpemUtb3B0aW9ucy5pbnRlcmZhY2UnO1xuaW1wb3J0IHtOZ3hQaWNhRXhpZlNlcnZpY2V9IGZyb20gJy4vbmd4LXBpY2EtZXhpZi5zZXJ2aWNlJztcbmltcG9ydCBQaWNhIGZyb20gJ3BpY2EnO1xuXG5cbmRlY2xhcmUgbGV0IHdpbmRvdzogYW55O1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTmd4UGljYVNlcnZpY2Uge1xuICAgIHByaXZhdGUgcGljYVJlc2l6ZXIgPSBuZXcgUGljYSgpO1xuICAgIHByaXZhdGUgTUFYX1NURVBTID0gMjA7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9uZ3hQaWNhRXhpZlNlcnZpY2U6IE5neFBpY2FFeGlmU2VydmljZSkge1xuICAgICAgICBpZiAoIXRoaXMucGljYVJlc2l6ZXIgfHwgIXRoaXMucGljYVJlc2l6ZXIucmVzaXplKSB7XG4gICAgICAgICAgICB0aGlzLnBpY2FSZXNpemVyID0gbmV3IHdpbmRvdy5QaWNhKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgcmVzaXplSW1hZ2VzKGZpbGVzOiBGaWxlW10sIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBvcHRpb25zPzogTmd4UGljYVJlc2l6ZU9wdGlvbnNJbnRlcmZhY2UpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgcmVzaXplZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcbiAgICAgICAgY29uc3QgdG90YWxGaWxlczogbnVtYmVyID0gZmlsZXMubGVuZ3RoO1xuXG4gICAgICAgIGlmICh0b3RhbEZpbGVzID4gMCkge1xuICAgICAgICAgICAgY29uc3QgbmV4dEZpbGU6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcblxuICAgICAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXh0RmlsZS5zdWJzY3JpYmUoKGZpbGU6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZUltYWdlKGZpbGUsIHdpZHRoLCBoZWlnaHQsIG9wdGlvbnMpLnN1YnNjcmliZShpbWFnZVJlc2l6ZWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UubmV4dChpbWFnZVJlc2l6ZWQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCA8IHRvdGFsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRGaWxlLm5leHQoZmlsZXNbaW5kZXhdKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzaXplZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgbmd4UGljYUVycm9yOiBOZ3hQaWNhRXJyb3JJbnRlcmZhY2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlOiBmaWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyOiBlcnJcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UuZXJyb3Iobmd4UGljYUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBuZXh0RmlsZS5uZXh0KGZpbGVzW2luZGV4XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBuZ3hQaWNhRXJyb3I6IE5neFBpY2FFcnJvckludGVyZmFjZSA9IHtcbiAgICAgICAgICAgICAgICBlcnI6IE5neFBpY2FFcnJvclR5cGUuTk9fRklMRVNfUkVDRUlWRURcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJlc2l6ZWRJbWFnZS5lcnJvcihuZ3hQaWNhRXJyb3IpO1xuICAgICAgICAgICAgcmVzaXplZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzaXplZEltYWdlLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZXNpemVJbWFnZShmaWxlOiBGaWxlLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgb3B0aW9ucz86IE5neFBpY2FSZXNpemVPcHRpb25zSW50ZXJmYWNlKTogT2JzZXJ2YWJsZTxGaWxlPiB7XG4gICAgICAgIGNvbnN0IHJlc2l6ZWRJbWFnZTogU3ViamVjdDxGaWxlPiA9IG5ldyBTdWJqZWN0KCk7XG4gICAgICAgIGNvbnN0IG9yaWdpbkNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgY29uc3QgY3R4ID0gb3JpZ2luQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuXG4gICAgICAgIGlmIChjdHgpIHtcbiAgICAgICAgICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbmd4UGljYUV4aWZTZXJ2aWNlLmdldEV4aWZPcmllbnRlZEltYWdlKGltZykudGhlbihvcmllbnRlZEltYWdlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwoaW1nLnNyYyk7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbkNhbnZhcy53aWR0aCA9IG9yaWVudGVkSW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbkNhbnZhcy5oZWlnaHQgPSBvcmllbnRlZEltYWdlLmhlaWdodDtcblxuICAgICAgICAgICAgICAgICAgICBjdHguZHJhd0ltYWdlKG9yaWVudGVkSW1hZ2UsIDAsIDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltYWdlRGF0YSA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgb3JpZW50ZWRJbWFnZS53aWR0aCwgb3JpZW50ZWRJbWFnZS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmFzcGVjdFJhdGlvICYmIG9wdGlvbnMuYXNwZWN0UmF0aW8ua2VlcEFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgcmF0aW8gPSAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5hc3BlY3RSYXRpby5mb3JjZU1pbkRpbWVuc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXRpbyA9IE1hdGgubWF4KHdpZHRoIC8gaW1hZ2VEYXRhLndpZHRoLCBoZWlnaHQgLyBpbWFnZURhdGEuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF0aW8gPSBNYXRoLm1pbih3aWR0aCAvIGltYWdlRGF0YS53aWR0aCwgaGVpZ2h0IC8gaW1hZ2VEYXRhLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gTWF0aC5yb3VuZChpbWFnZURhdGEud2lkdGggKiByYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSBNYXRoLnJvdW5kKGltYWdlRGF0YS5oZWlnaHQgKiByYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZXN0aW5hdGlvbkNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgICAgICAgICAgZGVzdGluYXRpb25DYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgZGVzdGluYXRpb25DYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGljYVJlc2l6ZShmaWxlLCBvcmlnaW5DYW52YXMsIGRlc3RpbmF0aW9uQ2FudmFzLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHJlc2l6ZWRJbWFnZS5lcnJvcihlcnIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKGltZ1Jlc2l6ZWQ6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNpemVkSW1hZ2UubmV4dChpbWdSZXNpemVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaW1nLnNyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGZpbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzaXplZEltYWdlLmVycm9yKE5neFBpY2FFcnJvclR5cGUuQ0FOVkFTX0NPTlRFWFRfSURFTlRJRklFUl9OT1RfU1VQUE9SVEVEKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNpemVkSW1hZ2UuYXNPYnNlcnZhYmxlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXByZXNzSW1hZ2VzKGZpbGVzOiBGaWxlW10sIHNpemVJbk1COiBudW1iZXIpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgY29tcHJlc3NlZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcbiAgICAgICAgY29uc3QgdG90YWxGaWxlczogbnVtYmVyID0gZmlsZXMubGVuZ3RoO1xuXG4gICAgICAgIGlmICh0b3RhbEZpbGVzID4gMCkge1xuICAgICAgICAgICAgY29uc3QgbmV4dEZpbGU6IFN1YmplY3Q8RmlsZT4gPSBuZXcgU3ViamVjdCgpO1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcblxuICAgICAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXh0RmlsZS5zdWJzY3JpYmUoKGZpbGU6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbXByZXNzSW1hZ2UoZmlsZSwgc2l6ZUluTUIpLnN1YnNjcmliZShpbWFnZUNvbXByZXNzZWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UubmV4dChpbWFnZUNvbXByZXNzZWQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCA8IHRvdGFsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRGaWxlLm5leHQoZmlsZXNbaW5kZXhdKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgbmd4UGljYUVycm9yOiBOZ3hQaWNhRXJyb3JJbnRlcmZhY2UgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlOiBmaWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyOiBlcnJcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UuZXJyb3Iobmd4UGljYUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBuZXh0RmlsZS5uZXh0KGZpbGVzW2luZGV4XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBuZ3hQaWNhRXJyb3I6IE5neFBpY2FFcnJvckludGVyZmFjZSA9IHtcbiAgICAgICAgICAgICAgICBlcnI6IE5neFBpY2FFcnJvclR5cGUuTk9fRklMRVNfUkVDRUlWRURcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5lcnJvcihuZ3hQaWNhRXJyb3IpO1xuICAgICAgICAgICAgY29tcHJlc3NlZEltYWdlLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcHJlc3NlZEltYWdlLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wcmVzc0ltYWdlKGZpbGU6IEZpbGUsIHNpemVJbk1COiBudW1iZXIpOiBPYnNlcnZhYmxlPEZpbGU+IHtcbiAgICAgICAgY29uc3QgY29tcHJlc3NlZEltYWdlOiBTdWJqZWN0PEZpbGU+ID0gbmV3IFN1YmplY3QoKTtcblxuICAgICAgICBjb25zdCBvcmlnaW5DYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgIGNvbnN0IGN0eCA9IG9yaWdpbkNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcblxuICAgICAgICBpZiAoY3R4KSB7XG4gICAgICAgICAgICBpbWcub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX25neFBpY2FFeGlmU2VydmljZS5nZXRFeGlmT3JpZW50ZWRJbWFnZShpbWcpLnRoZW4ob3JpZW50ZWRJbWFnZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKGltZy5zcmMpO1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5DYW52YXMud2lkdGggPSBvcmllbnRlZEltYWdlLndpZHRoO1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5DYW52YXMuaGVpZ2h0ID0gb3JpZW50ZWRJbWFnZS5oZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShvcmllbnRlZEltYWdlLCAwLCAwKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBpY2FSZXNpemVyLnRvQmxvYihvcmlnaW5DYW52YXMsIGZpbGUudHlwZSwgMSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiBjb21wcmVzc2VkSW1hZ2UuZXJyb3IoZXJyKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYnl0ZXNUb01CKGJsb2Iuc2l6ZSkgPD0gc2l6ZUluTUIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1nQ29tcHJlc3NlZDogRmlsZSA9IHRoaXMuYmxvYlRvRmlsZShibG9iLCBmaWxlLm5hbWUsIGZpbGUudHlwZSwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UubmV4dChpbWdDb21wcmVzc2VkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldENvbXByZXNzZWRJbWFnZShvcmlnaW5DYW52YXMsIGZpbGUudHlwZSwgMSwgc2l6ZUluTUIsIDApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gY29tcHJlc3NlZEltYWdlLmVycm9yKGVycikpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoYmxvYjogQmxvYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ0NvbXByZXNzZWQ6IEZpbGUgPSB0aGlzLmJsb2JUb0ZpbGUoYmxvYiwgZmlsZS5uYW1lLCBmaWxlLnR5cGUsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXByZXNzZWRJbWFnZS5uZXh0KGltZ0NvbXByZXNzZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpbWcuc3JjID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwoZmlsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb21wcmVzc2VkSW1hZ2UuZXJyb3IoTmd4UGljYUVycm9yVHlwZS5DQU5WQVNfQ09OVEVYVF9JREVOVElGSUVSX05PVF9TVVBQT1JURUQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbXByZXNzZWRJbWFnZS5hc09ic2VydmFibGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbXByZXNzZWRJbWFnZShjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCB0eXBlOiBzdHJpbmcsIHF1YWxpdHk6IG51bWJlciwgc2l6ZUluTUI6IG51bWJlciwgc3RlcDogbnVtYmVyKTogUHJvbWlzZTxCbG9iPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxCbG9iPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnBpY2FSZXNpemVyLnRvQmxvYihjYW52YXMsIHR5cGUsIHF1YWxpdHkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHJlamVjdChlcnIpKVxuICAgICAgICAgICAgICAgIC50aGVuKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tDb21wcmVzc2VkSW1hZ2VTaXplKGNhbnZhcywgYmxvYiwgcXVhbGl0eSwgc2l6ZUluTUIsIHN0ZXApXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gcmVqZWN0KGVycikpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoY29tcHJlc3NlZEJsb2I6IEJsb2IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShjb21wcmVzc2VkQmxvYik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaGVja0NvbXByZXNzZWRJbWFnZVNpemUoXG4gICAgICAgIGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsXG4gICAgICAgIGJsb2I6IEJsb2IsXG4gICAgICAgIHF1YWxpdHk6IG51bWJlcixcbiAgICAgICAgc2l6ZUluTUI6IG51bWJlcixcbiAgICAgICAgc3RlcDogbnVtYmVyXG4gICAgKTogUHJvbWlzZTxCbG9iPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxCbG9iPigocmVzb2x2ZSxcbiAgICAgICAgICAgIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoc3RlcCA+IHRoaXMuTUFYX1NURVBTKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KE5neFBpY2FFcnJvclR5cGUuTk9UX0JFX0FCTEVfVE9fQ09NUFJFU1NfRU5PVUdIKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5ieXRlc1RvTUIoYmxvYi5zaXplKSA8IHNpemVJbk1CKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShibG9iKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3UXVhbGl0eTogbnVtYmVyID0gcXVhbGl0eSAtIChxdWFsaXR5ICogMC4xKTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdTdGVwOiBudW1iZXIgPSBzdGVwICsgMTtcblxuICAgICAgICAgICAgICAgIC8vIHJlY3Vyc2l2ZWx5IGNvbXByZXNzaW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldENvbXByZXNzZWRJbWFnZShjYW52YXMsIGJsb2IudHlwZSwgbmV3UXVhbGl0eSwgc2l6ZUluTUIsIG5ld1N0ZXApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwaWNhUmVzaXplKGZpbGU6IEZpbGUsIGZyb206IEhUTUxDYW52YXNFbGVtZW50LCB0bzogSFRNTENhbnZhc0VsZW1lbnQsIG9wdGlvbnM6IGFueSk6IFByb21pc2U8RmlsZT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8RmlsZT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5waWNhUmVzaXplci5yZXNpemUoZnJvbSwgdG8sIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHJlamVjdChlcnIpKVxuICAgICAgICAgICAgICAgIC50aGVuKChyZXNpemVkQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCkgPT4gdGhpcy5waWNhUmVzaXplci50b0Jsb2IocmVzaXplZENhbnZhcywgZmlsZS50eXBlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoYmxvYjogQmxvYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxlUmVzaXplZDogRmlsZSA9IHRoaXMuYmxvYlRvRmlsZShibG9iLCBmaWxlLm5hbWUsIGZpbGUudHlwZSwgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGZpbGVSZXNpemVkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBibG9iVG9GaWxlKGJsb2I6IEJsb2IsIG5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBsYXN0TW9kaWZpZWQ6IG51bWJlcik6IEZpbGUge1xuICAgICAgICAvLyByZXR1cm4gbmV3IEZpbGUoW2Jsb2JdLCBuYW1lLCB7dHlwZTogdHlwZSwgbGFzdE1vZGlmaWVkOiBsYXN0TW9kaWZpZWR9KTtcbiAgICAgICAgbGV0IGZpbGUgPSBuZXcgQmxvYihbYmxvYl0sIHt0eXBlIDogdHlwZX0pIGFzIGFueTtcbiAgICAgICAgZmlsZS5uYW1lID0gbmFtZTtcbiAgICAgICAgZmlsZS5sYXN0TW9kaWZpZWREYXRlID0gbGFzdE1vZGlmaWVkO1xuICAgICAgICByZXR1cm4gZmlsZSBhcyBGaWxlXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBieXRlc1RvTUIoYnl0ZXM6IG51bWJlcikge1xuICAgICAgICByZXR1cm4gYnl0ZXMgLyAxMDQ4NTc2O1xuICAgIH1cbn1cbiJdfQ==