igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
576 lines • 55.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { ChangeDetectorRef, Component, ContentChild, ElementRef, forwardRef, Inject, QueryList, ContentChildren } from '@angular/core';
import { takeUntil, take } from 'rxjs/operators';
import { IgxForOfDirective } from '../directives/for-of/for_of.directive';
import { IGX_COMBO_COMPONENT } from './combo.common';
import { Navigate } from '../drop-down/drop-down.common';
import { IGX_DROPDOWN_BASE } from '../drop-down/drop-down.common';
import { IgxDropDownComponent } from '../drop-down/drop-down.component';
import { DropDownActionKey } from '../drop-down/drop-down.common';
import { IgxComboAddItemComponent } from './combo-add-item.component';
import { IgxComboAPIService } from './combo.api';
import { IgxSelectionAPIService } from '../core/selection';
import { IgxComboItemComponent } from './combo-item.component';
/**
* @hidden
*/
export class IgxComboDropDownComponent extends IgxDropDownComponent {
/**
* @param {?} elementRef
* @param {?} cdr
* @param {?} selection
* @param {?} combo
* @param {?} comboAPI
*/
constructor(elementRef, cdr, selection, combo, comboAPI) {
super(elementRef, cdr, selection);
this.elementRef = elementRef;
this.cdr = cdr;
this.selection = selection;
this.combo = combo;
this.comboAPI = comboAPI;
this._scrollPosition = 0;
/**
* @hidden
* \@internal
*/
this.children = null;
this.scrollHandler = () => {
this.comboAPI.disableTransitions = true;
};
}
/**
* @protected
* @return {?}
*/
get scrollContainer() {
return this.verticalScrollContainer.dc.location.nativeElement;
}
/**
* @protected
* @return {?}
*/
get isScrolledToLast() {
/** @type {?} */
const scrollTop = this.verticalScrollContainer.getVerticalScroll().scrollTop;
/** @type {?} */
const scrollHeight = this.verticalScrollContainer.getVerticalScroll().scrollHeight;
return Math.floor(scrollTop + this.verticalScrollContainer.igxForContainerSize) === scrollHeight;
}
/**
* @protected
* @return {?}
*/
get lastVisibleIndex() {
return this.combo.totalItemCount ?
Math.floor(this.combo.itemsMaxHeight / this.combo.itemHeight) :
this.items.length - 1;
}
/**
* @hidden \@internal
* @return {?}
*/
onFocus() {
this._focusedItem = this._focusedItem || this.items[0];
if (this._focusedItem) {
this._focusedItem.focused = true;
}
}
/**
* @hidden \@internal
* @param {?=} evt
* @return {?}
*/
onBlur(evt) {
if (this._focusedItem) {
this._focusedItem.focused = false;
this._focusedItem = null;
}
}
/**
* @hidden \@internal
* @return {?}
*/
onToggleOpened() {
this.onOpened.emit();
}
/**
* @hidden
* @return {?}
*/
navigatePrev() {
if (this._focusedItem.itemIndex === 0 && this.verticalScrollContainer.state.startIndex === 0) {
this.combo.focusSearchInput(false);
}
else {
super.navigatePrev();
}
}
/**
* @hidden \@internal
* @return {?}
*/
navigateFirst() {
/** @type {?} */
const vContainer = this.verticalScrollContainer;
if (vContainer.state.startIndex === 0) {
super.navigateItem(0);
return;
}
vContainer.scrollTo(0);
this.subscribeNext(vContainer, () => {
this.combo.triggerCheck();
super.navigateItem(0);
this.combo.triggerCheck();
});
}
/**
* @hidden \@internal
* @return {?}
*/
navigateLast() {
/** @type {?} */
const vContainer = this.verticalScrollContainer;
/** @type {?} */
const scrollTarget = this.combo.totalItemCount ?
this.combo.totalItemCount - 1 :
Math.max(this.combo.data.length - 1, vContainer.igxForOf.length - 1);
if (vContainer.igxForOf.length <= vContainer.state.startIndex + vContainer.state.chunkSize) {
super.navigateItem(this.items.length - 1);
return;
}
vContainer.scrollTo(scrollTarget);
this.subscribeNext(vContainer, () => {
this.combo.triggerCheck();
super.navigateItem(this.items.length - 1);
this.combo.triggerCheck();
});
}
/**
* @private
* @param {?} direction
* @return {?}
*/
navigateRemoteItem(direction) {
/** @type {?} */
const vContainer = this.verticalScrollContainer;
vContainer.addScrollTop(direction * this.combo.itemHeight);
this.subscribeNext(vContainer, () => {
if (direction === Navigate.Up) {
super.navigateItem(0);
}
else {
super.navigateItem(this.focusedItem.itemIndex);
}
});
}
/**
* @hidden \@internal
* @param {?} item
* @return {?}
*/
selectItem(item) {
if (item === null || item === undefined) {
return;
}
this.comboAPI.set_selected_item(item.itemID);
this._focusedItem = item;
}
/**
* @private
* @param {?=} newIndex
* @return {?}
*/
navigateDown(newIndex) {
/** @type {?} */
const vContainer = this.verticalScrollContainer;
/** @type {?} */
const allData = vContainer.igxForOf;
/** @type {?} */
const extraScroll = this.combo.isAddButtonVisible() ? 1 : 0;
/** @type {?} */
const focusedItem = this.focusedItem;
/** @type {?} */
const items = this.items;
/** @type {?} */
const children = this.sortedChildren;
if (focusedItem) {
if (this.isAddItemFocused()) {
return;
}
if (focusedItem.value === allData[allData.length - 1]) {
this.focusAddItemButton();
return;
}
}
/** @type {?} */
let targetDataIndex = newIndex === -1 ? this.itemIndexInData(this.focusedItem.itemIndex) + 1 : this.itemIndexInData(newIndex);
/** @type {?} */
const lastLoadedIndex = vContainer.state.startIndex + vContainer.state.chunkSize - 1;
if (targetDataIndex < lastLoadedIndex) { // If no scroll is required
if (newIndex !== -1 || newIndex === children.length - 1 - extraScroll) { // Use normal nav for visible items
super.navigateItem(newIndex);
}
}
else if (this.isScrolledToLast && targetDataIndex === lastLoadedIndex) { // If already at bottom and target is last item
super.navigateItem(items.length - 1 - extraScroll); // Focus the last item (excluding Add Button)
}
else { // If scroll is required
// If scroll is required
// If item is header, find next non-header index
/** @type {?} */
const addedIndex = allData[targetDataIndex].isHeader ? this.findNextFocusableItem(targetDataIndex, Navigate.Down, allData) : 0;
targetDataIndex += addedIndex; // Add steps to the target index
if (addedIndex === -1) { // If there are no more non-header items & add button is visible
this.focusAddItemButton();
}
else if (targetDataIndex === allData.length - 1 && !this.isScrolledToLast) {
// If target is very last loaded item, but scroll is not at the bottom (item is in DOM but not visible)
vContainer.scrollTo(targetDataIndex); // This will not trigger `onChunkLoad`
super.navigateItem(items.length - 1 - extraScroll); // Target last item (excluding Add Button)
}
else { // Perform virtual scroll
this.subscribeNext(vContainer, () => {
// children = all items in the DD (including addItemButton)
// length - 2 instead of -1, because we do not want to focus the last loaded item (in DOM, but not visible)
// Focus last item (excluding Add Button)
super.navigateItem(!addedIndex ? children[children.length - 1 - extraScroll].itemIndex : this.items.length - 2);
});
vContainer.scrollTo(targetDataIndex); // Perform virtual scroll
}
}
}
/**
* @private
* @param {?=} newIndex
* @return {?}
*/
navigateUp(newIndex) {
/** @type {?} */
const vContainer = this.verticalScrollContainer;
/** @type {?} */
const allData = vContainer.igxForOf;
/** @type {?} */
const focusedItem = this.focusedItem;
if (focusedItem.value === allData.find(e => !e.isHeader && !e.hidden)) { // If this is the very first non-header item
this.focusComboSearch(); // Focus combo search
return;
}
/** @type {?} */
let targetDataIndex = newIndex === -1 ? this.itemIndexInData(focusedItem.itemIndex) - 1 : this.itemIndexInData(newIndex);
if (newIndex !== -1) { // If no scroll is required
if (this.isScrolledToLast && targetDataIndex === vContainer.state.startIndex) {
// If virt scrollbar is @ bottom, first item is in DOM but not visible
vContainer.scrollTo(targetDataIndex); // This will not trigger `onChunkLoad`
super.navigateItem(0); // Focus first visible item
}
else {
super.navigateItem(newIndex); // Use normal navigation
}
}
else { // Perform virtual scroll
// Perform virtual scroll
// If item is header, find next non-header index
/** @type {?} */
const addedIndex = allData[targetDataIndex].isHeader ? this.findNextFocusableItem(targetDataIndex, Navigate.Up, allData) : 0;
targetDataIndex -= addedIndex; // Add steps to targetDataIndex
if (addedIndex === -1) { // If there is no non-header
vContainer.scrollTo(0);
this.focusComboSearch(); // Focus combo search;
}
else {
this.subscribeNext(vContainer, () => {
super.navigateItem(0); // Focus the first loaded item
});
vContainer.scrollTo(targetDataIndex); // Perform virtual scroll
}
}
}
/**
* @protected
* @param {?} direction
* @param {?=} currentIndex
* @return {?}
*/
navigate(direction, currentIndex) {
/** @type {?} */
let index = -1;
if (this._focusedItem) {
index = currentIndex ? currentIndex : this._focusedItem.itemIndex;
}
/** @type {?} */
const newIndex = this.getNearestSiblingFocusableItemIndex(index, direction);
/** @type {?} */
const vContainer = this.verticalScrollContainer;
/** @type {?} */
const notVirtual = vContainer.dc.instance.notVirtual;
if (notVirtual || !direction) { // If list has no scroll OR no direction is passed
super.navigateItem(newIndex); // use default scroll
}
else if (vContainer && vContainer.totalItemCount && vContainer.totalItemCount !== 0) { // Remote scroll
if (newIndex !== -1 &&
this.items[newIndex].isVisible(direction)) {
this.navigateItem(newIndex);
}
else {
this.navigateRemoteItem(direction);
}
}
else {
if (direction === Navigate.Up) { // Navigate UP
this.navigateUp(newIndex);
}
else if (direction === Navigate.Down) { // Navigate DOWN
this.navigateDown(newIndex);
}
}
}
/**
* @private
* @param {?} index
* @return {?}
*/
itemIndexInData(index) {
return this.sortedChildren.findIndex(e => e.itemIndex === index) + this.verticalScrollContainer.state.startIndex;
}
/**
* @private
* @param {?} indexInData
* @param {?} direction
* @param {?} data
* @return {?}
*/
findNextFocusableItem(indexInData, direction, data) {
if (direction === Navigate.Up) {
return [...data].splice(0, indexInData + 1).reverse().findIndex(e => !e.isHeader);
}
return [...data].splice(indexInData, data.length - 1).findIndex(e => !e.isHeader);
}
/**
* @private
* @return {?}
*/
focusComboSearch() {
this.combo.focusSearchInput(false);
if (this.focusedItem) {
this.focusedItem.focused = false;
}
this.focusedItem = null;
}
/**
* @private
* @return {?}
*/
focusAddItemButton() {
if (this.combo.isAddButtonVisible()) {
super.navigateItem(this.items.length - 1);
}
}
/**
* @private
* @param {?} virtualContainer
* @param {?} callback
* @return {?}
*/
subscribeNext(virtualContainer, callback) {
virtualContainer.onChunkLoad.pipe(take(1), takeUntil(this.destroy$)).subscribe({
next: (e) => {
callback(e);
}
});
}
/**
* @protected
* @param {?} newItem
* @return {?}
*/
scrollToHiddenItem(newItem) { }
/**
* @protected
* @return {?}
*/
get sortedChildren() {
if (this.children !== undefined) {
return this.children.toArray()
.sort((a, b) => {
return a.index - b.index;
});
}
return null;
}
/**
* Get all non-header items
*
* ```typescript
* let myDropDownItems = this.dropdown.items;
* ```
* @return {?}
*/
get items() {
/** @type {?} */
const items = [];
if (this.children !== undefined) {
/** @type {?} */
const sortedChildren = (/** @type {?} */ (this.sortedChildren));
for (const child of sortedChildren) {
if (!child.isHeader) {
items.push(child);
}
}
}
return items;
}
/**
* @protected
* @return {?}
*/
scrollToItem() {
}
/**
* @hidden \@internal
* @param {?} e
* @return {?}
*/
onToggleClosing(e) {
super.onToggleClosing(e);
this._scrollPosition = this.verticalScrollContainer.getVerticalScroll().scrollTop;
}
/**
* @hidden \@internal
* @return {?}
*/
updateScrollPosition() {
this.verticalScrollContainer.getVerticalScroll().scrollTop = this._scrollPosition;
}
/**
* @hidden \@internal
* @param {?} key
* @return {?}
*/
onItemActionKey(key) {
switch (key) {
case DropDownActionKey.ENTER:
this.handleEnter();
break;
case DropDownActionKey.SPACE:
this.handleSpace();
break;
case DropDownActionKey.ESCAPE:
this.close();
}
}
/**
* @private
* @return {?}
*/
handleEnter() {
if (this.isAddItemFocused()) {
this.combo.addItemToCollection();
}
else {
this.close();
}
}
/**
* @private
* @return {?}
*/
handleSpace() {
if (this.isAddItemFocused()) {
return;
}
else {
this.selectItem(this.focusedItem);
}
}
/**
* @private
* @return {?}
*/
isAddItemFocused() {
return this.focusedItem instanceof IgxComboAddItemComponent;
}
/**
* @return {?}
*/
ngAfterViewInit() {
this.verticalScrollContainer.getVerticalScroll().addEventListener('scroll', this.scrollHandler);
}
/**
* @hidden \@internal
* @return {?}
*/
ngOnDestroy() {
this.verticalScrollContainer.getVerticalScroll().removeEventListener('scroll', this.scrollHandler);
this.destroy$.next(true);
this.destroy$.complete();
}
}
IgxComboDropDownComponent.decorators = [
{ type: Component, args: [{
selector: 'igx-combo-drop-down',
template: "<div class=\"igx-drop-down__list\" igxToggle [style.width]=\"width\" [style.height]=\"height\"\n[style.maxHeight]=\"maxHeight\" [attr.id]=\"this.listId\" role=\"listbox\"\n (onOpening)=\"onToggleOpening($event)\" (onOpened)=\"onToggleOpened()\"\n (onClosing)=\"onToggleClosing($event)\" (onClosed)=\"onToggleClosed()\">\n <ng-container *ngIf=\"!collapsed\">\n <ng-content></ng-content>\n </ng-container>\n</div>\n",
providers: [{ provide: IGX_DROPDOWN_BASE, useExisting: IgxComboDropDownComponent }]
}] }
];
/** @nocollapse */
IgxComboDropDownComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: ChangeDetectorRef },
{ type: IgxSelectionAPIService },
{ type: undefined, decorators: [{ type: Inject, args: [IGX_COMBO_COMPONENT,] }] },
{ type: IgxComboAPIService }
];
IgxComboDropDownComponent.propDecorators = {
children: [{ type: ContentChildren, args: [IgxComboItemComponent, { descendants: true },] }],
verticalScrollContainer: [{ type: ContentChild, args: [forwardRef(() => IgxForOfDirective), { read: IgxForOfDirective },] }]
};
if (false) {
/**
* @type {?}
* @private
*/
IgxComboDropDownComponent.prototype._scrollPosition;
/**
* @hidden
* \@internal
* @type {?}
*/
IgxComboDropDownComponent.prototype.children;
/**
* @hidden \@internal
* @type {?}
*/
IgxComboDropDownComponent.prototype.verticalScrollContainer;
/**
* @type {?}
* @protected
*/
IgxComboDropDownComponent.prototype.scrollHandler;
/**
* @type {?}
* @protected
*/
IgxComboDropDownComponent.prototype.elementRef;
/**
* @type {?}
* @protected
*/
IgxComboDropDownComponent.prototype.cdr;
/**
* @type {?}
* @protected
*/
IgxComboDropDownComponent.prototype.selection;
/** @type {?} */
IgxComboDropDownComponent.prototype.combo;
/**
* @type {?}
* @protected
*/
IgxComboDropDownComponent.prototype.comboAPI;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm8tZHJvcGRvd24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9jb21iby9jb21iby1kcm9wZG93bi5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDSCxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBNEIsZUFBZSxFQUNuSSxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBRTFFLE9BQU8sRUFBZ0IsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDekQsT0FBTyxFQUFpQixpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7OztBQVEvRCxNQUFNLE9BQU8seUJBQTBCLFNBQVEsb0JBQW9COzs7Ozs7OztJQUMvRCxZQUNjLFVBQXNCLEVBQ3RCLEdBQXNCLEVBQ3RCLFNBQWlDLEVBQ1AsS0FBbUIsRUFDN0MsUUFBNEI7UUFDdEMsS0FB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QyxFQUFFLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFOzs7Ozs7O0lBWjlFLG9EQUE0Qjs7Ozs7O0lBTTVCLDZDQUN1RDs7Ozs7SUFLdkQsNERBQ3VEOzs7OztJQTZPdkQsa0RBRUM7Ozs7O0lBcFJHLCtDQUFnQzs7Ozs7SUFDaEMsd0NBQWdDOzs7OztJQUNoQyw4Q0FBMkM7O0lBQzNDLDBDQUF1RDs7Ozs7SUFDdkQsNkNBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBDb250ZW50Q2hpbGQsIEVsZW1lbnRSZWYsIGZvcndhcmRSZWYsIEluamVjdCwgUXVlcnlMaXN0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQsIENvbnRlbnRDaGlsZHJlblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbCwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElneEZvck9mRGlyZWN0aXZlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBDYW5jZWxhYmxlQnJvd3NlckV2ZW50QXJncyB9IGZyb20gJy4uL2NvcmUvdXRpbHMnO1xuaW1wb3J0IHsgSWd4Q29tYm9CYXNlLCBJR1hfQ09NQk9fQ09NUE9ORU5UIH0gZnJvbSAnLi9jb21iby5jb21tb24nO1xuaW1wb3J0IHsgTmF2aWdhdGUgfSBmcm9tICcuLi9kcm9wLWRvd24vZHJvcC1kb3duLmNvbW1vbic7XG5pbXBvcnQgeyBJRHJvcERvd25CYXNlLCBJR1hfRFJPUERPV05fQkFTRSB9IGZyb20gJy4uL2Ryb3AtZG93bi9kcm9wLWRvd24uY29tbW9uJztcbmltcG9ydCB7IElneERyb3BEb3duQ29tcG9uZW50IH0gZnJvbSAnLi4vZHJvcC1kb3duL2Ryb3AtZG93bi5jb21wb25lbnQnO1xuaW1wb3J0IHsgRHJvcERvd25BY3Rpb25LZXkgfSBmcm9tICcuLi9kcm9wLWRvd24vZHJvcC1kb3duLmNvbW1vbic7XG5pbXBvcnQgeyBJZ3hDb21ib0FkZEl0ZW1Db21wb25lbnQgfSBmcm9tICcuL2NvbWJvLWFkZC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hDb21ib0FQSVNlcnZpY2UgfSBmcm9tICcuL2NvbWJvLmFwaSc7XG5pbXBvcnQgeyBJZ3hEcm9wRG93bkl0ZW1CYXNlIH0gZnJvbSAnLi4vZHJvcC1kb3duL2Ryb3AtZG93bi1pdGVtLmJhc2UnO1xuaW1wb3J0IHsgSWd4U2VsZWN0aW9uQVBJU2VydmljZSB9IGZyb20gJy4uL2NvcmUvc2VsZWN0aW9uJztcbmltcG9ydCB7IElneENvbWJvSXRlbUNvbXBvbmVudCB9IGZyb20gJy4vY29tYm8taXRlbS5jb21wb25lbnQnO1xuXG4vKiogQGhpZGRlbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdpZ3gtY29tYm8tZHJvcC1kb3duJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4uL2Ryb3AtZG93bi9kcm9wLWRvd24uY29tcG9uZW50Lmh0bWwnLFxuICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogSUdYX0RST1BET1dOX0JBU0UsIHVzZUV4aXN0aW5nOiBJZ3hDb21ib0Ryb3BEb3duQ29tcG9uZW50IH1dXG59KVxuZXhwb3J0IGNsYXNzIElneENvbWJvRHJvcERvd25Db21wb25lbnQgZXh0ZW5kcyBJZ3hEcm9wRG93bkNvbXBvbmVudCBpbXBsZW1lbnRzIElEcm9wRG93bkJhc2UsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdCB7XG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByb3RlY3RlZCBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICBwcm90ZWN0ZWQgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHJvdGVjdGVkIHNlbGVjdGlvbjogSWd4U2VsZWN0aW9uQVBJU2VydmljZSxcbiAgICAgICAgQEluamVjdChJR1hfQ09NQk9fQ09NUE9ORU5UKSBwdWJsaWMgY29tYm86IElneENvbWJvQmFzZSxcbiAgICAgICAgcHJvdGVjdGVkIGNvbWJvQVBJOiBJZ3hDb21ib0FQSVNlcnZpY2UpIHtcbiAgICAgICAgc3VwZXIoZWxlbWVudFJlZiwgY2RyLCBzZWxlY3Rpb24pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgc2Nyb2xsQ29udGFpbmVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5kYy5sb2NhdGlvbi5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgaXNTY3JvbGxlZFRvTGFzdCgpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3Qgc2Nyb2xsVG9wID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5nZXRWZXJ0aWNhbFNjcm9sbCgpLnNjcm9sbFRvcDtcbiAgICAgICAgY29uc3Qgc2Nyb2xsSGVpZ2h0ID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5nZXRWZXJ0aWNhbFNjcm9sbCgpLnNjcm9sbEhlaWdodDtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3Ioc2Nyb2xsVG9wICsgdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5pZ3hGb3JDb250YWluZXJTaXplKSA9PT0gc2Nyb2xsSGVpZ2h0O1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgbGFzdFZpc2libGVJbmRleCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21iby50b3RhbEl0ZW1Db3VudCA/XG4gICAgICAgICAgICBNYXRoLmZsb29yKHRoaXMuY29tYm8uaXRlbXNNYXhIZWlnaHQgLyB0aGlzLmNvbWJvLml0ZW1IZWlnaHQpIDpcbiAgICAgICAgICAgIHRoaXMuaXRlbXMubGVuZ3RoIC0gMTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zY3JvbGxQb3NpdGlvbiA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihJZ3hDb21ib0l0ZW1Db21wb25lbnQsIHsgZGVzY2VuZGFudHM6IHRydWUgfSlcbiAgICBwdWJsaWMgY2hpbGRyZW46IFF1ZXJ5TGlzdDxJZ3hEcm9wRG93bkl0ZW1CYXNlPiA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIEBDb250ZW50Q2hpbGQoZm9yd2FyZFJlZigoKSA9PiBJZ3hGb3JPZkRpcmVjdGl2ZSksIHsgcmVhZDogSWd4Rm9yT2ZEaXJlY3RpdmUgfSlcbiAgICBwdWJsaWMgdmVydGljYWxTY3JvbGxDb250YWluZXI6IElneEZvck9mRGlyZWN0aXZlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBvbkZvY3VzKCkge1xuICAgICAgICB0aGlzLl9mb2N1c2VkSXRlbSA9IHRoaXMuX2ZvY3VzZWRJdGVtIHx8IHRoaXMuaXRlbXNbMF07XG4gICAgICAgIGlmICh0aGlzLl9mb2N1c2VkSXRlbSkge1xuICAgICAgICAgICAgdGhpcy5fZm9jdXNlZEl0ZW0uZm9jdXNlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBvbkJsdXIoZXZ0Pykge1xuICAgICAgICBpZiAodGhpcy5fZm9jdXNlZEl0ZW0pIHtcbiAgICAgICAgICAgIHRoaXMuX2ZvY3VzZWRJdGVtLmZvY3VzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2ZvY3VzZWRJdGVtID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW4gQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIG9uVG9nZ2xlT3BlbmVkKCkge1xuICAgICAgICB0aGlzLm9uT3BlbmVkLmVtaXQoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuYXZpZ2F0ZVByZXYoKSB7XG4gICAgICAgIGlmICh0aGlzLl9mb2N1c2VkSXRlbS5pdGVtSW5kZXggPT09IDAgJiYgdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5zdGF0ZS5zdGFydEluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLmZvY3VzU2VhcmNoSW5wdXQoZmFsc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVQcmV2KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBuYXZpZ2F0ZUZpcnN0KCkge1xuICAgICAgICBjb25zdCB2Q29udGFpbmVyID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lcjtcbiAgICAgICAgaWYgKHZDb250YWluZXIuc3RhdGUuc3RhcnRJbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZDb250YWluZXIuc2Nyb2xsVG8oMCk7XG4gICAgICAgIHRoaXMuc3Vic2NyaWJlTmV4dCh2Q29udGFpbmVyLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRyaWdnZXJDaGVjaygpO1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKDApO1xuICAgICAgICAgICAgdGhpcy5jb21iby50cmlnZ2VyQ2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlbiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgbmF2aWdhdGVMYXN0KCkge1xuICAgICAgICBjb25zdCB2Q29udGFpbmVyID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lcjtcbiAgICAgICAgY29uc3Qgc2Nyb2xsVGFyZ2V0ID0gdGhpcy5jb21iby50b3RhbEl0ZW1Db3VudCA/XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRvdGFsSXRlbUNvdW50IC0gMSA6XG4gICAgICAgICAgICBNYXRoLm1heCh0aGlzLmNvbWJvLmRhdGEubGVuZ3RoIC0gMSwgdkNvbnRhaW5lci5pZ3hGb3JPZi5sZW5ndGggLSAxKTtcbiAgICAgICAgaWYgKHZDb250YWluZXIuaWd4Rm9yT2YubGVuZ3RoIDw9IHZDb250YWluZXIuc3RhdGUuc3RhcnRJbmRleCArIHZDb250YWluZXIuc3RhdGUuY2h1bmtTaXplKSB7XG4gICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0odGhpcy5pdGVtcy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Q29udGFpbmVyLnNjcm9sbFRvKHNjcm9sbFRhcmdldCk7XG4gICAgICAgIHRoaXMuc3Vic2NyaWJlTmV4dCh2Q29udGFpbmVyLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRyaWdnZXJDaGVjaygpO1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKHRoaXMuaXRlbXMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRyaWdnZXJDaGVjaygpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG5hdmlnYXRlUmVtb3RlSXRlbShkaXJlY3Rpb246IE5hdmlnYXRlKSB7XG4gICAgICAgIGNvbnN0IHZDb250YWluZXIgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsQ29udGFpbmVyO1xuICAgICAgICB2Q29udGFpbmVyLmFkZFNjcm9sbFRvcChkaXJlY3Rpb24gKiB0aGlzLmNvbWJvLml0ZW1IZWlnaHQpO1xuICAgICAgICB0aGlzLnN1YnNjcmliZU5leHQodkNvbnRhaW5lciwgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gTmF2aWdhdGUuVXApIHtcbiAgICAgICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0oMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbSh0aGlzLmZvY3VzZWRJdGVtLml0ZW1JbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW4gQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIHNlbGVjdEl0ZW0oaXRlbTogSWd4RHJvcERvd25JdGVtQmFzZSkge1xuICAgICAgICBpZiAoaXRlbSA9PT0gbnVsbCB8fCBpdGVtID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbWJvQVBJLnNldF9zZWxlY3RlZF9pdGVtKGl0ZW0uaXRlbUlEKTtcbiAgICAgICAgdGhpcy5fZm9jdXNlZEl0ZW0gPSBpdGVtO1xuICAgIH1cblxuICAgIHByaXZhdGUgbmF2aWdhdGVEb3duKG5ld0luZGV4PzogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IHZDb250YWluZXIgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsQ29udGFpbmVyO1xuICAgICAgICBjb25zdCBhbGxEYXRhID0gdkNvbnRhaW5lci5pZ3hGb3JPZjtcbiAgICAgICAgY29uc3QgZXh0cmFTY3JvbGwgPSB0aGlzLmNvbWJvLmlzQWRkQnV0dG9uVmlzaWJsZSgpID8gMSA6IDA7XG4gICAgICAgIGNvbnN0IGZvY3VzZWRJdGVtID0gdGhpcy5mb2N1c2VkSXRlbTtcbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zO1xuICAgICAgICBjb25zdCBjaGlsZHJlbiA9IHRoaXMuc29ydGVkQ2hpbGRyZW47XG4gICAgICAgIGlmIChmb2N1c2VkSXRlbSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNBZGRJdGVtRm9jdXNlZCgpKSB7IHJldHVybjsgfVxuICAgICAgICAgICAgaWYgKGZvY3VzZWRJdGVtLnZhbHVlID09PSBhbGxEYXRhW2FsbERhdGEubGVuZ3RoIC0gMV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzQWRkSXRlbUJ1dHRvbigpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgdGFyZ2V0RGF0YUluZGV4ID0gbmV3SW5kZXggPT09IC0xID8gdGhpcy5pdGVtSW5kZXhJbkRhdGEodGhpcy5mb2N1c2VkSXRlbS5pdGVtSW5kZXgpICsgMSA6IHRoaXMuaXRlbUluZGV4SW5EYXRhKG5ld0luZGV4KTtcbiAgICAgICAgY29uc3QgbGFzdExvYWRlZEluZGV4ID0gdkNvbnRhaW5lci5zdGF0ZS5zdGFydEluZGV4ICsgdkNvbnRhaW5lci5zdGF0ZS5jaHVua1NpemUgLSAxOyAvLyBMYXN0IGl0ZW0gaXMgbm90IHZpc2libGUsIHNvIHJlcXVpcmUgc2Nyb2xsXG4gICAgICAgIGlmICh0YXJnZXREYXRhSW5kZXggPCBsYXN0TG9hZGVkSW5kZXgpIHsgLy8gSWYgbm8gc2Nyb2xsIGlzIHJlcXVpcmVkXG4gICAgICAgICAgICBpZiAobmV3SW5kZXggIT09IC0xIHx8IG5ld0luZGV4ID09PSBjaGlsZHJlbi5sZW5ndGggLSAxIC0gZXh0cmFTY3JvbGwpIHsgLy8gVXNlIG5vcm1hbCBuYXYgZm9yIHZpc2libGUgaXRlbXNcbiAgICAgICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0obmV3SW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNTY3JvbGxlZFRvTGFzdCAmJiB0YXJnZXREYXRhSW5kZXggPT09IGxhc3RMb2FkZWRJbmRleCkgeyAvLyBJZiBhbHJlYWR5IGF0IGJvdHRvbSBhbmQgdGFyZ2V0IGlzIGxhc3QgaXRlbVxuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKGl0ZW1zLmxlbmd0aCAtIDEgLSBleHRyYVNjcm9sbCk7IC8vIEZvY3VzIHRoZSBsYXN0IGl0ZW0gKGV4Y2x1ZGluZyBBZGQgQnV0dG9uKVxuICAgICAgICB9IGVsc2UgeyAvLyBJZiBzY3JvbGwgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgIC8vIElmIGl0ZW0gaXMgaGVhZGVyLCBmaW5kIG5leHQgbm9uLWhlYWRlciBpbmRleFxuICAgICAgICAgICAgY29uc3QgYWRkZWRJbmRleCA9IGFsbERhdGFbdGFyZ2V0RGF0YUluZGV4XS5pc0hlYWRlciA/IHRoaXMuZmluZE5leHRGb2N1c2FibGVJdGVtKHRhcmdldERhdGFJbmRleCwgTmF2aWdhdGUuRG93biwgYWxsRGF0YSkgOiAwO1xuICAgICAgICAgICAgdGFyZ2V0RGF0YUluZGV4ICs9IGFkZGVkSW5kZXg7IC8vIEFkZCBzdGVwcyB0byB0aGUgdGFyZ2V0IGluZGV4XG4gICAgICAgICAgICBpZiAoYWRkZWRJbmRleCA9PT0gLTEpIHsgLy8gSWYgdGhlcmUgYXJlIG5vIG1vcmUgbm9uLWhlYWRlciBpdGVtcyAmIGFkZCBidXR0b24gaXMgdmlzaWJsZVxuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNBZGRJdGVtQnV0dG9uKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldERhdGFJbmRleCA9PT0gYWxsRGF0YS5sZW5ndGggLSAxICYmICF0aGlzLmlzU2Nyb2xsZWRUb0xhc3QpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0YXJnZXQgaXMgdmVyeSBsYXN0IGxvYWRlZCBpdGVtLCBidXQgc2Nyb2xsIGlzIG5vdCBhdCB0aGUgYm90dG9tIChpdGVtIGlzIGluIERPTSBidXQgbm90IHZpc2libGUpXG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBUaGlzIHdpbGwgbm90IHRyaWdnZXIgYG9uQ2h1bmtMb2FkYFxuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbShpdGVtcy5sZW5ndGggLSAxIC0gZXh0cmFTY3JvbGwpOyAvLyBUYXJnZXQgbGFzdCBpdGVtIChleGNsdWRpbmcgQWRkIEJ1dHRvbilcbiAgICAgICAgICAgIH0gZWxzZSB7IC8vIFBlcmZvcm0gdmlydHVhbCBzY3JvbGxcbiAgICAgICAgICAgICAgICB0aGlzLnN1YnNjcmliZU5leHQodkNvbnRhaW5lciwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGlsZHJlbiA9IGFsbCBpdGVtcyBpbiB0aGUgREQgKGluY2x1ZGluZyBhZGRJdGVtQnV0dG9uKVxuICAgICAgICAgICAgICAgICAgICAvLyBsZW5ndGggLSAyIGluc3RlYWQgb2YgLTEsIGJlY2F1c2Ugd2UgZG8gbm90IHdhbnQgdG8gZm9jdXMgdGhlIGxhc3QgbG9hZGVkIGl0ZW0gKGluIERPTSwgYnV0IG5vdCB2aXNpYmxlKVxuICAgICAgICAgICAgICAgICAgICAvLyBGb2N1cyBsYXN0IGl0ZW0gKGV4Y2x1ZGluZyBBZGQgQnV0dG9uKVxuICAgICAgICAgICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0oIWFkZGVkSW5kZXggPyBjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxIC0gZXh0cmFTY3JvbGxdLml0ZW1JbmRleCA6IHRoaXMuaXRlbXMubGVuZ3RoIC0gMik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBQZXJmb3JtIHZpcnR1YWwgc2Nyb2xsXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG5hdmlnYXRlVXAobmV3SW5kZXg/OiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgdkNvbnRhaW5lciA9IHRoaXMudmVydGljYWxTY3JvbGxDb250YWluZXI7XG4gICAgICAgIGNvbnN0IGFsbERhdGEgPSB2Q29udGFpbmVyLmlneEZvck9mO1xuICAgICAgICBjb25zdCBmb2N1c2VkSXRlbSA9IHRoaXMuZm9jdXNlZEl0ZW07XG4gICAgICAgIGlmIChmb2N1c2VkSXRlbS52YWx1ZSA9PT0gYWxsRGF0YS5maW5kKGUgPT4gIWUuaXNIZWFkZXIgJiYgIWUuaGlkZGVuKSkgeyAvLyBJZiB0aGlzIGlzIHRoZSB2ZXJ5IGZpcnN0IG5vbi1oZWFkZXIgaXRlbVxuICAgICAgICAgICAgdGhpcy5mb2N1c0NvbWJvU2VhcmNoKCk7IC8vIEZvY3VzIGNvbWJvIHNlYXJjaFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGxldCB0YXJnZXREYXRhSW5kZXggPSBuZXdJbmRleCA9PT0gLTEgPyB0aGlzLml0ZW1JbmRleEluRGF0YShmb2N1c2VkSXRlbS5pdGVtSW5kZXgpIC0gMSA6IHRoaXMuaXRlbUluZGV4SW5EYXRhKG5ld0luZGV4KTtcbiAgICAgICAgaWYgKG5ld0luZGV4ICE9PSAtMSkgeyAvLyBJZiBubyBzY3JvbGwgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgIGlmICh0aGlzLmlzU2Nyb2xsZWRUb0xhc3QgJiYgdGFyZ2V0RGF0YUluZGV4ID09PSB2Q29udGFpbmVyLnN0YXRlLnN0YXJ0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB2aXJ0IHNjcm9sbGJhciBpcyBAIGJvdHRvbSwgZmlyc3QgaXRlbSBpcyBpbiBET00gYnV0IG5vdCB2aXNpYmxlXG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBUaGlzIHdpbGwgbm90IHRyaWdnZXIgYG9uQ2h1bmtMb2FkYFxuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbSgwKTsgLy8gRm9jdXMgZmlyc3QgdmlzaWJsZSBpdGVtXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbShuZXdJbmRleCk7IC8vIFVzZSBub3JtYWwgbmF2aWdhdGlvblxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgeyAvLyBQZXJmb3JtIHZpcnR1YWwgc2Nyb2xsXG4gICAgICAgICAgICAvLyBJZiBpdGVtIGlzIGhlYWRlciwgZmluZCBuZXh0IG5vbi1oZWFkZXIgaW5kZXhcbiAgICAgICAgICAgIGNvbnN0IGFkZGVkSW5kZXggPSBhbGxEYXRhW3RhcmdldERhdGFJbmRleF0uaXNIZWFkZXIgPyB0aGlzLmZpbmROZXh0Rm9jdXNhYmxlSXRlbSh0YXJnZXREYXRhSW5kZXgsIE5hdmlnYXRlLlVwLCBhbGxEYXRhKSA6IDA7XG4gICAgICAgICAgICB0YXJnZXREYXRhSW5kZXggLT0gYWRkZWRJbmRleDsgLy8gQWRkIHN0ZXBzIHRvIHRhcmdldERhdGFJbmRleFxuICAgICAgICAgICAgaWYgKGFkZGVkSW5kZXggPT09IC0xKSB7IC8vIElmIHRoZXJlIGlzIG5vIG5vbi1oZWFkZXJcbiAgICAgICAgICAgICAgICB2Q29udGFpbmVyLnNjcm9sbFRvKDApO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNDb21ib1NlYXJjaCgpOyAvLyBGb2N1cyBjb21ibyBzZWFyY2g7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3Vic2NyaWJlTmV4dCh2Q29udGFpbmVyLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbSgwKTsgLy8gRm9jdXMgdGhlIGZpcnN0IGxvYWRlZCBpdGVtXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBQZXJmb3JtIHZpcnR1YWwgc2Nyb2xsXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbmF2aWdhdGUoZGlyZWN0aW9uOiBOYXZpZ2F0ZSwgY3VycmVudEluZGV4PzogbnVtYmVyKSB7XG4gICAgICAgIGxldCBpbmRleCA9IC0xO1xuICAgICAgICBpZiAodGhpcy5fZm9jdXNlZEl0ZW0pIHtcbiAgICAgICAgICAgIGluZGV4ID0gY3VycmVudEluZGV4ID8gY3VycmVudEluZGV4IDogdGhpcy5fZm9jdXNlZEl0ZW0uaXRlbUluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5ld0luZGV4ID0gdGhpcy5nZXROZWFyZXN0U2libGluZ0ZvY3VzYWJsZUl0ZW1JbmRleChpbmRleCwgZGlyZWN0aW9uKTtcbiAgICAgICAgY29uc3QgdkNvbnRhaW5lciA9IHRoaXMudmVydGljYWxTY3JvbGxDb250YWluZXI7XG4gICAgICAgIGNvbnN0IG5vdFZpcnR1YWwgPSB2Q29udGFpbmVyLmRjLmluc3RhbmNlLm5vdFZpcnR1YWw7XG4gICAgICAgIGlmIChub3RWaXJ0dWFsIHx8ICFkaXJlY3Rpb24pIHsgLy8gSWYgbGlzdCBoYXMgbm8gc2Nyb2xsIE9SIG5vIGRpcmVjdGlvbiBpcyBwYXNzZWRcbiAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbShuZXdJbmRleCk7IC8vIHVzZSBkZWZhdWx0IHNjcm9sbFxuICAgICAgICB9IGVsc2UgaWYgKHZDb250YWluZXIgJiYgdkNvbnRhaW5lci50b3RhbEl0ZW1Db3VudCAmJiB2Q29udGFpbmVyLnRvdGFsSXRlbUNvdW50ICE9PSAwKSB7IC8vIFJlbW90ZSBzY3JvbGxcbiAgICAgICAgICAgIGlmIChuZXdJbmRleCAhPT0gLTEgJiZcbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1zW25ld0luZGV4XS5pc1Zpc2libGUoZGlyZWN0aW9uKSkge1xuICAgICAgICAgICAgICAgIHRoaXMubmF2aWdhdGVJdGVtKG5ld0luZGV4KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVJlbW90ZUl0ZW0oZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkaXJlY3Rpb24gPT09IE5hdmlnYXRlLlVwKSB7IC8vIE5hdmlnYXRlIFVQXG4gICAgICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVVwKG5ld0luZGV4KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGlyZWN0aW9uID09PSBOYXZpZ2F0ZS5Eb3duKSB7