UNPKG

ngx-dropzone-v14

Version:

A highly configurable dropzone component for Angular.

261 lines 35.3 kB
import { Component, EventEmitter, Output, Input, ViewChild, ContentChildren, QueryList, HostBinding, HostListener, Self, ElementRef } from '@angular/core'; import { NgxDropzoneService } from '../ngx-dropzone.service'; import { coerceBooleanProperty, coerceNumberProperty } from '../helpers'; import { NgxDropzonePreviewComponent } from '../ngx-dropzone-preview/ngx-dropzone-preview.component'; import * as i0 from "@angular/core"; import * as i1 from "../ngx-dropzone.service"; import * as i2 from "@angular/common"; export class NgxDropzoneComponent { constructor(service) { this.service = service; /** Emitted when any files were added or rejected. */ this.change = new EventEmitter(); /** Set the accepted file types. Defaults to '*'. */ this.accept = '*'; this._disabled = false; this._multiple = true; this._maxFileSize = undefined; this._expandable = false; this._disableClick = false; this._processDirectoryDrop = false; this._isHovered = false; } get _hasPreviews() { return !!this._previewChildren.length; } /** Disable any user interaction with the component. */ get disabled() { return this._disabled; } set disabled(value) { this._disabled = coerceBooleanProperty(value); if (this._isHovered) { this._isHovered = false; } } /** Allow the selection of multiple files. */ get multiple() { return this._multiple; } set multiple(value) { this._multiple = coerceBooleanProperty(value); } /** Set the maximum size a single file may have. */ get maxFileSize() { return this._maxFileSize; } set maxFileSize(value) { this._maxFileSize = coerceNumberProperty(value); } /** Allow the dropzone container to expand vertically. */ get expandable() { return this._expandable; } set expandable(value) { this._expandable = coerceBooleanProperty(value); } /** Open the file selector on click. */ get disableClick() { return this._disableClick; } set disableClick(value) { this._disableClick = coerceBooleanProperty(value); } /** Allow dropping directories. */ get processDirectoryDrop() { return this._processDirectoryDrop; } set processDirectoryDrop(value) { this._processDirectoryDrop = coerceBooleanProperty(value); } /** Show the native OS file explorer to select files. */ _onClick() { if (!this.disableClick) { this.showFileSelector(); } } _onDragOver(event) { if (this.disabled) { return; } this.preventDefault(event); this._isHovered = true; } _onDragLeave() { this._isHovered = false; } _onDrop(event) { if (this.disabled) { return; } this.preventDefault(event); this._isHovered = false; // if processDirectoryDrop is not enabled or webkitGetAsEntry is not supported we handle the drop as usual if (!this.processDirectoryDrop || !DataTransferItem.prototype.webkitGetAsEntry) { this.handleFileDrop(event.dataTransfer.files); // if processDirectoryDrop is enabled and webkitGetAsEntry is supported we can extract files from a dropped directory } else { const droppedItems = event.dataTransfer.items; if (droppedItems.length > 0) { const droppedFiles = []; const droppedDirectories = []; // seperate dropped files from dropped directories for easier handling for (let i = 0; i < droppedItems.length; i++) { const entry = droppedItems[i].webkitGetAsEntry(); if (entry.isFile) { droppedFiles.push(event.dataTransfer.files[i]); } else if (entry.isDirectory) { droppedDirectories.push(entry); } } // create a DataTransfer const droppedFilesList = new DataTransfer(); droppedFiles.forEach((droppedFile) => { droppedFilesList.items.add(droppedFile); }); // if no directory is dropped we are done and can call handleFileDrop if (!droppedDirectories.length && droppedFilesList.items.length) { this.handleFileDrop(droppedFilesList.files); } // if directories are dropped we extract the files from these directories one-by-one and add it to droppedFilesList if (droppedDirectories.length) { const extractFilesFromDirectoryCalls = []; for (const droppedDirectory of droppedDirectories) { extractFilesFromDirectoryCalls.push(this.extractFilesFromDirectory(droppedDirectory)); } // wait for all directories to be proccessed to add the extracted files afterwards Promise.all(extractFilesFromDirectoryCalls).then((allExtractedFiles) => { allExtractedFiles.reduce((a, b) => [...a, ...b]).forEach((extractedFile) => { droppedFilesList.items.add(extractedFile); }); this.handleFileDrop(droppedFilesList.files); }); } } } } extractFilesFromDirectory(directory) { async function getFileFromFileEntry(fileEntry) { try { return await new Promise((resolve, reject) => fileEntry.file(resolve, reject)); } catch (err) { console.log('Error converting a fileEntry to a File: ', err); } } return new Promise((resolve, reject) => { const files = []; const dirReader = directory.createReader(); // we need this to be a recursion because of this issue: https://bugs.chromium.org/p/chromium/issues/detail?id=514087 const readEntries = () => { dirReader.readEntries(async (dirItems) => { if (!dirItems.length) { resolve(files); } else { const fileEntries = dirItems.filter((dirItem) => dirItem.isFile); for (const fileEntry of fileEntries) { const file = await getFileFromFileEntry(fileEntry); files.push(file); } readEntries(); } }); }; readEntries(); }); } showFileSelector() { if (!this.disabled) { this._fileInput.nativeElement.click(); } } _onFilesSelected(event) { const files = event.target.files; this.handleFileDrop(files); // Reset the native file input element to allow selecting the same file again this._fileInput.nativeElement.value = ''; // fix(#32): Prevent the default event behaviour which caused the change event to emit twice. this.preventDefault(event); } handleFileDrop(files) { const result = this.service.parseFileList(files, this.accept, this.maxFileSize, this.multiple); this.change.next({ addedFiles: result.addedFiles, rejectedFiles: result.rejectedFiles, source: this }); } preventDefault(event) { event.preventDefault(); event.stopPropagation(); } } NgxDropzoneComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.2", ngImport: i0, type: NgxDropzoneComponent, deps: [{ token: i1.NgxDropzoneService, self: true }], target: i0.ɵɵFactoryTarget.Component }); NgxDropzoneComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.2", type: NgxDropzoneComponent, selector: "ngx-dropzone, [ngx-dropzone]", inputs: { accept: "accept", disabled: "disabled", multiple: "multiple", maxFileSize: "maxFileSize", expandable: "expandable", disableClick: "disableClick", processDirectoryDrop: "processDirectoryDrop", id: "id", ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledby: ["aria-labelledby", "ariaLabelledby"], ariaDescribedBy: ["aria-describedby", "ariaDescribedBy"] }, outputs: { change: "change" }, host: { listeners: { "click": "_onClick()", "dragover": "_onDragOver($event)", "dragleave": "_onDragLeave()", "drop": "_onDrop($event)" }, properties: { "class.ngx-dz-disabled": "this.disabled", "class.expandable": "this.expandable", "class.unclickable": "this.disableClick", "class.ngx-dz-hovered": "this._isHovered" } }, providers: [NgxDropzoneService], queries: [{ propertyName: "_previewChildren", predicate: NgxDropzonePreviewComponent, descendants: true }], viewQueries: [{ propertyName: "_fileInput", first: true, predicate: ["fileInput"], descendants: true, static: true }], ngImport: i0, template: "<input #fileInput type=\"file\" [id]=\"id\" [multiple]=\"multiple\" [accept]=\"accept\" [disabled]=\"disabled\"\n (change)=\"_onFilesSelected($event)\" [attr.aria-label]=\"ariaLabel\" [attr.aria-labelledby]=\"ariaLabelledby\"\n [attr.aria-describedby]=\"ariaDescribedBy\">\n<ng-content select=\"ngx-dropzone-label\" *ngIf=\"!_hasPreviews\"></ng-content>\n<ng-content select=\"ngx-dropzone-preview\"></ng-content>\n<ng-content></ng-content>\n", styles: [":host{display:flex;align-items:center;height:180px;background:#fff;cursor:pointer;color:#717386;border:2px dashed #717386;border-radius:5px;font-size:16px;overflow-x:auto}:host.ngx-dz-hovered{border-style:solid}:host.ngx-dz-disabled{opacity:.5;cursor:no-drop;pointer-events:none}:host.expandable{overflow:hidden;height:auto;height:initial;min-height:180px;flex-wrap:wrap}:host.unclickable{cursor:default}:host ::ng-deep ngx-dropzone-label{text-align:center;z-index:10;margin:10px auto}:host input{width:.1px;height:.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1}:host input:focus+::ng-deep ngx-dropzone-label{outline:1px dotted #000;outline:-webkit-focus-ring-color auto 5px}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.2", ngImport: i0, type: NgxDropzoneComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-dropzone, [ngx-dropzone]', providers: [NgxDropzoneService], template: "<input #fileInput type=\"file\" [id]=\"id\" [multiple]=\"multiple\" [accept]=\"accept\" [disabled]=\"disabled\"\n (change)=\"_onFilesSelected($event)\" [attr.aria-label]=\"ariaLabel\" [attr.aria-labelledby]=\"ariaLabelledby\"\n [attr.aria-describedby]=\"ariaDescribedBy\">\n<ng-content select=\"ngx-dropzone-label\" *ngIf=\"!_hasPreviews\"></ng-content>\n<ng-content select=\"ngx-dropzone-preview\"></ng-content>\n<ng-content></ng-content>\n", styles: [":host{display:flex;align-items:center;height:180px;background:#fff;cursor:pointer;color:#717386;border:2px dashed #717386;border-radius:5px;font-size:16px;overflow-x:auto}:host.ngx-dz-hovered{border-style:solid}:host.ngx-dz-disabled{opacity:.5;cursor:no-drop;pointer-events:none}:host.expandable{overflow:hidden;height:auto;height:initial;min-height:180px;flex-wrap:wrap}:host.unclickable{cursor:default}:host ::ng-deep ngx-dropzone-label{text-align:center;z-index:10;margin:10px auto}:host input{width:.1px;height:.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1}:host input:focus+::ng-deep ngx-dropzone-label{outline:1px dotted #000;outline:-webkit-focus-ring-color auto 5px}\n"] }] }], ctorParameters: function () { return [{ type: i1.NgxDropzoneService, decorators: [{ type: Self }] }]; }, propDecorators: { _previewChildren: [{ type: ContentChildren, args: [NgxDropzonePreviewComponent, { descendants: true }] }], _fileInput: [{ type: ViewChild, args: ['fileInput', { static: true }] }], change: [{ type: Output }], accept: [{ type: Input }], disabled: [{ type: Input }, { type: HostBinding, args: ['class.ngx-dz-disabled'] }], multiple: [{ type: Input }], maxFileSize: [{ type: Input }], expandable: [{ type: Input }, { type: HostBinding, args: ['class.expandable'] }], disableClick: [{ type: Input }, { type: HostBinding, args: ['class.unclickable'] }], processDirectoryDrop: [{ type: Input }], id: [{ type: Input }], ariaLabel: [{ type: Input, args: ['aria-label'] }], ariaLabelledby: [{ type: Input, args: ['aria-labelledby'] }], ariaDescribedBy: [{ type: Input, args: ['aria-describedby'] }], _isHovered: [{ type: HostBinding, args: ['class.ngx-dz-hovered'] }], _onClick: [{ type: HostListener, args: ['click'] }], _onDragOver: [{ type: HostListener, args: ['dragover', ['$event']] }], _onDragLeave: [{ type: HostListener, args: ['dragleave'] }], _onDrop: [{ type: HostListener, args: ['drop', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWRyb3B6b25lLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kcm9wem9uZS9zcmMvbGliL25neC1kcm9wem9uZS9uZ3gtZHJvcHpvbmUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRyb3B6b25lL3NyYy9saWIvbmd4LWRyb3B6b25lL25neC1kcm9wem9uZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzSixPQUFPLEVBQUMsa0JBQWtCLEVBQWUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDekUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sd0RBQXdELENBQUM7Ozs7QUFjckcsTUFBTSxPQUFPLG9CQUFvQjtJQUUvQixZQUNrQixPQUEyQjtRQUEzQixZQUFPLEdBQVAsT0FBTyxDQUFvQjtRQWM3QyxxREFBcUQ7UUFDbEMsV0FBTSxHQUFHLElBQUksWUFBWSxFQUEwQixDQUFDO1FBRXZFLG9EQUFvRDtRQUMzQyxXQUFNLEdBQUcsR0FBRyxDQUFDO1FBZWQsY0FBUyxHQUFHLEtBQUssQ0FBQztRQVVsQixjQUFTLEdBQUcsSUFBSSxDQUFDO1FBVWpCLGlCQUFZLEdBQVcsU0FBUyxDQUFDO1FBV2pDLGdCQUFXLEdBQVksS0FBSyxDQUFDO1FBVzdCLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBVXRCLDBCQUFxQixHQUFHLEtBQUssQ0FBQztRQVN0QyxlQUFVLEdBQUcsS0FBSyxD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QyxtQkFBbUI7Z0JBVzVCLG9CQUFvQjtzQkFEdkIsS0FBSztnQkFVRyxFQUFFO3NCQUFWLEtBQUs7Z0JBQ2UsU0FBUztzQkFBN0IsS0FBSzt1QkFBQyxZQUFZO2dCQUNPLGNBQWM7c0JBQXZDLEtBQUs7dUJBQUMsaUJBQWlCO2dCQUNHLGVBQWU7c0JBQXpDLEtBQUs7dUJBQUMsa0JBQWtCO2dCQUd6QixVQUFVO3NCQURULFdBQVc7dUJBQUMsc0JBQXNCO2dCQUtuQyxRQUFRO3NCQURQLFlBQVk7dUJBQUMsT0FBTztnQkFRckIsV0FBVztzQkFEVixZQUFZO3VCQUFDLFVBQVUsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFXcEMsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLFdBQVc7Z0JBTXpCLE9BQU87c0JBRE4sWUFBWTt1QkFBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgT3V0cHV0LCBJbnB1dCwgVmlld0NoaWxkLCBDb250ZW50Q2hpbGRyZW4sIFF1ZXJ5TGlzdCwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgU2VsZiwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtOZ3hEcm9wem9uZVNlcnZpY2UsIFJlamVjdGVkRmlsZX0gZnJvbSAnLi4vbmd4LWRyb3B6b25lLnNlcnZpY2UnO1xuaW1wb3J0IHsgY29lcmNlQm9vbGVhblByb3BlcnR5LCBjb2VyY2VOdW1iZXJQcm9wZXJ0eSB9IGZyb20gJy4uL2hlbHBlcnMnO1xuaW1wb3J0IHsgTmd4RHJvcHpvbmVQcmV2aWV3Q29tcG9uZW50IH0gZnJvbSAnLi4vbmd4LWRyb3B6b25lLXByZXZpZXcvbmd4LWRyb3B6b25lLXByZXZpZXcuY29tcG9uZW50JztcblxuZXhwb3J0IGludGVyZmFjZSBOZ3hEcm9wem9uZUNoYW5nZUV2ZW50IHtcbiAgc291cmNlOiBOZ3hEcm9wem9uZUNvbXBvbmVudDtcbiAgYWRkZWRGaWxlczogRmlsZVtdO1xuICByZWplY3RlZEZpbGVzOiBSZWplY3RlZEZpbGVbXTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWRyb3B6b25lLCBbbmd4LWRyb3B6b25lXScsXG4gIHRlbXBsYXRlVXJsOiAnLi9uZ3gtZHJvcHpvbmUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9uZ3gtZHJvcHpvbmUuY29tcG9uZW50LnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbTmd4RHJvcHpvbmVTZXJ2aWNlXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hEcm9wem9uZUNvbXBvbmVudCB7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQFNlbGYoKSBwcml2YXRlIHNlcnZpY2U6IE5neERyb3B6b25lU2VydmljZVxuICApIHt9XG5cbiAgLyoqIEEgbGlzdCBvZiB0aGUgY29udGVudC1wcm9qZWN0ZWQgcHJldmlldyBjaGlsZHJlbi4gKi9cbiAgQENvbnRlbnRDaGlsZHJlbihOZ3hEcm9wem9uZVByZXZpZXdDb21wb25lbnQsIHsgZGVzY2VuZGFudHM6IHRydWUgfSlcbiAgX3ByZXZpZXdDaGlsZHJlbjogUXVlcnlMaXN0PE5neERyb3B6b25lUHJldmlld0NvbXBvbmVudD47XG5cbiAgZ2V0IF9oYXNQcmV2aWV3cygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLl9wcmV2aWV3Q2hpbGRyZW4ubGVuZ3RoO1xuICB9XG5cbiAgLyoqIEEgdGVtcGxhdGUgcmVmZXJlbmNlIHRvIHRoZSBuYXRpdmUgZmlsZSBpbnB1dCBlbGVtZW50LiAqL1xuICBAVmlld0NoaWxkKCdmaWxlSW5wdXQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBfZmlsZUlucHV0OiBFbGVtZW50UmVmO1xuXG4gIC8qKiBFbWl0dGVkIHdoZW4gYW55IGZpbGVzIHdlcmUgYWRkZWQgb3IgcmVqZWN0ZWQuICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBjaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPE5neERyb3B6b25lQ2hhbmdlRXZlbnQ+KCk7XG5cbiAgLyoqIFNldCB0aGUgYWNjZXB0ZWQgZmlsZSB0eXBlcy4gRGVmYXVsdHMgdG8gJyonLiAqL1xuICBASW5wdXQoKSBhY2NlcHQgPSAnKic7XG5cbiAgLyoqIERpc2FibGUgYW55IHVzZXIgaW50ZXJhY3Rpb24gd2l0aCB0aGUgY29tcG9uZW50LiAqL1xuICBASW5wdXQoKVxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLm5neC1kei1kaXNhYmxlZCcpXG4gIGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZGlzYWJsZWQ7XG4gIH1cbiAgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fZGlzYWJsZWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuXG4gICAgaWYgKHRoaXMuX2lzSG92ZXJlZCkge1xuICAgICAgdGhpcy5faXNIb3ZlcmVkID0gZmFsc2U7XG4gICAgfVxuICB9XG4gIHByaXZhdGUgX2Rpc2FibGVkID0gZmFsc2U7XG5cbiAgLyoqIEFsbG93IHRoZSBzZWxlY3Rpb24gb2YgbXVsdGlwbGUgZmlsZXMuICovXG4gIEBJbnB1dCgpXG4gIGdldCBtdWx0aXBsZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fbXVsdGlwbGU7XG4gIH1cbiAgc2V0IG11bHRpcGxlKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fbXVsdGlwbGUgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICB9XG4gIHByaXZhdGUgX211bHRpcGxlID0gdHJ1ZTtcblxuICAvKiogU2V0IHRoZSBtYXhpbXVtIHNpemUgYSBzaW5nbGUgZmlsZSBtYXkgaGF2ZS4gKi9cbiAgQElucHV0KClcbiAgZ2V0IG1heEZpbGVTaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX21heEZpbGVTaXplO1xuICB9XG4gIHNldCBtYXhGaWxlU2l6ZSh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fbWF4RmlsZVNpemUgPSBjb2VyY2VOdW1iZXJQcm9wZXJ0eSh2YWx1ZSk7XG4gIH1cbiAgcHJpdmF0ZSBfbWF4RmlsZVNpemU6IG51bWJlciA9IHVuZGVmaW5lZDtcblxuICAvKiogQWxsb3cgdGhlIGRyb3B6b25lIGNvbnRhaW5lciB0byBleHBhbmQgdmVydGljYWxseS4gKi9cbiAgQElucHV0KClcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5leHBhbmRhYmxlJylcbiAgZ2V0IGV4cGFuZGFibGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2V4cGFuZGFibGU7XG4gIH1cbiAgc2V0IGV4cGFuZGFibGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9leHBhbmRhYmxlID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgfVxuICBwcml2YXRlIF9leHBhbmRhYmxlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIE9wZW4gdGhlIGZpbGUgc2VsZWN0b3Igb24gY2xpY2suICovXG4gIEBJbnB1dCgpXG4gIEBIb3N0QmluZGluZygnY2xhc3MudW5jbGlja2FibGUnKVxuICBnZXQgZGlzYWJsZUNsaWNrKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9kaXNhYmxlQ2xpY2s7XG4gIH1cbiAgc2V0IGRpc2FibGVDbGljayh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuX2Rpc2FibGVDbGljayA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gIH1cbiAgcHJpdmF0ZSBfZGlzYWJsZUNsaWNrID0gZmFsc2U7XG5cbiAgLyoqIEFsbG93IGRyb3BwaW5nIGRpcmVjdG9yaWVzLiAqL1xuICBASW5wdXQoKVxuICBnZXQgcHJvY2Vzc0RpcmVjdG9yeURyb3AoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3Byb2Nlc3NEaXJlY3RvcnlEcm9wO1xuICB9XG4gIHNldCBwcm9jZXNzRGlyZWN0b3J5RHJvcCh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuX3Byb2Nlc3NEaXJlY3RvcnlEcm9wID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgfVxuICBwcml2YXRlIF9wcm9jZXNzRGlyZWN0b3J5RHJvcCA9IGZhbHNlO1xuXG4gIC8qKiBFeHBvc2UgdGhlIGlkLCBhcmlhLWxhYmVsLCBhcmlhLWxhYmVsbGVkYnkgYW5kIGFyaWEtZGVzY3JpYmVkYnkgb2YgdGhlIG5hdGl2ZSBmaWxlIGlucHV0IGZvciBwcm9wZXIgYWNjZXNzaWJpbGl0eS4gKi9cbiAgQElucHV0KCkgaWQ6IHN0cmluZztcbiAgQElucHV0KCdhcmlhLWxhYmVsJykgYXJpYUxhYmVsOiBzdHJpbmc7XG4gIEBJbnB1dCgnYXJpYS1sYWJlbGxlZGJ5JykgYXJpYUxhYmVsbGVkYnk6IHN0cmluZztcbiAgQElucHV0KCdhcmlhLWRlc2NyaWJlZGJ5JykgYXJpYURlc2NyaWJlZEJ5OiBzdHJpbmc7XG5cbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5uZ3gtZHotaG92ZXJlZCcpXG4gIF9pc0hvdmVyZWQgPSBmYWxzZTtcblxuICAvKiogU2hvdyB0aGUgbmF0aXZlIE9TIGZpbGUgZXhwbG9yZXIgdG8gc2VsZWN0IGZpbGVzLiAqL1xuICBASG9zdExpc3RlbmVyKCdjbGljaycpXG4gIF9vbkNsaWNrKCkge1xuICAgIGlmICghdGhpcy5kaXNhYmxlQ2xpY2spIHtcbiAgICAgIHRoaXMuc2hvd0ZpbGVTZWxlY3RvcigpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RyYWdvdmVyJywgWyckZXZlbnQnXSlcbiAgX29uRHJhZ092ZXIoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMucHJldmVudERlZmF1bHQoZXZlbnQpO1xuICAgIHRoaXMuX2lzSG92ZXJlZCA9IHRydWU7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkcmFnbGVhdmUnKVxuICBfb25EcmFnTGVhdmUoKSB7XG4gICAgdGhpcy5faXNIb3ZlcmVkID0gZmFsc2U7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkcm9wJywgWyckZXZlbnQnXSlcbiAgX29uRHJvcChldmVudCkge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wcmV2ZW50RGVmYXVsdChldmVudCk7XG4gICAgdGhpcy5faXNIb3ZlcmVkID0gZmFsc2U7XG5cbiAgICAvLyBpZiBwcm9jZXNzRGlyZWN0b3J5RHJvcCBpcyBub3QgZW5hYmxlZCBvciB3ZWJraXRHZXRBc0VudHJ5IGlzIG5vdCBzdXBwb3J0ZWQgd2UgaGFuZGxlIHRoZSBkcm9wIGFzIHVzdWFsXG4gICAgaWYgKCF0aGlzLnByb2Nlc3NEaXJlY3RvcnlEcm9wIHx8ICFEYXRhVHJhbnNmZXJJdGVtLnByb3RvdHlwZS53ZWJraXRHZXRBc0VudHJ5KSB7XG4gICAgICB0aGlzLmhhbmRsZUZpbGVEcm9wKGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlcyk7XG5cbiAgICAvLyBpZiBwcm9jZXNzRGlyZWN0b3J5RHJvcCBpcyBlbmFibGVkIGFuZCB3ZWJraXRHZXRBc0VudHJ5IGlzIHN1cHBvcnRlZCB3ZSBjYW4gZXh0cmFjdCBmaWxlcyBmcm9tIGEgZHJvcHBlZCBkaXJlY3RvcnlcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZHJvcHBlZEl0ZW1zOiBEYXRhVHJhbnNmZXJJdGVtW10gPSBldmVudC5kYXRhVHJhbnNmZXIuaXRlbXM7XG5cbiAgICAgIGlmIChkcm9wcGVkSXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBkcm9wcGVkRmlsZXM6IEZpbGVbXSA9IFtdO1xuICAgICAgICBjb25zdCBkcm9wcGVkRGlyZWN0b3JpZXMgPSBbXTtcblxuICAgICAgICAvLyBzZXBlcmF0ZSBkcm9wcGVkIGZpbGVzIGZyb20gZHJvcHBlZCBkaXJlY3RvcmllcyBmb3IgZWFzaWVyIGhhbmRsaW5nXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZHJvcHBlZEl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgZW50cnkgPSBkcm9wcGVkSXRlbXNbaV0ud2Via2l0R2V0QXNFbnRyeSgpO1xuICAgICAgICAgIGlmIChlbnRyeS5pc0ZpbGUpIHtcbiAgICAgICAgICAgIGRyb3BwZWRGaWxlcy5wdXNoKGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlc1tpXSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChlbnRyeS5pc0RpcmVjdG9yeSkge1xuICAgICAgICAgICAgZHJvcHBlZERpcmVjdG9yaWVzLnB1c2goZW50cnkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNyZWF0ZSBhIERhdGFUcmFuc2ZlclxuICAgICAgICBjb25zdCBkcm9wcGVkRmlsZXNMaXN0ID0gbmV3IERhdGFUcmFuc2ZlcigpO1xuICAgICAgICBkcm9wcGVkRmlsZXMuZm9yRWFjaCgoZHJvcHBlZEZpbGUpID0+IHtcbiAgICAgICAgICBkcm9wcGVkRmlsZXNMaXN0Lml0ZW1zLmFkZChkcm9wcGVkRmlsZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGlmIG5vIGRpcmVjdG9yeSBpcyBkcm9wcGVkIHdlIGFyZSBkb25lIGFuZCBjYW4gY2FsbCBoYW5kbGVGaWxlRHJvcFxuICAgICAgICBpZiAoIWRyb3BwZWREaXJlY3Rvcmllcy5sZW5ndGggJiYgZHJvcHBlZEZpbGVzTGlzdC5pdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLmhhbmRsZUZpbGVEcm9wKGRyb3BwZWRGaWxlc0xpc3QuZmlsZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgZGlyZWN0b3JpZXMgYXJlIGRyb3BwZWQgd2UgZXh0cmFjdCB0aGUgZmlsZXMgZnJvbSB0aGVzZSBkaXJlY3RvcmllcyBvbmUtYnktb25lIGFuZCBhZGQgaXQgdG8gZHJvcHBlZEZpbGVzTGlzdFxuICAgICAgICBpZiAoZHJvcHBlZERpcmVjdG9yaWVzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IGV4dHJhY3RGaWxlc0Zyb21EaXJlY3RvcnlDYWxscyA9IFtdO1xuXG4gICAgICAgICAgZm9yIChjb25zdCBkcm9wcGVkRGlyZWN0b3J5IG9mIGRyb3BwZWREaXJlY3Rvcmllcykge1xuICAgICAgICAgICAgZXh0cmFjdEZpbGVzRnJvbURpcmVjdG9yeUNhbGxzLnB1c2godGhpcy5leHRyYWN0RmlsZXNGcm9tRGlyZWN0b3J5KGRyb3BwZWREaXJlY3RvcnkpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyB3YWl0IGZvciBhbGwgZGlyZWN0b3JpZXMgdG8gYmUgcHJvY2Nlc3NlZCB0byBhZGQgdGhlIGV4dHJhY3RlZCBmaWxlcyBhZnRlcndhcmRzXG4gICAgICAgICAgUHJvbWlzZS5hbGwoZXh0cmFjdEZpbGVzRnJvbURpcmVjdG9yeUNhbGxzKS50aGVuKChhbGxFeHRyYWN0ZWRGaWxlczogYW55W10pID0+IHtcbiAgICAgICAgICAgIGFsbEV4dHJhY3RlZEZpbGVzLnJlZHVjZSgoYSwgYikgPT4gWy4uLmEsIC4uLmJdKS5mb3JFYWNoKChleHRyYWN0ZWRGaWxlOiBGaWxlKSA9PiB7XG4gICAgICAgICAgICAgIGRyb3BwZWRGaWxlc0xpc3QuaXRlbXMuYWRkKGV4dHJhY3RlZEZpbGUpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRmlsZURyb3AoZHJvcHBlZEZpbGVzTGlzdC5maWxlcyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RGaWxlc0Zyb21EaXJlY3RvcnkoZGlyZWN0b3J5KSB7XG4gICAgYXN5bmMgZnVuY3Rpb24gZ2V0RmlsZUZyb21GaWxlRW50cnkoZmlsZUVudHJ5KSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gZmlsZUVudHJ5LmZpbGUocmVzb2x2ZSwgcmVqZWN0KSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ0Vycm9yIGNvbnZlcnRpbmcgYSBmaWxlRW50cnkgdG8gYSBGaWxlOiAnLCBlcnIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaWxlczogRmlsZVtdID0gW107XG5cbiAgICAgIGNvbnN0IGRpclJlYWRlciA9IGRpcmVjdG9yeS5jcmVhdGVSZWFkZXIoKTtcblxuICAgICAgLy8gd2UgbmVlZCB0aGlzIHRvIGJlIGEgcmVjdXJzaW9uIGJlY2F1c2Ugb2YgdGhpcyBpc3N1ZTogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NTE0MDg3XG4gICAgICBjb25zdCByZWFkRW50cmllcyA9ICgpID0+IHtcbiAgICAgICAgZGlyUmVhZGVyLnJlYWRFbnRyaWVzKGFzeW5jKGRpckl0ZW1zKSA9PiB7XG4gICAgICAgICAgaWYgKCFkaXJJdGVtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJlc29sdmUoZmlsZXMpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlRW50cmllcyA9IGRpckl0ZW1zLmZpbHRlcigoZGlySXRlbSkgPT4gZGlySXRlbS5pc0ZpbGUpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGVFbnRyeSBvZiBmaWxlRW50cmllcykge1xuICAgICAgICAgICAgICBjb25zdCBmaWxlOiBhbnkgPSBhd2FpdCBnZXRGaWxlRnJvbUZpbGVFbnRyeShmaWxlRW50cnkpO1xuICAgICAgICAgICAgICBmaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZWFkRW50cmllcygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgICAgcmVhZEVudHJpZXMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHNob3dGaWxlU2VsZWN0b3IoKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAodGhpcy5fZmlsZUlucHV0Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTElucHV0RWxlbWVudCkuY2xpY2soKTtcbiAgICB9XG4gIH1cblxuICBfb25GaWxlc1NlbGVjdGVkKGV2ZW50KSB7XG4gICAgY29uc3QgZmlsZXM6IEZpbGVMaXN0ID0gZXZlbnQudGFyZ2V0LmZpbGVzO1xuICAgIHRoaXMuaGFuZGxlRmlsZURyb3AoZmlsZXMpO1xuXG4gICAgLy8gUmVzZXQgdGhlIG5hdGl2ZSBmaWxlIGlucHV0IGVsZW1lbnQgdG8gYWxsb3cgc2VsZWN0aW5nIHRoZSBzYW1lIGZpbGUgYWdhaW5cbiAgICB0aGlzLl9maWxlSW5wdXQubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuXG4gICAgLy8gZml4KCMzMik6IFByZXZlbnQgdGhlIGRlZmF1bHQgZXZlbnQgYmVoYXZpb3VyIHdoaWNoIGNhdXNlZCB0aGUgY2hhbmdlIGV2ZW50IHRvIGVtaXQgdHdpY2UuXG4gICAgdGhpcy5wcmV2ZW50RGVmYXVsdChldmVudCk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUZpbGVEcm9wKGZpbGVzOiBGaWxlTGlzdCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2VydmljZS5wYXJzZUZpbGVMaXN0KGZpbGVzLCB0aGlzLmFjY2VwdCwgdGhpcy5tYXhGaWxlU2l6ZSwgdGhpcy5tdWx0aXBsZSk7XG5cbiAgICB0aGlzLmNoYW5nZS5uZXh0KHtcbiAgICAgIGFkZGVkRmlsZXM6IHJlc3VsdC5hZGRlZEZpbGVzLFxuICAgICAgcmVqZWN0ZWRGaWxlczogcmVzdWx0LnJlamVjdGVkRmlsZXMsXG4gICAgICBzb3VyY2U6IHRoaXNcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgcHJldmVudERlZmF1bHQoZXZlbnQ6IERyYWdFdmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cbn1cbiIsIjxpbnB1dCAjZmlsZUlucHV0IHR5cGU9XCJmaWxlXCIgW2lkXT1cImlkXCIgW211bHRpcGxlXT1cIm11bHRpcGxlXCIgW2FjY2VwdF09XCJhY2NlcHRcIiBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAoY2hhbmdlKT1cIl9vbkZpbGVzU2VsZWN0ZWQoJGV2ZW50KVwiIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsXCIgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cImFyaWFMYWJlbGxlZGJ5XCJcbiAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJhcmlhRGVzY3JpYmVkQnlcIj5cbjxuZy1jb250ZW50IHNlbGVjdD1cIm5neC1kcm9wem9uZS1sYWJlbFwiICpuZ0lmPVwiIV9oYXNQcmV2aWV3c1wiPjwvbmctY29udGVudD5cbjxuZy1jb250ZW50IHNlbGVjdD1cIm5neC1kcm9wem9uZS1wcmV2aWV3XCI+PC9uZy1jb250ZW50PlxuPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuIl19