@nova-ui/bits
Version:
SolarWinds Nova Framework
212 lines • 35.3 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { ActiveDescendantKeyManager, LiveAnnouncer } from "@angular/cdk/a11y";
import { Injectable } from "@angular/core";
import isNull from "lodash/isNull";
import { MenuItemComponent } from "./menu-item/menu-item/menu-item.component";
import { KEYBOARD_CODE } from "../../constants/keycode.constants";
import { MenuActionComponent } from "../menu/menu-item/menu-action/menu-action.component";
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/a11y";
export class MenuKeyControlService {
set scrollContainer(container) {
this._scrollContainer = container;
}
get scrollContainer() {
return this._scrollContainer || this.popup?.popupAreaContainer;
}
constructor(live) {
this.live = live;
this.keyControlItemsSource = false;
}
initKeyboardManager() {
this.keyboardEventsManager = this.keyControlItemsSource
? new ActiveDescendantKeyManager(this.menuPopup.menuItems).withVerticalOrientation()
: new ActiveDescendantKeyManager(this.menuItems).withVerticalOrientation();
if (this.keyboardEventsSubscription) {
this.keyboardEventsSubscription.unsubscribe();
}
this.initKeyManagerHandlers();
// when opening menu key 'focus' should disappear from items
if (this.menuOpenListener) {
this.menuOpenListenerSubscription = this.menuOpenListener.subscribe(() => {
// Uncomment in the scope of NUI-6104
// this.keyboardEventsManager.setFirstItemActive();
// Remove this in the scope of NUI-6104 in favor of the line above
this.keyboardEventsManager.setActiveItem(-1);
this.live.announce(`
${this.keyControlItemsSource
? this.menuPopup.menuItems.length
: this.menuItems.length} menu items available.`);
// Uncomment in the scope of NUI-6104 and adjust this to be the part of the announcer's string above
// Active item ${this.keyboardEventsManager?.activeItem?.menuItem.nativeElement.innerText}.`);
});
}
}
handleKeydown(event) {
this.popup.isOpen
? this.handleOpenKeyDown(event)
: this.handleClosedKeyDown(event);
}
setActiveItem(index) {
this.keyboardEventsManager.setActiveItem(index);
}
getActiveItemIndex() {
return this.keyboardEventsManager.activeItemIndex;
}
initKeyManagerHandlers() {
this.keyboardEventsSubscription =
this.keyboardEventsManager.change.subscribe((activeIndex) => {
// when the navigation item changes, we get new activeIndex
if (this.popup.isOpen && this.hasActiveItem()) {
this.scrollActiveOptionIntoView({
scrollContainer: this.scrollContainer ||
this.popup.popupAreaContainer,
menuItemHeight: this.keyboardEventsManager.activeItem?.menuItem
.nativeElement.offsetHeight,
activeOptionIndex: activeIndex,
menuGroups: this.menuGroups,
menuItems: this.menuItems,
});
}
});
}
shouldCloseOnEnter() {
return (this.keyboardEventsManager.activeItem instanceof
(MenuActionComponent || MenuItemComponent));
}
hasActiveItem() {
if (isNull(this.keyboardEventsManager.activeItem) ||
isNull(this.keyboardEventsManager.activeItemIndex)) {
return false;
}
return (this.keyboardEventsManager.activeItem &&
this.keyboardEventsManager.activeItemIndex >= 0);
}
handleOpenKeyDown(event) {
if (event.code === KEYBOARD_CODE.ARROW_DOWN ||
event.code === KEYBOARD_CODE.ARROW_UP) {
// passing the event to key manager so we get a change fired
this.keyboardEventsManager.onKeydown(event);
this.announceCurrentItem();
}
if (event.code === KEYBOARD_CODE.PAGE_UP ||
event.code === KEYBOARD_CODE.HOME ||
(event.metaKey && event.code === KEYBOARD_CODE.ARROW_UP)) {
event.preventDefault();
this.keyboardEventsManager.onKeydown(event);
this.keyboardEventsManager.setFirstItemActive();
this.announceCurrentItem();
}
if (event.code === KEYBOARD_CODE.PAGE_DOWN ||
event.code === KEYBOARD_CODE.END ||
(event.metaKey && event.code === KEYBOARD_CODE.ARROW_DOWN)) {
event.preventDefault();
this.keyboardEventsManager.onKeydown(event);
this.keyboardEventsManager.setLastItemActive();
this.announceCurrentItem();
}
// This keeps the active item visible within the visible area of the menu popup. In case there are disabled items in the list,
// this scrolls down to the nearest enabled item. Otherwise, the active item will "jump over" the disabled items and remain
// outside of the visible edge of the list.
this.keyboardEventsManager.activeItem?.menuItem?.nativeElement?.scrollIntoView({ block: "nearest" });
// prevent closing on enter
if (!this.hasActiveItem() && event.code === KEYBOARD_CODE.ENTER) {
event.preventDefault();
}
if (this.hasActiveItem() && event.code === KEYBOARD_CODE.ENTER) {
// perform action in menu item(select, switch, check etc).
this.keyboardEventsManager.activeItem?.doAction(event);
// closing items only if they are MenuAction or MenuItem, others should not close popup
if (!this.shouldCloseOnEnter()) {
event.preventDefault();
return;
}
this.popup.toggleOpened(event);
}
if (event.code === KEYBOARD_CODE.TAB ||
event.code === KEYBOARD_CODE.ESCAPE) {
this.popup.toggleOpened(event);
}
}
handleClosedKeyDown(event) {
// prevent opening on enter and prevent scrolling page on key down/key up when focused
if (this.shouldBePrevented(event)) {
event.preventDefault();
}
if (event.code === KEYBOARD_CODE.ARROW_DOWN) {
this.popup.toggleOpened(event);
}
}
shouldBePrevented(event) {
return (event.code === KEYBOARD_CODE.ARROW_DOWN ||
event.code === KEYBOARD_CODE.ARROW_UP ||
event.code === KEYBOARD_CODE.ENTER);
}
// functions to scroll items into view for ActiveDescendantKeyManager
countGroupLabelsBeforeOption(optionIndex, options, optionGroups) {
if (optionGroups.length) {
const optionsArray = options.toArray();
const groups = optionGroups.toArray();
let groupCounter = 0;
for (let i = 0; i < optionIndex + 1; i++) {
if (optionsArray[i].group &&
optionsArray[i].group === groups[groupCounter]) {
groupCounter++;
}
}
return groupCounter;
}
return 0;
}
getOptionScrollPosition(optionIndex, optionHeight, currentScrollPosition, panelHeight) {
const optionOffset = optionIndex * optionHeight;
if (optionOffset < currentScrollPosition) {
return optionOffset;
}
if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {
return Math.max(0, optionOffset - panelHeight + optionHeight);
}
return currentScrollPosition;
}
scrollActiveOptionIntoView(options) {
const activeOptionIndex = options.activeOptionIndex || 0;
const labelCount = this.countGroupLabelsBeforeOption(activeOptionIndex, options.menuItems, options.menuGroups);
options.scrollContainer.nativeElement.scrollTop =
this.getOptionScrollPosition(activeOptionIndex + labelCount, options.menuItemHeight + 4, options.scrollContainer.nativeElement.scrollTop, 300);
}
announceCurrentItem() {
this.live.announce(`Active item ${this.keyboardEventsManager?.activeItem?.menuItem.nativeElement.innerText}.`);
}
ngOnDestroy() {
if (this.keyboardEventsSubscription) {
this.keyboardEventsSubscription.unsubscribe();
}
if (this.menuOpenListenerSubscription) {
this.menuOpenListenerSubscription.unsubscribe();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuKeyControlService, deps: [{ token: i1.LiveAnnouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuKeyControlService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuKeyControlService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.LiveAnnouncer }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS1rZXktY29udHJvbC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9tZW51L21lbnUta2V5LWNvbnRyb2wuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUFFLDBCQUEwQixFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzlFLE9BQU8sRUFBYyxVQUFVLEVBQXdCLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sTUFBTSxNQUFNLGVBQWUsQ0FBQztBQUluQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUU5RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDbEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0scURBQXFELENBQUM7OztBQU0xRixNQUFNLE9BQU8scUJBQXFCO0lBYTlCLElBQVcsZUFBZSxDQUFDLFNBQXFCO1FBQzVDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQVcsZUFBZTtRQUN0QixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLGtCQUFrQixDQUFDO0lBQ25FLENBQUM7SUFFRCxZQUFvQixJQUFtQjtRQUFuQixTQUFJLEdBQUosSUFBSSxDQUFlO1FBZGhDLDBCQUFx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SSxDQUFDLDBCQUEwQixDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ2pEO1FBRUQsSUFBSSxJQUFJLENBQUMsNEJBQTRCLEVBQUU7WUFDbkMsSUFBSSxDQUFDLDRCQUE0QixDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ25EO0lBQ0wsQ0FBQzsrR0EzUVEscUJBQXFCO21IQUFyQixxQkFBcUI7OzRGQUFyQixxQkFBcUI7a0JBRGpDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHsgQWN0aXZlRGVzY2VuZGFudEtleU1hbmFnZXIsIExpdmVBbm5vdW5jZXIgfSBmcm9tIFwiQGFuZ3VsYXIvY2RrL2ExMXlcIjtcbmltcG9ydCB7IEVsZW1lbnRSZWYsIEluamVjdGFibGUsIE9uRGVzdHJveSwgUXVlcnlMaXN0IH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCBpc051bGwgZnJvbSBcImxvZGFzaC9pc051bGxcIjtcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gXCJyeGpzXCI7XG5cbmltcG9ydCB7IE1lbnVHcm91cENvbXBvbmVudCB9IGZyb20gXCIuL21lbnUtaXRlbS9tZW51LWdyb3VwL21lbnUtZ3JvdXAuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBNZW51SXRlbUNvbXBvbmVudCB9IGZyb20gXCIuL21lbnUtaXRlbS9tZW51LWl0ZW0vbWVudS1pdGVtLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgTWVudVBvcHVwQ29tcG9uZW50IH0gZnJvbSBcIi4vbWVudS1wb3B1cC9tZW51LXBvcHVwLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgS0VZQk9BUkRfQ09ERSB9IGZyb20gXCIuLi8uLi9jb25zdGFudHMva2V5Y29kZS5jb25zdGFudHNcIjtcbmltcG9ydCB7IE1lbnVBY3Rpb25Db21wb25lbnQgfSBmcm9tIFwiLi4vbWVudS9tZW51LWl0ZW0vbWVudS1hY3Rpb24vbWVudS1hY3Rpb24uY29tcG9uZW50XCI7XG5pbXBvcnQgeyBNZW51SXRlbUJhc2VDb21wb25lbnQgfSBmcm9tIFwiLi4vbWVudS9tZW51LWl0ZW0vbWVudS1pdGVtL21lbnUtaXRlbS1iYXNlXCI7XG5pbXBvcnQgeyBQb3B1cENvbXBvbmVudCB9IGZyb20gXCIuLi9wb3B1cC1hZGFwdGVyL3BvcHVwLWFkYXB0ZXIuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBJUG9wdXBBY3RpdmVPcHRpb25zIH0gZnJvbSBcIi4uL3B1YmxpYy1hcGlcIjtcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE1lbnVLZXlDb250cm9sU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gICAgcHVibGljIHBvcHVwOiBQb3B1cENvbXBvbmVudDtcbiAgICBwdWJsaWMgbWVudUdyb3VwczogUXVlcnlMaXN0PE1lbnVHcm91cENvbXBvbmVudD47XG4gICAgcHVibGljIG1lbnVJdGVtczogUXVlcnlMaXN0PE1lbnVJdGVtQmFzZUNvbXBvbmVudD47XG4gICAgcHVibGljIG1lbnVUb2dnbGU6IEVsZW1lbnRSZWY7XG4gICAgcHVibGljIG1lbnVQb3B1cDogTWVudVBvcHVwQ29tcG9uZW50O1xuICAgIHB1YmxpYyBtZW51T3Blbkxpc3RlbmVyOiBTdWJqZWN0PHZvaWQ+O1xuICAgIHB1YmxpYyBrZXlDb250cm9sSXRlbXNTb3VyY2U6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwdWJsaWMga2V5Ym9hcmRFdmVudHNNYW5hZ2VyOiBBY3RpdmVEZXNjZW5kYW50S2V5TWFuYWdlcjxNZW51SXRlbUJhc2VDb21wb25lbnQ+O1xuICAgIHB1YmxpYyBtZW51T3Blbkxpc3RlbmVyU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gICAgcHJpdmF0ZSBrZXlib2FyZEV2ZW50c1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICAgIHByaXZhdGUgX3Njcm9sbENvbnRhaW5lcjogRWxlbWVudFJlZjtcblxuICAgIHB1YmxpYyBzZXQgc2Nyb2xsQ29udGFpbmVyKGNvbnRhaW5lcjogRWxlbWVudFJlZikge1xuICAgICAgICB0aGlzLl9zY3JvbGxDb250YWluZXIgPSBjb250YWluZXI7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBzY3JvbGxDb250YWluZXIoKTogRWxlbWVudFJlZjxhbnk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Njcm9sbENvbnRhaW5lciB8fCB0aGlzLnBvcHVwPy5wb3B1cEFyZWFDb250YWluZXI7XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBsaXZlOiBMaXZlQW5ub3VuY2VyKSB7fVxuXG4gICAgcHVibGljIGluaXRLZXlib2FyZE1hbmFnZXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyID0gdGhpcy5rZXlDb250cm9sSXRlbXNTb3VyY2VcbiAgICAgICAgICAgID8gbmV3IEFjdGl2ZURlc2NlbmRhbnRLZXlNYW5hZ2VyKFxuICAgICAgICAgICAgICAgICAgdGhpcy5tZW51UG9wdXAubWVudUl0ZW1zXG4gICAgICAgICAgICAgICkud2l0aFZlcnRpY2FsT3JpZW50YXRpb24oKVxuICAgICAgICAgICAgOiBuZXcgQWN0aXZlRGVzY2VuZGFudEtleU1hbmFnZXIoXG4gICAgICAgICAgICAgICAgICB0aGlzLm1lbnVJdGVtc1xuICAgICAgICAgICAgICApLndpdGhWZXJ0aWNhbE9yaWVudGF0aW9uKCk7XG4gICAgICAgIGlmICh0aGlzLmtleWJvYXJkRXZlbnRzU3Vic2NyaXB0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRzU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbml0S2V5TWFuYWdlckhhbmRsZXJzKCk7XG5cbiAgICAgICAgLy8gd2hlbiBvcGVuaW5nIG1lbnUga2V5ICdmb2N1cycgc2hvdWxkIGRpc2FwcGVhciBmcm9tIGl0ZW1zXG4gICAgICAgIGlmICh0aGlzLm1lbnVPcGVuTGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHRoaXMubWVudU9wZW5MaXN0ZW5lclN1YnNjcmlwdGlvbiA9IHRoaXMubWVudU9wZW5MaXN0ZW5lci5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBVbmNvbW1lbnQgaW4gdGhlIHNjb3BlIG9mIE5VSS02MTA0XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLnNldEZpcnN0SXRlbUFjdGl2ZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGlzIGluIHRoZSBzY29wZSBvZiBOVUktNjEwNCBpbiBmYXZvciBvZiB0aGUgbGluZSBhYm92ZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRzTWFuYWdlci5zZXRBY3RpdmVJdGVtKC0xKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saXZlLmFubm91bmNlKGBcbiAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMua2V5Q29udHJvbEl0ZW1zU291cmNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB0aGlzLm1lbnVQb3B1cC5tZW51SXRlbXMubGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0aGlzLm1lbnVJdGVtcy5sZW5ndGhcbiAgICAgICAgICAgICAgICAgICAgfSBtZW51IGl0ZW1zIGF2YWlsYWJsZS5gKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVbmNvbW1lbnQgaW4gdGhlIHNjb3BlIG9mIE5VSS02MTA0IGFuZCBhZGp1c3QgdGhpcyB0byBiZSB0aGUgcGFydCBvZiB0aGUgYW5ub3VuY2VyJ3Mgc3RyaW5nIGFib3ZlXG4gICAgICAgICAgICAgICAgICAgIC8vIEFjdGl2ZSBpdGVtICR7dGhpcy5rZXlib2FyZEV2ZW50c01hbmFnZXI/LmFjdGl2ZUl0ZW0/Lm1lbnVJdGVtLm5hdGl2ZUVsZW1lbnQuaW5uZXJUZXh0fS5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGhhbmRsZUtleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wb3B1cC5pc09wZW5cbiAgICAgICAgICAgID8gdGhpcy5oYW5kbGVPcGVuS2V5RG93bihldmVudClcbiAgICAgICAgICAgIDogdGhpcy5oYW5kbGVDbG9zZWRLZXlEb3duKGV2ZW50KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0QWN0aXZlSXRlbShpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLnNldEFjdGl2ZUl0ZW0oaW5kZXgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRBY3RpdmVJdGVtSW5kZXgoKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmtleWJvYXJkRXZlbnRzTWFuYWdlci5hY3RpdmVJdGVtSW5kZXg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0S2V5TWFuYWdlckhhbmRsZXJzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRzU3Vic2NyaXB0aW9uID1cbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLmNoYW5nZS5zdWJzY3JpYmUoKGFjdGl2ZUluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gd2hlbiB0aGUgbmF2aWdhdGlvbiBpdGVtIGNoYW5nZXMsIHdlIGdldCBuZXcgYWN0aXZlSW5kZXhcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wb3B1cC5pc09wZW4gJiYgdGhpcy5oYXNBY3RpdmVJdGVtKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxBY3RpdmVPcHRpb25JbnRvVmlldyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxDb250YWluZXI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb250YWluZXIgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvcHVwLnBvcHVwQXJlYUNvbnRhaW5lcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lbnVJdGVtSGVpZ2h0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLmFjdGl2ZUl0ZW0/Lm1lbnVJdGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZU9wdGlvbkluZGV4OiBhY3RpdmVJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lbnVHcm91cHM6IHRoaXMubWVudUdyb3VwcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lbnVJdGVtczogdGhpcy5tZW51SXRlbXMsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2hvdWxkQ2xvc2VPbkVudGVyKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy5rZXlib2FyZEV2ZW50c01hbmFnZXIuYWN0aXZlSXRlbSBpbnN0YW5jZW9mXG4gICAgICAgICAgICAoTWVudUFjdGlvbkNvbXBvbmVudCB8fCBNZW51SXRlbUNvbXBvbmVudClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhc0FjdGl2ZUl0ZW0oKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGlzTnVsbCh0aGlzLmtleWJvYXJkRXZlbnRzTWFuYWdlci5hY3RpdmVJdGVtKSB8fFxuICAgICAgICAgICAgaXNOdWxsKHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLmFjdGl2ZUl0ZW1JbmRleClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLmFjdGl2ZUl0ZW0gJiZcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLmFjdGl2ZUl0ZW1JbmRleCA+PSAwXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVPcGVuS2V5RG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkFSUk9XX0RPV04gfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuQVJST1dfVVBcbiAgICAgICAgKSB7XG4gICAgICAgICAgICAvLyBwYXNzaW5nIHRoZSBldmVudCB0byBrZXkgbWFuYWdlciBzbyB3ZSBnZXQgYSBjaGFuZ2UgZmlyZWRcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLm9uS2V5ZG93bihldmVudCk7XG4gICAgICAgICAgICB0aGlzLmFubm91bmNlQ3VycmVudEl0ZW0oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLlBBR0VfVVAgfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuSE9NRSB8fFxuICAgICAgICAgICAgKGV2ZW50Lm1ldGFLZXkgJiYgZXZlbnQuY29kZSA9PT0gS0VZQk9BUkRfQ09ERS5BUlJPV19VUClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGhpcy5rZXlib2FyZEV2ZW50c01hbmFnZXIub25LZXlkb3duKGV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLnNldEZpcnN0SXRlbUFjdGl2ZSgpO1xuICAgICAgICAgICAgdGhpcy5hbm5vdW5jZUN1cnJlbnRJdGVtKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgZXZlbnQuY29kZSA9PT0gS0VZQk9BUkRfQ09ERS5QQUdFX0RPV04gfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuRU5EIHx8XG4gICAgICAgICAgICAoZXZlbnQubWV0YUtleSAmJiBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkFSUk9XX0RPV04pXG4gICAgICAgICkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyLm9uS2V5ZG93bihldmVudCk7XG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRzTWFuYWdlci5zZXRMYXN0SXRlbUFjdGl2ZSgpO1xuICAgICAgICAgICAgdGhpcy5hbm5vdW5jZUN1cnJlbnRJdGVtKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGlzIGtlZXBzIHRoZSBhY3RpdmUgaXRlbSB2aXNpYmxlIHdpdGhpbiB0aGUgdmlzaWJsZSBhcmVhIG9mIHRoZSBtZW51IHBvcHVwLiBJbiBjYXNlIHRoZXJlIGFyZSBkaXNhYmxlZCBpdGVtcyBpbiB0aGUgbGlzdCxcbiAgICAgICAgLy8gdGhpcyBzY3JvbGxzIGRvd24gdG8gdGhlIG5lYXJlc3QgZW5hYmxlZCBpdGVtLiBPdGhlcndpc2UsIHRoZSBhY3RpdmUgaXRlbSB3aWxsIFwianVtcCBvdmVyXCIgdGhlIGRpc2FibGVkIGl0ZW1zIGFuZCByZW1haW5cbiAgICAgICAgLy8gb3V0c2lkZSBvZiB0aGUgdmlzaWJsZSBlZGdlIG9mIHRoZSBsaXN0LlxuICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRzTWFuYWdlci5hY3RpdmVJdGVtPy5tZW51SXRlbT8ubmF0aXZlRWxlbWVudD8uc2Nyb2xsSW50b1ZpZXcoXG4gICAgICAgICAgICB7IGJsb2NrOiBcIm5lYXJlc3RcIiB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gcHJldmVudCBjbG9zaW5nIG9uIGVudGVyXG4gICAgICAgIGlmICghdGhpcy5oYXNBY3RpdmVJdGVtKCkgJiYgZXZlbnQuY29kZSA9PT0gS0VZQk9BUkRfQ09ERS5FTlRFUikge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmhhc0FjdGl2ZUl0ZW0oKSAmJiBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkVOVEVSKSB7XG4gICAgICAgICAgICAvLyBwZXJmb3JtIGFjdGlvbiBpbiBtZW51IGl0ZW0oc2VsZWN0LCBzd2l0Y2gsIGNoZWNrIGV0YykuXG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRzTWFuYWdlci5hY3RpdmVJdGVtPy5kb0FjdGlvbihldmVudCk7XG4gICAgICAgICAgICAvLyBjbG9zaW5nIGl0ZW1zIG9ubHkgaWYgdGhleSBhcmUgTWVudUFjdGlvbiBvciBNZW51SXRlbSwgb3RoZXJzIHNob3VsZCBub3QgY2xvc2UgcG9wdXBcbiAgICAgICAgICAgIGlmICghdGhpcy5zaG91bGRDbG9zZU9uRW50ZXIoKSkge1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wb3B1cC50b2dnbGVPcGVuZWQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuVEFCIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkVTQ0FQRVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMucG9wdXAudG9nZ2xlT3BlbmVkKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlQ2xvc2VkS2V5RG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICAvLyBwcmV2ZW50IG9wZW5pbmcgb24gZW50ZXIgYW5kIHByZXZlbnQgc2Nyb2xsaW5nIHBhZ2Ugb24ga2V5IGRvd24va2V5IHVwIHdoZW4gZm9jdXNlZFxuICAgICAgICBpZiAodGhpcy5zaG91bGRCZVByZXZlbnRlZChldmVudCkpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuY29kZSA9PT0gS0VZQk9BUkRfQ09ERS5BUlJPV19ET1dOKSB7XG4gICAgICAgICAgICB0aGlzLnBvcHVwLnRvZ2dsZU9wZW5lZChldmVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNob3VsZEJlUHJldmVudGVkKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBldmVudC5jb2RlID09PSBLRVlCT0FSRF9DT0RFLkFSUk9XX0RPV04gfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuQVJST1dfVVAgfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09IEtFWUJPQVJEX0NPREUuRU5URVJcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBmdW5jdGlvbnMgdG8gc2Nyb2xsIGl0ZW1zIGludG8gdmlldyBmb3IgQWN0aXZlRGVzY2VuZGFudEtleU1hbmFnZXJcbiAgICBwcml2YXRlIGNvdW50R3JvdXBMYWJlbHNCZWZvcmVPcHRpb24oXG4gICAgICAgIG9wdGlvbkluZGV4OiBudW1iZXIsXG4gICAgICAgIG9wdGlvbnM6IFF1ZXJ5TGlzdDxNZW51SXRlbUJhc2VDb21wb25lbnQ+LFxuICAgICAgICBvcHRpb25Hcm91cHM6IFF1ZXJ5TGlzdDxNZW51R3JvdXBDb21wb25lbnQ+XG4gICAgKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKG9wdGlvbkdyb3Vwcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnNBcnJheSA9IG9wdGlvbnMudG9BcnJheSgpO1xuICAgICAgICAgICAgY29uc3QgZ3JvdXBzID0gb3B0aW9uR3JvdXBzLnRvQXJyYXkoKTtcbiAgICAgICAgICAgIGxldCBncm91cENvdW50ZXIgPSAwO1xuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9wdGlvbkluZGV4ICsgMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zQXJyYXlbaV0uZ3JvdXAgJiZcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uc0FycmF5W2ldLmdyb3VwID09PSBncm91cHNbZ3JvdXBDb3VudGVyXVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBncm91cENvdW50ZXIrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBncm91cENvdW50ZXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRPcHRpb25TY3JvbGxQb3NpdGlvbihcbiAgICAgICAgb3B0aW9uSW5kZXg6IG51bWJlcixcbiAgICAgICAgb3B0aW9uSGVpZ2h0OiBudW1iZXIsXG4gICAgICAgIGN1cnJlbnRTY3JvbGxQb3NpdGlvbjogbnVtYmVyLFxuICAgICAgICBwYW5lbEhlaWdodDogbnVtYmVyXG4gICAgKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3Qgb3B0aW9uT2Zmc2V0ID0gb3B0aW9uSW5kZXggKiBvcHRpb25IZWlnaHQ7XG5cbiAgICAgICAgaWYgKG9wdGlvbk9mZnNldCA8IGN1cnJlbnRTY3JvbGxQb3NpdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbk9mZnNldDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25PZmZzZXQgKyBvcHRpb25IZWlnaHQgPiBjdXJyZW50U2Nyb2xsUG9zaXRpb24gKyBwYW5lbEhlaWdodCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubWF4KDAsIG9wdGlvbk9mZnNldCAtIHBhbmVsSGVpZ2h0ICsgb3B0aW9uSGVpZ2h0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjdXJyZW50U2Nyb2xsUG9zaXRpb247XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzY3JvbGxBY3RpdmVPcHRpb25JbnRvVmlldyhvcHRpb25zOiBJUG9wdXBBY3RpdmVPcHRpb25zKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZU9wdGlvbkluZGV4ID0gb3B0aW9ucy5hY3RpdmVPcHRpb25JbmRleCB8fCAwO1xuICAgICAgICBjb25zdCBsYWJlbENvdW50ID0gdGhpcy5jb3VudEdyb3VwTGFiZWxzQmVmb3JlT3B0aW9uKFxuICAgICAgICAgICAgYWN0aXZlT3B0aW9uSW5kZXgsXG4gICAgICAgICAgICBvcHRpb25zLm1lbnVJdGVtcyxcbiAgICAgICAgICAgIG9wdGlvbnMubWVudUdyb3Vwc1xuICAgICAgICApO1xuXG4gICAgICAgIG9wdGlvbnMuc2Nyb2xsQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID1cbiAgICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uU2Nyb2xsUG9zaXRpb24oXG4gICAgICAgICAgICAgICAgYWN0aXZlT3B0aW9uSW5kZXggKyBsYWJlbENvdW50LFxuICAgICAgICAgICAgICAgIG9wdGlvbnMubWVudUl0ZW1IZWlnaHQgKyA0LFxuICAgICAgICAgICAgICAgIG9wdGlvbnMuc2Nyb2xsQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgICAgIDMwMFxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFubm91bmNlQ3VycmVudEl0ZW0oKSB7XG4gICAgICAgIHRoaXMubGl2ZS5hbm5vdW5jZShcbiAgICAgICAgICAgIGBBY3RpdmUgaXRlbSAke3RoaXMua2V5Ym9hcmRFdmVudHNNYW5hZ2VyPy5hY3RpdmVJdGVtPy5tZW51SXRlbS5uYXRpdmVFbGVtZW50LmlubmVyVGV4dH0uYFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMua2V5Ym9hcmRFdmVudHNTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRFdmVudHNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm1lbnVPcGVuTGlzdGVuZXJTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMubWVudU9wZW5MaXN0ZW5lclN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19