UNPKG

angular-otp-box

Version:

Angular otp input field component for web applications. Easy to integrate and use.

150 lines 19.5 kB
import { Component, Input, Output, EventEmitter, ViewChildren } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; import { KeysPipe } from '../pipes/keys.pipe'; import { CounterDirective } from '../directives/timer.directive'; export class OtpInputComponent { constructor(keysPipe) { this.keysPipe = keysPipe; this.setting = { length: 4, timer: 0, timerType: 0 }; this.onValueChange = new EventEmitter(); this.inputControls = new Array(this.setting.length); this.componentKey = Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36); } ngOnInit() { console.log(this.setting); this.otpForm = new FormGroup({}); for (let index = 0; index < this.setting.length; index++) { this.otpForm.addControl(this.getControlName(index), new FormControl()); } } ngAfterViewInit() { let containerItem = document.getElementById(`c_${this.componentKey}`); if (containerItem) { let ele = containerItem.getElementsByClassName('.otp-input')[0]; if (ele && ele.focus) { ele.focus(); } } } getControlName(idx) { return `ctrl_${idx}`; } isLeftArrow(e) { return this.isKeyCode(e, 37); } isRightArrow(e) { return this.isKeyCode(e, 39); } isBackspaceOrDelete(e) { return e.key === "Backspace" || e.key === "Delete" || this.isKeyCode(e, 8) || this.isKeyCode(e, 46); } isKeyCode(e, targetCode) { var key = e.keyCode || e.charCode; if (key == targetCode) { return true; } return false; } keyUp(e, inputIdx) { let nextInputId = this.appendKey(`otp_${inputIdx + 1}`); let prevInputId = this.appendKey(`otp_${inputIdx - 1}`); if (this.isRightArrow(e)) { this.setSelected(nextInputId); return; } if (this.isLeftArrow(e)) { this.setSelected(prevInputId); return; } let isBackspace = this.isBackspaceOrDelete(e); if (isBackspace && !e.target.value) { this.setSelected(prevInputId); this.rebuildValue(); return; } if (!e.target.value) { return; } if (this.isValidEntry(e)) { this.focusTo(nextInputId); } this.rebuildValue(); } appendKey(id) { return `${id}_${this.componentKey}`; } setSelected(eleId) { this.focusTo(eleId); let ele = document.getElementById(eleId); if (ele && ele.setSelectionRange) { setTimeout(() => { ele.setSelectionRange(0, 1); }, 0); } } isValidEntry(e) { var inp = String.fromCharCode(e.keyCode); var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); return isMobile || /[a-zA-Z0-9-_]/.test(inp) || (this.setting.allowKeyCodes && this.setting.allowKeyCodes.includes(e.keyCode)) || (e.keyCode >= 96 && e.keyCode <= 105); } focusTo(eleId) { let ele = document.getElementById(eleId); if (ele) { ele.focus(); ele.selectionStart = ele.selectionEnd = 100; } } rebuildValue() { let val = ''; this.keysPipe.transform(this.otpForm.controls).forEach(k => { if (this.otpForm.controls[k].value) { val += this.otpForm.controls[k].value; } }); this.onValueChange.emit(val); } onCounterChange(e) { this.counter = e; if (this.counter == 0) { this.onValueChange.emit(-1); } } ressendOtp() { this.CounterDirective.first.startTimer(); this.onValueChange.emit(-2); } formatSecsToMins(time) { // Hours, minutes and seconds var hrs = ~~(time / 3600); var mins = ~~((time % 3600) / 60); var secs = ~~time % 60; // Output like "1:01" or "4:03:59" or "123:03:59" var ret = ""; if (hrs > 0) { ret += "" + hrs + ":" + (mins < 10 ? "0" : ""); } ret += "" + mins + ":" + (secs < 10 ? "0" : ""); ret += "" + secs; return ret; } } OtpInputComponent.decorators = [ { type: Component, args: [{ selector: 'otp', template: "<div class=\"otp-container {{setting.wrapperClass}}\" id=\"c_{{componentKey}}\" *ngIf=\"otpForm?.controls\"\n [ngStyle]=\"setting.wrapperStyles\">\n <input \n [type]=\"setting.numbersOnly ? 'tel' : 'text'\" \n numberOnly [disabledNumberOnly]=\"!setting.numbersOnly\"\n [ngStyle]=\"setting.inputStyles\" \n maxlength=\"1\" \n class=\"otp-input {{setting.inputClass}}\" \n autocomplete=\"off\"\n *ngFor=\"let item of otpForm?.controls | keys; let i = index\" \n [formControl]=\"otpForm.controls[item]\"\n id=\"otp_{{i}}_{{componentKey}}\" \n (keyup)=\"keyUp($event, i)\"\n >\n <ng-container counter [counter]=\"setting.timer\" (value)=\"onCounterChange($event)\">\n <div>\n <button class=\"btn {{setting.btnClass}}\" [disabled]=\"counter != 0\" (click)=\"ressendOtp()\">\n Resend OTP \n <span *ngIf=\"counter != 0\">\n <ng-container *ngIf=\"!setting.timerType\">\n in {{ counter }} seconds.\n </ng-container>\n <ng-container *ngIf=\"setting.timerType\">\n in {{ formatSecsToMins(counter) }} minutes.\n </ng-container>\n </span>\n </button>\n </div>\n </ng-container>\n</div>", styles: [".otp-input{width:2em;height:2em;border-radius:4px;border:1px solid #c5c5c5;text-align:center;font-size:28px}.otp-input:focus{outline-offset:0;outline-color:#2b91e2;outline-style:auto;outline-width:5px}.otp-container .otp-input:not(:last-child){margin-right:8px}@media screen and (max-width:767px){.otp-input{font-size:24px}}@media screen and (max-width:420px){.otp-input{font-size:18px}}"] },] } ]; OtpInputComponent.ctorParameters = () => [ { type: KeysPipe } ]; OtpInputComponent.propDecorators = { setting: [{ type: Input }], onValueChange: [{ type: Output }], CounterDirective: [{ type: ViewChildren, args: [CounterDirective,] }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1vdHAtaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1vdHAtYm94L3NyYy9saWIvY29tcG9uZW50cy9hbmd1bGFyLW90cC1pbnB1dC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0YsT0FBTyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFOUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFRakUsTUFBTSxPQUFPLGlCQUFpQjtJQWE3QixZQUFvQixRQUFrQjtRQUFsQixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBWjdCLFlBQU8sR0FBWTtZQUMzQixNQUFNLEVBQUUsQ0FBQztZQUNULEtBQUssRUFBRSxDQUFDO1lBQ1IsU0FBUyxFQUFFLENBQUM7U0FDWixDQUFDO1FBQ1Esa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO1FBR2xELGtCQUFhLEdBQWtCLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUQsaUJBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7SUFLN0YsQ0FBQztJQUVNLFFBQVE7UUFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ2hDLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUN6RCxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsQ0FBQTtTQUN0RTtJQUNGLENBQUM7SUFFTSxlQUFlO1FBQ3JCLElBQUksYUFBYSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUN0RSxJQUFJLGFBQWEsRUFBRTtZQUNsQixJQUFJLEdBQUcsR0FBUSxhQUFhLENBQUMsc0JBQXNCLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDcEUsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRTtnQkFDckIsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQ1o7U0FDRDtJQUNGLENBQUM7SUFFTyxjQUFjLENBQUMsR0FBRztRQUN6QixPQUFPLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVELFdBQVcsQ0FBQyxDQUFDO1FBQ1osT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQsWUFBWSxDQUFDLENBQUM7UUFDYixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRCxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3BCLE9BQU8sQ0FBQyxDQUFDLEdBQUcsS0FBSyxXQUFXLElBQUksQ0FBQyxDQUFDLEdBQUcsS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckcsQ0FBQztJQUVELFNBQVMsQ0FBQyxDQUFDLEVBQUUsVUFBVTtRQUN0QixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUM7UUFDbEMsSUFBRyxHQUFHLElBQUksVUFBVSxFQUFFO1lBQUUsT0FBTyxJQUFJLENBQUM7U0FBRTtRQUN0QyxPQUFPLEtBQUssQ0FBQztJQUNkLENBQUM7SUFFRCxLQUFLLENBQUMsQ0FBQyxFQUFFLFFBQWdCO1FBQ3hCLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxRQUFRLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4RCxJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sUUFBUSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDeEQsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ3pCLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDOUIsT0FBTztTQUNQO1FBQ0QsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDOUIsT0FBTztTQUNQO1FBQ0QsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlDLElBQUksV0FBVyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7WUFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM5QixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDcEIsT0FBTztTQUNQO1FBQ0QsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1lBQ3BCLE9BQU87U0FDUDtRQUNELElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUN6QixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1NBQzFCO1FBQ0QsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxTQUFTLENBQUMsRUFBRTtRQUNYLE9BQU8sR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3JDLENBQUM7SUFFRCxXQUFXLENBQUMsS0FBSztRQUNoQixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BCLElBQUksR0FBRyxHQUFRLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDOUMsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFO1lBQ2pDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2YsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM3QixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDTjtJQUNGLENBQUM7SUFFRCxZQUFZLENBQUMsQ0FBQztRQUNiLElBQUksR0FBRyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLElBQUksUUFBUSxHQUFHLDJCQUEyQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckUsT0FBTyxRQUFRLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLElBQUksR0FBRyxDQUFDLENBQUM7SUFDekssQ0FBQztJQUVELE9BQU8sQ0FBQyxLQUFLO1FBQ1osSUFBSSxHQUFHLEdBQVEsUUFBUSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QyxJQUFJLEdBQUcsRUFBRTtZQUNSLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNaLEdBQUcsQ0FBQyxjQUFjLEdBQUcsR0FBRyxDQUFDLFlBQVksR0FBRyxHQUFHLENBQUM7U0FDNUM7SUFDRixDQUFDO0lBRUQsWUFBWTtRQUNYLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNiLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzFELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFO2dCQUNuQyxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO2FBQ3RDO1FBQ0YsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRU0sZUFBZSxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFDakIsSUFBRyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsRUFBRTtZQUNyQixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzVCO0lBQ0YsQ0FBQztJQUVELFVBQVU7UUFDVCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVNLGdCQUFnQixDQUFDLElBQUk7UUFDM0IsNkJBQTZCO1FBQzdCLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQztRQUMxQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNsQyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUV2QixpREFBaUQ7UUFDakQsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ2IsSUFBSSxHQUFHLEdBQUcsQ0FBQyxFQUFFO1lBQ1osR0FBRyxJQUFJLEVBQUUsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUMvQztRQUNELEdBQUcsSUFBSSxFQUFFLEdBQUcsSUFBSSxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEQsR0FBRyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDakIsT0FBTyxHQUFHLENBQUM7SUFDWixDQUFDOzs7WUF6SkQsU0FBUyxTQUFDO2dCQUNWLFFBQVEsRUFBRSxLQUFLO2dCQUNmLDQxQ0FBaUQ7O2FBRWpEOzs7WUFSUSxRQUFROzs7c0JBV2YsS0FBSzs0QkFLTCxNQUFNOytCQUNOLFlBQVksU0FBQyxnQkFBZ0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBWaWV3Q2hpbGRyZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBLZXlzUGlwZSB9IGZyb20gJy4uL3BpcGVzL2tleXMucGlwZSc7XG5pbXBvcnQgeyBTZXR0aW5nIH0gZnJvbSAnLi4vbW9kZWxzL3NldHRpbmcnO1xuaW1wb3J0IHsgQ291bnRlckRpcmVjdGl2ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvdGltZXIuZGlyZWN0aXZlJztcblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yOiAnb3RwJyxcblx0dGVtcGxhdGVVcmw6ICcuL2FuZ3VsYXItb3RwLWlucHV0LmNvbXBvbmVudC5odG1sJyxcblx0c3R5bGVVcmxzOiBbJy4vYW5ndWxhci1vdHAtaW5wdXQuY29tcG9uZW50LnNjc3MnXVxufSlcblxuZXhwb3J0IGNsYXNzIE90cElucHV0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblx0QElucHV0KCkgc2V0dGluZzogU2V0dGluZyA9IHsgXG5cdFx0bGVuZ3RoOiA0LCBcblx0XHR0aW1lcjogMCxcblx0XHR0aW1lclR5cGU6IDBcblx0fTtcblx0QE91dHB1dCgpIG9uVmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblx0QFZpZXdDaGlsZHJlbihDb3VudGVyRGlyZWN0aXZlKSBDb3VudGVyRGlyZWN0aXZlO1xuXHRvdHBGb3JtOiBGb3JtR3JvdXA7XG5cdGlucHV0Q29udHJvbHM6IEZvcm1Db250cm9sW10gPSBuZXcgQXJyYXkodGhpcy5zZXR0aW5nLmxlbmd0aCk7XG5cdGNvbXBvbmVudEtleSA9IE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygyKSArIChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkudG9TdHJpbmcoMzYpO1xuXHRwdWJsaWMgY291bnRlcjogbnVtYmVyO1xuXHRcblx0Y29uc3RydWN0b3IocHJpdmF0ZSBrZXlzUGlwZTogS2V5c1BpcGUpIHtcblx0XHRcblx0fVxuXG5cdHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcblx0XHRjb25zb2xlLmxvZyh0aGlzLnNldHRpbmcpO1xuXHRcdHRoaXMub3RwRm9ybSA9IG5ldyBGb3JtR3JvdXAoe30pXG5cdFx0Zm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMuc2V0dGluZy5sZW5ndGg7IGluZGV4KyspIHtcblx0XHRcdHRoaXMub3RwRm9ybS5hZGRDb250cm9sKHRoaXMuZ2V0Q29udHJvbE5hbWUoaW5kZXgpLCBuZXcgRm9ybUNvbnRyb2woKSlcblx0XHR9XG5cdH1cblx0XG5cdHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG5cdFx0bGV0IGNvbnRhaW5lckl0ZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChgY18ke3RoaXMuY29tcG9uZW50S2V5fWApO1xuXHRcdGlmIChjb250YWluZXJJdGVtKSB7XG5cdFx0XHRsZXQgZWxlOiBhbnkgPSBjb250YWluZXJJdGVtLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJy5vdHAtaW5wdXQnKVswXVxuXHRcdFx0aWYgKGVsZSAmJiBlbGUuZm9jdXMpIHtcblx0XHRcdFx0ZWxlLmZvY3VzKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBnZXRDb250cm9sTmFtZShpZHgpIHtcblx0XHRyZXR1cm4gYGN0cmxfJHtpZHh9YDtcblx0fVxuXG5cdGlzTGVmdEFycm93KGUpIHtcblx0XHRyZXR1cm4gdGhpcy5pc0tleUNvZGUoZSwgMzcpO1xuXHR9XG5cblx0aXNSaWdodEFycm93KGUpIHtcblx0XHRyZXR1cm4gdGhpcy5pc0tleUNvZGUoZSwgMzkpO1xuXHR9XG5cblx0aXNCYWNrc3BhY2VPckRlbGV0ZShlKSB7XG5cdFx0cmV0dXJuIGUua2V5ID09PSBcIkJhY2tzcGFjZVwiIHx8IGUua2V5ID09PSBcIkRlbGV0ZVwiIHx8IHRoaXMuaXNLZXlDb2RlKGUsIDgpIHx8IHRoaXMuaXNLZXlDb2RlKGUsIDQ2KTtcblx0fVxuXG5cdGlzS2V5Q29kZShlLCB0YXJnZXRDb2RlKSB7XG5cdFx0dmFyIGtleSA9IGUua2V5Q29kZSB8fCBlLmNoYXJDb2RlO1xuXHRcdGlmKGtleSA9PSB0YXJnZXRDb2RlKSB7IHJldHVybiB0cnVlOyB9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0a2V5VXAoZSwgaW5wdXRJZHg6IG51bWJlcikge1xuXHRcdGxldCBuZXh0SW5wdXRJZCA9IHRoaXMuYXBwZW5kS2V5KGBvdHBfJHtpbnB1dElkeCArIDF9YCk7XG5cdFx0bGV0IHByZXZJbnB1dElkID0gdGhpcy5hcHBlbmRLZXkoYG90cF8ke2lucHV0SWR4IC0gMX1gKTtcblx0XHRpZiAodGhpcy5pc1JpZ2h0QXJyb3coZSkpIHtcblx0XHRcdHRoaXMuc2V0U2VsZWN0ZWQobmV4dElucHV0SWQpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAodGhpcy5pc0xlZnRBcnJvdyhlKSkge1xuXHRcdFx0dGhpcy5zZXRTZWxlY3RlZChwcmV2SW5wdXRJZCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGxldCBpc0JhY2tzcGFjZSA9IHRoaXMuaXNCYWNrc3BhY2VPckRlbGV0ZShlKTtcblx0XHRpZiAoaXNCYWNrc3BhY2UgJiYgIWUudGFyZ2V0LnZhbHVlKSB7XG5cdFx0XHR0aGlzLnNldFNlbGVjdGVkKHByZXZJbnB1dElkKTtcblx0XHRcdHRoaXMucmVidWlsZFZhbHVlKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmICghZS50YXJnZXQudmFsdWUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0aWYgKHRoaXMuaXNWYWxpZEVudHJ5KGUpKSB7XG5cdFx0XHR0aGlzLmZvY3VzVG8obmV4dElucHV0SWQpO1xuXHRcdH1cblx0XHR0aGlzLnJlYnVpbGRWYWx1ZSgpO1xuXHR9XG5cblx0YXBwZW5kS2V5KGlkKSB7XG5cdFx0cmV0dXJuIGAke2lkfV8ke3RoaXMuY29tcG9uZW50S2V5fWA7XG5cdH1cblxuXHRzZXRTZWxlY3RlZChlbGVJZCkge1xuXHRcdHRoaXMuZm9jdXNUbyhlbGVJZCk7XG5cdFx0bGV0IGVsZTogYW55ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxlSWQpO1xuXHRcdGlmIChlbGUgJiYgZWxlLnNldFNlbGVjdGlvblJhbmdlKSB7XG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0ZWxlLnNldFNlbGVjdGlvblJhbmdlKDAsIDEpO1xuXHRcdFx0fSwgMCk7XG5cdFx0fVxuXHR9XG5cblx0aXNWYWxpZEVudHJ5KGUpIHtcblx0XHR2YXIgaW5wID0gU3RyaW5nLmZyb21DaGFyQ29kZShlLmtleUNvZGUpO1xuXHRcdHZhciBpc01vYmlsZSA9IC9pUGhvbmV8aVBhZHxpUG9kfEFuZHJvaWQvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuXHRcdHJldHVybiBpc01vYmlsZSB8fCAvW2EtekEtWjAtOS1fXS8udGVzdChpbnApIHx8ICh0aGlzLnNldHRpbmcuYWxsb3dLZXlDb2RlcyAmJiB0aGlzLnNldHRpbmcuYWxsb3dLZXlDb2Rlcy5pbmNsdWRlcyhlLmtleUNvZGUpKSB8fCAoZS5rZXlDb2RlID49IDk2ICYmIGUua2V5Q29kZSA8PSAxMDUpO1xuXHR9XG5cblx0Zm9jdXNUbyhlbGVJZCkge1xuXHRcdGxldCBlbGU6IGFueSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZUlkKTtcblx0XHRpZiAoZWxlKSB7XG5cdFx0XHRlbGUuZm9jdXMoKTtcblx0XHRcdGVsZS5zZWxlY3Rpb25TdGFydCA9IGVsZS5zZWxlY3Rpb25FbmQgPSAxMDA7XG5cdFx0fVxuXHR9XG5cblx0cmVidWlsZFZhbHVlKCkge1xuXHRcdGxldCB2YWwgPSAnJztcblx0XHR0aGlzLmtleXNQaXBlLnRyYW5zZm9ybSh0aGlzLm90cEZvcm0uY29udHJvbHMpLmZvckVhY2goayA9PiB7XG5cdFx0XHRpZiAodGhpcy5vdHBGb3JtLmNvbnRyb2xzW2tdLnZhbHVlKSB7XG5cdFx0XHRcdHZhbCArPSB0aGlzLm90cEZvcm0uY29udHJvbHNba10udmFsdWU7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0dGhpcy5vblZhbHVlQ2hhbmdlLmVtaXQodmFsKTtcblx0fVxuXG5cdHB1YmxpYyBvbkNvdW50ZXJDaGFuZ2UoZSk6IHZvaWQge1xuXHRcdHRoaXMuY291bnRlciA9IGU7XG5cdFx0aWYodGhpcy5jb3VudGVyID09IDApIHtcblx0XHRcdHRoaXMub25WYWx1ZUNoYW5nZS5lbWl0KC0xKTtcblx0XHR9XG5cdH1cblxuXHRyZXNzZW5kT3RwKCk6IHZvaWQge1xuXHRcdHRoaXMuQ291bnRlckRpcmVjdGl2ZS5maXJzdC5zdGFydFRpbWVyKCk7XG5cdFx0dGhpcy5vblZhbHVlQ2hhbmdlLmVtaXQoLTIpO1xuXHR9XG5cblx0cHVibGljIGZvcm1hdFNlY3NUb01pbnModGltZSkgeyAgIFxuXHRcdC8vIEhvdXJzLCBtaW51dGVzIGFuZCBzZWNvbmRzXG5cdFx0dmFyIGhycyA9IH5+KHRpbWUgLyAzNjAwKTtcblx0XHR2YXIgbWlucyA9IH5+KCh0aW1lICUgMzYwMCkgLyA2MCk7XG5cdFx0dmFyIHNlY3MgPSB+fnRpbWUgJSA2MDtcblx0XG5cdFx0Ly8gT3V0cHV0IGxpa2UgXCIxOjAxXCIgb3IgXCI0OjAzOjU5XCIgb3IgXCIxMjM6MDM6NTlcIlxuXHRcdHZhciByZXQgPSBcIlwiO1xuXHRcdGlmIChocnMgPiAwKSB7XG5cdFx0XHRyZXQgKz0gXCJcIiArIGhycyArIFwiOlwiICsgKG1pbnMgPCAxMCA/IFwiMFwiIDogXCJcIik7XG5cdFx0fVxuXHRcdHJldCArPSBcIlwiICsgbWlucyArIFwiOlwiICsgKHNlY3MgPCAxMCA/IFwiMFwiIDogXCJcIik7XG5cdFx0cmV0ICs9IFwiXCIgKyBzZWNzO1xuXHRcdHJldHVybiByZXQ7XG5cdH1cbn0iXX0=