@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
180 lines • 23.2 kB
JavaScript
import { Injectable } from '@angular/core';
import { Subject, combineLatest, distinctUntilChanged, fromEvent, map, merge, of, startWith, switchMap, takeUntil } from 'rxjs';
import { findIndex } from 'lodash';
import * as i0 from "@angular/core";
/**
* This service provides keyboard navigation for dropdowns.
*
* It allows to navigate over the items in the dropdown using the keyboard
* or search for them. For this to correctly work, the service needs to provided
* as component provider in the component. Additionally the `ListItemComponent`
* needs to be used in the dropdown items. Also each item needs to have a
* span[data-search-label] element to search for the item.
*/
export class SelectKeyboardService {
constructor() {
this.KEYCODE_UP = 'ArrowUp';
this.KEYCODE_DOWN = 'ArrowDown';
this.KEYCODE_TAB = 'Tab';
this.KEYCODE_ENTER = 'Enter';
this.KEYCODE_ESC = 'Escape';
this.KEYCODE_SPACE = 'Space';
this.destroyed$ = new Subject();
/**
* Conifguration options for the keyboard service.
*/
this.options = {
/**
* If true, the input will be cleared when the user selects an item.
*/
emptyInput: false,
/**
* Search on key event.
*/
keyboardSearch: false,
/**
* Space key event is used to select.
*/
spaceSelect: false
};
}
/**
* Registers the keyboard event listener for the dropdown.
*
* @param input The input element to search for items.
* @param list A QueryList of all the [ListItemComponent] on which can be searched
* @param dropdown The dropdown itself as [BsDropdownDirective].
* @returns A Observable<number> where number is the index of the selected [ListItemComponent]
*/
register$(input, list, dropdown) {
if (this.destroyed$.isStopped) {
this.destroyed$ = new Subject();
}
return list.changes.pipe(startWith(list), switchMap((items) => combineLatest([
merge(fromEvent(input, 'keyup'), fromEvent(input, 'keydown')),
of(items.toArray())
])), map(([e, items]) => this.handleKeyboard(e, input, items, dropdown)), distinctUntilChanged(), takeUntil(this.destroyed$));
}
ngOnDestroy() {
this.unregister();
}
/**
* Unregister the keyboard event listner.
*/
unregister() {
this.destroyed$.next();
this.destroyed$.complete();
}
/**
* Returns true if the keyboard event is fired by a selection event (Enter, Down, Tab, Up, Space)
* @returns true if the event is a selection event.
*/
isSelectionEvent(event) {
return [
this.KEYCODE_ENTER,
this.KEYCODE_DOWN,
this.KEYCODE_TAB,
this.KEYCODE_UP,
...(this.options.spaceSelect ? [this.KEYCODE_SPACE] : [])
].includes(event.code);
}
handleKeyboard(event, input, items, dropdown) {
if (this.isSelectionEvent(event)) {
return this.handleArrowKeySelection(event, input, items, dropdown);
}
if (event.code === this.KEYCODE_ESC) {
return this.handleCancel(event, dropdown, input);
}
if (this.options.keyboardSearch) {
return this.handleInputBoxSearch(items, input);
}
return -1;
}
handleInputBoxSearch(items, input) {
if (!input.value) {
return -1;
}
const index = findIndex(items, item => {
const label = item.element.nativeElement.querySelector('span[data-search-label]');
if (!label) {
return false;
}
return label
.getAttribute('data-search-label')
.toLowerCase()
.startsWith(input.value.toLowerCase());
});
if (index > -1) {
items.forEach(item => (item.highlighted = false));
items[index].highlighted = true;
}
return index;
}
handleArrowKeySelection(event, input, items, dropdown) {
const keyCode = event.code;
const activeIndex = findIndex(items, item => item.active);
const highlightedIndex = findIndex(items, item => item.highlighted);
const index = highlightedIndex > -1 ? highlightedIndex : activeIndex;
if (event.type !== 'keydown') {
return index;
}
if (this.options.emptyInput) {
input.value = '';
}
if (keyCode === this.KEYCODE_ENTER || keyCode === this.KEYCODE_TAB) {
if (index > -1) {
event.preventDefault();
items[index].element.nativeElement.click();
}
dropdown.hide();
input.blur();
return index;
}
if (keyCode === this.KEYCODE_SPACE) {
if (index > -1) {
const clickEvent = new MouseEvent('click', {
bubbles: false
});
items[index].element.nativeElement.dispatchEvent(clickEvent);
}
dropdown.show();
return index;
}
const upOrDown = keyCode === this.KEYCODE_DOWN ? 1 : -1;
if (index > -1) {
items[index].highlighted = false;
}
return this.selectNextItemOnKeyboardMove(items, index, upOrDown);
}
handleCancel(event, dropdown, input) {
event.stopPropagation();
dropdown.hide();
input.blur();
return -1;
}
selectNextItemOnKeyboardMove(items, index, upOrDown) {
if (items[index + upOrDown]) {
if (!items[index + upOrDown].selectable) {
return this.selectNextItemOnKeyboardMove(items, index + upOrDown, upOrDown);
}
this.highlightItem(items[index + upOrDown]);
return index;
}
if (index + upOrDown > -1) {
this.highlightItem(items[0]);
return 0;
}
this.highlightItem(items[items.length - 1]);
return items.length - 1;
}
highlightItem(item) {
item.highlighted = true;
item.element.nativeElement.scrollIntoView({ block: 'nearest' });
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectKeyboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectKeyboardService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectKeyboardService, decorators: [{
type: Injectable
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LWtleWJvYXJkLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL3NlbGVjdC9zZWxlY3Qta2V5Ym9hcmQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQ3RELE9BQU8sRUFFTCxPQUFPLEVBQ1AsYUFBYSxFQUNiLG9CQUFvQixFQUNwQixTQUFTLEVBQ1QsR0FBRyxFQUNILEtBQUssRUFDTCxFQUFFLEVBQ0YsU0FBUyxFQUNULFNBQVMsRUFDVCxTQUFTLEVBQ1YsTUFBTSxNQUFNLENBQUM7QUFFZCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sUUFBUSxDQUFDOztBQUduQzs7Ozs7Ozs7R0FRRztBQUVILE1BQU0sT0FBTyxxQkFBcUI7SUFEbEM7UUFFbUIsZUFBVSxHQUFHLFNBQVMsQ0FBQztRQUN2QixpQkFBWSxHQUFHLFdBQVcsQ0FBQztRQUMzQixnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUNwQixrQkFBYSxHQUFHLE9BQU8sQ0FBQztRQUN4QixnQkFBVyxHQUFHLFFBQVEsQ0FBQztRQUN2QixrQkFBYSxHQUFHLE9BQU8sQ0FBQztRQUVqQyxlQUFVLEdBQWtCLElBQUksT0FBTyxFQUFFLENBQUM7UUFFbEQ7O1dBRUc7UUFDSCxZQUFPLEdBQUc7WUFDUjs7ZUFFRztZQUNILFVBQVUsRUFBRSxLQUFLO1lBQ2pCOztlQUVHO1lBQ0gsY0FBYyxFQUFFLEtBQUs7WUFDckI7O2VBRUc7WUFDSCxXQUFXLEVBQUUsS0FBSztTQUNuQixDQUFDO0tBdUxIO0lBckxDOzs7Ozs7O09BT0c7SUFDSCxTQUFTLENBQ1AsS0FBdUIsRUFDdkIsSUFBa0MsRUFDbEMsUUFBNkI7UUFFN0IsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxPQUFPLEVBQVEs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RGpDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBRdWVyeUxpc3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIE9ic2VydmFibGUsXG4gIFN1YmplY3QsXG4gIGNvbWJpbmVMYXRlc3QsXG4gIGRpc3RpbmN0VW50aWxDaGFuZ2VkLFxuICBmcm9tRXZlbnQsXG4gIG1hcCxcbiAgbWVyZ2UsXG4gIG9mLFxuICBzdGFydFdpdGgsXG4gIHN3aXRjaE1hcCxcbiAgdGFrZVVudGlsXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTGlzdEl0ZW1Db21wb25lbnQgfSBmcm9tICcuLi9saXN0LWdyb3VwJztcbmltcG9ydCB7IGZpbmRJbmRleCB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBCc0Ryb3Bkb3duRGlyZWN0aXZlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9kcm9wZG93bic7XG5cbi8qKlxuICogVGhpcyBzZXJ2aWNlIHByb3ZpZGVzIGtleWJvYXJkIG5hdmlnYXRpb24gZm9yIGRyb3Bkb3ducy5cbiAqXG4gKiBJdCBhbGxvd3MgdG8gbmF2aWdhdGUgb3ZlciB0aGUgaXRlbXMgaW4gdGhlIGRyb3Bkb3duIHVzaW5nIHRoZSBrZXlib2FyZFxuICogb3Igc2VhcmNoIGZvciB0aGVtLiBGb3IgdGhpcyB0byBjb3JyZWN0bHkgd29yaywgdGhlIHNlcnZpY2UgbmVlZHMgdG8gcHJvdmlkZWRcbiAqIGFzIGNvbXBvbmVudCBwcm92aWRlciBpbiB0aGUgY29tcG9uZW50LiBBZGRpdGlvbmFsbHkgdGhlIGBMaXN0SXRlbUNvbXBvbmVudGBcbiAqIG5lZWRzIHRvIGJlIHVzZWQgaW4gdGhlIGRyb3Bkb3duIGl0ZW1zLiBBbHNvIGVhY2ggaXRlbSBuZWVkcyB0byBoYXZlIGFcbiAqIHNwYW5bZGF0YS1zZWFyY2gtbGFiZWxdIGVsZW1lbnQgdG8gc2VhcmNoIGZvciB0aGUgaXRlbS5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNlbGVjdEtleWJvYXJkU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgS0VZQ09ERV9VUCA9ICdBcnJvd1VwJztcbiAgcHJpdmF0ZSByZWFkb25seSBLRVlDT0RFX0RPV04gPSAnQXJyb3dEb3duJztcbiAgcHJpdmF0ZSByZWFkb25seSBLRVlDT0RFX1RBQiA9ICdUYWInO1xuICBwcml2YXRlIHJlYWRvbmx5IEtFWUNPREVfRU5URVIgPSAnRW50ZXInO1xuICBwcml2YXRlIHJlYWRvbmx5IEtFWUNPREVfRVNDID0gJ0VzY2FwZSc7XG4gIHByaXZhdGUgcmVhZG9ubHkgS0VZQ09ERV9TUEFDRSA9ICdTcGFjZSc7XG5cbiAgcHJpdmF0ZSBkZXN0cm95ZWQkOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3QoKTtcblxuICAvKipcbiAgICogQ29uaWZndXJhdGlvbiBvcHRpb25zIGZvciB0aGUga2V5Ym9hcmQgc2VydmljZS5cbiAgICovXG4gIG9wdGlvbnMgPSB7XG4gICAgLyoqXG4gICAgICogSWYgdHJ1ZSwgdGhlIGlucHV0IHdpbGwgYmUgY2xlYXJlZCB3aGVuIHRoZSB1c2VyIHNlbGVjdHMgYW4gaXRlbS5cbiAgICAgKi9cbiAgICBlbXB0eUlucHV0OiBmYWxzZSxcbiAgICAvKipcbiAgICAgKiBTZWFyY2ggb24ga2V5IGV2ZW50LlxuICAgICAqL1xuICAgIGtleWJvYXJkU2VhcmNoOiBmYWxzZSxcbiAgICAvKipcbiAgICAgKiBTcGFjZSBrZXkgZXZlbnQgaXMgdXNlZCB0byBzZWxlY3QuXG4gICAgICovXG4gICAgc3BhY2VTZWxlY3Q6IGZhbHNlXG4gIH07XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyB0aGUga2V5Ym9hcmQgZXZlbnQgbGlzdGVuZXIgZm9yIHRoZSBkcm9wZG93bi5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IFRoZSBpbnB1dCBlbGVtZW50IHRvIHNlYXJjaCBmb3IgaXRlbXMuXG4gICAqIEBwYXJhbSBsaXN0IEEgUXVlcnlMaXN0IG9mIGFsbCB0aGUgW0xpc3RJdGVtQ29tcG9uZW50XSBvbiB3aGljaCBjYW4gYmUgc2VhcmNoZWRcbiAgICogQHBhcmFtIGRyb3Bkb3duIFRoZSBkcm9wZG93biBpdHNlbGYgYXMgW0JzRHJvcGRvd25EaXJlY3RpdmVdLlxuICAgKiBAcmV0dXJucyBBIE9ic2VydmFibGU8bnVtYmVyPiB3aGVyZSBudW1iZXIgaXMgdGhlIGluZGV4IG9mIHRoZSBzZWxlY3RlZCBbTGlzdEl0ZW1Db21wb25lbnRdXG4gICAqL1xuICByZWdpc3RlciQoXG4gICAgaW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQsXG4gICAgbGlzdDogUXVlcnlMaXN0PExpc3RJdGVtQ29tcG9uZW50PixcbiAgICBkcm9wZG93bjogQnNEcm9wZG93bkRpcmVjdGl2ZVxuICApOiBPYnNlcnZhYmxlPG51bWJlcj4ge1xuICAgIGlmICh0aGlzLmRlc3Ryb3llZCQuaXNTdG9wcGVkKSB7XG4gICAgICB0aGlzLmRlc3Ryb3llZCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAgIH1cbiAgICByZXR1cm4gbGlzdC5jaGFuZ2VzLnBpcGUoXG4gICAgICBzdGFydFdpdGgobGlzdCksXG4gICAgICBzd2l0Y2hNYXAoKGl0ZW1zOiBRdWVyeUxpc3Q8TGlzdEl0ZW1Db21wb25lbnQ+KSA9PlxuICAgICAgICBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgICBtZXJnZShcbiAgICAgICAgICAgIGZyb21FdmVudDxLZXlib2FyZEV2ZW50PihpbnB1dCwgJ2tleXVwJyksXG4gICAgICAgICAgICBmcm9tRXZlbnQ8S2V5Ym9hcmRFdmVudD4oaW5wdXQsICdrZXlkb3duJylcbiAgICAgICAgICApLFxuICAgICAgICAgIG9mKGl0ZW1zLnRvQXJyYXkoKSlcbiAgICAgICAgXSlcbiAgICAgICksXG4gICAgICBtYXAoKFtlLCBpdGVtc10pID0+IHRoaXMuaGFuZGxlS2V5Ym9hcmQoZSwgaW5wdXQsIGl0ZW1zLCBkcm9wZG93bikpLFxuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcbiAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3llZCQpXG4gICAgKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMudW5yZWdpc3RlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucmVnaXN0ZXIgdGhlIGtleWJvYXJkIGV2ZW50IGxpc3RuZXIuXG4gICAqL1xuICB1bnJlZ2lzdGVyKCkge1xuICAgIHRoaXMuZGVzdHJveWVkJC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95ZWQkLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoZSBrZXlib2FyZCBldmVudCBpcyBmaXJlZCBieSBhIHNlbGVjdGlvbiBldmVudCAoRW50ZXIsIERvd24sIFRhYiwgVXAsIFNwYWNlKVxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBldmVudCBpcyBhIHNlbGVjdGlvbiBldmVudC5cbiAgICovXG4gIGlzU2VsZWN0aW9uRXZlbnQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gW1xuICAgICAgdGhpcy5LRVlDT0RFX0VOVEVSLFxuICAgICAgdGhpcy5LRVlDT0RFX0RPV04sXG4gICAgICB0aGlzLktFWUNPREVfVEFCLFxuICAgICAgdGhpcy5LRVlDT0RFX1VQLFxuICAgICAgLi4uKHRoaXMub3B0aW9ucy5zcGFjZVNlbGVjdCA/IFt0aGlzLktFWUNPREVfU1BBQ0VdIDogW10pXG4gICAgXS5pbmNsdWRlcyhldmVudC5jb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlS2V5Ym9hcmQoXG4gICAgZXZlbnQ6IEtleWJvYXJkRXZlbnQsXG4gICAgaW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQsXG4gICAgaXRlbXM6IExpc3RJdGVtQ29tcG9uZW50W10sXG4gICAgZHJvcGRvd246IEJzRHJvcGRvd25EaXJlY3RpdmVcbiAgKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5pc1NlbGVjdGlvbkV2ZW50KGV2ZW50KSkge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQXJyb3dLZXlTZWxlY3Rpb24oZXZlbnQsIGlucHV0LCBpdGVtcywgZHJvcGRvd24pO1xuICAgIH1cblxuICAgIGlmIChldmVudC5jb2RlID09PSB0aGlzLktFWUNPREVfRVNDKSB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVDYW5jZWwoZXZlbnQsIGRyb3Bkb3duLCBpbnB1dCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5rZXlib2FyZFNlYXJjaCkge1xuICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlSW5wdXRCb3hTZWFyY2goaXRlbXMsIGlucHV0KTtcbiAgICB9XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVJbnB1dEJveFNlYXJjaChpdGVtczogTGlzdEl0ZW1Db21wb25lbnRbXSwgaW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQpIHtcbiAgICBpZiAoIWlucHV0LnZhbHVlKSB7XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGNvbnN0IGluZGV4ID0gZmluZEluZGV4KGl0ZW1zLCBpdGVtID0+IHtcbiAgICAgIGNvbnN0IGxhYmVsOiBIVE1MRWxlbWVudCA9XG4gICAgICAgIGl0ZW0uZWxlbWVudC5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NwYW5bZGF0YS1zZWFyY2gtbGFiZWxdJyk7XG4gICAgICBpZiAoIWxhYmVsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsYWJlbFxuICAgICAgICAuZ2V0QXR0cmlidXRlKCdkYXRhLXNlYXJjaC1sYWJlbCcpXG4gICAgICAgIC50b0xvd2VyQ2FzZSgpXG4gICAgICAgIC5zdGFydHNXaXRoKGlucHV0LnZhbHVlLnRvTG93ZXJDYXNlKCkpO1xuICAgIH0pO1xuICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICBpdGVtcy5mb3JFYWNoKGl0ZW0gPT4gKGl0ZW0uaGlnaGxpZ2h0ZWQgPSBmYWxzZSkpO1xuICAgICAgaXRlbXNbaW5kZXhdLmhpZ2hsaWdodGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVBcnJvd0tleVNlbGVjdGlvbihcbiAgICBldmVudDogS2V5Ym9hcmRFdmVudCxcbiAgICBpbnB1dDogSFRNTElucHV0RWxlbWVudCxcbiAgICBpdGVtczogTGlzdEl0ZW1Db21wb25lbnRbXSxcbiAgICBkcm9wZG93bjogQnNEcm9wZG93bkRpcmVjdGl2ZVxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IGtleUNvZGUgPSBldmVudC5jb2RlO1xuICAgIGNvbnN0IGFjdGl2ZUluZGV4ID0gZmluZEluZGV4KGl0ZW1zLCBpdGVtID0+IGl0ZW0uYWN0aXZlKTtcbiAgICBjb25zdCBoaWdobGlnaHRlZEluZGV4ID0gZmluZEluZGV4KGl0ZW1zLCBpdGVtID0+IGl0ZW0uaGlnaGxpZ2h0ZWQpO1xuICAgIGNvbnN0IGluZGV4ID0gaGlnaGxpZ2h0ZWRJbmRleCA+IC0xID8gaGlnaGxpZ2h0ZWRJbmRleCA6IGFjdGl2ZUluZGV4O1xuXG4gICAgaWYgKGV2ZW50LnR5cGUgIT09ICdrZXlkb3duJykge1xuICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMuZW1wdHlJbnB1dCkge1xuICAgICAgaW5wdXQudmFsdWUgPSAnJztcbiAgICB9XG5cbiAgICBpZiAoa2V5Q29kZSA9PT0gdGhpcy5LRVlDT0RFX0VOVEVSIHx8IGtleUNvZGUgPT09IHRoaXMuS0VZQ09ERV9UQUIpIHtcbiAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGl0ZW1zW2luZGV4XS5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY2xpY2soKTtcbiAgICAgIH1cbiAgICAgIGRyb3Bkb3duLmhpZGUoKTtcbiAgICAgIGlucHV0LmJsdXIoKTtcbiAgICAgIHJldHVybiBpbmRleDtcbiAgICB9XG4gICAgaWYgKGtleUNvZGUgPT09IHRoaXMuS0VZQ09ERV9TUEFDRSkge1xuICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgY29uc3QgY2xpY2tFdmVudCA9IG5ldyBNb3VzZUV2ZW50KCdjbGljaycsIHtcbiAgICAgICAgICBidWJibGVzOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgaXRlbXNbaW5kZXhdLmVsZW1lbnQubmF0aXZlRWxlbWVudC5kaXNwYXRjaEV2ZW50KGNsaWNrRXZlbnQpO1xuICAgICAgfVxuICAgICAgZHJvcGRvd24uc2hvdygpO1xuICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbiAgICBjb25zdCB1cE9yRG93biA9IGtleUNvZGUgPT09IHRoaXMuS0VZQ09ERV9ET1dOID8gMSA6IC0xO1xuICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICBpdGVtc1tpbmRleF0uaGlnaGxpZ2h0ZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0TmV4dEl0ZW1PbktleWJvYXJkTW92ZShpdGVtcywgaW5kZXgsIHVwT3JEb3duKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlQ2FuY2VsKFxuICAgIGV2ZW50OiBLZXlib2FyZEV2ZW50LFxuICAgIGRyb3Bkb3duOiBCc0Ryb3Bkb3duRGlyZWN0aXZlLFxuICAgIGlucHV0OiBIVE1MSW5wdXRFbGVtZW50XG4gICkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGRyb3Bkb3duLmhpZGUoKTtcbiAgICBpbnB1dC5ibHVyKCk7XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgcHJpdmF0ZSBzZWxlY3ROZXh0SXRlbU9uS2V5Ym9hcmRNb3ZlKFxuICAgIGl0ZW1zOiBMaXN0SXRlbUNvbXBvbmVudFtdLFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgdXBPckRvd246IC0xIHwgMVxuICApOiBudW1iZXIge1xuICAgIGlmIChpdGVtc1tpbmRleCArIHVwT3JEb3duXSkge1xuICAgICAgaWYgKCFpdGVtc1tpbmRleCArIHVwT3JEb3duXS5zZWxlY3RhYmxlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdE5leHRJdGVtT25LZXlib2FyZE1vdmUoaXRlbXMsIGluZGV4ICsgdXBPckRvd24sIHVwT3JEb3duKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuaGlnaGxpZ2h0SXRlbShpdGVtc1tpbmRleCArIHVwT3JEb3duXSk7XG4gICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxuICAgIGlmIChpbmRleCArIHVwT3JEb3duID4gLTEpIHtcbiAgICAgIHRoaXMuaGlnaGxpZ2h0SXRlbShpdGVtc1swXSk7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgdGhpcy5oaWdobGlnaHRJdGVtKGl0ZW1zW2l0ZW1zLmxlbmd0aCAtIDFdKTtcbiAgICByZXR1cm4gaXRlbXMubGVuZ3RoIC0gMTtcbiAgfVxuXG4gIHByaXZhdGUgaGlnaGxpZ2h0SXRlbShpdGVtOiBMaXN0SXRlbUNvbXBvbmVudCkge1xuICAgIGl0ZW0uaGlnaGxpZ2h0ZWQgPSB0cnVlO1xuICAgIGl0ZW0uZWxlbWVudC5uYXRpdmVFbGVtZW50LnNjcm9sbEludG9WaWV3KHsgYmxvY2s6ICduZWFyZXN0JyB9KTtcbiAgfVxufVxuIl19