angular-material-datatransfer-lib
Version:
A HTML5 datatransfer UI for handling upload and download of multiple simultaneous files.
347 lines • 33.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: lib/io/downloaders/blob.downloader.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Injectable } from '@angular/core';
import { saveAs } from 'file-saver';
import { BaseDownloader } from './base.downloader';
import { DatatransferItem } from '../../models/datatransfer-item.model';
import { ConfigService } from '../../services/config.service';
import { LoggerService } from '../../services/logger.service';
import { GuidUtil } from '../../utils/guid.util';
import { CryptoService } from '../../services/crypto.service';
import { CommonUtil } from '../../utils/common.util';
import { TransferStatus } from '../../enums/transfer-status.enum';
import { SizeContainer } from '../../models/size-container.model';
import { DecimalByteUnit } from '../../enums/decimal-byte-unit.enum';
import { ProgressContainer } from '../../models/progress-container.model';
import { TransferType } from '../../enums/transfer-type.enum';
export class BlobDownloader extends BaseDownloader {
/**
* @param {?} logger
* @param {?} guidUtil
* @param {?} cryptoService
* @param {?} commonUtil
*/
constructor(logger, guidUtil, cryptoService, commonUtil) {
super(logger, guidUtil, cryptoService);
this.logger = logger;
this.guidUtil = guidUtil;
this.cryptoService = cryptoService;
this.commonUtil = commonUtil;
this.throttleProgressCallbacks = 0.1;
this.files = [];
this.queue = [];
this.downloading = [];
}
/**
* @return {?}
*/
startAll() {
if (!this.isWorking()) {
for (let index = 0; index < ConfigService.settings.core.simultaneousDownloads; index++) {
this.downloadNext();
}
}
}
/**
* @return {?}
*/
pauseAll() {
}
/**
* @return {?}
*/
removeAll() {
this.files.forEach((/**
* @param {?} item
* @param {?} index
* @return {?}
*/
(item, index) => {
/** @type {?} */
const that = (/** @type {?} */ (this));
that.abortDownload(item);
}));
this.files.length = 0;
this.queue.length = 0;
this.downloading.length = 0;
this._isWorking = false;
this.updateOverallSize(this.getSize());
this.updateOverallProgress(this.transferType, this.getProgress());
}
/**
* @param {?} item
* @return {?}
*/
removeItem(item) {
this.abortDownload(item);
this.removeItemFromArray(item, this.files);
this.removeItemFromArray(item, this.queue);
this.removeItemFromArray(item, this.downloading);
this.downloadNext();
}
/**
* @private
* @param {?} item
* @param {?} array
* @return {?}
*/
removeItemFromArray(item, array) {
for (let i = array.length - 1; i >= 0; i--) {
if (array[i] === item) {
array.splice(i, 1);
break;
}
}
}
/**
* @param {?} item
* @return {?}
*/
retryItem(item) {
this.abortDownload(item);
this.removeItemFromArray(item, this.queue);
this.removeItemFromArray(item, this.downloading);
this._isWorking = this.downloading.length > 0;
item.externalItem.progress = 0;
this.updateItemProgress(item, item.externalItem.progress);
this.changeItemStatus(item, TransferStatus.Queued);
this.queue.push(item);
this.initDownload(item);
this.downloadNext();
}
/**
* @param {?} filename
* @param {?} url
* @param {?} sizeInBytes
* @return {?}
*/
download(filename, url, sizeInBytes) {
/** @type {?} */
const newItem = new DatatransferItem({
id: this.generateUniqueIdentifier(),
name: filename,
sizeContainer: new SizeContainer({ decimalByteUnit: DecimalByteUnit.Byte, decimalByteUnitSize: sizeInBytes }),
progressContainer: new ProgressContainer(sizeInBytes),
transferType: TransferType.Download,
status: TransferStatus.Queued,
externalItem: {
url,
progress: 0,
size: sizeInBytes,
lastProgressCallback: new Date()
}
});
this.addItem(newItem);
this.files.push(newItem);
this.queue.push(newItem);
this.initDownload(newItem);
this.downloadNext();
}
/**
* @private
* @param {?} item
* @return {?}
*/
initDownload(item) {
/** @type {?} */
const xhr = new XMLHttpRequest();
item.externalItem.xhr = xhr;
xhr.open(ConfigService.settings.core.downloadMethod, item.externalItem.url);
xhr.timeout = ConfigService.settings.core.downloadXhrTimeout;
xhr.withCredentials = ConfigService.settings.core.downloadWithCredentials;
// Add data from header options
/** @type {?} */
let customHeaders = ConfigService.settings.core.downloadHeaders;
if (typeof customHeaders === 'function') {
customHeaders = customHeaders(item);
}
this.commonUtil.each(customHeaders, (/**
* @param {?} k
* @param {?} v
* @return {?}
*/
function (k, v) {
xhr.setRequestHeader(k, v);
}));
xhr.responseType = 'blob';
xhr.onloadstart = (/**
* @param {?} e
* @return {?}
*/
function (e) {
/** @type {?} */
const that = (/** @type {?} */ (this));
that.changeItemStatus(item, TransferStatus.Downloading);
}).bind(this);
xhr.onprogress = (/**
* @param {?} e
* @return {?}
*/
function (e) {
/** @type {?} */
const that = (/** @type {?} */ (this));
if (new Date().getTime() - item.externalItem.lastProgressCallback.getTime() > that.throttleProgressCallbacks * 1000) {
item.externalItem.progress = e.loaded / e.total;
that.updateItemProgress(item, item.externalItem.progress);
that.updateOverallProgress(that.transferType, that.getProgress());
item.externalItem.lastProgressCallback = new Date();
}
}).bind(this);
xhr.onloadend = (/**
* @param {?} e
* @return {?}
*/
function (e) {
/*
Value State Description
0 UNSENT Client has been created. open() not called yet.
1 OPENED open() has been called.
2 HEADERS_RECEIVED send() has been called, and headers and status are available.
3 LOADING Downloading; responseText holds partial data.
4 DONE The operation is complete.
*/
/** @type {?} */
const that = (/** @type {?} */ (this));
if (xhr.readyState === 4) {
item.externalItem.progress = 1;
that.updateItemProgress(item, item.externalItem.progress);
if (xhr.status === 200) {
that.changeItemStatus(item, TransferStatus.Finished);
saveAs(xhr.response, item.name);
}
else if (xhr.status !== 0) { // don't change status for aborted items
that.changeItemStatus(item, TransferStatus.Failed);
}
that.removeItemFromArray(item, that.downloading);
that.downloadNext();
}
}).bind(this);
}
/**
* @private
* @return {?}
*/
downloadNext() {
this.updateOverallSize(this.getSize());
this.updateOverallProgress(this.transferType, this.getProgress());
if (this.downloading.length < ConfigService.settings.core.simultaneousDownloads) {
/** @type {?} */
const item = this.queue.shift();
if (!!item && !!item.externalItem && !!item.externalItem.xhr) {
this.changeItemStatus(item, TransferStatus.Downloading);
this.downloading.push(item);
this._isWorking = this.downloading.length > 0;
item.externalItem.xhr.send();
}
}
}
/**
* @private
* @param {?} item
* @return {?}
*/
abortDownload(item) {
if (!!item && !!item.externalItem && !!item.externalItem.xhr) {
item.externalItem.xhr.abort();
item.externalItem.xhr = null;
}
}
/**
* @private
* @return {?}
*/
getSize() {
/** @type {?} */
let totalSize = 0;
this.files.forEach((/**
* @param {?} file
* @param {?} index
* @return {?}
*/
(file, index) => {
totalSize += file.externalItem.size;
}));
return totalSize;
}
/**
* @private
* @return {?}
*/
getProgress() {
/** @type {?} */
let totalDone = 0;
/** @type {?} */
let totalSize = 0;
this.files.forEach((/**
* @param {?} file
* @param {?} index
* @return {?}
*/
(file, index) => {
/** @type {?} */
let currentFileProgress = file.externalItem.progress;
if (file.status === TransferStatus.Failed) {
currentFileProgress = 1;
}
totalDone += currentFileProgress * file.externalItem.size;
totalSize += file.externalItem.size;
}));
return totalSize > 0 ? totalDone / totalSize : 0;
}
}
BlobDownloader.decorators = [
{ type: Injectable }
];
/** @nocollapse */
BlobDownloader.ctorParameters = () => [
{ type: LoggerService },
{ type: GuidUtil },
{ type: CryptoService },
{ type: CommonUtil }
];
if (false) {
/**
* @type {?}
* @private
*/
BlobDownloader.prototype.throttleProgressCallbacks;
/**
* @type {?}
* @private
*/
BlobDownloader.prototype.files;
/**
* @type {?}
* @private
*/
BlobDownloader.prototype.queue;
/**
* @type {?}
* @private
*/
BlobDownloader.prototype.downloading;
/**
* @type {?}
* @protected
*/
BlobDownloader.prototype.logger;
/**
* @type {?}
* @protected
*/
BlobDownloader.prototype.guidUtil;
/**
* @type {?}
* @protected
*/
BlobDownloader.prototype.cryptoService;
/**
* @type {?}
* @private
*/
BlobDownloader.prototype.commonUtil;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvYi5kb3dubG9hZGVyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhci1tYXRlcmlhbC1kYXRhdHJhbnNmZXItbGliLyIsInNvdXJjZXMiOlsibGliL2lvL2Rvd25sb2FkZXJzL2Jsb2IuZG93bmxvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNwQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFxQixnQkFBZ0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzNGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDckUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRzlELE1BQU0sT0FBTyxjQUFlLFNBQVEsY0FBYzs7Ozs7OztJQU85QyxZQUFzQixNQUFxQixFQUFZLFFBQWtCLEVBQ25ELGFBQTRCLEVBQVUsVUFBc0I7UUFDOUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVB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Q0FBQztRQUN4QyxDQUFDLEVBQUMsQ0FBQztRQUNILE9BQU8sU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7OztZQTVMSixVQUFVOzs7O1lBVkYsYUFBYTtZQUNiLFFBQVE7WUFDUixhQUFhO1lBQ2IsVUFBVTs7Ozs7OztJQVVmLG1EQUF3Qzs7Ozs7SUFDeEMsK0JBQXdDOzs7OztJQUN4QywrQkFBd0M7Ozs7O0lBQ3hDLHFDQUE4Qzs7Ozs7SUFFbEMsZ0NBQStCOzs7OztJQUFFLGtDQUE0Qjs7Ozs7SUFDN0QsdUNBQXNDOzs7OztJQUFFLG9DQUE4QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgc2F2ZUFzIH0gZnJvbSAnZmlsZS1zYXZlcic7XHJcbmltcG9ydCB7IEJhc2VEb3dubG9hZGVyIH0gZnJvbSAnLi9iYXNlLmRvd25sb2FkZXInO1xyXG5pbXBvcnQgeyBJRGF0YXRyYW5zZmVySXRlbSwgRGF0YXRyYW5zZmVySXRlbSB9IGZyb20gJy4uLy4uL21vZGVscy9kYXRhdHJhbnNmZXItaXRlbS5tb2RlbCc7XHJcbmltcG9ydCB7IENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9jb25maWcuc2VydmljZSc7XHJcbmltcG9ydCB7IExvZ2dlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9sb2dnZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IEd1aWRVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbHMvZ3VpZC51dGlsJztcclxuaW1wb3J0IHsgQ3J5cHRvU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2NyeXB0by5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQ29tbW9uVXRpbCB9IGZyb20gJy4uLy4uL3V0aWxzL2NvbW1vbi51dGlsJztcclxuaW1wb3J0IHsgVHJhbnNmZXJTdGF0dXMgfSBmcm9tICcuLi8uLi9lbnVtcy90cmFuc2Zlci1zdGF0dXMuZW51bSc7XHJcbmltcG9ydCB7IFNpemVDb250YWluZXIgfSBmcm9tICcuLi8uLi9tb2RlbHMvc2l6ZS1jb250YWluZXIubW9kZWwnO1xyXG5pbXBvcnQgeyBEZWNpbWFsQnl0ZVVuaXQgfSBmcm9tICcuLi8uLi9lbnVtcy9kZWNpbWFsLWJ5dGUtdW5pdC5lbnVtJztcclxuaW1wb3J0IHsgUHJvZ3Jlc3NDb250YWluZXIgfSBmcm9tICcuLi8uLi9tb2RlbHMvcHJvZ3Jlc3MtY29udGFpbmVyLm1vZGVsJztcclxuaW1wb3J0IHsgVHJhbnNmZXJUeXBlIH0gZnJvbSAnLi4vLi4vZW51bXMvdHJhbnNmZXItdHlwZS5lbnVtJztcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEJsb2JEb3dubG9hZGVyIGV4dGVuZHMgQmFzZURvd25sb2FkZXIge1xyXG5cclxuICAgIHByaXZhdGUgdGhyb3R0bGVQcm9ncmVzc0NhbGxiYWNrcyA9IDAuMTtcclxuICAgIHByaXZhdGUgZmlsZXM6IElEYXRhdHJhbnNmZXJJdGVtW10gPSBbXTtcclxuICAgIHByaXZhdGUgcXVldWU6IElEYXRhdHJhbnNmZXJJdGVtW10gPSBbXTtcclxuICAgIHByaXZhdGUgZG93bmxvYWRpbmc6IElEYXRhdHJhbnNmZXJJdGVtW10gPSBbXTtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgbG9nZ2VyOiBMb2dnZXJTZXJ2aWNlLCBwcm90ZWN0ZWQgZ3VpZFV0aWw6IEd1aWRVdGlsLFxyXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIGNyeXB0b1NlcnZpY2U6IENyeXB0b1NlcnZpY2UsIHByaXZhdGUgY29tbW9uVXRpbDogQ29tbW9uVXRpbCkge1xyXG4gICAgICAgIHN1cGVyKGxvZ2dlciwgZ3VpZFV0aWwsIGNyeXB0b1NlcnZpY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdGFydEFsbCgpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIXRoaXMuaXNXb3JraW5nKCkpIHtcclxuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IENvbmZpZ1NlcnZpY2Uuc2V0dGluZ3MuY29yZS5zaW11bHRhbmVvdXNEb3dubG9hZHM7IGluZGV4KyspIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZG93bmxvYWROZXh0KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHBhdXNlQWxsKCk6IHZvaWQge1xyXG5cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgcmVtb3ZlQWxsKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuZmlsZXMuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgdGhhdCA9IHRoaXMgYXMgQmxvYkRvd25sb2FkZXI7XHJcbiAgICAgICAgICAgIHRoYXQuYWJvcnREb3dubG9hZChpdGVtKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLmZpbGVzLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgdGhpcy5xdWV1ZS5sZW5ndGggPSAwO1xyXG4gICAgICAgIHRoaXMuZG93bmxvYWRpbmcubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLl9pc1dvcmtpbmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnVwZGF0ZU92ZXJhbGxTaXplKHRoaXMuZ2V0U2l6ZSgpKTtcclxuICAgICAgICB0aGlzLnVwZGF0ZU92ZXJhbGxQcm9ncmVzcyh0aGlzLnRyYW5zZmVyVHlwZSwgdGhpcy5nZXRQcm9ncmVzcygpKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgcmVtb3ZlSXRlbShpdGVtOiBJRGF0YXRyYW5zZmVySXRlbSk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuYWJvcnREb3dubG9hZChpdGVtKTtcclxuICAgICAgICB0aGlzLnJlbW92ZUl0ZW1Gcm9tQXJyYXkoaXRlbSwgdGhpcy5maWxlcyk7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVJdGVtRnJvbUFycmF5KGl0ZW0sIHRoaXMucXVldWUpO1xyXG4gICAgICAgIHRoaXMucmVtb3ZlSXRlbUZyb21BcnJheShpdGVtLCB0aGlzLmRvd25sb2FkaW5nKTtcclxuICAgICAgICB0aGlzLmRvd25sb2FkTmV4dCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgcmVtb3ZlSXRlbUZyb21BcnJheShpdGVtOiBJRGF0YXRyYW5zZmVySXRlbSwgYXJyYXk6IElEYXRhdHJhbnNmZXJJdGVtW10pOiB2b2lkIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gYXJyYXkubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgaWYgKGFycmF5W2ldID09PSBpdGVtKSB7XHJcbiAgICAgICAgICAgICAgICBhcnJheS5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgcmV0cnlJdGVtKGl0ZW06IElEYXRhdHJhbnNmZXJJdGVtKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5hYm9ydERvd25sb2FkKGl0ZW0pO1xyXG4gICAgICAgIHRoaXMucmVtb3ZlSXRlbUZyb21BcnJheShpdGVtLCB0aGlzLnF1ZXVlKTtcclxuICAgICAgICB0aGlzLnJlbW92ZUl0ZW1Gcm9tQXJyYXkoaXRlbSwgdGhpcy5kb3dubG9hZGluZyk7XHJcbiAgICAgICAgdGhpcy5faXNXb3JraW5nID0gdGhpcy5kb3dubG9hZGluZy5sZW5ndGggPiAwO1xyXG4gICAgICAgIGl0ZW0uZXh0ZXJuYWxJdGVtLnByb2dyZXNzID0gMDtcclxuICAgICAgICB0aGlzLnVwZGF0ZUl0ZW1Qcm9ncmVzcyhpdGVtLCBpdGVtLmV4dGVybmFsSXRlbS5wcm9ncmVzcyk7XHJcbiAgICAgICAgdGhpcy5jaGFuZ2VJdGVtU3RhdHVzKGl0ZW0sIFRyYW5zZmVyU3RhdHVzLlF1ZXVlZCk7XHJcbiAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xyXG4gICAgICAgIHRoaXMuaW5pdERvd25sb2FkKGl0ZW0pO1xyXG4gICAgICAgIHRoaXMuZG93bmxvYWROZXh0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGRvd25sb2FkKGZpbGVuYW1lOiBzdHJpbmcsIHVybDogc3RyaW5nLCBzaXplSW5CeXRlczogbnVtYmVyKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgbmV3SXRlbSA9IG5ldyBEYXRhdHJhbnNmZXJJdGVtKHtcclxuICAgICAgICAgICAgaWQ6IHRoaXMuZ2VuZXJhdGVVbmlxdWVJZGVudGlmaWVyKCksXHJcbiAgICAgICAgICAgIG5hbWU6IGZpbGVuYW1lLFxyXG4gICAgICAgICAgICBzaXplQ29udGFpbmVyOiBuZXcgU2l6ZUNvbnRhaW5lcih7IGRlY2ltYWxCeXRlVW5pdDogRGVjaW1hbEJ5dGVVbml0LkJ5dGUsIGRlY2ltYWxCeXRlVW5pdFNpemU6IHNpemVJbkJ5dGVzIH0pLFxyXG4gICAgICAgICAgICBwcm9ncmVzc0NvbnRhaW5lcjogbmV3IFByb2dyZXNzQ29udGFpbmVyKHNpemVJbkJ5dGVzKSxcclxuICAgICAgICAgICAgdHJhbnNmZXJUeXBlOiBUcmFuc2ZlclR5cGUuRG93bmxvYWQsXHJcbiAgICAgICAgICAgIHN0YXR1czogVHJhbnNmZXJTdGF0dXMuUXVldWVkLFxyXG4gICAgICAgICAgICBleHRlcm5hbEl0ZW06IHtcclxuICAgICAgICAgICAgICAgIHVybCxcclxuICAgICAgICAgICAgICAgIHByb2dyZXNzOiAwLFxyXG4gICAgICAgICAgICAgICAgc2l6ZTogc2l6ZUluQnl0ZXMsXHJcbiAgICAgICAgICAgICAgICBsYXN0UHJvZ3Jlc3NDYWxsYmFjazogbmV3IERhdGUoKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuYWRkSXRlbShuZXdJdGVtKTtcclxuICAgICAgICB0aGlzLmZpbGVzLnB1c2gobmV3SXRlbSk7XHJcbiAgICAgICAgdGhpcy5xdWV1ZS5wdXNoKG5ld0l0ZW0pO1xyXG4gICAgICAgIHRoaXMuaW5pdERvd25sb2FkKG5ld0l0ZW0pO1xyXG4gICAgICAgIHRoaXMuZG93bmxvYWROZXh0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBpbml0RG93bmxvYWQoaXRlbTogSURhdGF0cmFuc2Zlckl0ZW0pOiB2b2lkIHtcclxuICAgICAgICBjb25zdCB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcclxuICAgICAgICBpdGVtLmV4dGVybmFsSXRlbS54aHIgPSB4aHI7XHJcblxyXG4gICAgICAgIHhoci5vcGVuKENvbmZpZ1NlcnZpY2Uuc2V0dGluZ3MuY29yZS5kb3dubG9hZE1ldGhvZCwgaXRlbS5leHRlcm5hbEl0ZW0udXJsKTtcclxuICAgICAgICB4aHIudGltZW91dCA9IENvbmZpZ1NlcnZpY2Uuc2V0dGluZ3MuY29yZS5kb3dubG9hZFhoclRpbWVvdXQ7XHJcbiAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IENvbmZpZ1NlcnZpY2Uuc2V0dGluZ3MuY29yZS5kb3dubG9hZFdpdGhDcmVkZW50aWFscztcclxuXHJcbiAgICAgICAgLy8gQWRkIGRhdGEgZnJvbSBoZWFkZXIgb3B0aW9uc1xyXG4gICAgICAgIGxldCBjdXN0b21IZWFkZXJzID0gQ29uZmlnU2VydmljZS5zZXR0aW5ncy5jb3JlLmRvd25sb2FkSGVhZGVycztcclxuICAgICAgICBpZiAodHlwZW9mIGN1c3RvbUhlYWRlcnMgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgY3VzdG9tSGVhZGVycyA9IGN1c3RvbUhlYWRlcnMoaXRlbSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuY29tbW9uVXRpbC5lYWNoKGN1c3RvbUhlYWRlcnMsIGZ1bmN0aW9uKGs6IHN0cmluZywgdjogc3RyaW5nKSB7XHJcbiAgICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKGssIHYpO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gJ2Jsb2InO1xyXG4gICAgICAgIHhoci5vbmxvYWRzdGFydCA9IGZ1bmN0aW9uKGUpIHtcclxuICAgICAgICAgICAgY29uc3QgdGhhdCA9IHRoaXMgYXMgQmxvYkRvd25sb2FkZXI7XHJcbiAgICAgICAgICAgIHRoYXQuY2hhbmdlSXRlbVN0YXR1cyhpdGVtLCBUcmFuc2ZlclN0YXR1cy5Eb3dubG9hZGluZyk7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xyXG4gICAgICAgIHhoci5vbnByb2dyZXNzID0gZnVuY3Rpb24oZSkge1xyXG4gICAgICAgICAgICBjb25zdCB0aGF0ID0gdGhpcyBhcyBCbG9iRG93bmxvYWRlcjtcclxuICAgICAgICAgICAgaWYgKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gaXRlbS5leHRlcm5hbEl0ZW0ubGFzdFByb2dyZXNzQ2FsbGJhY2suZ2V0VGltZSgpID4gdGhhdC50aHJvdHRsZVByb2dyZXNzQ2FsbGJhY2tzICogMTAwMCkge1xyXG4gICAgICAgICAgICAgICAgaXRlbS5leHRlcm5hbEl0ZW0ucHJvZ3Jlc3MgPSBlLmxvYWRlZCAvIGUudG90YWw7XHJcbiAgICAgICAgICAgICAgICB0aGF0LnVwZGF0ZUl0ZW1Qcm9ncmVzcyhpdGVtLCBpdGVtLmV4dGVybmFsSXRlbS5wcm9ncmVzcyk7XHJcbiAgICAgICAgICAgICAgICB0aGF0LnVwZGF0ZU92ZXJhbGxQcm9ncmVzcyh0aGF0LnRyYW5zZmVyVHlwZSwgdGhhdC5nZXRQcm9ncmVzcygpKTtcclxuICAgICAgICAgICAgICAgIGl0ZW0uZXh0ZXJuYWxJdGVtLmxhc3RQcm9ncmVzc0NhbGxiYWNrID0gbmV3IERhdGUoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0uYmluZCh0aGlzKTtcclxuICAgICAgICB4aHIub25sb2FkZW5kID0gZnVuY3Rpb24oZSkge1xyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICBWYWx1ZVx0U3RhdGVcdERlc2NyaXB0aW9uXHJcbiAgICAgICAgICAgIDBcdFVOU0VOVFx0Q2xpZW50IGhhcyBiZWVuIGNyZWF0ZWQuIG9wZW4oKSBub3QgY2FsbGVkIHlldC5cclxuICAgICAgICAgICAgMVx0T1BFTkVEXHRvcGVuKCkgaGFzIGJlZW4gY2FsbGVkLlxyXG4gICAgICAgICAgICAyXHRIRUFERVJTX1JFQ0VJVkVEXHRzZW5kKCkgaGFzIGJlZW4gY2FsbGVkLCBhbmQgaGVhZGVycyBhbmQgc3RhdHVzIGFyZSBhdmFpbGFibGUuXHJcbiAgICAgICAgICAgIDNcdExPQURJTkdcdERvd25sb2FkaW5nOyByZXNwb25zZVRleHQgaG9sZHMgcGFydGlhbCBkYXRhLlxyXG4gICAgICAgICAgICA0XHRET05FXHRUaGUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlLlxyXG4gICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBjb25zdCB0aGF0ID0gdGhpcyBhcyBCbG9iRG93bmxvYWRlcjtcclxuICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09PSA0KSB7XHJcbiAgICAgICAgICAgICAgICBpdGVtLmV4dGVybmFsSXRlbS5wcm9ncmVzcyA9IDE7XHJcbiAgICAgICAgICAgICAgICB0aGF0LnVwZGF0ZUl0ZW1Qcm9ncmVzcyhpdGVtLCBpdGVtLmV4dGVybmFsSXRlbS5wcm9ncmVzcyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PT0gMjAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5jaGFuZ2VJdGVtU3RhdHVzKGl0ZW0sIFRyYW5zZmVyU3RhdHVzLkZpbmlzaGVkKTtcclxuICAgICAgICAgICAgICAgICAgICBzYXZlQXMoeGhyLnJlc3BvbnNlLCBpdGVtLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh4aHIuc3RhdHVzICE9PSAwKSB7IC8vIGRvbid0IGNoYW5nZSBzdGF0dXMgZm9yIGFib3J0ZWQgaXRlbXNcclxuICAgICAgICAgICAgICAgICAgICB0aGF0LmNoYW5nZUl0ZW1TdGF0dXMoaXRlbSwgVHJhbnNmZXJTdGF0dXMuRmFpbGVkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRoYXQucmVtb3ZlSXRlbUZyb21BcnJheShpdGVtLCB0aGF0LmRvd25sb2FkaW5nKTtcclxuICAgICAgICAgICAgICAgIHRoYXQuZG93bmxvYWROZXh0KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LmJpbmQodGhpcyk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBkb3dubG9hZE5leHQoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy51cGRhdGVPdmVyYWxsU2l6ZSh0aGlzLmdldFNpemUoKSk7XHJcbiAgICAgICAgdGhpcy51cGRhdGVPdmVyYWxsUHJvZ3Jlc3ModGhpcy50cmFuc2ZlclR5cGUsIHRoaXMuZ2V0UHJvZ3Jlc3MoKSk7XHJcbiAgICAgICAgaWYgKHRoaXMuZG93bmxvYWRpbmcubGVuZ3RoIDwgQ29uZmlnU2VydmljZS5zZXR0aW5ncy5jb3JlLnNpbXVsdGFuZW91c0Rvd25sb2Fkcykge1xyXG4gICAgICAgICAgICBjb25zdCBpdGVtID0gdGhpcy5xdWV1ZS5zaGlmdCgpO1xyXG4gICAgICAgICAgICBpZiAoISFpdGVtICYmICEhaXRlbS5leHRlcm5hbEl0ZW0gJiYgISFpdGVtLmV4dGVybmFsSXRlbS54aHIpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hhbmdlSXRlbVN0YXR1cyhpdGVtLCBUcmFuc2ZlclN0YXR1cy5Eb3dubG9hZGluZyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRvd25sb2FkaW5nLnB1c2goaXRlbSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9pc1dvcmtpbmcgPSB0aGlzLmRvd25sb2FkaW5nLmxlbmd0aCA+IDA7XHJcbiAgICAgICAgICAgICAgICBpdGVtLmV4dGVybmFsSXRlbS54aHIuc2VuZCgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYWJvcnREb3dubG9hZChpdGVtOiBJRGF0YXRyYW5zZmVySXRlbSk6IHZvaWQge1xyXG4gICAgICAgIGlmICghIWl0ZW0gJiYgISFpdGVtLmV4dGVybmFsSXRlbSAmJiAhIWl0ZW0uZXh0ZXJuYWxJdGVtLnhocikge1xyXG4gICAgICAgICAgICBpdGVtLmV4dGVybmFsSXRlbS54aHIuYWJvcnQoKTtcclxuICAgICAgICAgICAgaXRlbS5leHRlcm5hbEl0ZW0ueGhyID0gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBnZXRTaXplKCk6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IHRvdGFsU2l6ZSA9IDA7XHJcbiAgICAgICAgdGhpcy5maWxlcy5mb3JFYWNoKChmaWxlLCBpbmRleCkgPT4ge1xyXG4gICAgICAgICAgICB0b3RhbFNpemUgKz0gZmlsZS5leHRlcm5hbEl0ZW0uc2l6ZTtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gdG90YWxTaXplO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0UHJvZ3Jlc3MoKTogbnVtYmVyIHtcclxuICAgICAgICBsZXQgdG90YWxEb25lID0gMDtcclxuICAgICAgICBsZXQgdG90YWxTaXplID0gMDtcclxuICAgICAgICB0aGlzLmZpbGVzLmZvckVhY2goKGZpbGUsIGluZGV4KSA9PiB7XHJcbiAgICAgICAgICAgIGxldCBjdXJyZW50RmlsZVByb2dyZXNzID0gZmlsZS5leHRlcm5hbEl0ZW0ucHJvZ3Jlc3M7XHJcbiAgICAgICAgICAgIGlmIChmaWxlLnN0YXR1cyA9PT0gVHJhbnNmZXJTdGF0dXMuRmFpbGVkKSB7XHJcbiAgICAgICAgICAgICAgICBjdXJyZW50RmlsZVByb2dyZXNzID0gMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0b3RhbERvbmUgKz0gY3VycmVudEZpbGVQcm9ncmVzcyAqIGZpbGUuZXh0ZXJuYWxJdGVtLnNpemU7XHJcbiAgICAgICAgICAgIHRvdGFsU2l6ZSArPSBmaWxlLmV4dGVybmFsSXRlbS5zaXplO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiB0b3RhbFNpemUgPiAwID8gdG90YWxEb25lIC8gdG90YWxTaXplIDogMDtcclxuICAgIH1cclxufVxyXG4iXX0=