@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
218 lines • 32.6 kB
JavaScript
import { FocusKeyManager } from '@angular/cdk/a11y';
import { DOWN_ARROW, END, HOME, LEFT_ARROW, RIGHT_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as i0 from "@angular/core";
export class TabbableListService {
constructor() {
/** Indicate is this is being using on a hierarchichal set of items */
this.hierarchy = false;
/** Determine if we all the alt key */
this.allowAltModifier = true;
/** Determine if we all the ctrl key */
this.allowCtrlModifier = true;
/** Determine if we allow the Home/End keys */
this.allowBoundaryKeys = false;
/** Determine if we should scroll the item into view on focus */
this.shouldScrollInView = true;
/** Indicate if we should refocus an item on QueryList change - for use within virtual lists */
this.shouldFocusOnChange = true;
/** Emit whenever focus does not change but tabindexes have */
this.onTabIndexChange = new Subject();
/** Determine if focus is currently within the tabbable list */
this.isFocused = false;
/** Unsubscribe from all observables on destroy */
this._onDestroy = new Subject();
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
this.onTabIndexChange.complete();
}
initialize(items, direction, wrap) {
// store the items
this._items = items;
// create the new focus key manager
this.focusKeyManager = new FocusKeyManager(items);
// set the direction of the list
direction === 'vertical' ? this.focusKeyManager.withVerticalOrientation() : this.focusKeyManager.withHorizontalOrientation('ltr');
this._direction = direction;
// enable wrapping if required
if (wrap) {
this.focusKeyManager.withWrap();
}
// make sure the first item in the list is tabbable
this.setFirstItemTabbable();
// call the init function on each item
this._items.forEach(item => item.onInit());
// if the list changes we need to ensure there is always at least one tabbable item
this._items.changes.pipe(takeUntil(this._onDestroy)).subscribe(() => {
// call the on init function on any new items
this._items.filter(item => !item.initialized).forEach(item => item.onInit());
// ensure we update the tab indexes
this.onTabIndexChange.next();
// ensure there is at least one item tabbable at all times
this.ensureTabbableItem();
});
}
/** Give and item focus or just make it the current tabbable item */
activate(item, updateIndexOnly = false) {
if (!item) {
return;
}
// get the item index
const index = this._items.toArray().indexOf(item);
this.activateItemAtIndex(index, updateIndexOnly);
}
/** Give and item focus or just make it the current tabbable item */
activateItemAtIndex(index, updateIndexOnly = false) {
// if we only want to update the index
if (updateIndexOnly) {
return this.updateActiveItemIndex(index);
}
// update active the item only if it is not already active
if (this.focusKeyManager.activeItemIndex !== index) {
this.focusKeyManager.setActiveItem(index);
}
}
isItemActive(item) {
// if this is called before the items have been set then do nothing
if (!this._items) {
return false;
}
// find the index of the item
const index = this._items.toArray().findIndex(_item => _item.id === item.id);
// check if the item is active (we check against index as it can be updated without setting the activeItem)
return this.focusKeyManager && this.focusKeyManager.activeItemIndex === index;
}
setFirstItemTabbable() {
// find the first item that is not disabled
const first = this._items.toArray().findIndex(item => !item.disabled);
if (first !== -1) {
this.updateActiveItemIndex(first);
}
}
isAnyItemTabbable() {
const tabbable = this._items.toArray().find(item => item.tabindex === 0);
return tabbable ? true : false;
}
ensureTabbableItem() {
// check to see if any item is tabbable
const active = this._items.find(item => this.isItemActive(item));
if (!active) {
this.setFirstItemTabbable();
}
}
focusTabbableItem() {
if (!this._items) {
return;
}
// find the item in the list with a tab index
const index = this._items.toArray().findIndex(item => this.isItemActive(item));
// if an item was found then focus it
if (index !== -1) {
this.focusKeyManager.setActiveItem(index);
}
}
onKeydown(source, event) {
// prevent anything happening when modifier keys are pressed if they have been disabled
if (!this.allowAltModifier && event.altKey || !this.allowCtrlModifier && event.ctrlKey) {
return;
}
this.focusKeyManager.onKeydown(event);
// if the key is a boundary key and boundary keys are enabled
if (this.allowBoundaryKeys) {
switch (event.which) {
case HOME:
this.focusKeyManager.setFirstItemActive();
event.preventDefault();
break;
case END:
this.focusKeyManager.setLastItemActive();
event.preventDefault();
break;
}
}
if (this.hierarchy) {
if ((this._direction === 'horizontal' && event.keyCode === DOWN_ARROW) ||
(this._direction === 'vertical' && event.keyCode === RIGHT_ARROW)) {
source.keyboardExpanded$.next(true);
}
else if ((this._direction === 'horizontal' && event.keyCode === UP_ARROW) ||
(this._direction === 'vertical' && event.keyCode === LEFT_ARROW)) {
if (source.children.length > 0 && source.expanded) {
source.keyboardExpanded$.next(false);
}
else if (source.parent) {
source.parent.keyboardExpanded$.next(false);
}
}
}
}
sortItemsByHierarchy(list) {
const topLevel = [];
// Populating children - clear previously generated collection
list.forEach(item => item.children = []);
// Populating children - map from child -> parent relationship
list.forEach(item => {
if (item.parent) {
item.parent.children.push(item);
}
else {
topLevel.push(item);
}
});
// Flatten the tree to produce the cursor key order
return this.flattenHierarchy(topLevel);
}
/**
* In a uxVirtualFor list cells can be resused. This means that when we scroll
* the data associated with a given element may change and not the actual elements. If only the data changes
* then the QueryList will not emit a change so we may show focus indicatator on the element that previously displayed
* the correct data but no longer does.
*
* We need to handle this correctly here. We already have keys implements to handle virtual elements so we can check
* if a key changes and use it to update the focused item even if the QueryList doesn't inform us that we have changed.
*/
itemReferenceChange(previousKey, origin) {
// find the item that now has the previously focused key
const item = this.getItemByKey(previousKey);
// if no key was found then we should ensure there is a tabbable item
if (!item) {
return this.ensureTabbableItem();
}
// get the item index
const index = this._items.toArray().indexOf(item);
// activate the item without side effects
this.updateActiveItemIndex(index);
// focus the item with the same origin that it previously had
item.focusWithOrigin(origin);
}
/** Update the active item without causing focus */
updateActiveItemIndex(index) {
this.focusKeyManager.updateActiveItem(index);
this.onTabIndexChange.next();
}
/** Determine if there is an item with a tabindex of 0 */
hasTabbableItem() {
return this.focusKeyManager && this.focusKeyManager.activeItemIndex >= 0;
}
getItemByKey(key) {
return this._items.find(item => item.key === key);
}
flattenHierarchy(items) {
const flatList = [];
items.forEach(item => {
item.children.sort((a, b) => a.rank - b.rank);
flatList.push(item, ...this.flattenHierarchy(item.children));
});
return flatList;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TabbableListService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TabbableListService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TabbableListService, decorators: [{
type: Injectable
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiYmFibGUtbGlzdC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2RpcmVjdGl2ZXMvYWNjZXNzaWJpbGl0eS90YWJiYWJsZS1saXN0L3RhYmJhYmxlLWxpc3Quc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFlLE1BQU0sbUJBQW1CLENBQUM7QUFDakUsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakcsT0FBTyxFQUFFLFVBQVUsRUFBd0IsTUFBTSxlQUFlLENBQUM7QUFDakUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7O0FBSTNDLE1BQU0sT0FBTyxtQkFBbUI7SUFEaEM7UUFHSSxzRUFBc0U7UUFDdEUsY0FBUyxHQUFZLEtBQUssQ0FBQztRQUUzQixzQ0FBc0M7UUFDdEMscUJBQWdCLEdBQVksSUFBSSxDQUFDO1FBRWpDLHVDQUF1QztRQUN2QyxzQkFBaUIsR0FBWSxJQUFJLENBQUM7UUFFbEMsOENBQThDO1FBQzlDLHNCQUFpQixHQUFZLEtBQUssQ0FBQztRQUVuQyxnRUFBZ0U7UUFDaEUsdUJBQWtCLEdBQVksSUFBSSxDQUFDO1FBS25DLCtGQUErRjtRQUMvRix3QkFBbUIsR0FBWSxJQUFJLENBQUM7UUFLcEMsOERBQThEO1FBQzlELHFCQUFnQixHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7UUFFdkMsK0RBQStEO1FBQy9ELGNBQVMsR0FBWSxLQUFLLENBQUM7UUFRM0Isa0RBQWtEO1FBQ2pDLGVBQVUsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0tBNE9yRDtJQTFPRyxXQUFXO1FBQ1AsSUFBSSxDQUFDLFVBQVUsQ0FB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LElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRU8sZ0JBQWdCLENBQUMsS0FBa0M7UUFDdkQsTUFBTSxRQUFRLEdBQWdDLEVBQUUsQ0FBQztRQUNqRCxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDakUsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLFFBQVEsQ0FBQztJQUNwQixDQUFDOytHQWxSUSxtQkFBbUI7bUhBQW5CLG1CQUFtQjs7NEZBQW5CLG1CQUFtQjtrQkFEL0IsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZvY3VzS2V5TWFuYWdlciwgRm9jdXNPcmlnaW4gfSBmcm9tICdAYW5ndWxhci9jZGsvYTExeSc7XG5pbXBvcnQgeyBET1dOX0FSUk9XLCBFTkQsIEhPTUUsIExFRlRfQVJST1csIFJJR0hUX0FSUk9XLCBVUF9BUlJPVyB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9rZXljb2Rlcyc7XG5pbXBvcnQgeyBJbmplY3RhYmxlLCBPbkRlc3Ryb3ksIFF1ZXJ5TGlzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4vdGFiYmFibGUtbGlzdC1pdGVtLmRpcmVjdGl2ZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBUYWJiYWJsZUxpc3RTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcblxuICAgIC8qKiBJbmRpY2F0ZSBpcyB0aGlzIGlzIGJlaW5nIHVzaW5nIG9uIGEgaGllcmFyY2hpY2hhbCBzZXQgb2YgaXRlbXMgKi9cbiAgICBoaWVyYXJjaHk6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBEZXRlcm1pbmUgaWYgd2UgYWxsIHRoZSBhbHQga2V5ICovXG4gICAgYWxsb3dBbHRNb2RpZmllcjogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogRGV0ZXJtaW5lIGlmIHdlIGFsbCB0aGUgY3RybCBrZXkgKi9cbiAgICBhbGxvd0N0cmxNb2RpZmllcjogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogRGV0ZXJtaW5lIGlmIHdlIGFsbG93IHRoZSBIb21lL0VuZCBrZXlzICovXG4gICAgYWxsb3dCb3VuZGFyeUtleXM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIHNjcm9sbCB0aGUgaXRlbSBpbnRvIHZpZXcgb24gZm9jdXMgKi9cbiAgICBzaG91bGRTY3JvbGxJblZpZXc6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFN0b3JlIHRoZSBpbnN0YW5jZSBvZiB0aGUgZm9jdXMga2V5IG1hbmFnZXIgKi9cbiAgICBmb2N1c0tleU1hbmFnZXI6IEZvY3VzS2V5TWFuYWdlcjxUYWJiYWJsZUxpc3RJdGVtRGlyZWN0aXZlPjtcblxuICAgIC8qKiBJbmRpY2F0ZSBpZiB3ZSBzaG91bGQgcmVmb2N1cyBhbiBpdGVtIG9uIFF1ZXJ5TGlzdCBjaGFuZ2UgLSBmb3IgdXNlIHdpdGhpbiB2aXJ0dWFsIGxpc3RzICovXG4gICAgc2hvdWxkRm9jdXNPbkNoYW5nZTogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKiogU3RvcmUgdGhlIGNvbnRhaW5lciBlbGVtZW50ICovXG4gICAgY29udGFpbmVyUmVmOiBIVE1MRWxlbWVudDtcblxuICAgIC8qKiBFbWl0IHdoZW5ldmVyIGZvY3VzIGRvZXMgbm90IGNoYW5nZSBidXQgdGFiaW5kZXhlcyBoYXZlICovXG4gICAgb25UYWJJbmRleENoYW5nZSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICAvKiogRGV0ZXJtaW5lIGlmIGZvY3VzIGlzIGN1cnJlbnRseSB3aXRoaW4gdGhlIHRhYmJhYmxlIGxpc3QgKi9cbiAgICBpc0ZvY3VzZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBTdG9yZSB0aGUgbGlzdCBvZiB0YWJiYWJsZSBpdGVtcyAqL1xuICAgIHByaXZhdGUgX2l0ZW1zOiBRdWVyeUxpc3Q8VGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZT47XG5cbiAgICAvKiogU3RvcmUgdGhlIGRpcmVjdGlvbiBvZiB0aGUgbGlzdCAqL1xuICAgIHByaXZhdGUgX2RpcmVjdGlvbjogJ2hvcml6b250YWwnIHwgJ3ZlcnRpY2FsJztcblxuICAgIC8qKiBVbnN1YnNjcmliZSBmcm9tIGFsbCBvYnNlcnZhYmxlcyBvbiBkZXN0cm95ICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kubmV4dCgpO1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcbiAgICAgICAgdGhpcy5vblRhYkluZGV4Q2hhbmdlLmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgaW5pdGlhbGl6ZShpdGVtczogUXVlcnlMaXN0PFRhYmJhYmxlTGlzdEl0ZW1EaXJlY3RpdmU+LCBkaXJlY3Rpb246ICdob3Jpem9udGFsJyB8ICd2ZXJ0aWNhbCcsIHdyYXA6IGJvb2xlYW4pOiB2b2lkIHtcblxuICAgICAgICAvLyBzdG9yZSB0aGUgaXRlbXNcbiAgICAgICAgdGhpcy5faXRlbXMgPSBpdGVtcztcblxuICAgICAgICAvLyBjcmVhdGUgdGhlIG5ldyBmb2N1cyBrZXkgbWFuYWdlclxuICAgICAgICB0aGlzLmZvY3VzS2V5TWFuYWdlciA9IG5ldyBGb2N1c0tleU1hbmFnZXIoaXRlbXMpO1xuXG4gICAgICAgIC8vIHNldCB0aGUgZGlyZWN0aW9uIG9mIHRoZSBsaXN0XG4gICAgICAgIGRpcmVjdGlvbiA9PT0gJ3ZlcnRpY2FsJyA/IHRoaXMuZm9jdXNLZXlNYW5hZ2VyLndpdGhWZXJ0aWNhbE9yaWVudGF0aW9uKCkgOiB0aGlzLmZvY3VzS2V5TWFuYWdlci53aXRoSG9yaXpvbnRhbE9yaWVudGF0aW9uKCdsdHInKTtcbiAgICAgICAgdGhpcy5fZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXG4gICAgICAgIC8vIGVuYWJsZSB3cmFwcGluZyBpZiByZXF1aXJlZFxuICAgICAgICBpZiAod3JhcCkge1xuICAgICAgICAgICAgdGhpcy5mb2N1c0tleU1hbmFnZXIud2l0aFdyYXAoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgbGlzdCBpcyB0YWJiYWJsZVxuICAgICAgICB0aGlzLnNldEZpcnN0SXRlbVRhYmJhYmxlKCk7XG5cbiAgICAgICAgLy8gY2FsbCB0aGUgaW5pdCBmdW5jdGlvbiBvbiBlYWNoIGl0ZW1cbiAgICAgICAgdGhpcy5faXRlbXMuZm9yRWFjaChpdGVtID0+IGl0ZW0ub25Jbml0KCkpO1xuXG4gICAgICAgIC8vIGlmIHRoZSBsaXN0IGNoYW5nZXMgd2UgbmVlZCB0byBlbnN1cmUgdGhlcmUgaXMgYWx3YXlzIGF0IGxlYXN0IG9uZSB0YWJiYWJsZSBpdGVtXG4gICAgICAgIHRoaXMuX2l0ZW1zLmNoYW5nZXMucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKCgpID0+IHtcblxuICAgICAgICAgICAgLy8gY2FsbCB0aGUgb24gaW5pdCBmdW5jdGlvbiBvbiBhbnkgbmV3IGl0ZW1zXG4gICAgICAgICAgICB0aGlzLl9pdGVtcy5maWx0ZXIoaXRlbSA9PiAhaXRlbS5pbml0aWFsaXplZCkuZm9yRWFjaChpdGVtID0+IGl0ZW0ub25Jbml0KCkpO1xuXG4gICAgICAgICAgICAvLyBlbnN1cmUgd2UgdXBkYXRlIHRoZSB0YWIgaW5kZXhlc1xuICAgICAgICAgICAgdGhpcy5vblRhYkluZGV4Q2hhbmdlLm5leHQoKTtcblxuICAgICAgICAgICAgLy8gZW5zdXJlIHRoZXJlIGlzIGF0IGxlYXN0IG9uZSBpdGVtIHRhYmJhYmxlIGF0IGFsbCB0aW1lc1xuICAgICAgICAgICAgdGhpcy5lbnN1cmVUYWJiYWJsZUl0ZW0oKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEdpdmUgYW5kIGl0ZW0gZm9jdXMgb3IganVzdCBtYWtlIGl0IHRoZSBjdXJyZW50IHRhYmJhYmxlIGl0ZW0gKi9cbiAgICBhY3RpdmF0ZShpdGVtOiBUYWJiYWJsZUxpc3RJdGVtRGlyZWN0aXZlLCB1cGRhdGVJbmRleE9ubHk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuXG4gICAgICAgIGlmICghaXRlbSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZ2V0IHRoZSBpdGVtIGluZGV4XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5faXRlbXMudG9BcnJheSgpLmluZGV4T2YoaXRlbSk7XG5cbiAgICAgICAgdGhpcy5hY3RpdmF0ZUl0ZW1BdEluZGV4KGluZGV4LCB1cGRhdGVJbmRleE9ubHkpO1xuICAgIH1cblxuICAgIC8qKiBHaXZlIGFuZCBpdGVtIGZvY3VzIG9yIGp1c3QgbWFrZSBpdCB0aGUgY3VycmVudCB0YWJiYWJsZSBpdGVtICovXG4gICAgYWN0aXZhdGVJdGVtQXRJbmRleChpbmRleDogbnVtYmVyLCB1cGRhdGVJbmRleE9ubHk6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuXG4gICAgICAgIC8vIGlmIHdlIG9ubHkgd2FudCB0byB1cGRhdGUgdGhlIGluZGV4XG4gICAgICAgIGlmICh1cGRhdGVJbmRleE9ubHkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnVwZGF0ZUFjdGl2ZUl0ZW1JbmRleChpbmRleCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB1cGRhdGUgYWN0aXZlIHRoZSBpdGVtIG9ubHkgaWYgaXQgaXMgbm90IGFscmVhZHkgYWN0aXZlXG4gICAgICAgIGlmICh0aGlzLmZvY3VzS2V5TWFuYWdlci5hY3RpdmVJdGVtSW5kZXggIT09IGluZGV4KSB7XG4gICAgICAgICAgICB0aGlzLmZvY3VzS2V5TWFuYWdlci5zZXRBY3RpdmVJdGVtKGluZGV4KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlzSXRlbUFjdGl2ZShpdGVtOiBUYWJiYWJsZUxpc3RJdGVtRGlyZWN0aXZlKTogYm9vbGVhbiB7XG5cbiAgICAgICAgLy8gaWYgdGhpcyBpcyBjYWxsZWQgYmVmb3JlIHRoZSBpdGVtcyBoYXZlIGJlZW4gc2V0IHRoZW4gZG8gbm90aGluZ1xuICAgICAgICBpZiAoIXRoaXMuX2l0ZW1zKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaW5kIHRoZSBpbmRleCBvZiB0aGUgaXRlbVxuICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuX2l0ZW1zLnRvQXJyYXkoKS5maW5kSW5kZXgoX2l0ZW0gPT4gX2l0ZW0uaWQgPT09IGl0ZW0uaWQpO1xuXG4gICAgICAgIC8vIGNoZWNrIGlmIHRoZSBpdGVtIGlzIGFjdGl2ZSAod2UgY2hlY2sgYWdhaW5zdCBpbmRleCBhcyBpdCBjYW4gYmUgdXBkYXRlZCB3aXRob3V0IHNldHRpbmcgdGhlIGFjdGl2ZUl0ZW0pXG4gICAgICAgIHJldHVybiB0aGlzLmZvY3VzS2V5TWFuYWdlciAmJiB0aGlzLmZvY3VzS2V5TWFuYWdlci5hY3RpdmVJdGVtSW5kZXggPT09IGluZGV4O1xuICAgIH1cblxuICAgIHNldEZpcnN0SXRlbVRhYmJhYmxlKCk6IHZvaWQge1xuICAgICAgICAvLyBmaW5kIHRoZSBmaXJzdCBpdGVtIHRoYXQgaXMgbm90IGRpc2FibGVkXG4gICAgICAgIGNvbnN0IGZpcnN0ID0gdGhpcy5faXRlbXMudG9BcnJheSgpLmZpbmRJbmRleChpdGVtID0+ICFpdGVtLmRpc2FibGVkKTtcblxuICAgICAgICBpZiAoZmlyc3QgIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUFjdGl2ZUl0ZW1JbmRleChmaXJzdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpc0FueUl0ZW1UYWJiYWJsZSgpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgdGFiYmFibGUgPSB0aGlzLl9pdGVtcy50b0FycmF5KCkuZmluZChpdGVtID0+IGl0ZW0udGFiaW5kZXggPT09IDApO1xuICAgICAgICByZXR1cm4gdGFiYmFibGUgPyB0cnVlIDogZmFsc2U7XG4gICAgfVxuXG4gICAgZW5zdXJlVGFiYmFibGVJdGVtKCk6IHZvaWQge1xuICAgICAgICAvLyBjaGVjayB0byBzZWUgaWYgYW55IGl0ZW0gaXMgdGFiYmFibGVcbiAgICAgICAgY29uc3QgYWN0aXZlID0gdGhpcy5faXRlbXMuZmluZChpdGVtID0+IHRoaXMuaXNJdGVtQWN0aXZlKGl0ZW0pKTtcblxuICAgICAgICBpZiAoIWFjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRGaXJzdEl0ZW1UYWJiYWJsZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9jdXNUYWJiYWJsZUl0ZW0oKTogdm9pZCB7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9pdGVtcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluZCB0aGUgaXRlbSBpbiB0aGUgbGlzdCB3aXRoIGEgdGFiIGluZGV4XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5faXRlbXMudG9BcnJheSgpLmZpbmRJbmRleChpdGVtID0+IHRoaXMuaXNJdGVtQWN0aXZlKGl0ZW0pKTtcblxuICAgICAgICAvLyBpZiBhbiBpdGVtIHdhcyBmb3VuZCB0aGVuIGZvY3VzIGl0XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNLZXlNYW5hZ2VyLnNldEFjdGl2ZUl0ZW0oaW5kZXgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25LZXlkb3duKHNvdXJjZTogVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZSwgZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBwcmV2ZW50IGFueXRoaW5nIGhhcHBlbmluZyB3aGVuIG1vZGlmaWVyIGtleXMgYXJlIHByZXNzZWQgaWYgdGhleSBoYXZlIGJlZW4gZGlzYWJsZWRcbiAgICAgICAgaWYgKCF0aGlzLmFsbG93QWx0TW9kaWZpZXIgJiYgZXZlbnQuYWx0S2V5IHx8ICF0aGlzLmFsbG93Q3RybE1vZGlmaWVyICYmIGV2ZW50LmN0cmxLZXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZm9jdXNLZXlNYW5hZ2VyLm9uS2V5ZG93bihldmVudCk7XG5cbiAgICAgICAgLy8gaWYgdGhlIGtleSBpcyBhIGJvdW5kYXJ5IGtleSBhbmQgYm91bmRhcnkga2V5cyBhcmUgZW5hYmxlZFxuICAgICAgICBpZiAodGhpcy5hbGxvd0JvdW5kYXJ5S2V5cykge1xuICAgICAgICAgICAgc3dpdGNoIChldmVudC53aGljaCkge1xuICAgICAgICAgICAgICAgIGNhc2UgSE9NRTpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb2N1c0tleU1hbmFnZXIuc2V0Rmlyc3RJdGVtQWN0aXZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBFTkQ6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNLZXlNYW5hZ2VyLnNldExhc3RJdGVtQWN0aXZlKCk7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaGllcmFyY2h5KSB7XG5cbiAgICAgICAgICAgIGlmICgodGhpcy5fZGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgJiYgZXZlbnQua2V5Q29kZSA9PT0gRE9XTl9BUlJPVykgfHxcbiAgICAgICAgICAgICAgICAodGhpcy5fZGlyZWN0aW9uID09PSAndmVydGljYWwnICYmIGV2ZW50LmtleUNvZGUgPT09IFJJR0hUX0FSUk9XKSkge1xuICAgICAgICAgICAgICAgIHNvdXJjZS5rZXlib2FyZEV4cGFuZGVkJC5uZXh0KHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgodGhpcy5fZGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgJiYgZXZlbnQua2V5Q29kZSA9PT0gVVBfQVJST1cpIHx8XG4gICAgICAgICAgICAgICAgKHRoaXMuX2RpcmVjdGlvbiA9PT0gJ3ZlcnRpY2FsJyAmJiBldmVudC5rZXlDb2RlID09PSBMRUZUX0FSUk9XKSkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHNvdXJjZS5jaGlsZHJlbi5sZW5ndGggPiAwICYmIHNvdXJjZS5leHBhbmRlZCkge1xuICAgICAgICAgICAgICAgICAgICBzb3VyY2Uua2V5Ym9hcmRFeHBhbmRlZCQubmV4dChmYWxzZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzb3VyY2UucGFyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZS5wYXJlbnQua2V5Ym9hcmRFeHBhbmRlZCQubmV4dChmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc29ydEl0ZW1zQnlIaWVyYXJjaHkobGlzdDogUXVlcnlMaXN0PFRhYmJhYmxlTGlzdEl0ZW1EaXJlY3RpdmU+KTogVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZVtdIHtcblxuICAgICAgICBjb25zdCB0b3BMZXZlbDogVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZVtdID0gW107XG5cbiAgICAgICAgLy8gUG9wdWxhdGluZyBjaGlsZHJlbiAtIGNsZWFyIHByZXZpb3VzbHkgZ2VuZXJhdGVkIGNvbGxlY3Rpb25cbiAgICAgICAgbGlzdC5mb3JFYWNoKGl0ZW0gPT4gaXRlbS5jaGlsZHJlbiA9IFtdKTtcblxuICAgICAgICAvLyBQb3B1bGF0aW5nIGNoaWxkcmVuIC0gbWFwIGZyb20gY2hpbGQgLT4gcGFyZW50IHJlbGF0aW9uc2hpcFxuICAgICAgICBsaXN0LmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgICAgICBpZiAoaXRlbS5wYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBpdGVtLnBhcmVudC5jaGlsZHJlbi5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0b3BMZXZlbC5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBGbGF0dGVuIHRoZSB0cmVlIHRvIHByb2R1Y2UgdGhlIGN1cnNvciBrZXkgb3JkZXJcbiAgICAgICAgcmV0dXJuIHRoaXMuZmxhdHRlbkhpZXJhcmNoeSh0b3BMZXZlbCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW4gYSB1eFZpcnR1YWxGb3IgbGlzdCBjZWxscyBjYW4gYmUgcmVzdXNlZC4gVGhpcyBtZWFucyB0aGF0IHdoZW4gd2Ugc2Nyb2xsXG4gICAgICogdGhlIGRhdGEgYXNzb2NpYXRlZCB3aXRoIGEgZ2l2ZW4gZWxlbWVudCBtYXkgY2hhbmdlIGFuZCBub3QgdGhlIGFjdHVhbCBlbGVtZW50cy4gSWYgb25seSB0aGUgZGF0YSBjaGFuZ2VzXG4gICAgICogdGhlbiB0aGUgUXVlcnlMaXN0IHdpbGwgbm90IGVtaXQgYSBjaGFuZ2Ugc28gd2UgbWF5IHNob3cgZm9jdXMgaW5kaWNhdGF0b3Igb24gdGhlIGVsZW1lbnQgdGhhdCBwcmV2aW91c2x5IGRpc3BsYXllZFxuICAgICAqIHRoZSBjb3JyZWN0IGRhdGEgYnV0IG5vIGxvbmdlciBkb2VzLlxuICAgICAqXG4gICAgICogV2UgbmVlZCB0byBoYW5kbGUgdGhpcyBjb3JyZWN0bHkgaGVyZS4gV2UgYWxyZWFkeSBoYXZlIGtleXMgaW1wbGVtZW50cyB0byBoYW5kbGUgdmlydHVhbCBlbGVtZW50cyBzbyB3ZSBjYW4gY2hlY2tcbiAgICAgKiBpZiBhIGtleSBjaGFuZ2VzIGFuZCB1c2UgaXQgdG8gdXBkYXRlIHRoZSBmb2N1c2VkIGl0ZW0gZXZlbiBpZiB0aGUgUXVlcnlMaXN0IGRvZXNuJ3QgaW5mb3JtIHVzIHRoYXQgd2UgaGF2ZSBjaGFuZ2VkLlxuICAgICAqL1xuICAgIGl0ZW1SZWZlcmVuY2VDaGFuZ2UocHJldmlvdXNLZXk6IHVua25vd24sIG9yaWdpbjogRm9jdXNPcmlnaW4pOiB2b2lkIHtcbiAgICAgICAgLy8gZmluZCB0aGUgaXRlbSB0aGF0IG5vdyBoYXMgdGhlIHByZXZpb3VzbHkgZm9jdXNlZCBrZXlcbiAgICAgICAgY29uc3QgaXRlbSA9IHRoaXMuZ2V0SXRlbUJ5S2V5KHByZXZpb3VzS2V5KTtcblxuICAgICAgICAvLyBpZiBubyBrZXkgd2FzIGZvdW5kIHRoZW4gd2Ugc2hvdWxkIGVuc3VyZSB0aGVyZSBpcyBhIHRhYmJhYmxlIGl0ZW1cbiAgICAgICAgaWYgKCFpdGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbnN1cmVUYWJiYWJsZUl0ZW0oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCB0aGUgaXRlbSBpbmRleFxuICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuX2l0ZW1zLnRvQXJyYXkoKS5pbmRleE9mKGl0ZW0pO1xuXG4gICAgICAgIC8vIGFjdGl2YXRlIHRoZSBpdGVtIHdpdGhvdXQgc2lkZSBlZmZlY3RzXG4gICAgICAgIHRoaXMudXBkYXRlQWN0aXZlSXRlbUluZGV4KGluZGV4KTtcblxuICAgICAgICAvLyBmb2N1cyB0aGUgaXRlbSB3aXRoIHRoZSBzYW1lIG9yaWdpbiB0aGF0IGl0IHByZXZpb3VzbHkgaGFkXG4gICAgICAgIGl0ZW0uZm9jdXNXaXRoT3JpZ2luKG9yaWdpbik7XG4gICAgfVxuXG4gICAgLyoqIFVwZGF0ZSB0aGUgYWN0aXZlIGl0ZW0gd2l0aG91dCBjYXVzaW5nIGZvY3VzICovXG4gICAgdXBkYXRlQWN0aXZlSXRlbUluZGV4KGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb2N1c0tleU1hbmFnZXIudXBkYXRlQWN0aXZlSXRlbShpbmRleCk7XG4gICAgICAgIHRoaXMub25UYWJJbmRleENoYW5nZS5uZXh0KCk7XG4gICAgfVxuXG4gICAgLyoqIERldGVybWluZSBpZiB0aGVyZSBpcyBhbiBpdGVtIHdpdGggYSB0YWJpbmRleCBvZiAwICovXG4gICAgaGFzVGFiYmFibGVJdGVtKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c0tleU1hbmFnZXIgJiYgdGhpcy5mb2N1c0tleU1hbmFnZXIuYWN0aXZlSXRlbUluZGV4ID49IDA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJdGVtQnlLZXkoa2V5OiB1bmtub3duKTogVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5faXRlbXMuZmluZChpdGVtID0+IGl0ZW0ua2V5ID09PSBrZXkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZmxhdHRlbkhpZXJhcmNoeShpdGVtczogVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZVtdKTogVGFiYmFibGVMaXN0SXRlbURpcmVjdGl2ZVtdIHtcbiAgICAgICAgY29uc3QgZmxhdExpc3Q6IFRhYmJhYmxlTGlzdEl0ZW1EaXJlY3RpdmVbXSA9IFtdO1xuICAgICAgICBpdGVtcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICAgICAgaXRlbS5jaGlsZHJlbi5zb3J0KChhLCBiKSA9PiBhLnJhbmsgLSBiLnJhbmspO1xuICAgICAgICAgICAgZmxhdExpc3QucHVzaChpdGVtLCAuLi50aGlzLmZsYXR0ZW5IaWVyYXJjaHkoaXRlbS5jaGlsZHJlbikpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGZsYXRMaXN0O1xuICAgIH1cbn1cbiJdfQ==