UNPKG

ng-scroll-picker

Version:

Base logic inspired from https://github.com/hiyali/ng-data-picker

437 lines (431 loc) 59.9 kB
import { Inject, Component, Input, Output, EventEmitter, ElementRef, ViewChild, ViewChildren, } from '@angular/core'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class NgScrollPickerComponent { constructor(elementRef) { this.data = []; this.change = new EventEmitter(); this.touchOrMouse = { isTouchable: 'ontouchstart' in window, isMouseDown: false, }; this.draggingInfo = { isDragging: false, groupIndex: null, startPageY: null, }; this.itemPerDegree = 23; this.safeDoTimeoutId = null; } ngOnInit() { this.currentIndexList = this.getInitialCurrentIndexList(); this.lastCurrentIndexList = new Array().concat(this.currentIndexList); this.groupsRectList = new Array(this.data.length); } ngAfterViewInit() { this.eventsRegister(); window.addEventListener('resize', this.safeGetRectsBindEvents.bind(this)); this.getGroupsRectList(); } ngOnDestroy() { window.removeEventListener('resize', this.safeGetRectsBindEvents.bind(this)); } setGroupData(gIndex, groupData) { if (!this.currentIndexList) { this.currentIndexList = this.getInitialCurrentIndexList(); } this.data[gIndex] = groupData; const iCI = groupData.currentIndex; let movedIndex = 0; if (typeof iCI === 'number' && iCI >= 0 && groupData.list && groupData.list.length && iCI <= groupData.list.length - 1) { movedIndex = Math.round(iCI); } this.currentIndexList[gIndex] = movedIndex; this.lastCurrentIndexList = new Array().concat(this.currentIndexList); } getInitialCurrentIndexList() { return this.data.map((item, index) => { const iCI = item.currentIndex; if (typeof iCI === 'number' && iCI >= 0 && item.list && item.list.length && iCI <= item.list.length - 1) { return Math.round(iCI); } return 0; }); } safeGetRectsBindEvents() { if (this.safeDoTimeoutId) { clearTimeout(this.safeDoTimeoutId); } this.safeDoTimeoutId = setTimeout(() => { this.getGroupsRectList(); }, 200); } getGroupsRectList() { if (this.pickerGroupLayer) { this.pickerGroupLayer.toArray().forEach((item, index) => { this.groupsRectList[index] = item.nativeElement.getBoundingClientRect(); }); } } eventsRegister() { const handleEventLayer = this.pickerHandleLayer.nativeElement; if (handleEventLayer) { this.addEventsForElement(handleEventLayer); } } addEventsForElement(el) { const _ = this.touchOrMouse.isTouchable; const eventHandlerList = [ { name: _ ? 'touchstart' : 'mousedown', handler: this.handleStart }, { name: _ ? 'touchmove' : 'mousemove', handler: this.handleMove }, { name: _ ? 'touchend' : 'mouseup', handler: this.handleEnd }, { name: _ ? 'touchcancel' : 'mouseleave', handler: this.handleCancel }, { name: 'wheel', handler: this.handleScroll }, ]; eventHandlerList.forEach((item, index) => { el.removeEventListener(item.name, item.handler, false); el.addEventListener(item.name, item.handler.bind(this), false); }); } triggerMiddleLayerGroupClick(gIndex) { const data = this.data; if (data[gIndex].onClick !== undefined) { const click = data[gIndex].onClick; if (typeof gIndex === 'number' && typeof data[gIndex].onClick === 'function') { // click( // gIndex, // this.currentIndexList[gIndex], // this.data[gIndex].list[this.currentIndexList[gIndex]] // ); const response = { gIndex, iIndex: this.currentIndexList[gIndex], selectedValue: this.data[gIndex].list[this.currentIndexList[gIndex]], groupName: this.data[gIndex].groupName, }; click(response); } } } triggerAboveLayerClick(ev, gIndex) { const movedIndex = this.currentIndexList[gIndex] + 1; this.currentIndexList[gIndex] = movedIndex; this.correctionCurrentIndex(ev, gIndex); } triggerMiddleLayerClick(ev, gIndex) { this.triggerMiddleLayerGroupClick(gIndex); } triggerBelowLayerClick(ev, gIndex) { const movedIndex = this.currentIndexList[gIndex] - 1; this.currentIndexList[gIndex] = movedIndex; this.correctionCurrentIndex(ev, gIndex); } getTouchInfo(ev) { return this.touchOrMouse.isTouchable ? ev.changedTouches[0] || ev.touches[0] : ev; } getGroupIndexBelongsEvent(ev) { const touchInfo = this.getTouchInfo(ev); for (let i = 0; i < this.groupsRectList.length; i++) { const item = this.groupsRectList[i]; if (item.left < touchInfo.pageX && touchInfo.pageX < item.right) { return i; } } return null; } handleEventClick(ev) { const gIndex = this.getGroupIndexBelongsEvent(ev); switch (ev.target.dataset.type) { case 'top': this.triggerAboveLayerClick(ev, gIndex); break; case 'middle': this.triggerMiddleLayerClick(ev, gIndex); break; case 'bottom': this.triggerBelowLayerClick(ev, gIndex); break; default: } } handleStart(ev) { if (ev.cancelable) { ev.preventDefault(); ev.stopPropagation(); } const touchInfo = this.getTouchInfo(ev); this.draggingInfo.startPageY = touchInfo.pageY; if (!this.touchOrMouse.isTouchable) { this.touchOrMouse.isMouseDown = true; } } handleMove(ev) { ev.preventDefault(); ev.stopPropagation(); if (this.touchOrMouse.isTouchable || this.touchOrMouse.isMouseDown) { this.draggingInfo.isDragging = true; this.setCurrentIndexOnMove(ev); } } handleEnd(ev) { ev.preventDefault(); ev.stopPropagation(); if (!this.draggingInfo.isDragging) { this.handleEventClick(ev); } this.draggingInfo.isDragging = false; this.touchOrMouse.isMouseDown = false; this.correctionAfterDragging(ev); } handleCancel(ev) { ev.preventDefault(); ev.stopPropagation(); if (this.touchOrMouse.isTouchable || this.touchOrMouse.isMouseDown) { this.correctionAfterDragging(ev); this.touchOrMouse.isMouseDown = false; this.draggingInfo.isDragging = false; } } handleScroll(ev) { ev.preventDefault(); ev.stopPropagation(); if (ev instanceof WheelEvent) { ev = ev; const gIndex = this.getGroupIndexBelongsEvent(ev); const deltaY = ev.deltaY; if (deltaY > 0) { // Scrolling down console.log('Scrolling down'); this.triggerAboveLayerClick(ev, gIndex); } else if (deltaY < 0) { // Scrolling up console.log('Scrolling up'); this.triggerBelowLayerClick(ev, gIndex); } else { // No vertical scrolling console.log('No vertical scrolling'); } } } setCurrentIndexOnMove(ev) { const touchInfo = this.getTouchInfo(ev); if (this.draggingInfo.groupIndex === null) { this.draggingInfo.groupIndex = this.getGroupIndexBelongsEvent(ev); } if (this.draggingInfo.groupIndex !== null) { const gIndex = this.draggingInfo.groupIndex; if (typeof gIndex === 'number' && (this.data[gIndex].divider || !this.data[gIndex].list)) { return; } if (this.draggingInfo.startPageY !== null) { const moveCount = (this.draggingInfo.startPageY - touchInfo.pageY) / 32; const movedIndex = this.currentIndexList[gIndex] + moveCount; this.currentIndexList[gIndex] = movedIndex; this.draggingInfo.startPageY = touchInfo.pageY; } } } correctionAfterDragging(ev) { const gIndex = this.draggingInfo.groupIndex; this.correctionCurrentIndex(ev, gIndex); this.draggingInfo.groupIndex = null; this.draggingInfo.startPageY = null; this.getCurrentIndexList(); } correctionCurrentIndex(ev, gIndex) { setTimeout(() => { if (typeof gIndex === 'number' && this.data[gIndex].divider !== true && this.data[gIndex].list.length > 0) { const unsafeGroupIndex = this.currentIndexList[gIndex]; let movedIndex = unsafeGroupIndex; if (unsafeGroupIndex > this.data[gIndex].list.length - 1) { movedIndex = this.data[gIndex].list.length - 1; } else if (unsafeGroupIndex < 0) { movedIndex = 0; } movedIndex = Math.round(movedIndex); this.currentIndexList[gIndex] = movedIndex; if (movedIndex !== this.lastCurrentIndexList[gIndex]) { const response = { gIndex, iIndex: movedIndex, selectedValue: this.data[gIndex].list[movedIndex], groupName: this.data[gIndex].groupName, }; // this.change.emit({ // gIndex, // iIndex: movedIndex, // selectedValue: this.data[gIndex].list[movedIndex], // }); this.change.emit(response); } this.lastCurrentIndexList = new Array().concat(this.currentIndexList); } }, 100); } isCurrentItem(gIndex, iIndex) { return this.currentIndexList[gIndex] === iIndex; } getCurrentIndexList() { return this.currentIndexList; } getGroupClass(gIndex) { const group = this.data[gIndex]; const defaultWeightClass = 'weight-' + (group.weight || 1); const groupClass = [defaultWeightClass]; if (group.className) { groupClass.push(group.className); } return groupClass; } getItemClass(gIndex, iIndex, isDivider = false) { const group = this.data[gIndex]; const itemClass = []; if (!isDivider && this.isCurrentItem(gIndex, iIndex)) { itemClass.push('smooth-item-selected'); } if (group.textAlign) { itemClass.push('text-' + group.textAlign); } return itemClass; } getItemStyle(gIndex, iIndex) { const gapCount = this.currentIndexList[gIndex] - iIndex; if (Math.abs(gapCount) < 90 / this.itemPerDegree) { const rotateStyle = { transform: 'rotateX(' + gapCount * this.itemPerDegree + 'deg) translate3d(0, 0, 5.625em)', opacity: (1 - Math.abs(gapCount) / (90 / this.itemPerDegree)).toString(), // color: gapCount === 0 ? 'rgba(237, 27, 45, 1)' : '', }; if (!this.draggingInfo.isDragging) { rotateStyle['transition'] = 'transform 150ms ease-out'; } return rotateStyle; } if (gapCount > 0) { return { transform: 'rotateX(90deg) translate3d(0, 0, 5.625em)' }; } else { return { transform: 'rotateX(-90deg) translate3d(0, 0, 5.625em)' }; } } } NgScrollPickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: NgScrollPickerComponent, deps: [{ token: ElementRef }], target: i0.ɵɵFactoryTarget.Component }); NgScrollPickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: NgScrollPickerComponent, selector: "ng-scroll-picker", inputs: { data: "data" }, outputs: { change: "change" }, viewQueries: [{ propertyName: "pickerHandleLayer", first: true, predicate: ["pickerHandleLayer"], descendants: true }, { propertyName: "pickerGroupLayer", predicate: ["pickerGroupLayer"], descendants: true }], ngImport: i0, template: ` <div class="ng-data-picker flex-box"> <div class="picker-handle-layer flex-box dir-column"> <div data-type="top" class="picker-top weight-1"></div> <div data-type="middle" class="picker-middle tengah"></div> <div data-type="bottom" class="picker-bottom weight-1"></div> </div> <div #pickerGroupLayer *ngFor="let group of data; let gIndex = index" class="picker-group" [ngClass]="getGroupClass(gIndex)" > <div class="picker-list"> <div *ngIf="group.divider; else ngIfElse" class="picker-item divider" [ngClass]="getItemClass(gIndex, gIndex, true)" > {{ group.text }} </div> <ng-template #ngIfElse> <div #ngIfElse *ngFor="let item of group.list; let iIndex = index" class="picker-item" [ngClass]="getItemClass(gIndex, iIndex)" [ngStyle]="getItemStyle(gIndex, iIndex)" > {{ item.label }} </div> </ng-template> </div> </div> <div #pickerHandleLayer class="picker-handle-layer flex-box dir-column"> <div data-type="top" class="picker-top weight-1"></div> <div data-type="middle" class="picker-middle"></div> <div data-type="bottom" class="picker-bottom weight-1"></div> </div> </div> `, isInline: true, styles: [".ng-data-picker{font-size:1rem;height:10em;position:relative;background-color:#fff;overflow:hidden}.ng-data-picker.black{color:#fff}.ng-data-picker .picker-list{height:6.25em;position:relative;top:4em}.ng-data-picker .picker-item{position:absolute;top:0;left:0;overflow:hidden;width:100%;text-overflow:ellipsis;white-space:nowrap;display:block;text-align:center;will-change:transform;contain:strict;height:2em;line-height:2;font-size:1em}.ng-data-picker .picker-handle-layer{position:absolute;width:100%;height:calc(100% + 2px);inset:-1px 0}.ng-data-picker .picker-handle-layer .picker-top{background:linear-gradient(to bottom,white 2%,rgba(255,255,255,.1) 100%);transform:translateZ(5.625em)}.ng-data-picker .picker-handle-layer .picker-middle{height:2em}.tengah{background-color:#dcdcdc;border-radius:5px}.ng-data-picker .picker-handle-layer .picker-bottom{background:linear-gradient(to top,white 2%,rgba(255,255,255,.1) 100%);transform:translateZ(5.625em)}.flex-box{display:flex}.flex-box.dir-column{flex-direction:column}.flex-box.dir-row{flex-direction:row}.flex-box .weight-1{flex:1}.flex-box .weight-2{flex:2}.flex-box .weight-3{flex:3}.flex-box .weight-4{flex:4}.flex-box .weight-5{flex:5}.flex-box .weight-6{flex:6}.flex-box .weight-7{flex:7}.flex-box .weight-8{flex:8}.flex-box .weight-9{flex:9}.flex-box .weight-10{flex:10}.flex-box .weight-11{flex:11}.flex-box .weight-12{flex:12}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: NgScrollPickerComponent, decorators: [{ type: Component, args: [{ selector: 'ng-scroll-picker', template: ` <div class="ng-data-picker flex-box"> <div class="picker-handle-layer flex-box dir-column"> <div data-type="top" class="picker-top weight-1"></div> <div data-type="middle" class="picker-middle tengah"></div> <div data-type="bottom" class="picker-bottom weight-1"></div> </div> <div #pickerGroupLayer *ngFor="let group of data; let gIndex = index" class="picker-group" [ngClass]="getGroupClass(gIndex)" > <div class="picker-list"> <div *ngIf="group.divider; else ngIfElse" class="picker-item divider" [ngClass]="getItemClass(gIndex, gIndex, true)" > {{ group.text }} </div> <ng-template #ngIfElse> <div #ngIfElse *ngFor="let item of group.list; let iIndex = index" class="picker-item" [ngClass]="getItemClass(gIndex, iIndex)" [ngStyle]="getItemStyle(gIndex, iIndex)" > {{ item.label }} </div> </ng-template> </div> </div> <div #pickerHandleLayer class="picker-handle-layer flex-box dir-column"> <div data-type="top" class="picker-top weight-1"></div> <div data-type="middle" class="picker-middle"></div> <div data-type="bottom" class="picker-bottom weight-1"></div> </div> </div> `, styles: [".ng-data-picker{font-size:1rem;height:10em;position:relative;background-color:#fff;overflow:hidden}.ng-data-picker.black{color:#fff}.ng-data-picker .picker-list{height:6.25em;position:relative;top:4em}.ng-data-picker .picker-item{position:absolute;top:0;left:0;overflow:hidden;width:100%;text-overflow:ellipsis;white-space:nowrap;display:block;text-align:center;will-change:transform;contain:strict;height:2em;line-height:2;font-size:1em}.ng-data-picker .picker-handle-layer{position:absolute;width:100%;height:calc(100% + 2px);inset:-1px 0}.ng-data-picker .picker-handle-layer .picker-top{background:linear-gradient(to bottom,white 2%,rgba(255,255,255,.1) 100%);transform:translateZ(5.625em)}.ng-data-picker .picker-handle-layer .picker-middle{height:2em}.tengah{background-color:#dcdcdc;border-radius:5px}.ng-data-picker .picker-handle-layer .picker-bottom{background:linear-gradient(to top,white 2%,rgba(255,255,255,.1) 100%);transform:translateZ(5.625em)}.flex-box{display:flex}.flex-box.dir-column{flex-direction:column}.flex-box.dir-row{flex-direction:row}.flex-box .weight-1{flex:1}.flex-box .weight-2{flex:2}.flex-box .weight-3{flex:3}.flex-box .weight-4{flex:4}.flex-box .weight-5{flex:5}.flex-box .weight-6{flex:6}.flex-box .weight-7{flex:7}.flex-box .weight-8{flex:8}.flex-box .weight-9{flex:9}.flex-box .weight-10{flex:10}.flex-box .weight-11{flex:11}.flex-box .weight-12{flex:12}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef, decorators: [{ type: Inject, args: [ElementRef] }] }]; }, propDecorators: { pickerGroupLayer: [{ type: ViewChildren, args: ['pickerGroupLayer'] }], pickerHandleLayer: [{ type: ViewChild, args: ['pickerHandleLayer'] }], data: [{ type: Input }], change: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctc2Nyb2xsLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1zY3JvbGwtcGlja2VyL3NyYy9saWIvbmctc2Nyb2xsLXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUlMLE1BQU0sRUFDTixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBQ1osVUFBVSxFQUNWLFNBQVMsRUFDVCxZQUFZLEdBQ2IsTUFBTSxlQUFlLENBQUM7OztBQW1MdkIsTUFBTSxPQUFPLHVCQUF1QjtJQTZCbEMsWUFBZ0MsVUFBc0I7UUF2QjdDLFNBQUksR0FBc0IsRUFBRSxDQUFDO1FBQzVCLFdBQU0sR0FDZCxJQUFJLFlBQVksRUFBdUIsQ0FBQztRQUsxQyxpQkFBWSxHQUFHO1lBQ2IsV0FBVyxFQUFFLGNBQWMsSUFBSSxNQUFNO1lBQ3JDLFdBQVcsRUFBRSxLQUFLO1NBQ25CLENBQUM7UUFDRixpQkFBWSxHQUFHO1lBQ2IsVUFBVSxFQUFFLEtBQUs7WUFDakIsVUFBVSxFQUFFLElBQUk7WUFDaEIsVUFBVSxFQUFFLElBQUk7U0FLakIsQ0FBQztRQUNGLGtCQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ25CLG9CQUFlLEdBQVEsSUFBSSxDQUFDO0lBRTZCLENBQUM7SUFFMUQsUUFBUTtRQUNOLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUMxRCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQyxNQUFNLENBQ3BELElBQUksQ0FBQyxnQkFBZ0IsQ0FDdEIsQ0FBQztRQUVGLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQyxjQUFj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ZXJWaWV3SW5pdCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgSW5qZWN0LFxyXG4gIENvbXBvbmVudCxcclxuICBJbnB1dCxcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgVmlld0NoaWxkLFxyXG4gIFZpZXdDaGlsZHJlbixcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7IFBpY2tlckRhdGFNb2RlbCwgUGlja2VyUmVzcG9uc2VNb2RlbCB9IGZyb20gJy4vbmctc2Nyb2xsLWRhdGEubW9kZWwnO1xyXG5leHBvcnQgeyBQaWNrZXJEYXRhTW9kZWwsIFBpY2tlclJlc3BvbnNlTW9kZWwgfTtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmctc2Nyb2xsLXBpY2tlcicsXHJcbiAgdGVtcGxhdGU6IGBcclxuICAgIDxkaXYgY2xhc3M9XCJuZy1kYXRhLXBpY2tlciBmbGV4LWJveFwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicGlja2VyLWhhbmRsZS1sYXllciBmbGV4LWJveCBkaXItY29sdW1uXCI+XHJcbiAgICAgICAgPGRpdiBkYXRhLXR5cGU9XCJ0b3BcIiBjbGFzcz1cInBpY2tlci10b3Agd2VpZ2h0LTFcIj48L2Rpdj5cclxuICAgICAgICA8ZGl2IGRhdGEtdHlwZT1cIm1pZGRsZVwiIGNsYXNzPVwicGlja2VyLW1pZGRsZSB0ZW5nYWhcIj48L2Rpdj5cclxuICAgICAgICA8ZGl2IGRhdGEtdHlwZT1cImJvdHRvbVwiIGNsYXNzPVwicGlja2VyLWJvdHRvbSB3ZWlnaHQtMVwiPjwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDxkaXZcclxuICAgICAgICAjcGlja2VyR3JvdXBMYXllclxyXG4gICAgICAgICpuZ0Zvcj1cImxldCBncm91cCBvZiBkYXRhOyBsZXQgZ0luZGV4ID0gaW5kZXhcIlxyXG4gICAgICAgIGNsYXNzPVwicGlja2VyLWdyb3VwXCJcclxuICAgICAgICBbbmdDbGFzc109XCJnZXRHcm91cENsYXNzKGdJbmRleClcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInBpY2tlci1saXN0XCI+XHJcbiAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICpuZ0lmPVwiZ3JvdXAuZGl2aWRlcjsgZWxzZSBuZ0lmRWxzZVwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwicGlja2VyLWl0ZW0gZGl2aWRlclwiXHJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cImdldEl0ZW1DbGFzcyhnSW5kZXgsIGdJbmRleCwgdHJ1ZSlcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICB7eyBncm91cC50ZXh0IH19XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8bmctdGVtcGxhdGUgI25nSWZFbHNlPlxyXG4gICAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgI25nSWZFbHNlXHJcbiAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZ3JvdXAubGlzdDsgbGV0IGlJbmRleCA9IGluZGV4XCJcclxuICAgICAgICAgICAgICBjbGFzcz1cInBpY2tlci1pdGVtXCJcclxuICAgICAgICAgICAgICBbbmdDbGFzc109XCJnZXRJdGVtQ2xhc3MoZ0luZGV4LCBpSW5kZXgpXCJcclxuICAgICAgICAgICAgICBbbmdTdHlsZV09XCJnZXRJdGVtU3R5bGUoZ0luZGV4LCBpSW5kZXgpXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIHt7IGl0ZW0ubGFiZWwgfX1cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDxkaXYgI3BpY2tlckhhbmRsZUxheWVyIGNsYXNzPVwicGlja2VyLWhhbmRsZS1sYXllciBmbGV4LWJveCBkaXItY29sdW1uXCI+XHJcbiAgICAgICAgPGRpdiBkYXRhLXR5cGU9XCJ0b3BcIiBjbGFzcz1cInBpY2tlci10b3Agd2VpZ2h0LTFcIj48L2Rpdj5cclxuICAgICAgICA8ZGl2IGRhdGEtdHlwZT1cIm1pZGRsZVwiIGNsYXNzPVwicGlja2VyLW1pZGRsZVwiPjwvZGl2PlxyXG4gICAgICAgIDxkaXYgZGF0YS10eXBlPVwiYm90dG9tXCIgY2xhc3M9XCJwaWNrZXItYm90dG9tIHdlaWdodC0xXCI+PC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgYCxcclxuICBzdHlsZXM6IFtcclxuICAgIGBcclxuICAgICAgLm5nLWRhdGEtcGlja2VyIHtcclxuICAgICAgICBmb250LXNpemU6IDFyZW07XHJcbiAgICAgICAgaGVpZ2h0OiAxMGVtO1xyXG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTtcclxuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICB9XHJcbiAgICAgIC5uZy1kYXRhLXBpY2tlci5ibGFjayB7XHJcbiAgICAgICAgY29sb3I6IHdoaXRlO1xyXG4gICAgICB9XHJcbiAgICAgIC5uZy1kYXRhLXBpY2tlciAucGlja2VyLWdyb3VwIHtcclxuICAgICAgfVxyXG4gICAgICAubmctZGF0YS1waWNrZXIgLnBpY2tlci1saXN0IHtcclxuICAgICAgICBoZWlnaHQ6IDYuMjVlbTtcclxuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICAgICAgdG9wOiA0ZW07XHJcbiAgICAgIH1cclxuICAgICAgLm5nLWRhdGEtcGlja2VyIC5waWNrZXItaXRlbSB7XHJcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgIHRvcDogMDtcclxuICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XHJcbiAgICAgICAgd2lsbC1jaGFuZ2U6IHRyYW5zZm9ybTtcclxuICAgICAgICBjb250YWluOiBzdHJpY3Q7XHJcbiAgICAgICAgaGVpZ2h0OiAyZW07XHJcbiAgICAgICAgbGluZS1oZWlnaHQ6IDI7XHJcbiAgICAgICAgZm9udC1zaXplOiAxZW07XHJcbiAgICAgIH1cclxuICAgICAgLm5nLWRhdGEtcGlja2VyIC5zZWxlY3RlZC1pdGVtIHtcclxuICAgICAgfVxyXG5cclxuICAgICAgLyogcGlja2VyIGhhbmRsZSBsYXllciAqL1xyXG4gICAgICAubmctZGF0YS1waWNrZXIgLnBpY2tlci1oYW5kbGUtbGF5ZXIge1xyXG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgICBoZWlnaHQ6IGNhbGMoMTAwJSArIDJweCk7XHJcbiAgICAgICAgbGVmdDogMDtcclxuICAgICAgICByaWdodDogMDtcclxuICAgICAgICB0b3A6IC0xcHg7XHJcbiAgICAgICAgYm90dG9tOiAtMXB4O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZy1kYXRhLXBpY2tlciAucGlja2VyLWhhbmRsZS1sYXllciAucGlja2VyLXRvcCB7XHJcbiAgICAgICAgLyogYm9yZGVyLWJvdHRvbTogMC41NXB4IHNvbGlkIHJnYmEoNzQsIDczLCA4OSwgMC41KTsgKi9cclxuICAgICAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoXHJcbiAgICAgICAgICB0byBib3R0b20sXHJcbiAgICAgICAgICB3aGl0ZSAyJSxcclxuICAgICAgICAgIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4xKSAxMDAlXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDUuNjI1ZW0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAubmctZGF0YS1waWNrZXIgLnBpY2tlci1oYW5kbGUtbGF5ZXIgLnBpY2tlci1taWRkbGUge1xyXG4gICAgICAgIGhlaWdodDogMmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAudGVuZ2FoIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyMCwgMjIwLCAyMjAsIDEpO1xyXG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDVweDtcclxuICAgICAgfVxyXG5cclxuICAgICAgLm5nLWRhdGEtcGlja2VyIC5waWNrZXItaGFuZGxlLWxheWVyIC5waWNrZXItYm90dG9tIHtcclxuICAgICAgICAvKiBib3JkZXItdG9wOiAwLjU1cHggc29saWQgcmdiYSg3NCwgNzMsIDg5LCAwLjUpOyAqL1xyXG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudChcclxuICAgICAgICAgIHRvIHRvcCxcclxuICAgICAgICAgIHdoaXRlIDIlLFxyXG4gICAgICAgICAgcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjEpIDEwMCVcclxuICAgICAgICApO1xyXG4gICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMCwgNS42MjVlbSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8qIGZsZXggc3lzdGVtICovXHJcbiAgICAgIC5mbGV4LWJveCB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgfVxyXG4gICAgICAuZmxleC1ib3guZGlyLWNvbHVtbiB7XHJcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgfVxyXG4gICAgICAuZmxleC1ib3guZGlyLXJvdyB7XHJcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IHJvdztcclxuICAgICAgfVxyXG5cclxuICAgICAgLyogZmxleCBzeXN0ZW0gLSBmb3IgaXRlbXMgKi9cclxuICAgICAgLmZsZXgtYm94IC53ZWlnaHQtMSB7XHJcbiAgICAgICAgZmxleDogMTtcclxuICAgICAgfVxyXG4gICAgICAuZmxleC1ib3ggLndlaWdodC0yIHtcclxuICAgICAgICBmbGV4OiAyO1xyXG4gICAgICB9XHJcbiAgICAgIC5mbGV4LWJveCAud2VpZ2h0LTMge1xyXG4gICAgICAgIGZsZXg6IDM7XHJcbiAgICAgIH1cclxuICAgICAgLmZsZXgtYm94IC53ZWlnaHQtNCB7XHJcbiAgICAgICAgZmxleDogNDtcclxuICAgICAgfVxyXG4gICAgICAuZmxleC1ib3ggLndlaWdodC01IHtcclxuICAgICAgICBmbGV4OiA1O1xyXG4gICAgICB9XHJcbiAgICAgIC5mbGV4LWJveCAud2VpZ2h0LTYge1xyXG4gICAgICAgIGZsZXg6IDY7XHJcbiAgICAgIH1cclxuICAgICAgLmZsZXgtYm94IC53ZWlnaHQtNyB7XHJcbiAgICAgICAgZmxleDogNztcclxuICAgICAgfVxyXG4gICAgICAuZmxleC1ib3ggLndlaWdodC04IHtcclxuICAgICAgICBmbGV4OiA4O1xyXG4gICAgICB9XHJcbiAgICAgIC5mbGV4LWJveCAud2VpZ2h0LTkge1xyXG4gICAgICAgIGZsZXg6IDk7XHJcbiAgICAgIH1cclxuICAgICAgLmZsZXgtYm94IC53ZWlnaHQtMTAge1xyXG4gICAgICAgIGZsZXg6IDEwO1xyXG4gICAgICB9XHJcbiAgICAgIC5mbGV4LWJveCAud2VpZ2h0LTExIHtcclxuICAgICAgICBmbGV4OiAxMTtcclxuICAgICAgfVxyXG4gICAgICAuZmxleC1ib3ggLndlaWdodC0xMiB7XHJcbiAgICAgICAgZmxleDogMTI7XHJcbiAgICAgIH1cclxuICAgIGAsXHJcbiAgXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIE5nU2Nyb2xsUGlja2VyQ29tcG9uZW50XHJcbiAgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveVxyXG57XHJcbiAgQFZpZXdDaGlsZHJlbigncGlja2VyR3JvdXBMYXllcicpIHBpY2tlckdyb3VwTGF5ZXI6IGFueTtcclxuICBAVmlld0NoaWxkKCdwaWNrZXJIYW5kbGVMYXllcicpIHBpY2tlckhhbmRsZUxheWVyOiBhbnk7XHJcblxyXG4gIEBJbnB1dCgpIGRhdGE6IFBpY2tlckRhdGFNb2RlbFtdID0gW107XHJcbiAgQE91dHB1dCgpIGNoYW5nZTogRXZlbnRFbWl0dGVyPFBpY2tlclJlc3BvbnNlTW9kZWw+ID1cclxuICAgIG5ldyBFdmVudEVtaXR0ZXI8UGlja2VyUmVzcG9uc2VNb2RlbD4oKTtcclxuXHJcbiAgY3VycmVudEluZGV4TGlzdCE6IG51bWJlcltdO1xyXG4gIGxhc3RDdXJyZW50SW5kZXhMaXN0ITogbnVtYmVyW107XHJcbiAgZ3JvdXBzUmVjdExpc3QhOiBhbnlbXTtcclxuICB0b3VjaE9yTW91c2UgPSB7XHJcbiAgICBpc1RvdWNoYWJsZTogJ29udG91Y2hzdGFydCcgaW4gd2luZG93LFxyXG4gICAgaXNNb3VzZURvd246IGZhbHNlLFxyXG4gIH07XHJcbiAgZHJhZ2dpbmdJbmZvID0ge1xyXG4gICAgaXNEcmFnZ2luZzogZmFsc2UsXHJcbiAgICBncm91cEluZGV4OiBudWxsLFxyXG4gICAgc3RhcnRQYWdlWTogbnVsbCxcclxuICB9IGFzIHtcclxuICAgIGlzRHJhZ2dpbmc6IGJvb2xlYW47XHJcbiAgICBncm91cEluZGV4OiBudW1iZXIgfCBudWxsO1xyXG4gICAgc3RhcnRQYWdlWTogbnVtYmVyIHwgbnVsbDtcclxuICB9O1xyXG4gIGl0ZW1QZXJEZWdyZWUgPSAyMztcclxuICBzYWZlRG9UaW1lb3V0SWQ6IGFueSA9IG51bGw7XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoRWxlbWVudFJlZikgZWxlbWVudFJlZjogRWxlbWVudFJlZikge31cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLmN1cnJlbnRJbmRleExpc3QgPSB0aGlzLmdldEluaXRpYWxDdXJyZW50SW5kZXhMaXN0KCk7XHJcbiAgICB0aGlzLmxhc3RDdXJyZW50SW5kZXhMaXN0ID0gbmV3IEFycmF5PG51bWJlcj4oKS5jb25jYXQoXHJcbiAgICAgIHRoaXMuY3VycmVudEluZGV4TGlzdFxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLmdyb3Vwc1JlY3RMaXN0ID0gbmV3IEFycmF5KHRoaXMuZGF0YS5sZW5ndGgpO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgdGhpcy5ldmVudHNSZWdpc3RlcigpO1xyXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuc2FmZUdldFJlY3RzQmluZEV2ZW50cy5iaW5kKHRoaXMpKTtcclxuICAgIHRoaXMuZ2V0R3JvdXBzUmVjdExpc3QoKTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICdyZXNpemUnLFxyXG4gICAgICB0aGlzLnNhZmVHZXRSZWN0c0JpbmRFdmVudHMuYmluZCh0aGlzKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHNldEdyb3VwRGF0YShnSW5kZXg6IG51bWJlciwgZ3JvdXBEYXRhOiBQaWNrZXJEYXRhTW9kZWwpIHtcclxuICAgIGlmICghdGhpcy5jdXJyZW50SW5kZXhMaXN0KSB7XHJcbiAgICAgIHRoaXMuY3VycmVudEluZGV4TGlzdCA9IHRoaXMuZ2V0SW5pdGlhbEN1cnJlbnRJbmRleExpc3QoKTtcclxuICAgIH1cclxuICAgIHRoaXMuZGF0YVtnSW5kZXhdID0gZ3JvdXBEYXRhO1xyXG4gICAgY29uc3QgaUNJID0gZ3JvdXBEYXRhLmN1cnJlbnRJbmRleDtcclxuICAgIGxldCBtb3ZlZEluZGV4ID0gMDtcclxuICAgIGlmIChcclxuICAgICAgdHlwZW9mIGlDSSA9PT0gJ251bWJlcicgJiZcclxuICAgICAgaUNJID49IDAgJiZcclxuICAgICAgZ3JvdXBEYXRhLmxpc3QgJiZcclxuICAgICAgZ3JvdXBEYXRhLmxpc3QubGVuZ3RoICYmXHJcbiAgICAgIGlDSSA8PSBncm91cERhdGEubGlzdC5sZW5ndGggLSAxXHJcbiAgICApIHtcclxuICAgICAgbW92ZWRJbmRleCA9IE1hdGgucm91bmQoaUNJKTtcclxuICAgIH1cclxuICAgIHRoaXMuY3VycmVudEluZGV4TGlzdFtnSW5kZXhdID0gbW92ZWRJbmRleDtcclxuICAgIHRoaXMubGFzdEN1cnJlbnRJbmRleExpc3QgPSBuZXcgQXJyYXk8bnVtYmVyPigpLmNvbmNhdChcclxuICAgICAgdGhpcy5jdXJyZW50SW5kZXhMaXN0XHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgZ2V0SW5pdGlhbEN1cnJlbnRJbmRleExpc3QoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5kYXRhLm1hcCgoaXRlbSwgaW5kZXgpID0+IHtcclxuICAgICAgY29uc3QgaUNJID0gaXRlbS5jdXJyZW50SW5kZXg7XHJcbiAgICAgIGlmIChcclxuICAgICAgICB0eXBlb2YgaUNJID09PSAnbnVtYmVyJyAmJlxyXG4gICAgICAgIGlDSSA+PSAwICYmXHJcbiAgICAgICAgaXRlbS5saXN0ICYmXHJcbiAgICAgICAgaXRlbS5saXN0Lmxlbmd0aCAmJlxyXG4gICAgICAgIGlDSSA8PSBpdGVtLmxpc3QubGVuZ3RoIC0gMVxyXG4gICAgICApIHtcclxuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChpQ0kpO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiAwO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzYWZlR2V0UmVjdHNCaW5kRXZlbnRzKCkge1xyXG4gICAgaWYgKHRoaXMuc2FmZURvVGltZW91dElkKSB7XHJcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnNhZmVEb1RpbWVvdXRJZCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnNhZmVEb1RpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLmdldEdyb3Vwc1JlY3RMaXN0KCk7XHJcbiAgICB9LCAyMDApO1xyXG4gIH1cclxuXHJcbiAgZ2V0R3JvdXBzUmVjdExpc3QoKSB7XHJcbiAgICBpZiAodGhpcy5waWNrZXJHcm91cExheWVyKSB7XHJcbiAgICAgIHRoaXMucGlja2VyR3JvdXBMYXllci50b0FycmF5KCkuZm9yRWFjaCgoaXRlbTogYW55LCBpbmRleDogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgdGhpcy5ncm91cHNSZWN0TGlzdFtpbmRleF0gPSBpdGVtLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZXZlbnRzUmVnaXN0ZXIoKSB7XHJcbiAgICBjb25zdCBoYW5kbGVFdmVudExheWVyID0gdGhpcy5waWNrZXJIYW5kbGVMYXllci5uYXRpdmVFbGVtZW50O1xyXG4gICAgaWYgKGhhbmRsZUV2ZW50TGF5ZXIpIHtcclxuICAgICAgdGhpcy5hZGRFdmVudHNGb3JFbGVtZW50KGhhbmRsZUV2ZW50TGF5ZXIpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYWRkRXZlbnRzRm9yRWxlbWVudChlbDogYW55KSB7XHJcbiAgICBjb25zdCBfID0gdGhpcy50b3VjaE9yTW91c2UuaXNUb3VjaGFibGU7XHJcbiAgICBjb25zdCBldmVudEhhbmRsZXJMaXN0ID0gW1xyXG4gICAgICB7IG5hbWU6IF8gPyAndG91Y2hzdGFydCcgOiAnbW91c2Vkb3duJywgaGFuZGxlcjogdGhpcy5oYW5kbGVTdGFydCB9LFxyXG4gICAgICB7IG5hbWU6IF8gPyAndG91Y2htb3ZlJyA6ICdtb3VzZW1vdmUnLCBoYW5kbGVyOiB0aGlzLmhhbmRsZU1vdmUgfSxcclxuICAgICAgeyBuYW1lOiBfID8gJ3RvdWNoZW5kJyA6ICdtb3VzZXVwJywgaGFuZGxlcjogdGhpcy5oYW5kbGVFbmQgfSxcclxuICAgICAgeyBuYW1lOiBfID8gJ3RvdWNoY2FuY2VsJyA6ICdtb3VzZWxlYXZlJywgaGFuZGxlcjogdGhpcy5oYW5kbGVDYW5jZWwgfSxcclxuICAgICAgeyBuYW1lOiAnd2hlZWwnLCBoYW5kbGVyOiB0aGlzLmhhbmRsZVNjcm9sbCB9LFxyXG4gICAgXTtcclxuICAgIGV2ZW50SGFuZGxlckxpc3QuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IHtcclxuICAgICAgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihpdGVtLm5hbWUsIGl0ZW0uaGFuZGxlciwgZmFsc2UpO1xyXG4gICAgICBlbC5hZGRFdmVudExpc3RlbmVyKGl0ZW0ubmFtZSwgaXRlbS5oYW5kbGVyLmJpbmQodGhpcyksIGZhbHNlKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgdHJpZ2dlck1pZGRsZUxheWVyR3JvdXBDbGljayhnSW5kZXg6IGFueSkge1xyXG4gICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTtcclxuICAgIGlmIChkYXRhW2dJbmRleF0ub25DbGljayAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIGNvbnN0IGNsaWNrID0gZGF0YVtnSW5kZXhdLm9uQ2xpY2sgYXMgRnVuY3Rpb247XHJcbiAgICAgIGlmIChcclxuICAgICAgICB0eXBlb2YgZ0luZGV4ID09PSAnbnVtYmVyJyAmJlxyXG4gICAgICAgIHR5cGVvZiBkYXRhW2dJbmRleF0ub25DbGljayA9PT0gJ2Z1bmN0aW9uJ1xyXG4gICAgICApIHtcclxuICAgICAgICAvLyBjbGljayhcclxuICAgICAgICAvLyAgIGdJbmRleCxcclxuICAgICAgICAvLyAgIHRoaXMuY3VycmVudEluZGV4TGlzdFtnSW5kZXhdLFxyXG4gICAgICAgIC8vICAgdGhpcy5kYXRhW2dJbmRleF0ubGlzdFt0aGlzLmN1cnJlbnRJbmRleExpc3RbZ0luZGV4XV1cclxuICAgICAgICAvLyApO1xyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlOiBQaWNrZXJSZXNwb25zZU1vZGVsID0ge1xyXG4gICAgICAgICAgZ0luZGV4LFxyXG4gICAgICAgICAgaUluZGV4OiB0aGlzLmN1cnJlbnRJbmRleExpc3RbZ0luZGV4XSxcclxuICAgICAgICAgIHNlbGVjdGVkVmFsdWU6IHRoaXMuZGF0YVtnSW5kZXhdLmxpc3RbdGhpcy5jdXJyZW50SW5kZXhMaXN0W2dJbmRleF1dLFxyXG4gICAgICAgICAgZ3JvdXBOYW1lOiB0aGlzLmRhdGFbZ0luZGV4XS5ncm91cE5hbWUsXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjbGljayhyZXNwb25zZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHRyaWdnZXJBYm92ZUxheWVyQ2xpY2soZXY6IGFueSwgZ0luZGV4OiBhbnkpIHtcclxuICAgIGNvbnN0IG1vdmVkSW5kZXggPSB0aGlzLmN1cnJlbnRJbmRleExpc3RbZ0luZGV4XSArIDE7XHJcbiAgICB0aGlzLmN1cnJlbnRJbmRleExpc3RbZ0luZGV4XSA9IG1vdmVkSW5kZXg7XHJcbiAgICB0aGlzLmNvcnJlY3Rpb25DdXJyZW50SW5kZXgoZXYsIGdJbmRleCk7XHJcbiAgfVxyXG5cclxuICB0cmlnZ2VyTWlkZGxlTGF5ZXJDbGljayhldjogYW55LCBnSW5kZXg6IGFueSkge1xyXG4gICAgdGhpcy50cmlnZ2VyTWlkZGxlTGF5ZXJHcm91cENsaWNrKGdJbmRleCk7XHJcbiAgfVxyXG5cclxuICB0cmlnZ2VyQmVsb3dMYXllckNsaWNrKGV2OiBhbnksIGdJbmRleDogYW55KSB7XHJcbiAgICBjb25zdCBtb3ZlZEluZGV4ID0gdGhpcy5jdXJyZW50SW5kZXhMaXN0W2dJbmRleF0gLSAxO1x