UNPKG

systelab-components

Version:

systelab-components is a set of components that use wide accepted and adopted standard technologies like Angular and Bootstrap, as well as other popular libraries. Please read the ATTRIBUTION.md file for a complete list of dependencies.

145 lines 26 kB
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'; import { fromEvent } from 'rxjs'; import { pairwise, switchMap, takeUntil } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/forms"; import * as i3 from "../button/button.component"; import * as i4 from "systelab-translate"; export class Point { constructor(x, y) { this.x = x; this.y = y; } } export class SignatureCanvasComponent { constructor() { this.downPath = ''; this.href = ''; this.verificationActive = false; this.isCanvasEmpty = true; this.width = 400; this.signatureChange = new EventEmitter(); this.finish = new EventEmitter(); this.codeChange = new EventEmitter(); } get signature() { return this._signature; } set signature(value) { this._signature = value; this.signatureChange.emit(this._signature); } dofinish() { this.finish.emit(); } get code() { return this._code; } set code(value) { this._code = value; this.codeChange.emit(this._code); } ngAfterViewInit() { this.configureCanvas(); } configureCanvas() { const canvas = this.sign.nativeElement; if (canvas) { this.cx = canvas.getContext('2d'); canvas.width = this.width; canvas.height = this.height; this.cx.lineWidth = 4; this.cx.lineCap = 'round'; this.cx.strokeStyle = '#000000'; this.captureEvents(canvas); } } captureEvents(canvas) { fromEvent(canvas, 'mousedown') .pipe(switchMap((e) => { return fromEvent(canvas, 'mousemove').pipe(takeUntil(fromEvent(canvas, 'mouseup')), takeUntil(fromEvent(canvas, 'mouseleave')), pairwise()); })) .subscribe((res) => { const rect = canvas.getBoundingClientRect(); const prevPos = new Point(res[0].clientX - rect.left, res[0].clientY - rect.top); const currentPos = new Point(res[1].clientX - rect.left, res[1].clientY - rect.top); this.draw(prevPos, currentPos); if (this.isCanvasEmpty) { this.isCanvasEmpty = false; } }); } draw(previousPoint, currentPoint) { if (!this.cx) { return; } this.cx.beginPath(); if (previousPoint) { this.cx.moveTo(previousPoint.x, previousPoint.y); this.cx.lineTo(currentPoint.x, currentPoint.y); this.cx.stroke(); } } downloadImage() { const canvas = this.sign.nativeElement; const dataURL = canvas.toDataURL('image/png'); this.href = dataURL; const date = new Date(); this.downPath = date + 'signature.png'; } cleanCanvas() { this.isCanvasEmpty = true; this.cx.clearRect(0, 0, this.width, this.height); } finishDrawing() { const canvas = this.sign.nativeElement; const dataURL = canvas.toDataURL('image/png'); this.signature = dataURL; if (this.withCodeVerification) { canvas.setAttribute('style', 'display:none;'); this.verificationActive = true; } else { this.finish.emit(); } } returnCanvas() { const canvas = this.sign.nativeElement; canvas.setAttribute('style', 'display:block;'); this.verificationActive = false; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SignatureCanvasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: SignatureCanvasComponent, selector: "systelab-signature-canvas", inputs: { width: "width", height: "height", withCodeVerification: "withCodeVerification", isDownloadable: "isDownloadable", isIncorrectCode: "isIncorrectCode", signature: "signature", code: "code" }, outputs: { signatureChange: "signatureChange", finish: "finish", codeChange: "codeChange" }, viewQueries: [{ propertyName: "sign", first: true, predicate: ["signature"], descendants: true }, { propertyName: "img", first: true, predicate: ["img"], descendants: true }], ngImport: i0, template: "<div>\n <div class=\"mb-2\" *ngIf=\"!verificationActive\">\n {{ 'SIGN_TEXT_EXPLANATION' | translate | async }}\n </div>\n <canvas class=\"border rounded\" #signature></canvas>\n <div class=\"text-right mt-2\" [style.width.px]=\"width\" *ngIf=\"!verificationActive\">\n <systelab-button class=\"mr-1\" (click)=\"cleanCanvas()\">{{ 'SIGN_CLEAN' | translate | async }}</systelab-button>\n <a href=\"#\" *ngIf=\"isDownloadable\" class=\"btn btn-outline-primary mr-1\" [attr.download]=\"downPath\" [attr.href]=\"href\" id=\"btn-download\"\n (click)=\"downloadImage()\">{{ 'SIGN_DOWNLOAD' | translate | async }}</a>\n <systelab-button type=\"primary\" [disabled]=\"isCanvasEmpty\" (click)=\"finishDrawing()\">{{ 'SIGN_FINISH' | translate | async }}</systelab-button>\n\n </div>\n <div class=\"align-content-center p-3\" *ngIf=\"verificationActive\" [style.width.px]=\"width\" [style.height.px]=\"height\">\n <div [style.width.px]=\"width - 50\" [style.height.px]=\"height - 50\">\n <div class=\"mb-2\">{{ 'SIGN_VERIFICATION_TEXT' | translate | async }}</div>\n <form novalidate class=\"w-100\">\n <input type=\"password\" class=\"w-100 form-control\" [(ngModel)]=\"code\" [class.slab-error]=\"inputCode.invalid && inputCode.touched || isIncorrectCode\"\n id=\"inputCode\" placeholder=\"{{ 'SIGNATURE_CODE' | translate | async }}\" #inputCode=\"ngModel\" name=\"inputCode\"\n (keyup.enter)=\"dofinish()\" required autocomplete=\"off\">\n <systelab-button type=\"primary\" class=\"w-100 mt-4\" [disabled]=\"inputCode.invalid\" (click)=\"dofinish()\">{{ 'SIGN_VERIFY' | translate | async }}\n </systelab-button>\n <div *ngIf=\"isIncorrectCode\" class=\"alert alert-danger alert-sm text-center mt-3\">\n <a>{{ 'SIGN_ERROR_ENTERED_CODE' | translate | async }}</a>\n </div>\n <div class=\"mt-3 text-center\">\n <systelab-button type=\"link\" (click)=\"returnCanvas()\">{{ 'SIGN_RETURN' | translate | async }}</systelab-button>\n </div>\n </form>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i3.ButtonComponent, selector: "systelab-button", inputs: ["disabled", "type", "size"], outputs: ["action"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.GeneralTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SignatureCanvasComponent, decorators: [{ type: Component, args: [{ selector: 'systelab-signature-canvas', template: "<div>\n <div class=\"mb-2\" *ngIf=\"!verificationActive\">\n {{ 'SIGN_TEXT_EXPLANATION' | translate | async }}\n </div>\n <canvas class=\"border rounded\" #signature></canvas>\n <div class=\"text-right mt-2\" [style.width.px]=\"width\" *ngIf=\"!verificationActive\">\n <systelab-button class=\"mr-1\" (click)=\"cleanCanvas()\">{{ 'SIGN_CLEAN' | translate | async }}</systelab-button>\n <a href=\"#\" *ngIf=\"isDownloadable\" class=\"btn btn-outline-primary mr-1\" [attr.download]=\"downPath\" [attr.href]=\"href\" id=\"btn-download\"\n (click)=\"downloadImage()\">{{ 'SIGN_DOWNLOAD' | translate | async }}</a>\n <systelab-button type=\"primary\" [disabled]=\"isCanvasEmpty\" (click)=\"finishDrawing()\">{{ 'SIGN_FINISH' | translate | async }}</systelab-button>\n\n </div>\n <div class=\"align-content-center p-3\" *ngIf=\"verificationActive\" [style.width.px]=\"width\" [style.height.px]=\"height\">\n <div [style.width.px]=\"width - 50\" [style.height.px]=\"height - 50\">\n <div class=\"mb-2\">{{ 'SIGN_VERIFICATION_TEXT' | translate | async }}</div>\n <form novalidate class=\"w-100\">\n <input type=\"password\" class=\"w-100 form-control\" [(ngModel)]=\"code\" [class.slab-error]=\"inputCode.invalid && inputCode.touched || isIncorrectCode\"\n id=\"inputCode\" placeholder=\"{{ 'SIGNATURE_CODE' | translate | async }}\" #inputCode=\"ngModel\" name=\"inputCode\"\n (keyup.enter)=\"dofinish()\" required autocomplete=\"off\">\n <systelab-button type=\"primary\" class=\"w-100 mt-4\" [disabled]=\"inputCode.invalid\" (click)=\"dofinish()\">{{ 'SIGN_VERIFY' | translate | async }}\n </systelab-button>\n <div *ngIf=\"isIncorrectCode\" class=\"alert alert-danger alert-sm text-center mt-3\">\n <a>{{ 'SIGN_ERROR_ENTERED_CODE' | translate | async }}</a>\n </div>\n <div class=\"mt-3 text-center\">\n <systelab-button type=\"link\" (click)=\"returnCanvas()\">{{ 'SIGN_RETURN' | translate | async }}</systelab-button>\n </div>\n </form>\n </div>\n </div>\n</div>\n" }] }], propDecorators: { sign: [{ type: ViewChild, args: ['signature', { static: false }] }], img: [{ type: ViewChild, args: ['img', { static: false }] }], width: [{ type: Input }], height: [{ type: Input }], withCodeVerification: [{ type: Input }], isDownloadable: [{ type: Input }], isIncorrectCode: [{ type: Input }], signature: [{ type: Input }], signatureChange: [{ type: Output }], finish: [{ type: Output }], code: [{ type: Input }], codeChange: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmF0dXJlLWNhbnZhcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zeXN0ZWxhYi1jb21wb25lbnRzL3NyYy9saWIvc2lnbmF0dXJlLWNhbnZhcy9zaWduYXR1cmUtY2FudmFzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N5c3RlbGFiLWNvbXBvbmVudHMvc3JjL2xpYi9zaWduYXR1cmUtY2FudmFzL3NpZ25hdHVyZS1jYW52YXMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQWMsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdHLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDakMsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7OztBQUVoRSxNQUFNLE9BQU8sS0FBSztJQUNqQixZQUFtQixDQUFTLEVBQVMsQ0FBUztRQUEzQixNQUFDLEdBQUQsQ0FBQyxDQUFRO1FBQVMsTUFBQyxHQUFELENBQUMsQ0FBUTtJQUM5QyxDQUFDO0NBQ0Q7QUFNRCxNQUFNLE9BQU8sd0JBQXdCO0lBSnJDO1FBWVEsYUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNkLFNBQUksR0FBRyxFQUFFLENBQUM7UUFDVix1QkFBa0IsR0FBRyxLQUFLLENBQUM7UUFDM0Isa0JBQWEsR0FBRyxJQUFJLENBQUM7UUFJWixVQUFLLEdBQUcsR0FBRyxDQUFDO1FBV1gsb0JBQWUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBTzVDLFdBQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBVzVCLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0tBb0YxQztJQTNHQSxJQUNJLFNBQVM7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QW9CLEVBQUU7WUFDOUIsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztTQUMvQjthQUFNO1lBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNuQjtJQUNGLENBQUM7SUFFTSxZQUFZO1FBQ2xCLE1BQU0sTUFBTSxHQUFzQixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUMxRCxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUM7SUFDakMsQ0FBQzs4R0EvSFcsd0JBQXdCO2tHQUF4Qix3QkFBd0Isc2hCQ2JyQywyc0VBK0JBOzsyRkRsQmEsd0JBQXdCO2tCQUpwQyxTQUFTOytCQUNJLDJCQUEyQjs4QkFRQyxJQUFJO3NCQUE1QyxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUM7Z0JBQ0osR0FBRztzQkFBckMsU0FBUzt1QkFBQyxLQUFLLEVBQUUsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFDO2dCQVNqQixLQUFLO3NCQUFwQixLQUFLO2dCQUNVLE1BQU07c0JBQXJCLEtBQUs7Z0JBQ1Usb0JBQW9CO3NCQUFuQyxLQUFLO2dCQUNVLGNBQWM7c0JBQTdCLEtBQUs7Z0JBQ1UsZUFBZTtzQkFBOUIsS0FBSztnQkFHRixTQUFTO3NCQURaLEtBQUs7Z0JBS1csZUFBZTtzQkFBL0IsTUFBTTtnQkFPRyxNQUFNO3NCQUFmLE1BQU07Z0JBT0gsSUFBSTtzQkFEUCxLQUFLO2dCQUtJLFVBQVU7c0JBQW5CLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZnRlclZpZXdJbml0LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE91dHB1dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBmcm9tRXZlbnQgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHBhaXJ3aXNlLCBzd2l0Y2hNYXAsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuZXhwb3J0IGNsYXNzIFBvaW50IHtcblx0Y29uc3RydWN0b3IocHVibGljIHg6IG51bWJlciwgcHVibGljIHk6IG51bWJlcikge1xuXHR9XG59XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogICAgJ3N5c3RlbGFiLXNpZ25hdHVyZS1jYW52YXMnLFxuXHR0ZW1wbGF0ZVVybDogJy4vc2lnbmF0dXJlLWNhbnZhcy5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgU2lnbmF0dXJlQ2FudmFzQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCB7XG5cblx0cHJpdmF0ZSBfY29kZTogc3RyaW5nO1xuXHRwcml2YXRlIF9zaWduYXR1cmU6IHN0cmluZztcblxuXHRAVmlld0NoaWxkKCdzaWduYXR1cmUnLCB7c3RhdGljOiBmYWxzZX0pIHNpZ246IEVsZW1lbnRSZWY7XG5cdEBWaWV3Q2hpbGQoJ2ltZycsIHtzdGF0aWM6IGZhbHNlfSkgaW1nOiBFbGVtZW50UmVmO1xuXG5cdHB1YmxpYyBkb3duUGF0aCA9ICcnO1xuXHRwdWJsaWMgaHJlZiA9ICcnO1xuXHRwdWJsaWMgdmVyaWZpY2F0aW9uQWN0aXZlID0gZmFsc2U7XG5cdHB1YmxpYyBpc0NhbnZhc0VtcHR5ID0gdHJ1ZTtcblxuXHRwcml2YXRlIGN4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG5cblx0QElucHV0KCkgcHVibGljIHdpZHRoID0gNDAwO1xuXHRASW5wdXQoKSBwdWJsaWMgaGVpZ2h0OiBudW1iZXI7XG5cdEBJbnB1dCgpIHB1YmxpYyB3aXRoQ29kZVZlcmlmaWNhdGlvbjogYm9vbGVhbjtcblx0QElucHV0KCkgcHVibGljIGlzRG93bmxvYWRhYmxlOiBib29sZWFuO1xuXHRASW5wdXQoKSBwdWJsaWMgaXNJbmNvcnJlY3RDb2RlOiBib29sZWFuO1xuXG5cdEBJbnB1dCgpXG5cdGdldCBzaWduYXR1cmUoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy5fc2lnbmF0dXJlO1xuXHR9XG5cblx0QE91dHB1dCgpIHB1YmxpYyBzaWduYXR1cmVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cblx0c2V0IHNpZ25hdHVyZSh2YWx1ZTogc3RyaW5nKSB7XG5cdFx0dGhpcy5fc2lnbmF0dXJlID0gdmFsdWU7XG5cdFx0dGhpcy5zaWduYXR1cmVDaGFuZ2UuZW1pdCh0aGlzLl9zaWduYXR1cmUpO1xuXHR9XG5cblx0QE91dHB1dCgpIGZpbmlzaCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXHRwdWJsaWMgZG9maW5pc2goKSB7XG5cdFx0dGhpcy5maW5pc2guZW1pdCgpO1xuXHR9XG5cblx0QElucHV0KClcblx0Z2V0IGNvZGUoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy5fY29kZTtcblx0fVxuXG5cdEBPdXRwdXQoKSBjb2RlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cdHNldCBjb2RlKHZhbHVlOiBzdHJpbmcpIHtcblx0XHR0aGlzLl9jb2RlID0gdmFsdWU7XG5cdFx0dGhpcy5jb2RlQ2hhbmdlLmVtaXQodGhpcy5fY29kZSk7XG5cdH1cblxuXHRwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xuXHRcdHRoaXMuY29uZmlndXJlQ2FudmFzKCk7XG5cdH1cblxuXHRwdWJsaWMgY29uZmlndXJlQ2FudmFzKCkge1xuXHRcdGNvbnN0IGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSB0aGlzLnNpZ24ubmF0aXZlRWxlbWVudDtcblx0XHRpZiAoY2FudmFzKSB7XG5cdFx0XHR0aGlzLmN4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cdFx0XHRjYW52YXMud2lkdGggPSB0aGlzLndpZHRoO1xuXHRcdFx0Y2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0O1xuXHRcdFx0dGhpcy5jeC5saW5lV2lkdGggPSA0O1xuXHRcdFx0dGhpcy5jeC5saW5lQ2FwID0gJ3JvdW5kJztcblx0XHRcdHRoaXMuY3guc3Ryb2tlU3R5bGUgPSAnIzAwMDAwMCc7XG5cdFx0XHR0aGlzLmNhcHR1cmVFdmVudHMoY2FudmFzKTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgY2FwdHVyZUV2ZW50cyhjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50KSB7XG5cdFx0ZnJvbUV2ZW50KGNhbnZhcywgJ21vdXNlZG93bicpXG5cdFx0XHQucGlwZShzd2l0Y2hNYXAoKGUpID0+IHtcblx0XHRcdFx0cmV0dXJuIGZyb21FdmVudChjYW52YXMsICdtb3VzZW1vdmUnKS5waXBlKFxuXHRcdFx0XHRcdFx0dGFrZVVudGlsKGZyb21FdmVudChjYW52YXMsICdtb3VzZXVwJykpLFxuXHRcdFx0XHRcdFx0dGFrZVVudGlsKGZyb21FdmVudChjYW52YXMsICdtb3VzZWxlYXZlJykpLCBwYWlyd2lzZSgpKTtcblx0XHRcdH0pKVxuXHRcdFx0LnN1YnNjcmliZSgocmVzOiBbTW91c2VFdmVudCwgTW91c2VFdmVudF0pID0+IHtcblx0XHRcdFx0Y29uc3QgcmVjdCA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRcdFx0Y29uc3QgcHJldlBvcyA9IG5ldyBQb2ludChyZXNbMF0uY2xpZW50WCAtIHJlY3QubGVmdCwgcmVzWzBdLmNsaWVudFkgLSByZWN0LnRvcCk7XG5cdFx0XHRcdGNvbnN0IGN1cnJlbnRQb3MgPSBuZXcgUG9pbnQocmVzWzFdLmNsaWVudFggLSByZWN0LmxlZnQsIHJlc1sxXS5jbGllbnRZIC0gcmVjdC50b3ApO1xuXHRcdFx0XHR0aGlzLmRyYXcocHJldlBvcywgY3VycmVudFBvcyk7XG5cdFx0XHRcdGlmICh0aGlzLmlzQ2FudmFzRW1wdHkpIHtcblx0XHRcdFx0XHR0aGlzLmlzQ2FudmFzRW1wdHkgPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdH1cblxuXHRwdWJsaWMgZHJhdyhwcmV2aW91c1BvaW50OiBQb2ludCwgY3VycmVudFBvaW50OiBQb2ludCkge1xuXHRcdGlmICghdGhpcy5jeCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLmN4LmJlZ2luUGF0aCgpO1xuXHRcdGlmIChwcmV2aW91c1BvaW50KSB7XG5cdFx0XHR0aGlzLmN4Lm1vdmVUbyhwcmV2aW91c1BvaW50LngsIHByZXZpb3VzUG9pbnQueSk7XG5cdFx0XHR0aGlzLmN4LmxpbmVUbyhjdXJyZW50UG9pbnQueCwgY3VycmVudFBvaW50LnkpO1xuXHRcdFx0dGhpcy5jeC5zdHJva2UoKTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgZG93bmxvYWRJbWFnZSgpIHtcblx0XHRjb25zdCBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gdGhpcy5zaWduLm5hdGl2ZUVsZW1lbnQ7XG5cdFx0Y29uc3QgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuXHRcdHRoaXMuaHJlZiA9IGRhdGFVUkw7XG5cdFx0Y29uc3QgZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0dGhpcy5kb3duUGF0aCA9IGRhdGUgKyAnc2lnbmF0dXJlLnBuZyc7XG5cdH1cblxuXHRwdWJsaWMgY2xlYW5DYW52YXMoKSB7XG5cdFx0dGhpcy5pc0NhbnZhc0VtcHR5ID0gdHJ1ZTtcblx0XHR0aGlzLmN4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG5cdH1cblxuXHRwdWJsaWMgZmluaXNoRHJhd2luZygpIHtcblx0XHRjb25zdCBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gdGhpcy5zaWduLm5hdGl2ZUVsZW1lbnQ7XG5cdFx0Y29uc3QgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuXHRcdHRoaXMuc2lnbmF0dXJlID0gZGF0YVVSTDtcblx0XHRpZiAodGhpcy53aXRoQ29kZVZlcmlmaWNhdGlvbikge1xuXHRcdFx0Y2FudmFzLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCAnZGlzcGxheTpub25lOycpO1xuXHRcdFx0dGhpcy52ZXJpZmljYXRpb25BY3RpdmUgPSB0cnVlO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmZpbmlzaC5lbWl0KCk7XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHJldHVybkNhbnZhcygpIHtcblx0XHRjb25zdCBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gdGhpcy5zaWduLm5hdGl2ZUVsZW1lbnQ7XG5cdFx0Y2FudmFzLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCAnZGlzcGxheTpibG9jazsnKTtcblx0XHR0aGlzLnZlcmlmaWNhdGlvbkFjdGl2ZSA9IGZhbHNlO1xuXHR9XG59XG4iLCI8ZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJtYi0yXCIgKm5nSWY9XCIhdmVyaWZpY2F0aW9uQWN0aXZlXCI+XG4gICAgICAgIHt7ICdTSUdOX1RFWFRfRVhQTEFOQVRJT04nIHwgdHJhbnNsYXRlIHwgYXN5bmMgfX1cbiAgICA8L2Rpdj5cbiAgICA8Y2FudmFzIGNsYXNzPVwiYm9yZGVyIHJvdW5kZWRcIiAjc2lnbmF0dXJlPjwvY2FudmFzPlxuICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LXJpZ2h0IG10LTJcIiBbc3R5bGUud2lkdGgucHhdPVwid2lkdGhcIiAqbmdJZj1cIiF2ZXJpZmljYXRpb25BY3RpdmVcIj5cbiAgICAgICAgPHN5c3RlbGFiLWJ1dHRvbiBjbGFzcz1cIm1yLTFcIiAoY2xpY2spPVwiY2xlYW5DYW52YXMoKVwiPnt7ICdTSUdOX0NMRUFOJyB8IHRyYW5zbGF0ZSB8IGFzeW5jIH19PC9zeXN0ZWxhYi1idXR0b24+XG4gICAgICAgIDxhIGhyZWY9XCIjXCIgKm5nSWY9XCJpc0Rvd25sb2FkYWJsZVwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgbXItMVwiIFthdHRyLmRvd25sb2FkXT1cImRvd25QYXRoXCIgW2F0dHIuaHJlZl09XCJocmVmXCIgaWQ9XCJidG4tZG93bmxvYWRcIlxuICAgICAgICAgICAgKGNsaWNrKT1cImRvd25sb2FkSW1hZ2UoKVwiPnt7ICdTSUdOX0RPV05MT0FEJyB8IHRyYW5zbGF0ZSB8IGFzeW5jIH19PC9hPlxuICAgICAgICA8c3lzdGVsYWItYnV0dG9uIHR5cGU9XCJwcmltYXJ5XCIgW2Rpc2FibGVkXT1cImlzQ2FudmFzRW1wdHlcIiAoY2xpY2spPVwiZmluaXNoRHJhd2luZygpXCI+e3sgJ1NJR05fRklOSVNIJyB8IHRyYW5zbGF0ZSB8IGFzeW5jIH19PC9zeXN0ZWxhYi1idXR0b24+XG5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxpZ24tY29udGVudC1jZW50ZXIgcC0zXCIgKm5nSWY9XCJ2ZXJpZmljYXRpb25BY3RpdmVcIiBbc3R5bGUud2lkdGgucHhdPVwid2lkdGhcIiBbc3R5bGUuaGVpZ2h0LnB4XT1cImhlaWdodFwiPlxuICAgICAgICA8ZGl2IFtzdHlsZS53aWR0aC5weF09XCJ3aWR0aCAtIDUwXCIgW3N0eWxlLmhlaWdodC5weF09XCJoZWlnaHQgLSA1MFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTJcIj57eyAnU0lHTl9WRVJJRklDQVRJT05fVEVYVCcgfCB0cmFuc2xhdGUgfCBhc3luYyB9fTwvZGl2PlxuICAgICAgICAgICAgPGZvcm0gbm92YWxpZGF0ZSBjbGFzcz1cInctMTAwXCI+XG4gICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJwYXNzd29yZFwiIGNsYXNzPVwidy0xMDAgZm9ybS1jb250cm9sXCIgWyhuZ01vZGVsKV09XCJjb2RlXCIgW2NsYXNzLnNsYWItZXJyb3JdPVwiaW5wdXRDb2RlLmludmFsaWQgJiYgaW5wdXRDb2RlLnRvdWNoZWQgfHwgaXNJbmNvcnJlY3RDb2RlXCJcbiAgICAgICAgICAgICAgICAgICAgaWQ9XCJpbnB1dENvZGVcIiBwbGFjZWhvbGRlcj1cInt7ICdTSUdOQVRVUkVfQ09ERScgfCB0cmFuc2xhdGUgfCBhc3luYyB9fVwiICNpbnB1dENvZGU9XCJuZ01vZGVsXCIgbmFtZT1cImlucHV0Q29kZVwiXG4gICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJkb2ZpbmlzaCgpXCIgcmVxdWlyZWQgYXV0b2NvbXBsZXRlPVwib2ZmXCI+XG4gICAgICAgICAgICAgICAgPHN5c3RlbGFiLWJ1dHRvbiB0eXBlPVwicHJpbWFyeVwiIGNsYXNzPVwidy0xMDAgbXQtNFwiIFtkaXNhYmxlZF09XCJpbnB1dENvZGUuaW52YWxpZFwiIChjbGljayk9XCJkb2ZpbmlzaCgpXCI+e3sgJ1NJR05fVkVSSUZZJyB8IHRyYW5zbGF0ZSB8IGFzeW5jIH19XG4gICAgICAgICAgICAgICAgPC9zeXN0ZWxhYi1idXR0b24+XG4gICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImlzSW5jb3JyZWN0Q29kZVwiIGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyIGFsZXJ0LXNtIHRleHQtY2VudGVyIG10LTNcIj5cbiAgICAgICAgICAgICAgICAgICAgPGE+e3sgJ1NJR05fRVJST1JfRU5URVJFRF9DT0RFJyB8IHRyYW5zbGF0ZSB8IGFzeW5jIH19PC9hPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC0zIHRleHQtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxzeXN0ZWxhYi1idXR0b24gdHlwZT1cImxpbmtcIiAoY2xpY2spPVwicmV0dXJuQ2FudmFzKClcIj57eyAnU0lHTl9SRVRVUk4nIHwgdHJhbnNsYXRlIHwgYXN5bmMgfX08L3N5c3RlbGFiLWJ1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==