ng-zorro-antd-mobile
Version:
An enterprise-class mobile UI components based on Ant Design and Angular
251 lines • 31.9 kB
JavaScript
import { Component, Input, Output, EventEmitter, ViewChild, ViewContainerRef } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "ng-zorro-antd-mobile/flex";
export class ImagePickerComponent {
get files() {
return this._files;
}
set files(value) {
this._files = value;
this.sortItem();
}
get accept() {
return this._accept;
}
set accept(value) {
this._accept = value;
this.sortItem();
}
get length() {
return this._count;
}
set length(value) {
if (value > 0) {
this._count = value;
}
else {
this._count = 4;
}
this.sortItem();
}
get multiple() {
return this._multiple;
}
set multiple(value) {
this._multiple = value;
this.sortItem();
}
get selectable() {
return this._selectable;
}
set selectable(value) {
this._selectable = value;
this.sortItem();
}
constructor() {
this.prefixCls = 'am-image-picker';
this.flexEl = [];
this._accept = 'image/*';
this._count = 4;
this._selectable = true;
this._files = [];
this._multiple = false;
this.capture = false;
this.disableDelete = false;
this.onFail = new EventEmitter();
this.onChange = new EventEmitter();
this.onImageClick = new EventEmitter();
this.onAddImageClick = new EventEmitter();
}
sortItem() {
if (!this._files) {
return;
}
let count = parseInt('' + this._count, 10);
if (count <= 0) {
count = 4;
}
let allEl = this._files.map(item => {
return {
type: 'img',
backgroundImage: 'url(' + item.url + ')',
transform: 'rotate(' + this.getRotation(item.orientation) + 'deg)'
};
});
if (this._selectable) {
allEl.push({
type: 'select',
backgroundImage: '',
transform: ''
});
}
const length = allEl.length;
if (length !== 0 && length % count !== 0) {
const blankCount = count - (length % count);
const fillBlankEl = [];
for (let i = 0; i < blankCount; i++) {
fillBlankEl.push({
type: 'white',
backgroundImage: '',
transform: ''
});
}
allEl = allEl.concat(fillBlankEl);
}
this.flexEl = [];
for (let i = 0; i < allEl.length / count; i++) {
const rowEl = allEl.slice(i * count, i * count + count);
this.flexEl.push(rowEl);
}
}
addImage(imgItem) {
this._files.push({
type: 'img',
url: imgItem.url,
orientation: imgItem.orientation
});
this.sortItem();
this.onChange.emit({
files: this._files,
operationType: 'add',
index: this._files.length - 1
});
}
removeImage(index) {
this._files.splice(index, 1);
this.sortItem();
this.onChange.emit({
files: this._files,
operationType: 'remove',
index: index
});
}
imageClick(index) {
this.onImageClick.emit({
index: index,
files: this._files
});
}
addImageClick(e) {
this.onAddImageClick.emit(e);
}
parseFile(file, index) {
const reader = new FileReader();
reader.onload = e => {
const dataURL = e.target.result;
if (!dataURL) {
this.onFail.emit(`Fail to get the ${index} image`);
return;
}
let orientation = 1;
this.getOrientation(file, res => {
// -2: not jpeg , -1: not defined
if (res > 0) {
orientation = res;
}
this.addImage({
url: dataURL,
orientation,
file
});
});
};
reader.readAsDataURL(file);
}
fileChange(event) {
const fileList = event.target.files;
if (fileList && fileList.length) {
for (let i = 0; i < fileList.length; i++) {
this.parseFile(fileList[i], i);
}
}
}
getRotation(orientation = 1) {
let imgRotation = 0;
switch (orientation) {
case 3:
imgRotation = 180;
break;
case 6:
imgRotation = 90;
break;
case 8:
imgRotation = 270;
break;
default:
}
return imgRotation;
}
// https://stackoverflow.com/questions/7584794/accessing-jpeg-exif-rotation-data-in-javascript-on-the-client-side
getOrientation(file, callback) {
const reader = new FileReader();
reader.onload = e => {
const view = new DataView(e.target.result);
if (view.getUint16(0, false) !== 0xffd8) {
return callback(-2);
}
const length = view.byteLength;
let offset = 2;
while (offset < length) {
const marker = view.getUint16(offset, false);
offset += 2;
if (marker === 0xffe1) {
const tmp = view.getUint32((offset += 2), false);
if (tmp !== 0x45786966) {
return callback(-1);
}
const little = view.getUint16((offset += 6), false) === 0x4949;
offset += view.getUint32(offset + 4, little);
const tags = view.getUint16(offset, little);
offset += 2;
for (let i = 0; i < tags; i++) {
if (view.getUint16(offset + i * 12, little) === 0x0112) {
return callback(view.getUint16(offset + i * 12 + 8, little));
}
}
}
else if ((marker & 0xff00) !== 0xff00) {
break;
}
else {
offset += view.getUint16(offset, false);
}
}
return callback(-1);
};
reader.readAsArrayBuffer(file.slice(0, 64 * 1024));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: ImagePickerComponent, selector: "ImagePicker, nzm-image-picker", inputs: { capture: "capture", disableDelete: "disableDelete", files: "files", accept: "accept", length: "length", multiple: "multiple", selectable: "selectable" }, outputs: { onFail: "onFail", onChange: "onChange", onImageClick: "onImageClick", onAddImageClick: "onAddImageClick" }, viewQueries: [{ propertyName: "_fileSelectorInput", first: true, predicate: ["fileSelectorInput"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div class=\"{{ prefixCls }}-list\" role=\"group\">\n <Flex *ngFor=\"let rowItem of flexEl; let i = index\">\n <FlexItem *ngFor=\"let item of rowItem; let j = index\">\n <div *ngIf=\"item && 'img' === item.type && item.backgroundImage\" class=\"{{ prefixCls }}-item\">\n <div\n role=\"button\"\n *ngIf=\"!disableDelete\"\n aria-label=\"Click and Remove this image\"\n class=\"{{ prefixCls }}-item-remove\"\n (click)=\"removeImage(i * length + j)\"\n ></div>\n <div\n role=\"button\"\n aria-label=\"Image can be clicked\"\n class=\"{{ prefixCls }}-item-content\"\n [ngStyle]=\"{ 'background-image': item.backgroundImage, transform: item.transform }\"\n (click)=\"imageClick(i * length + j)\"\n ></div>\n </div>\n <div\n role=\"button\"\n aria-label=\"Choose and add image\"\n *ngIf=\"item && 'select' === item.type\"\n class=\"{{ prefixCls }}-item {{ prefixCls }}-upload-btn\"\n (click)=\"addImageClick($event)\"\n >\n <input\n #fileSelectorInput\n type=\"file\"\n [accept]=\"accept\"\n [multiple]=\"multiple\"\n [attr.capture]=\"capture ? capture : null\"\n (change)=\"fileChange($event)\"\n />\n </div>\n <div *ngIf=\"item && 'white' === item.type\" class=\"{{ prefixCls }}-item-white\"></div>\n </FlexItem>\n </Flex>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.FlexComponent, selector: "Flex, nzm-flex", inputs: ["direction", "wrap", "justify", "align", "alignContent"] }, { kind: "component", type: i2.FlexItemComponent, selector: "FlexItem, nzm-flex-item" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: ImagePickerComponent, decorators: [{
type: Component,
args: [{ selector: 'ImagePicker, nzm-image-picker', template: "<div class=\"{{ prefixCls }}-list\" role=\"group\">\n <Flex *ngFor=\"let rowItem of flexEl; let i = index\">\n <FlexItem *ngFor=\"let item of rowItem; let j = index\">\n <div *ngIf=\"item && 'img' === item.type && item.backgroundImage\" class=\"{{ prefixCls }}-item\">\n <div\n role=\"button\"\n *ngIf=\"!disableDelete\"\n aria-label=\"Click and Remove this image\"\n class=\"{{ prefixCls }}-item-remove\"\n (click)=\"removeImage(i * length + j)\"\n ></div>\n <div\n role=\"button\"\n aria-label=\"Image can be clicked\"\n class=\"{{ prefixCls }}-item-content\"\n [ngStyle]=\"{ 'background-image': item.backgroundImage, transform: item.transform }\"\n (click)=\"imageClick(i * length + j)\"\n ></div>\n </div>\n <div\n role=\"button\"\n aria-label=\"Choose and add image\"\n *ngIf=\"item && 'select' === item.type\"\n class=\"{{ prefixCls }}-item {{ prefixCls }}-upload-btn\"\n (click)=\"addImageClick($event)\"\n >\n <input\n #fileSelectorInput\n type=\"file\"\n [accept]=\"accept\"\n [multiple]=\"multiple\"\n [attr.capture]=\"capture ? capture : null\"\n (change)=\"fileChange($event)\"\n />\n </div>\n <div *ngIf=\"item && 'white' === item.type\" class=\"{{ prefixCls }}-item-white\"></div>\n </FlexItem>\n </Flex>\n</div>\n" }]
}], ctorParameters: () => [], propDecorators: { _fileSelectorInput: [{
type: ViewChild,
args: ['fileSelectorInput', { read: ViewContainerRef }]
}], capture: [{
type: Input
}], disableDelete: [{
type: Input
}], files: [{
type: Input
}], accept: [{
type: Input
}], length: [{
type: Input
}], multiple: [{
type: Input
}], selectable: [{
type: Input
}], onFail: [{
type: Output
}], onChange: [{
type: Output
}], onImageClick: [{
type: Output
}], onAddImageClick: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2NvbXBvbmVudHMvaW1hZ2UtcGlja2VyL2ltYWdlLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi9jb21wb25lbnRzL2ltYWdlLXBpY2tlci9pbWFnZS1waWNrZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxlQUFlLENBQUM7Ozs7QUFZcEcsTUFBTSxPQUFPLG9CQUFvQjtJQWUvQixJQUNJLEtBQUs7UUFDUCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDckIsQ0FBQztJQUNELElBQUksS0FBSyxDQUFDLEtBQWlCO1FBQ3pCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBQ0QsSUFDSSxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxLQUFhO1FBQ3RCLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBQ0QsSUFDSSxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxLQUFhO1FBQ3RCLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRTtZQUNiLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1NBQ3JCO2FBQU07WUFDTCxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztTQUNqQjtRQUNELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsQixDQUFD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aUJBQ3pDO2FBQ0Y7WUFDRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RCLENBQUMsQ0FBQztRQUNGLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNyRCxDQUFDOzhHQTFPVSxvQkFBb0I7a0dBQXBCLG9CQUFvQixvY0FVUyxnQkFBZ0IsNkJDdEIxRCxpOUNBdUNBOzsyRkQzQmEsb0JBQW9CO2tCQUpoQyxTQUFTOytCQUNFLCtCQUErQjt3REFjakMsa0JBQWtCO3NCQUR6QixTQUFTO3VCQUFDLG1CQUFtQixFQUFFLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFO2dCQUdqRCxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFFRixLQUFLO3NCQURSLEtBQUs7Z0JBU0YsTUFBTTtzQkFEVCxLQUFLO2dCQVNGLE1BQU07c0JBRFQsS0FBSztnQkFhRixRQUFRO3NCQURYLEtBQUs7Z0JBU0YsVUFBVTtzQkFEYixLQUFLO2dCQVNOLE1BQU07c0JBREwsTUFBTTtnQkFHUCxRQUFRO3NCQURQLE1BQU07Z0JBR1AsWUFBWTtzQkFEWCxNQUFNO2dCQUdQLGVBQWU7c0JBRGQsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBWaWV3Q2hpbGQsIFZpZXdDb250YWluZXJSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBFbGVtZW50VHlwZSB7XG4gIHR5cGU6IHN0cmluZzsgLy8gJ2ltZycgfCAnc2VsZWN0JyB8ICd3aGl0ZSdcbiAgYmFja2dyb3VuZEltYWdlOiBzdHJpbmc7XG4gIHRyYW5zZm9ybTogc3RyaW5nO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdJbWFnZVBpY2tlciwgbnptLWltYWdlLXBpY2tlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9pbWFnZS1waWNrZXIuY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIEltYWdlUGlja2VyQ29tcG9uZW50IHtcbiAgcHJlZml4Q2xzOiBzdHJpbmcgPSAnYW0taW1hZ2UtcGlja2VyJztcbiAgZmxleEVsOiBFbGVtZW50VHlwZVtdW10gPSBbXTtcblxuICBwcml2YXRlIF9hY2NlcHQ6IHN0cmluZyA9ICdpbWFnZS8qJztcbiAgcHJpdmF0ZSBfY291bnQ6IG51bWJlciA9IDQ7XG4gIHByaXZhdGUgX3NlbGVjdGFibGU6IGJvb2xlYW4gPSB0cnVlO1xuICBwcml2YXRlIF9maWxlczogQXJyYXk8YW55PiA9IFtdO1xuICBwcml2YXRlIF9tdWx0aXBsZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBWaWV3Q2hpbGQoJ2ZpbGVTZWxlY3RvcklucHV0JywgeyByZWFkOiBWaWV3Q29udGFpbmVyUmVmIH0pXG4gIHByaXZhdGUgX2ZpbGVTZWxlY3RvcklucHV0OiBWaWV3Q29udGFpbmVyUmVmO1xuXG4gIEBJbnB1dCgpIGNhcHR1cmU6IGJvb2xlYW4gfCBzdHJpbmcgPSBmYWxzZTtcbiAgQElucHV0KCkgZGlzYWJsZURlbGV0ZTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKVxuICBnZXQgZmlsZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2ZpbGVzO1xuICB9XG4gIHNldCBmaWxlcyh2YWx1ZTogQXJyYXk8YW55Pikge1xuICAgIHRoaXMuX2ZpbGVzID0gdmFsdWU7XG4gICAgdGhpcy5zb3J0SXRlbSgpO1xuICB9XG4gIEBJbnB1dCgpXG4gIGdldCBhY2NlcHQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fYWNjZXB0O1xuICB9XG4gIHNldCBhY2NlcHQodmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuX2FjY2VwdCA9IHZhbHVlO1xuICAgIHRoaXMuc29ydEl0ZW0oKTtcbiAgfVxuICBASW5wdXQoKVxuICBnZXQgbGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2NvdW50O1xuICB9XG4gIHNldCBsZW5ndGgodmFsdWU6IG51bWJlcikge1xuICAgIGlmICh2YWx1ZSA+IDApIHtcbiAgICAgIHRoaXMuX2NvdW50ID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2NvdW50ID0gNDtcbiAgICB9XG4gICAgdGhpcy5zb3J0SXRlbSgpO1xuICB9XG4gIEBJbnB1dCgpXG4gIGdldCBtdWx0aXBsZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fbXVsdGlwbGU7XG4gIH1cbiAgc2V0IG11bHRpcGxlKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fbXVsdGlwbGUgPSB2YWx1ZTtcbiAgICB0aGlzLnNvcnRJdGVtKCk7XG4gIH1cbiAgQElucHV0KClcbiAgZ2V0IHNlbGVjdGFibGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbGVjdGFibGU7XG4gIH1cbiAgc2V0IHNlbGVjdGFibGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9zZWxlY3RhYmxlID0gdmFsdWU7XG4gICAgdGhpcy5zb3J0SXRlbSgpO1xuICB9XG4gIEBPdXRwdXQoKVxuICBvbkZhaWw6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KClcbiAgb25DaGFuZ2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KClcbiAgb25JbWFnZUNsaWNrOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpXG4gIG9uQWRkSW1hZ2VDbGljazogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIHNvcnRJdGVtKCkge1xuICAgIGlmICghdGhpcy5fZmlsZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IGNvdW50ID0gcGFyc2VJbnQoJycgKyB0aGlzLl9jb3VudCwgMTApO1xuICAgIGlmIChjb3VudCA8PSAwKSB7XG4gICAgICBjb3VudCA9IDQ7XG4gICAgfVxuICAgIGxldCBhbGxFbDogRWxlbWVudFR5cGVbXSA9IHRoaXMuX2ZpbGVzLm1hcChpdGVtID0+IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6ICdpbWcnLFxuICAgICAgICBiYWNrZ3JvdW5kSW1hZ2U6ICd1cmwoJyArIGl0ZW0udXJsICsgJyknLFxuICAgICAgICB0cmFuc2Zvcm06ICdyb3RhdGUoJyArIHRoaXMuZ2V0Um90YXRpb24oaXRlbS5vcmllbnRhdGlvbikgKyAnZGVnKSdcbiAgICAgIH07XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuX3NlbGVjdGFibGUpIHtcbiAgICAgIGFsbEVsLnB1c2goe1xuICAgICAgICB0eXBlOiAnc2VsZWN0JyxcbiAgICAgICAgYmFja2dyb3VuZEltYWdlOiAnJyxcbiAgICAgICAgdHJhbnNmb3JtOiAnJ1xuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IGxlbmd0aCA9IGFsbEVsLmxlbmd0aDtcbiAgICBpZiAobGVuZ3RoICE9PSAwICYmIGxlbmd0aCAlIGNvdW50ICE9PSAwKSB7XG4gICAgICBjb25zdCBibGFua0NvdW50ID0gY291bnQgLSAobGVuZ3RoICUgY291bnQpO1xuICAgICAgY29uc3QgZmlsbEJsYW5rRWw6IGFueVtdID0gW107XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJsYW5rQ291bnQ7IGkrKykge1xuICAgICAgICBmaWxsQmxhbmtFbC5wdXNoKHtcbiAgICAgICAgICB0eXBlOiAnd2hpdGUnLFxuICAgICAgICAgIGJhY2tncm91bmRJbWFnZTogJycsXG4gICAgICAgICAgdHJhbnNmb3JtOiAnJ1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGFsbEVsID0gYWxsRWwuY29uY2F0KGZpbGxCbGFua0VsKTtcbiAgICB9XG4gICAgdGhpcy5mbGV4RWwgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFsbEVsLmxlbmd0aCAvIGNvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IHJvd0VsID0gYWxsRWwuc2xpY2UoaSAqIGNvdW50LCBpICogY291bnQgKyBjb3VudCk7XG4gICAgICB0aGlzLmZsZXhFbC5wdXNoKHJvd0VsKTtcbiAgICB9XG4gIH1cblxuICBhZGRJbWFnZShpbWdJdGVtOiBhbnkpIHtcbiAgICB0aGlzLl9maWxlcy5wdXNoKHtcbiAgICAgIHR5cGU6ICdpbWcnLFxuICAgICAgdXJsOiBpbWdJdGVtLnVybCxcbiAgICAgIG9yaWVudGF0aW9uOiBpbWdJdGVtLm9yaWVudGF0aW9uXG4gICAgfSk7XG4gICAgdGhpcy5zb3J0SXRlbSgpO1xuICAgIHRoaXMub25DaGFuZ2UuZW1pdCh7XG4gICAgICBmaWxlczogdGhpcy5fZmlsZXMsXG4gICAgICBvcGVyYXRpb25UeXBlOiAnYWRkJyxcbiAgICAgIGluZGV4OiB0aGlzLl9maWxlcy5sZW5ndGggLSAxXG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVJbWFnZShpbmRleDogbnVtYmVyKSB7XG4gICAgdGhpcy5fZmlsZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB0aGlzLnNvcnRJdGVtKCk7XG4gICAgdGhpcy5vbkNoYW5nZS5lbWl0KHtcbiAgICAgIGZpbGVzOiB0aGlzLl9maWxlcyxcbiAgICAgIG9wZXJhdGlvblR5cGU6ICdyZW1vdmUnLFxuICAgICAgaW5kZXg6IGluZGV4XG4gICAgfSk7XG4gIH1cblxuICBpbWFnZUNsaWNrKGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLm9uSW1hZ2VDbGljay5lbWl0KHtcbiAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgIGZpbGVzOiB0aGlzLl9maWxlc1xuICAgIH0pO1xuICB9XG5cbiAgYWRkSW1hZ2VDbGljayhlKSB7XG4gICAgdGhpcy5vbkFkZEltYWdlQ2xpY2suZW1pdChlKTtcbiAgfVxuXG4gIHBhcnNlRmlsZShmaWxlOiBhbnksIGluZGV4OiBudW1iZXIpIHtcbiAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgIHJlYWRlci5vbmxvYWQgPSBlID0+IHtcbiAgICAgIGNvbnN0IGRhdGFVUkwgPSAoZS50YXJnZXQgYXMgYW55KS5yZXN1bHQ7XG4gICAgICBpZiAoIWRhdGFVUkwpIHtcbiAgICAgICAgdGhpcy5vbkZhaWwuZW1pdChgRmFpbCB0byBnZXQgdGhlICR7aW5kZXh9IGltYWdlYCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IG9yaWVudGF0aW9uID0gMTtcbiAgICAgIHRoaXMuZ2V0T3JpZW50YXRpb24oZmlsZSwgcmVzID0+IHtcbiAgICAgICAgLy8gLTI6IG5vdCBqcGVnICwgLTE6IG5vdCBkZWZpbmVkXG4gICAgICAgIGlmIChyZXMgPiAwKSB7XG4gICAgICAgICAgb3JpZW50YXRpb24gPSByZXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZGRJbWFnZSh7XG4gICAgICAgICAgdXJsOiBkYXRhVVJMLFxuICAgICAgICAgIG9yaWVudGF0aW9uLFxuICAgICAgICAgIGZpbGVcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9O1xuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xuICB9XG5cbiAgZmlsZUNoYW5nZShldmVudCkge1xuICAgIGNvbnN0IGZpbGVMaXN0OiBGaWxlTGlzdCA9IGV2ZW50LnRhcmdldC5maWxlcztcbiAgICBpZiAoZmlsZUxpc3QgJiYgZmlsZUxpc3QubGVuZ3RoKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMucGFyc2VGaWxlKGZpbGVMaXN0W2ldLCBpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXRSb3RhdGlvbihvcmllbnRhdGlvbiA9IDEpIHtcbiAgICBsZXQgaW1nUm90YXRpb24gPSAwO1xuICAgIHN3aXRjaCAob3JpZW50YXRpb24pIHtcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgaW1nUm90YXRpb24gPSAxODA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA2OlxuICAgICAgICBpbWdSb3RhdGlvbiA9IDkwO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODpcbiAgICAgICAgaW1nUm90YXRpb24gPSAyNzA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICB9XG4gICAgcmV0dXJuIGltZ1JvdGF0aW9uO1xuICB9XG5cbiAgLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNzU4NDc5NC9hY2Nlc3NpbmctanBlZy1leGlmLXJvdGF0aW9uLWRhdGEtaW4tamF2YXNjcmlwdC1vbi10aGUtY2xpZW50LXNpZGVcbiAgZ2V0T3JpZW50YXRpb24oZmlsZTogYW55LCBjYWxsYmFjazogKF86IG51bWJlcikgPT4gdm9pZCkge1xuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgcmVhZGVyLm9ubG9hZCA9IGUgPT4ge1xuICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldygoZS50YXJnZXQgYXMgYW55KS5yZXN1bHQpO1xuICAgICAgaWYgKHZpZXcuZ2V0VWludDE2KDAsIGZhbHNlKSAhPT0gMHhmZmQ4KSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjaygtMik7XG4gICAgICB9XG4gICAgICBjb25zdCBsZW5ndGggPSB2aWV3LmJ5dGVMZW5ndGg7XG4gICAgICBsZXQgb2Zmc2V0ID0gMjtcbiAgICAgIHdoaWxlIChvZmZzZXQgPCBsZW5ndGgpIHtcbiAgICAgICAgY29uc3QgbWFya2VyID0gdmlldy5nZXRVaW50MTYob2Zmc2V0LCBmYWxzZSk7XG4gICAgICAgIG9mZnNldCArPSAyO1xuICAgICAgICBpZiAobWFya2VyID09PSAweGZmZTEpIHtcbiAgICAgICAgICBjb25zdCB0bXAgPSB2aWV3LmdldFVpbnQzMigob2Zmc2V0ICs9IDIpLCBmYWxzZSk7XG4gICAgICAgICAgaWYgKHRtcCAhPT0gMHg0NTc4Njk2Nikge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKC0xKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgbGl0dGxlID0gdmlldy5nZXRVaW50MTYoKG9mZnNldCArPSA2KSwgZmFsc2UpID09PSAweDQ5NDk7XG4gICAgICAgICAgb2Zmc2V0ICs9IHZpZXcuZ2V0VWludDMyKG9mZnNldCArIDQsIGxpdHRsZSk7XG4gICAgICAgICAgY29uc3QgdGFncyA9IHZpZXcuZ2V0VWludDE2KG9mZnNldCwgbGl0dGxlKTtcbiAgICAgICAgICBvZmZzZXQgKz0gMjtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRhZ3M7IGkrKykge1xuICAgICAgICAgICAgaWYgKHZpZXcuZ2V0VWludDE2KG9mZnNldCArIGkgKiAxMiwgbGl0dGxlKSA9PT0gMHgwMTEyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayh2aWV3LmdldFVpbnQxNihvZmZzZXQgKyBpICogMTIgKyA4LCBsaXR0bGUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoKG1hcmtlciAmIDB4ZmYwMCkgIT09IDB4ZmYwMCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9mZnNldCArPSB2aWV3LmdldFVpbnQxNihvZmZzZXQsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGxiYWNrKC0xKTtcbiAgICB9O1xuICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcihmaWxlLnNsaWNlKDAsIDY0ICogMTAyNCkpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LWxpc3RcIiByb2xlPVwiZ3JvdXBcIj5cbiAgPEZsZXggKm5nRm9yPVwibGV0IHJvd0l0ZW0gb2YgZmxleEVsOyBsZXQgaSA9IGluZGV4XCI+XG4gICAgPEZsZXhJdGVtICpuZ0Zvcj1cImxldCBpdGVtIG9mIHJvd0l0ZW07IGxldCBqID0gaW5kZXhcIj5cbiAgICAgIDxkaXYgKm5nSWY9XCJpdGVtICYmICdpbWcnID09PSBpdGVtLnR5cGUgJiYgaXRlbS5iYWNrZ3JvdW5kSW1hZ2VcIiBjbGFzcz1cInt7IHByZWZpeENscyB9fS1pdGVtXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAgICAgICAqbmdJZj1cIiFkaXNhYmxlRGVsZXRlXCJcbiAgICAgICAgICBhcmlhLWxhYmVsPVwiQ2xpY2sgYW5kIFJlbW92ZSB0aGlzIGltYWdlXCJcbiAgICAgICAgICBjbGFzcz1cInt7IHByZWZpeENscyB9fS1pdGVtLXJlbW92ZVwiXG4gICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUltYWdlKGkgKiBsZW5ndGggKyBqKVwiXG4gICAgICAgID48L2Rpdj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIHJvbGU9XCJidXR0b25cIlxuICAgICAgICAgIGFyaWEtbGFiZWw9XCJJbWFnZSBjYW4gYmUgY2xpY2tlZFwiXG4gICAgICAgICAgY2xhc3M9XCJ7eyBwcmVmaXhDbHMgfX0taXRlbS1jb250ZW50XCJcbiAgICAgICAgICBbbmdTdHlsZV09XCJ7ICdiYWNrZ3JvdW5kLWltYWdlJzogaXRlbS5iYWNrZ3JvdW5kSW1hZ2UsIHRyYW5zZm9ybTogaXRlbS50cmFuc2Zvcm0gfVwiXG4gICAgICAgICAgKGNsaWNrKT1cImltYWdlQ2xpY2soaSAqIGxlbmd0aCArIGopXCJcbiAgICAgICAgPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2XG4gICAgICAgIHJvbGU9XCJidXR0b25cIlxuICAgICAgICBhcmlhLWxhYmVsPVwiQ2hvb3NlIGFuZCBhZGQgaW1hZ2VcIlxuICAgICAgICAqbmdJZj1cIml0ZW0gJiYgJ3NlbGVjdCcgPT09IGl0ZW0udHlwZVwiXG4gICAgICAgIGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LWl0ZW0ge3sgcHJlZml4Q2xzIH19LXVwbG9hZC1idG5cIlxuICAgICAgICAoY2xpY2spPVwiYWRkSW1hZ2VDbGljaygkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgI2ZpbGVTZWxlY3RvcklucHV0XG4gICAgICAgICAgdHlwZT1cImZpbGVcIlxuICAgICAgICAgIFthY2NlcHRdPVwiYWNjZXB0XCJcbiAgICAgICAgICBbbXVsdGlwbGVdPVwibXVsdGlwbGVcIlxuICAgICAgICAgIFthdHRyLmNhcHR1cmVdPVwiY2FwdHVyZSA/IGNhcHR1cmUgOiBudWxsXCJcbiAgICAgICAgICAoY2hhbmdlKT1cImZpbGVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgKm5nSWY9XCJpdGVtICYmICd3aGl0ZScgPT09IGl0ZW0udHlwZVwiIGNsYXNzPVwie3sgcHJlZml4Q2xzIH19LWl0ZW0td2hpdGVcIj48L2Rpdj5cbiAgICA8L0ZsZXhJdGVtPlxuICA8L0ZsZXg+XG48L2Rpdj5cbiJdfQ==