@ifsworld/granite-components 15.0.2 → 16.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/date-picker/lib/date-picker-base.d.ts +3 -3
- package/date-picker/lib/date-picker.module.d.ts +2 -2
- package/fesm2022/ifsworld-granite-components-carousel.mjs +9 -9
- package/fesm2022/ifsworld-granite-components-carousel.mjs.map +1 -1
- package/fesm2022/ifsworld-granite-components-date-picker.mjs +34 -30
- package/fesm2022/ifsworld-granite-components-date-picker.mjs.map +1 -1
- package/fesm2022/ifsworld-granite-components-file-upload.mjs +13 -12
- package/fesm2022/ifsworld-granite-components-file-upload.mjs.map +1 -1
- package/fesm2022/ifsworld-granite-components-table.mjs +32 -29
- package/fesm2022/ifsworld-granite-components-table.mjs.map +1 -1
- package/fesm2022/ifsworld-granite-components-tooltip.mjs +16 -15
- package/fesm2022/ifsworld-granite-components-tooltip.mjs.map +1 -1
- package/fesm2022/ifsworld-granite-components.mjs +341 -322
- package/fesm2022/ifsworld-granite-components.mjs.map +1 -1
- package/lib/contacts/contacts-trigger/contacts-trigger-data.d.ts +1 -1
- package/lib/core/overlay-base.d.ts +1 -1
- package/lib/core/radio-checkbox-base.d.ts +1 -1
- package/lib/menu/menu-base.d.ts +1 -1
- package/lib/progress-bar/progress-bar-legend-base.d.ts +1 -1
- package/package.json +13 -25
- package/src/lib/core/style/_mixins.scss +10 -9
- package/src/lib/core/style/_range-functions.scss +6 -4
- package/src/lib/core/style/_z-index.scss +6 -4
- package/table/lib/cell/cell.d.ts +1 -1
- package/esm2022/carousel/ifsworld-granite-components-carousel.mjs +0 -5
- package/esm2022/carousel/index.mjs +0 -3
- package/esm2022/carousel/lib/carousel.component.mjs +0 -156
- package/esm2022/carousel/lib/carousel.module.mjs +0 -31
- package/esm2022/date-picker/ifsworld-granite-components-date-picker.mjs +0 -5
- package/esm2022/date-picker/index.mjs +0 -5
- package/esm2022/date-picker/lib/date-picker-base.mjs +0 -53
- package/esm2022/date-picker/lib/date-picker-trigger-for.directive.mjs +0 -228
- package/esm2022/date-picker/lib/date-picker.component.mjs +0 -30
- package/esm2022/date-picker/lib/date-picker.module.mjs +0 -58
- package/esm2022/date-picker/lib/date-range-picker.component.mjs +0 -46
- package/esm2022/file-upload/ifsworld-granite-components-file-upload.mjs +0 -5
- package/esm2022/file-upload/index.mjs +0 -3
- package/esm2022/file-upload/lib/directives/file-drag-and-drop.directive.mjs +0 -102
- package/esm2022/file-upload/lib/file-upload.component.mjs +0 -182
- package/esm2022/file-upload/lib/file-upload.constants.mjs +0 -45
- package/esm2022/file-upload/lib/file-upload.module.mjs +0 -32
- package/esm2022/file-upload/lib/file-upload.utils.mjs +0 -13
- package/esm2022/ifsworld-granite-components.mjs +0 -5
- package/esm2022/index.mjs +0 -90
- package/esm2022/lib/arrange-grid/arrange-grid-item.component.mjs +0 -44
- package/esm2022/lib/arrange-grid/arrange-grid.component.mjs +0 -125
- package/esm2022/lib/arrange-grid/arrange-grid.module.mjs +0 -19
- package/esm2022/lib/avatar/avatar-default-status/avatar-default-status.component.mjs +0 -36
- package/esm2022/lib/avatar/avatar.component.mjs +0 -68
- package/esm2022/lib/avatar/avatar.component.public-types.mjs +0 -7
- package/esm2022/lib/avatar/avatar.module.mjs +0 -37
- package/esm2022/lib/avatar/custom-avatar-status.directive.mjs +0 -18
- package/esm2022/lib/avatar/empty-avatar/empty-avatar.component.mjs +0 -37
- package/esm2022/lib/badge/badge.component.mjs +0 -39
- package/esm2022/lib/badge/badge.module.mjs +0 -18
- package/esm2022/lib/badge/testing/badge.harness.mjs +0 -25
- package/esm2022/lib/button/button.component.mjs +0 -87
- package/esm2022/lib/button/button.module.mjs +0 -16
- package/esm2022/lib/card-list/card/card-avatar.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-actions.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-body.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-content.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-footer.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-header-subtitle.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-header-title.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card-content/card-header.component.mjs +0 -11
- package/esm2022/lib/card-list/card/card.component.mjs +0 -11
- package/esm2022/lib/card-list/card-list.component.mjs +0 -24
- package/esm2022/lib/card-list/card-list.module.mjs +0 -68
- package/esm2022/lib/checkbox/checkbox-group.component.mjs +0 -17
- package/esm2022/lib/checkbox/checkbox.component.mjs +0 -99
- package/esm2022/lib/checkbox/checkbox.module.mjs +0 -17
- package/esm2022/lib/chips/chip-input.mjs +0 -195
- package/esm2022/lib/chips/chip-list.component.mjs +0 -567
- package/esm2022/lib/chips/chip.component.mjs +0 -288
- package/esm2022/lib/chips/chips.module.mjs +0 -31
- package/esm2022/lib/collapsible-group/collapsible-group-body.directive.mjs +0 -17
- package/esm2022/lib/collapsible-group/collapsible-group-header.directive.mjs +0 -17
- package/esm2022/lib/collapsible-group/collapsible-group.component.mjs +0 -46
- package/esm2022/lib/collapsible-group/collapsible-group.module.mjs +0 -33
- package/esm2022/lib/contacts/contact-item/contact-item.component.mjs +0 -27
- package/esm2022/lib/contacts/contact-item-default-status/contact-item-default-status.component.mjs +0 -20
- package/esm2022/lib/contacts/contact-item-title/contact-item-title.component.mjs +0 -15
- package/esm2022/lib/contacts/contacts-profile/contacts-profile.component.mjs +0 -18
- package/esm2022/lib/contacts/contacts-trigger/contacts-trigger-data.mjs +0 -24
- package/esm2022/lib/contacts/contacts-trigger/contacts-trigger-for.directive.mjs +0 -231
- package/esm2022/lib/contacts/contacts-types/contacts.component.private-types.mjs +0 -2
- package/esm2022/lib/contacts/contacts-types/contacts.component.public-types.mjs +0 -9
- package/esm2022/lib/contacts/contacts.component.mjs +0 -92
- package/esm2022/lib/contacts/contacts.module.mjs +0 -53
- package/esm2022/lib/contacts/custom-profile.directive.mjs +0 -16
- package/esm2022/lib/contacts/custom-status.directive.mjs +0 -18
- package/esm2022/lib/core/animation.mjs +0 -34
- package/esm2022/lib/core/client-environment.mjs +0 -20
- package/esm2022/lib/core/common-behaviors/disabled.mjs +0 -27
- package/esm2022/lib/core/core.module.mjs +0 -44
- package/esm2022/lib/core/devices/client-input-desktop.directive.mjs +0 -29
- package/esm2022/lib/core/devices/client-input-touch.directive.mjs +0 -29
- package/esm2022/lib/core/devices/client-output-desktop.directive.mjs +0 -29
- package/esm2022/lib/core/devices/client-output-touch.directive.mjs +0 -29
- package/esm2022/lib/core/hide-on-overflow.directive.mjs +0 -83
- package/esm2022/lib/core/overlay-base.mjs +0 -18
- package/esm2022/lib/core/overlay-position-config.mjs +0 -2
- package/esm2022/lib/core/overlay-trigger-for-base.directive.mjs +0 -121
- package/esm2022/lib/core/overlay.service.mjs +0 -90
- package/esm2022/lib/core/pipes/pure-pipes.module.mjs +0 -16
- package/esm2022/lib/core/pipes/title.pipe.mjs +0 -21
- package/esm2022/lib/core/radio-checkbox-base.mjs +0 -19
- package/esm2022/lib/core/services/names-utils-service.mjs +0 -51
- package/esm2022/lib/core/theme.library.mjs +0 -59
- package/esm2022/lib/core/types.mjs +0 -2
- package/esm2022/lib/grid/grid.component.mjs +0 -128
- package/esm2022/lib/grid/grid.module.mjs +0 -18
- package/esm2022/lib/icon/icon.component.mjs +0 -43
- package/esm2022/lib/icon/icon.module.mjs +0 -16
- package/esm2022/lib/input-field/input-field.component.mjs +0 -167
- package/esm2022/lib/input-field/input-field.module.mjs +0 -20
- package/esm2022/lib/label/label.component.mjs +0 -31
- package/esm2022/lib/label/label.module.mjs +0 -18
- package/esm2022/lib/menu/divider.directive.mjs +0 -23
- package/esm2022/lib/menu/menu-base.mjs +0 -364
- package/esm2022/lib/menu/menu-desktop-animations.mjs +0 -23
- package/esm2022/lib/menu/menu-errors.mjs +0 -37
- package/esm2022/lib/menu/menu-item.component.mjs +0 -89
- package/esm2022/lib/menu/menu-panel.mjs +0 -7
- package/esm2022/lib/menu/menu-positions.mjs +0 -9
- package/esm2022/lib/menu/menu-touch-animations.mjs +0 -137
- package/esm2022/lib/menu/menu-touch-close.component.mjs +0 -13
- package/esm2022/lib/menu/menu-touch-title.component.mjs +0 -59
- package/esm2022/lib/menu/menu-trigger-for.directive.mjs +0 -738
- package/esm2022/lib/menu/menu.component.mjs +0 -30
- package/esm2022/lib/menu/menu.module.mjs +0 -55
- package/esm2022/lib/menu/testing/menu.harness.mjs +0 -109
- package/esm2022/lib/menu/title.directive.mjs +0 -17
- package/esm2022/lib/progress-bar/progress-bar-legend/progress-bar-legend.component.mjs +0 -19
- package/esm2022/lib/progress-bar/progress-bar-legend-base.mjs +0 -17
- package/esm2022/lib/progress-bar/progress-bar-legend-trigger-for.directive.mjs +0 -54
- package/esm2022/lib/progress-bar/progress-bar.component.mjs +0 -92
- package/esm2022/lib/progress-bar/progress-bar.model.mjs +0 -2
- package/esm2022/lib/progress-bar/progress-bar.module.mjs +0 -44
- package/esm2022/lib/radio-button/radio-button.component.mjs +0 -119
- package/esm2022/lib/radio-button/radio-button.module.mjs +0 -17
- package/esm2022/lib/radio-button/radio-group.component.mjs +0 -17
- package/esm2022/lib/toggle-switch/toggle-switch.component.mjs +0 -100
- package/esm2022/lib/toggle-switch/toggle-switch.module.mjs +0 -16
- package/esm2022/table/ifsworld-granite-components-table.mjs +0 -5
- package/esm2022/table/index.mjs +0 -5
- package/esm2022/table/lib/cell/cell-align/cell-align-classes.directive.mjs +0 -26
- package/esm2022/table/lib/cell/cell.mjs +0 -15
- package/esm2022/table/lib/cell/table-data-cell.component.mjs +0 -25
- package/esm2022/table/lib/cell/table-header-cell.component.mjs +0 -14
- package/esm2022/table/lib/column/table-column.directive.mjs +0 -33
- package/esm2022/table/lib/column-size/column-size.directive.mjs +0 -34
- package/esm2022/table/lib/table-constants.library.mjs +0 -7
- package/esm2022/table/lib/table.component.mjs +0 -62
- package/esm2022/table/lib/table.model.mjs +0 -2
- package/esm2022/table/lib/table.module.mjs +0 -38
- package/esm2022/tooltip/ifsworld-granite-components-tooltip.mjs +0 -5
- package/esm2022/tooltip/index.mjs +0 -4
- package/esm2022/tooltip/lib/Services/granite-tooltip.service.mjs +0 -28
- package/esm2022/tooltip/lib/tooltip-constants.library.mjs +0 -4
- package/esm2022/tooltip/lib/tooltip-trigger-for.directive.mjs +0 -147
- package/esm2022/tooltip/lib/tooltip.component.mjs +0 -14
- package/esm2022/tooltip/lib/tooltip.module.mjs +0 -19
|
@@ -1,738 +0,0 @@
|
|
|
1
|
-
import { ChangeDetectorRef, Directive, ElementRef, Inject, Input, Optional, Self, ViewContainerRef, } from '@angular/core';
|
|
2
|
-
import { DOCUMENT } from '@angular/common';
|
|
3
|
-
import { FocusMonitor, isFakeMousedownFromScreenReader, } from '@angular/cdk/a11y';
|
|
4
|
-
import { Directionality } from '@angular/cdk/bidi';
|
|
5
|
-
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
|
|
6
|
-
import { Overlay, OverlayConfig, } from '@angular/cdk/overlay';
|
|
7
|
-
import { TemplatePortal } from '@angular/cdk/portal';
|
|
8
|
-
import { asapScheduler, fromEvent, merge, of as observableOf, Subscription, } from 'rxjs';
|
|
9
|
-
import { delay, filter, take, takeUntil } from 'rxjs/operators';
|
|
10
|
-
import { _MenuBaseComponent } from './menu-base';
|
|
11
|
-
import { GraniteMenuItemComponent } from './menu-item.component';
|
|
12
|
-
import { GRANITE_MENU_PANEL } from './menu-panel';
|
|
13
|
-
//#region --- Touch device customizations ---
|
|
14
|
-
import { GRANITE_CLIENT_INPUT, GRANITE_CLIENT_OUTPUT, } from '../core/client-environment';
|
|
15
|
-
import { throwGraniteMenuMissingError } from './menu-errors';
|
|
16
|
-
import * as i0 from "@angular/core";
|
|
17
|
-
import * as i1 from "@angular/cdk/overlay";
|
|
18
|
-
import * as i2 from "./menu-item.component";
|
|
19
|
-
import * as i3 from "@angular/cdk/bidi";
|
|
20
|
-
import * as i4 from "@angular/cdk/a11y";
|
|
21
|
-
import * as i5 from "./menu-base";
|
|
22
|
-
/** Options for binding a passive event listener. */
|
|
23
|
-
const passiveEventListenerOptions = normalizePassiveListenerOptions({
|
|
24
|
-
passive: true,
|
|
25
|
-
});
|
|
26
|
-
//#endregion --- Touch device customizations ---
|
|
27
|
-
/**
|
|
28
|
-
* Directive used to turn a button element into a (popup) menu trigger
|
|
29
|
-
*
|
|
30
|
-
* Stripped-down version of Angular Material's menu trigger directive (.../menu/menu-trigger.ts)
|
|
31
|
-
*/
|
|
32
|
-
export class GraniteMenuTriggerForDirective {
|
|
33
|
-
constructor(_overlay, _element, _viewContainerRef, _changeDetectionRef,
|
|
34
|
-
/** If this is a _submenu_ trigger, it will have a parent menu */
|
|
35
|
-
_parentMenu,
|
|
36
|
-
//#region --- Touch device customizations ---
|
|
37
|
-
/** Client input device information */
|
|
38
|
-
_clientInput,
|
|
39
|
-
/** Client output device information */
|
|
40
|
-
_clientOutput,
|
|
41
|
-
//#endregion --- Touch device customizations ---
|
|
42
|
-
/**
|
|
43
|
-
* If this is a _submenu_ trigger, there should be a corresponding menu
|
|
44
|
-
* item directive present as well:
|
|
45
|
-
*
|
|
46
|
-
* <button graniteMenuItem [graniteMenuTriggerFor]="...">
|
|
47
|
-
* ^-- This one
|
|
48
|
-
*/
|
|
49
|
-
_menuItemInstance, _dir, _focusMonitor,
|
|
50
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
51
|
-
document) {
|
|
52
|
-
this._overlay = _overlay;
|
|
53
|
-
this._element = _element;
|
|
54
|
-
this._viewContainerRef = _viewContainerRef;
|
|
55
|
-
this._changeDetectionRef = _changeDetectionRef;
|
|
56
|
-
this._parentMenu = _parentMenu;
|
|
57
|
-
this._clientInput = _clientInput;
|
|
58
|
-
this._clientOutput = _clientOutput;
|
|
59
|
-
this._menuItemInstance = _menuItemInstance;
|
|
60
|
-
this._dir = _dir;
|
|
61
|
-
this._focusMonitor = _focusMonitor;
|
|
62
|
-
this.openOnClick = true;
|
|
63
|
-
/** Whether the associated menu is open */
|
|
64
|
-
this.isMenuOpened = false;
|
|
65
|
-
// Tracking input type is necessary so it's possible to only auto-focus
|
|
66
|
-
// the first item of the list when the menu is opened via the keyboard
|
|
67
|
-
this.openedBy = null;
|
|
68
|
-
this._hoverSubscription = Subscription.EMPTY;
|
|
69
|
-
this._menuCloseSubscription = Subscription.EMPTY;
|
|
70
|
-
this._closingActionsSubscription = Subscription.EMPTY;
|
|
71
|
-
this._portal = null;
|
|
72
|
-
this._overlayRef = null;
|
|
73
|
-
this._touchTouchingElement = false;
|
|
74
|
-
/**
|
|
75
|
-
* Handles touch start events on the trigger.
|
|
76
|
-
* Needs to be an arrow function so we can easily use addEventListener and removeEventListener.
|
|
77
|
-
*/
|
|
78
|
-
this._handleTouchStart = () => {
|
|
79
|
-
this.openedBy = 'touch';
|
|
80
|
-
};
|
|
81
|
-
// ----------------------------------------- //
|
|
82
|
-
// --- Here be poor man's touch gestures --- //
|
|
83
|
-
// ----------------------------------------- //
|
|
84
|
-
// TODO: Replace with Hammer or other gesture library
|
|
85
|
-
/**
|
|
86
|
-
* Handles touch start events on the overlay host element (wrapper).
|
|
87
|
-
* Needs to be an arrow function so we can easily use addEventListener and removeEventListener.
|
|
88
|
-
*/
|
|
89
|
-
this._handleOverlayTouchStart = (event) => {
|
|
90
|
-
if (this.menu._isAnimating) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
this._touchStartTime = new Date().getTime();
|
|
94
|
-
this._touchStartX = event.changedTouches[0].clientX;
|
|
95
|
-
this._touchStartY = event.changedTouches[0].clientY;
|
|
96
|
-
this._touchCurrentX = this._touchStartX;
|
|
97
|
-
this._touchCurrentY = this._touchStartY;
|
|
98
|
-
this._touchTranslateX = 0;
|
|
99
|
-
this._touchMaxX =
|
|
100
|
-
this._overlayRef.hostElement.getBoundingClientRect().width;
|
|
101
|
-
this._touchLockedX = null;
|
|
102
|
-
this._touchTouchingElement = true;
|
|
103
|
-
};
|
|
104
|
-
this._handleOverlayTouchMove = (event) => {
|
|
105
|
-
if (!this._touchTouchingElement || this.menu._isAnimating) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
if (this._touchLockedX) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
this._touchCurrentX = event.changedTouches[0].clientX;
|
|
112
|
-
this._touchCurrentY = event.changedTouches[0].clientY;
|
|
113
|
-
// Lock X-axis pan if initiating pan on Y-axis
|
|
114
|
-
if (this._touchLockedX === null) {
|
|
115
|
-
const dy = Math.abs(this._touchCurrentY - this._touchStartY);
|
|
116
|
-
const dx = Math.abs(this._touchCurrentX - this._touchStartX);
|
|
117
|
-
if (dx > 10 || dy > 10) {
|
|
118
|
-
this._touchLockedX = dy > dx;
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// Restrict to right pan/swipe and make menu movement extremely slow when
|
|
123
|
-
// moved past allowed limits.
|
|
124
|
-
const menuMargin = 16;
|
|
125
|
-
this._touchTranslateX = this._touchCurrentX - this._touchStartX;
|
|
126
|
-
if (this._touchTranslateX < 0) {
|
|
127
|
-
this._touchTranslateX = this.easeOutExpo(this._touchTranslateX, 0, -menuMargin / 2, this._touchMaxX * -4);
|
|
128
|
-
}
|
|
129
|
-
else if (!this._parentMenu) {
|
|
130
|
-
this._touchTranslateX = this.easeOutExpo(this._touchTranslateX, 0, menuMargin / 2, this._touchMaxX * 4);
|
|
131
|
-
}
|
|
132
|
-
else if (this._touchTranslateX > this._touchMaxX) {
|
|
133
|
-
this._touchTranslateX = this.easeOutExpo(this._touchTranslateX - this._touchMaxX, this._touchMaxX, menuMargin / 2, this._touchMaxX * 4);
|
|
134
|
-
}
|
|
135
|
-
// Set new sub menu position and tell any parent to follow;
|
|
136
|
-
this.animateSetMenuPosition(this._touchTranslateX);
|
|
137
|
-
};
|
|
138
|
-
this._handleOverlayTouchEnd = () => {
|
|
139
|
-
if (!this._touchTouchingElement || this.menu._isAnimating) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
this._touchTranslateX = this._touchCurrentX - this._touchStartX;
|
|
143
|
-
if (this._touchTranslateX === 0) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
this._touchTouchingElement = false;
|
|
147
|
-
this._touchTimeTaken = new Date().getTime() - this._touchStartTime;
|
|
148
|
-
const swipeMinDistance = 10;
|
|
149
|
-
const swipeMinTime = 50;
|
|
150
|
-
const swipeMaxTime = 300;
|
|
151
|
-
const pannedHalfwayRight = this._touchTranslateX > this._touchMaxX / 2;
|
|
152
|
-
const swipedRight = this._touchTranslateX > this._touchMaxX / swipeMinDistance &&
|
|
153
|
-
this._touchTimeTaken > swipeMinTime &&
|
|
154
|
-
this._touchTimeTaken < swipeMaxTime;
|
|
155
|
-
if (!!this._parentMenu && (swipedRight || pannedHalfwayRight)) {
|
|
156
|
-
// Close submenu keydown-style: close only this menu and leave parents open
|
|
157
|
-
this.menu.closed.emit('keydown');
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
// Pan ended but the menu was not moved far enough. Reset menus to
|
|
161
|
-
// where they were before panning stared.
|
|
162
|
-
this.animateOpenMenu();
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
_element.nativeElement.addEventListener('touchstart', this._handleTouchStart, passiveEventListenerOptions);
|
|
166
|
-
if (_menuItemInstance) {
|
|
167
|
-
_menuItemInstance._triggersSubmenu = this.triggersSubmenu();
|
|
168
|
-
}
|
|
169
|
-
this._document = document;
|
|
170
|
-
}
|
|
171
|
-
ngOnChanges(changes) {
|
|
172
|
-
if (changes.menu) {
|
|
173
|
-
this._handleMenuChange();
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
ngAfterContentInit() {
|
|
177
|
-
// removed checkMenu here to avoid errors in dynamically genarated menus
|
|
178
|
-
// menu is checked when opening the menu
|
|
179
|
-
// this._checkMenu();
|
|
180
|
-
this._handleHover();
|
|
181
|
-
}
|
|
182
|
-
ngOnDestroy() {
|
|
183
|
-
if (this._overlayRef) {
|
|
184
|
-
//#region --- Touch device customizations ---
|
|
185
|
-
this.removeOverlayListeners();
|
|
186
|
-
//#endregion --- Touch device customizations ---
|
|
187
|
-
this._overlayRef.dispose();
|
|
188
|
-
this._overlayRef = null;
|
|
189
|
-
}
|
|
190
|
-
this._element.nativeElement.removeEventListener('touchstart', this._handleTouchStart, passiveEventListenerOptions);
|
|
191
|
-
this._hoverSubscription.unsubscribe();
|
|
192
|
-
this._menuCloseSubscription.unsubscribe();
|
|
193
|
-
this._closingActionsSubscription.unsubscribe();
|
|
194
|
-
}
|
|
195
|
-
/** Handles change of associated menu */
|
|
196
|
-
_handleMenuChange() {
|
|
197
|
-
this._menuCloseSubscription.unsubscribe();
|
|
198
|
-
// Close the menu overlay when the menu itself says it wants to be closed
|
|
199
|
-
if (this.menu) {
|
|
200
|
-
const closed = this.menu.closed;
|
|
201
|
-
this._menuCloseSubscription = closed.subscribe((reason) => {
|
|
202
|
-
//#region --- Touch device customizations ---
|
|
203
|
-
if (this.menu._isClosing) {
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
this.menu._isClosing = true;
|
|
207
|
-
// Get rid of the menu and tell any parent to restore its position
|
|
208
|
-
if (this._clientOutput.device === 'touch') {
|
|
209
|
-
// First we wait for any running animation to complete
|
|
210
|
-
const runningAnimationDone = this.menu._isAnimating
|
|
211
|
-
? this.menu._animationDone
|
|
212
|
-
: observableOf([null]);
|
|
213
|
-
runningAnimationDone
|
|
214
|
-
.pipe(take(1), delay(0, asapScheduler))
|
|
215
|
-
.subscribe(() => {
|
|
216
|
-
this.animateCloseMenu(reason !== 'keydown', reason === 'click');
|
|
217
|
-
this.menu._animationDone
|
|
218
|
-
.pipe(take(1), delay(0, asapScheduler))
|
|
219
|
-
.subscribe(() => this._destroyMenu());
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
//#endregion --- Touch device customizations ---
|
|
224
|
-
this._destroyMenu();
|
|
225
|
-
}
|
|
226
|
-
// If a click closed the menu, we should close the entire chain of nested menus.
|
|
227
|
-
if ((reason === 'click' || reason === 'tab') && this._parentMenu) {
|
|
228
|
-
this._parentMenu.closed.emit(reason);
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
isOpen() {
|
|
234
|
-
return this.isMenuOpened;
|
|
235
|
-
}
|
|
236
|
-
/** Open the associated menu */
|
|
237
|
-
openMenu() {
|
|
238
|
-
if (this.isMenuOpened) {
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
this.openedEvent();
|
|
242
|
-
this._checkMenu();
|
|
243
|
-
this.menu.parentMenu = this.triggersSubmenu()
|
|
244
|
-
? this._parentMenu
|
|
245
|
-
: undefined;
|
|
246
|
-
this.menu.direction = this._dir.value === 'rtl' ? 'rtl' : 'ltr';
|
|
247
|
-
if (this._parentMenu) {
|
|
248
|
-
// Menu triggers inherit target device types from their parent.
|
|
249
|
-
// Ultimately it is the root trigger that determines device types for
|
|
250
|
-
// the whole menu hierarchy.
|
|
251
|
-
this._clientInput = this._parentMenu._clientInput;
|
|
252
|
-
this._clientOutput = this._parentMenu._clientOutput;
|
|
253
|
-
}
|
|
254
|
-
//#region --- Touch device customizations ---
|
|
255
|
-
// Make the menu we're about to open use the same devices as the trigger
|
|
256
|
-
this.menu._setDevice(this._clientInput, this._clientOutput);
|
|
257
|
-
if (this._clientOutput.device === 'touch') {
|
|
258
|
-
this.menu.showBackButton = !!this._parentMenu;
|
|
259
|
-
this.menu._updateShowTitle();
|
|
260
|
-
if (!this.menu.closeLabel) {
|
|
261
|
-
this.menu.closeLabel = this._parentMenu?.closeLabel;
|
|
262
|
-
}
|
|
263
|
-
this.menu.showCloseButton = !!this.menu.closeLabel;
|
|
264
|
-
}
|
|
265
|
-
this.menu._isClosing = false;
|
|
266
|
-
const panelClass = [];
|
|
267
|
-
if (this._clientOutput.device === 'touch') {
|
|
268
|
-
panelClass.push('granite-overlay-pane-fill-width-bottom');
|
|
269
|
-
}
|
|
270
|
-
// setting scrollStrategy options to overlay
|
|
271
|
-
const scrollStrategy = this.setScrollStrategyToOverylay(this._clientOutput.device, this.menu.scrollStrategy);
|
|
272
|
-
const hasBackdrop = this._clientOutput.device === 'touch' && !this.triggersSubmenu();
|
|
273
|
-
//#endregion --- Touch device customizations ---
|
|
274
|
-
// Create an overlay to stuff the menu (portal) into below
|
|
275
|
-
if (!this._overlayRef) {
|
|
276
|
-
const config = new OverlayConfig({
|
|
277
|
-
positionStrategy: this._positionStrategy(),
|
|
278
|
-
backdropClass: 'granite-overlay-dark-glass-backdrop',
|
|
279
|
-
scrollStrategy,
|
|
280
|
-
direction: this._dir,
|
|
281
|
-
panelClass,
|
|
282
|
-
hasBackdrop,
|
|
283
|
-
});
|
|
284
|
-
this._overlayRef = this._overlay.create(config);
|
|
285
|
-
//#region --- Touch device customizations ---
|
|
286
|
-
// Add touch listener for submenu back pan/swipe
|
|
287
|
-
if (this._clientOutput.device === 'touch') {
|
|
288
|
-
this.addOverlayListeners();
|
|
289
|
-
}
|
|
290
|
-
//#endregion --- Touch device customizations ---
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
// Reset animation state for reused overlays
|
|
294
|
-
if (this._clientOutput.device === 'touch') {
|
|
295
|
-
this.menu._panelAnimationState = 'void';
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
// Create portal from associated menu's template
|
|
299
|
-
if (!this._portal || this._portal.templateRef !== this.menu.templateRef) {
|
|
300
|
-
this._portal = new TemplatePortal(this.menu.templateRef, this._viewContainerRef);
|
|
301
|
-
}
|
|
302
|
-
// Attach menu portal to overlay ref (which is a portal outlet)
|
|
303
|
-
this._overlayRef.attach(this._portal);
|
|
304
|
-
// Subscribe to stream that emits whenever an action that should close the menu occurs
|
|
305
|
-
this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());
|
|
306
|
-
this.animateOpenMenu();
|
|
307
|
-
this._setIsMenuOpen(true);
|
|
308
|
-
this.menu.focusFirstItem(this.openedBy || 'program');
|
|
309
|
-
}
|
|
310
|
-
/** Emits an eventtype when the menu is opened */
|
|
311
|
-
openedEvent() {
|
|
312
|
-
if (this.openedBy === 'touch' || this.openedBy === 'mouse') {
|
|
313
|
-
this.menu.opened.emit('click');
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
this.menu.opened.emit('keydown');
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
/** Whether the menu triggers a sub-menu or a top-level one. */
|
|
320
|
-
triggersSubmenu() {
|
|
321
|
-
return !!(this._menuItemInstance && this._parentMenu);
|
|
322
|
-
}
|
|
323
|
-
/** Toggles the menu between the open and closed states. */
|
|
324
|
-
toggleMenu() {
|
|
325
|
-
if (this.isMenuOpened) {
|
|
326
|
-
this.closeMenu();
|
|
327
|
-
}
|
|
328
|
-
else if (this.openOnClick) {
|
|
329
|
-
this.openMenu();
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
/** Close the associated menu */
|
|
333
|
-
closeMenu() {
|
|
334
|
-
this.menu.closed.emit();
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Focuses the menu trigger.
|
|
338
|
-
* @param origin Source of the menu trigger's focus.
|
|
339
|
-
*/
|
|
340
|
-
focus(origin = 'program', options) {
|
|
341
|
-
if (this._focusMonitor) {
|
|
342
|
-
this._focusMonitor.focusVia(this._element, origin, options);
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
this._element.nativeElement.focus(options);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
/** Detach menu portal from overlay and update open state */
|
|
349
|
-
_destroyMenu() {
|
|
350
|
-
if (!this._overlayRef || !this.isMenuOpened) {
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
this._closingActionsSubscription.unsubscribe();
|
|
354
|
-
this._overlayRef.detach();
|
|
355
|
-
this._restoreFocus();
|
|
356
|
-
this.menu._resetAnimation();
|
|
357
|
-
this._setIsMenuOpen(false);
|
|
358
|
-
}
|
|
359
|
-
/** Handles mouse presses on the trigger. */
|
|
360
|
-
_handleMousedown(event) {
|
|
361
|
-
if (!isFakeMousedownFromScreenReader(event)) {
|
|
362
|
-
if (this.openedBy !== 'touch') {
|
|
363
|
-
// Since right or middle button clicks won't trigger the `click` event,
|
|
364
|
-
// we shouldn't consider the menu as opened by mouse in those cases.
|
|
365
|
-
this.openedBy = event.button === 0 ? 'mouse' : null;
|
|
366
|
-
}
|
|
367
|
-
// Since clicking on the trigger won't close the menu if it opens a sub-menu,
|
|
368
|
-
// we should prevent focus from moving onto it via click to avoid the
|
|
369
|
-
// highlight from lingering on the menu item.
|
|
370
|
-
if (this.triggersSubmenu() && !this._toggleOnSubmenuClick()) {
|
|
371
|
-
event.preventDefault();
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/** Handles key presses on the trigger. */
|
|
376
|
-
_handleKeydown(event) {
|
|
377
|
-
const key = event.key;
|
|
378
|
-
if (this.triggersSubmenu() &&
|
|
379
|
-
((key === 'ArrowRight' && this._dir.value === 'ltr') ||
|
|
380
|
-
(key === 'ArrowLeft' && this._dir.value === 'rtl'))) {
|
|
381
|
-
this.openMenu();
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
/** Handles click events on the trigger. */
|
|
385
|
-
_handleClick(event) {
|
|
386
|
-
if (this.triggersSubmenu()) {
|
|
387
|
-
// Stop event propagation to avoid closing the parent menu.
|
|
388
|
-
event.stopPropagation();
|
|
389
|
-
this._toggleOnSubmenuClick() ? this.toggleMenu() : this.openMenu();
|
|
390
|
-
}
|
|
391
|
-
else {
|
|
392
|
-
this.toggleMenu();
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
/** Handles the cases where the user hovers over the trigger. */
|
|
396
|
-
_handleHover() {
|
|
397
|
-
// Subscribe to changes in the hovered item in order to toggle the panel.
|
|
398
|
-
if (!this.triggersSubmenu() || !this._parentMenu) {
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
this._hoverSubscription = this._parentMenu
|
|
402
|
-
._hovered()
|
|
403
|
-
.pipe(filter(() => this._openOnHover()),
|
|
404
|
-
// Since we might have multiple competing triggers for the same menu (e.g. a sub-menu
|
|
405
|
-
// with different data and triggers), we have to delay it by a tick to ensure that
|
|
406
|
-
// it won't be closed immediately after it is opened.
|
|
407
|
-
filter((active) => active === this._menuItemInstance /*&& !active.disabled*/), delay(0, asapScheduler))
|
|
408
|
-
.subscribe(() => {
|
|
409
|
-
this.openedBy = 'mouse';
|
|
410
|
-
// If the same menu is used between multiple triggers, it might still be animating
|
|
411
|
-
// while the new trigger tries to re-open it. Wait for the animation to finish
|
|
412
|
-
// before doing so. Also interrupt if the user moves to another item.
|
|
413
|
-
if (this.menu instanceof _MenuBaseComponent && this.menu._isAnimating) {
|
|
414
|
-
// We need the `delay(0)` here in order to avoid
|
|
415
|
-
// 'changed after checked' errors in some cases. See Angular Material #12194.
|
|
416
|
-
this.menu._animationDone
|
|
417
|
-
.pipe(take(1), delay(0, asapScheduler), takeUntil(this._parentMenu._hovered()))
|
|
418
|
-
.subscribe(() => this.openMenu());
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
this.openMenu();
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* Restores focus to the element that was focused before the menu was open.
|
|
427
|
-
* Could be the root trigger button or a submenu trigger item
|
|
428
|
-
*/
|
|
429
|
-
_restoreFocus() {
|
|
430
|
-
// We should reset focus if the user is navigating using a keyboard or
|
|
431
|
-
// if we have a top-level trigger which might cause focus to be lost
|
|
432
|
-
// when clicking outside of the menu.
|
|
433
|
-
if (!this.openedBy) {
|
|
434
|
-
// Note that the focus style will show up both for `program` and
|
|
435
|
-
// `keyboard` so we don't have to specify which one it is.
|
|
436
|
-
this.focus();
|
|
437
|
-
}
|
|
438
|
-
else if (!this.triggersSubmenu()) {
|
|
439
|
-
this.focus(this.openedBy);
|
|
440
|
-
}
|
|
441
|
-
this.openedBy = null;
|
|
442
|
-
}
|
|
443
|
-
// Set state rather than toggle to support triggers sharing a menu
|
|
444
|
-
_setIsMenuOpen(isOpen) {
|
|
445
|
-
if (this.isMenuOpened !== isOpen) {
|
|
446
|
-
this._changeDetectionRef.markForCheck();
|
|
447
|
-
}
|
|
448
|
-
this.isMenuOpened = isOpen;
|
|
449
|
-
if (this.triggersSubmenu()) {
|
|
450
|
-
this._menuItemInstance._highlighted =
|
|
451
|
-
isOpen && this._clientOutput.device !== 'touch';
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* This method checks that a valid instance of MenuComponent has been passed into
|
|
456
|
-
* graniteMenuTriggerFor. If not, an exception is thrown.
|
|
457
|
-
*/
|
|
458
|
-
_checkMenu() {
|
|
459
|
-
if (!this.menu) {
|
|
460
|
-
throwGraniteMenuMissingError();
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Returns strategy for positioning the overlay for desktop devices:
|
|
465
|
-
* Place adjacent to the trigger button (preferably immediately below)
|
|
466
|
-
* in order to show as much of the menu as possible.
|
|
467
|
-
*/
|
|
468
|
-
_desktopPositionStrategy() {
|
|
469
|
-
const positionStrategy = this._overlay
|
|
470
|
-
.position()
|
|
471
|
-
.flexibleConnectedTo(this._element)
|
|
472
|
-
.withLockedPosition()
|
|
473
|
-
.withTransformOriginOn('.granite-menu');
|
|
474
|
-
this._setPosition(positionStrategy);
|
|
475
|
-
return positionStrategy;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Sets the appropriate positions on a position strategy
|
|
479
|
-
* so the overlay connects with the trigger correctly.
|
|
480
|
-
* @param positionStrategy Strategy whose position to update.
|
|
481
|
-
*/
|
|
482
|
-
_setPosition(positionStrategy) {
|
|
483
|
-
const MENU_PANEL_TOP_PADDING = 0;
|
|
484
|
-
let [originX, originFallbackX] = this.menu.xPosition === 'before' ? ['end', 'start'] : ['start', 'end'];
|
|
485
|
-
const [overlayY, overlayFallbackY] = this.menu.yPosition === 'above' ? ['bottom', 'top'] : ['top', 'bottom'];
|
|
486
|
-
let [originY, originFallbackY] = [overlayY, overlayFallbackY];
|
|
487
|
-
let [overlayX, overlayFallbackX] = [originX, originFallbackX];
|
|
488
|
-
let offsetY = 0;
|
|
489
|
-
if (this.triggersSubmenu()) {
|
|
490
|
-
// When the menu is a sub-menu, it should always align itself
|
|
491
|
-
// to the edges of the trigger, instead of overlapping it.
|
|
492
|
-
overlayFallbackX = originX =
|
|
493
|
-
this.menu.xPosition === 'before' ? 'start' : 'end';
|
|
494
|
-
originFallbackX = overlayX = originX === 'end' ? 'start' : 'end';
|
|
495
|
-
offsetY =
|
|
496
|
-
overlayY === 'bottom'
|
|
497
|
-
? MENU_PANEL_TOP_PADDING
|
|
498
|
-
: -MENU_PANEL_TOP_PADDING;
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
originY = overlayY === 'top' ? 'bottom' : 'top';
|
|
502
|
-
originFallbackY = overlayFallbackY === 'top' ? 'bottom' : 'top';
|
|
503
|
-
}
|
|
504
|
-
positionStrategy.withPositions([
|
|
505
|
-
{ originX, originY, overlayX, overlayY, offsetY },
|
|
506
|
-
{
|
|
507
|
-
originX: originFallbackX,
|
|
508
|
-
originY,
|
|
509
|
-
overlayX: overlayFallbackX,
|
|
510
|
-
overlayY,
|
|
511
|
-
offsetY,
|
|
512
|
-
},
|
|
513
|
-
{
|
|
514
|
-
originX,
|
|
515
|
-
originY: originFallbackY,
|
|
516
|
-
overlayX,
|
|
517
|
-
overlayY: overlayFallbackY,
|
|
518
|
-
offsetY: -offsetY,
|
|
519
|
-
},
|
|
520
|
-
{
|
|
521
|
-
originX: originFallbackX,
|
|
522
|
-
originY: originFallbackY,
|
|
523
|
-
overlayX: overlayFallbackX,
|
|
524
|
-
overlayY: overlayFallbackY,
|
|
525
|
-
offsetY: -offsetY,
|
|
526
|
-
},
|
|
527
|
-
]);
|
|
528
|
-
}
|
|
529
|
-
/** Returns a stream that emits whenever an action that should close the menu occurs. */
|
|
530
|
-
_menuClosingActions() {
|
|
531
|
-
const detachments = this._overlayRef?.detachments();
|
|
532
|
-
const parentClose = this._parentMenu
|
|
533
|
-
? this._parentMenu.closed
|
|
534
|
-
: observableOf(null);
|
|
535
|
-
const hover = this._clientOutput.device === 'desktop' && this._parentMenu
|
|
536
|
-
? this._parentMenu._hovered().pipe(filter((item) => item !== this._menuItemInstance), filter(() => this.isMenuOpened))
|
|
537
|
-
: observableOf(null);
|
|
538
|
-
// Note: Quick fix. Feature reportedly exists in CDK for Angular 10
|
|
539
|
-
// Filter to prevent closing when animating added though. Applied to
|
|
540
|
-
// root menu only.
|
|
541
|
-
const outsideClick = !this._parentMenu
|
|
542
|
-
? fromEvent(this._document, 'click').pipe(filter((e) => e.target !== this._element.nativeElement &&
|
|
543
|
-
e.target.closest('.granite-menu') === null), filter(() => !this.menu._isAnimating))
|
|
544
|
-
: observableOf(null);
|
|
545
|
-
return merge(detachments, hover, parentClose, outsideClick).pipe(filter((event) => event !== null));
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* Whether to automatically open submenus on hover. This is true when showing
|
|
549
|
-
* desktop menus and having mouse support.
|
|
550
|
-
*/
|
|
551
|
-
_openOnHover() {
|
|
552
|
-
return ((this.triggersSubmenu()
|
|
553
|
-
? this._parentMenu.openOnHover
|
|
554
|
-
: this.menu.openOnHover) &&
|
|
555
|
-
this._parentMenu._clientOutput?.device === 'desktop' &&
|
|
556
|
-
this._parentMenu._clientInput?.devices.includes('mouse'));
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* Whether to toggle submenus on click. This is true when showing desktop menus
|
|
560
|
-
* without mouse support. Which, by the way, is not a great idea to begin with.
|
|
561
|
-
*/
|
|
562
|
-
_toggleOnSubmenuClick() {
|
|
563
|
-
return (!(this.triggersSubmenu()
|
|
564
|
-
? this._parentMenu.openOnHover
|
|
565
|
-
: this.menu.openOnHover) ||
|
|
566
|
-
(this._parentMenu._clientOutput?.device === 'desktop' &&
|
|
567
|
-
!this._parentMenu._clientInput?.devices.includes('mouse')));
|
|
568
|
-
}
|
|
569
|
-
// ------------------------------------------- //
|
|
570
|
-
// --- Here be touch device customizations --- //
|
|
571
|
-
// ------------------------------------------- //
|
|
572
|
-
/** Set animation state to bring a newly opened menu into view */
|
|
573
|
-
animateOpenMenu() {
|
|
574
|
-
this._clientOutput.device === 'touch'
|
|
575
|
-
? this.animateTouchOpenMenu()
|
|
576
|
-
: this.menu._startAnimation();
|
|
577
|
-
}
|
|
578
|
-
animateTouchOpenMenu() {
|
|
579
|
-
if (this.triggersSubmenu()) {
|
|
580
|
-
// Slide newly opened sub menu into view from the side,
|
|
581
|
-
// pushing any parent menu out of view on the other side
|
|
582
|
-
this.menu._startTouchSubmenuEnterAnimation();
|
|
583
|
-
this._parentMenu._startTouchHideAnimation();
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
// Slide root menu into view from below
|
|
587
|
-
this.menu._startTouchRootEnterAnimation();
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
/** Set animation state to close the active menu */
|
|
591
|
-
animateCloseMenu(toBelow, withDelay) {
|
|
592
|
-
this._clientOutput.device === 'touch'
|
|
593
|
-
? this._animateTouchCloseMenu(toBelow, withDelay)
|
|
594
|
-
: this._parentMenu._resetAnimation();
|
|
595
|
-
}
|
|
596
|
-
_animateTouchCloseMenu(toBelow, withDelay) {
|
|
597
|
-
if (toBelow) {
|
|
598
|
-
// Slide menu out of view below the viewport
|
|
599
|
-
withDelay
|
|
600
|
-
? this.menu._startTouchCloseDownAnimationWithDelay()
|
|
601
|
-
: this.menu._startTouchCloseDownAnimation();
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
// Slide the closed menu out of view to the side
|
|
605
|
-
// and slide any parent menu back into view
|
|
606
|
-
this.menu._startTouchCloseSideAnimation();
|
|
607
|
-
this._parentMenu?._startTouchSubmenuEnterAnimation();
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Set animation state to place the menu and any parent at the given
|
|
612
|
-
* horizontal position, i.e. following touch pan movement.
|
|
613
|
-
*
|
|
614
|
-
* @param xOffset Horizontal offset
|
|
615
|
-
*/
|
|
616
|
-
animateSetMenuPosition(xOffset) {
|
|
617
|
-
this.menu._startTouchPanAnimation(xOffset);
|
|
618
|
-
if (this._parentMenu) {
|
|
619
|
-
this._parentMenu._startTouchHidePanAnimation(xOffset);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
/**
|
|
623
|
-
* Returns strategy for positioning the overlay depending on what type of
|
|
624
|
-
* device the menu is being shown on
|
|
625
|
-
*/
|
|
626
|
-
_positionStrategy() {
|
|
627
|
-
return this._clientOutput.device === 'touch'
|
|
628
|
-
? this._touchPositionStrategy()
|
|
629
|
-
: this._desktopPositionStrategy();
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Returns strategy for positioning the overlay for touch devices:
|
|
633
|
-
* Place centered at the bottom of the screen.
|
|
634
|
-
*/
|
|
635
|
-
_touchPositionStrategy() {
|
|
636
|
-
return this._overlay.position().global();
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* Remove touch device pan/swipe listeners from overlay host element
|
|
640
|
-
*/
|
|
641
|
-
addOverlayListeners() {
|
|
642
|
-
this._overlayRef.hostElement.addEventListener('touchstart', this._handleOverlayTouchStart, passiveEventListenerOptions);
|
|
643
|
-
this._overlayRef.hostElement.addEventListener('touchmove', this._handleOverlayTouchMove, passiveEventListenerOptions);
|
|
644
|
-
this._overlayRef.hostElement.addEventListener('touchend', this._handleOverlayTouchEnd, passiveEventListenerOptions);
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Remove touch device pan/swipe listeners from overlay host element
|
|
648
|
-
*/
|
|
649
|
-
removeOverlayListeners() {
|
|
650
|
-
this._overlayRef.hostElement.removeEventListener('touchstart', this._handleOverlayTouchStart, passiveEventListenerOptions);
|
|
651
|
-
this._overlayRef.hostElement.removeEventListener('touchmove', this._handleOverlayTouchMove, passiveEventListenerOptions);
|
|
652
|
-
this._overlayRef.hostElement.removeEventListener('touchend', this._handleOverlayTouchEnd, passiveEventListenerOptions);
|
|
653
|
-
}
|
|
654
|
-
/**
|
|
655
|
-
* Standard exponential ease out function
|
|
656
|
-
*
|
|
657
|
-
* @param current Current value
|
|
658
|
-
* @param offset Offset value, to which calculated value will be added
|
|
659
|
-
* @param target The target value
|
|
660
|
-
* @param end Value to which current value is compared
|
|
661
|
-
*/
|
|
662
|
-
easeOutExpo(current, offset, target, end) {
|
|
663
|
-
return current === end
|
|
664
|
-
? offset + target
|
|
665
|
-
: target * (-Math.pow(2, (-10 * current) / end) + 1) + offset;
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
* Sets the scroll strategy for the overlay based on the client output device and menu scroll strategy input.
|
|
669
|
-
*
|
|
670
|
-
* @param {OutputDeviceTypes} clientOutputDevice - The type of client output device (e.g., 'touch').
|
|
671
|
-
* @param {'reposition' | 'close'} menuScrollStrategyInput - The scroll strategy input for the menu.
|
|
672
|
-
* @returns {ScrollStrategy} The appropriate scroll strategy for the overlay.
|
|
673
|
-
*/
|
|
674
|
-
setScrollStrategyToOverylay(clientOutputDevice, menuScrollStrategyInput) {
|
|
675
|
-
if (clientOutputDevice === 'touch') {
|
|
676
|
-
return undefined;
|
|
677
|
-
}
|
|
678
|
-
else {
|
|
679
|
-
if (menuScrollStrategyInput === 'close') {
|
|
680
|
-
return this._overlay.scrollStrategies.close();
|
|
681
|
-
}
|
|
682
|
-
else if (menuScrollStrategyInput === 'reposition') {
|
|
683
|
-
return this._overlay.scrollStrategies.reposition();
|
|
684
|
-
}
|
|
685
|
-
else {
|
|
686
|
-
return undefined;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GraniteMenuTriggerForDirective, deps: [{ token: i1.Overlay }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }, { token: GRANITE_MENU_PANEL, optional: true }, { token: GRANITE_CLIENT_INPUT, optional: true }, { token: GRANITE_CLIENT_OUTPUT, optional: true }, { token: i2.GraniteMenuItemComponent, optional: true, self: true }, { token: i3.Directionality, optional: true }, { token: i4.FocusMonitor }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
691
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GraniteMenuTriggerForDirective, selector: "[graniteMenuTriggerFor]", inputs: { menu: ["graniteMenuTriggerFor", "menu"], openOnClick: "openOnClick" }, host: { attributes: { "aria-haspopup": "true" }, listeners: { "mousedown": "_handleMousedown($event)", "keydown": "_handleKeydown($event)", "click": "_handleClick($event)" }, properties: { "attr.aria-expanded": "isMenuOpened || null", "attr.aria-controls": "isMenuOpened ? menu.panelId : null" }, classAttribute: "granite-menu-trigger" }, exportAs: ["graniteMenuTriggerFor"], usesOnChanges: true, ngImport: i0 }); }
|
|
692
|
-
}
|
|
693
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GraniteMenuTriggerForDirective, decorators: [{
|
|
694
|
-
type: Directive,
|
|
695
|
-
args: [{
|
|
696
|
-
selector: `[graniteMenuTriggerFor]`,
|
|
697
|
-
exportAs: 'graniteMenuTriggerFor',
|
|
698
|
-
host: {
|
|
699
|
-
class: 'granite-menu-trigger', // Required for test harness host selector
|
|
700
|
-
'aria-haspopup': 'true',
|
|
701
|
-
'[attr.aria-expanded]': 'isMenuOpened || null',
|
|
702
|
-
'[attr.aria-controls]': 'isMenuOpened ? menu.panelId : null',
|
|
703
|
-
'(mousedown)': '_handleMousedown($event)',
|
|
704
|
-
'(keydown)': '_handleKeydown($event)',
|
|
705
|
-
'(click)': '_handleClick($event)',
|
|
706
|
-
},
|
|
707
|
-
}]
|
|
708
|
-
}], ctorParameters: () => [{ type: i1.Overlay }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }, { type: i5._MenuBaseComponent, decorators: [{
|
|
709
|
-
type: Inject,
|
|
710
|
-
args: [GRANITE_MENU_PANEL]
|
|
711
|
-
}, {
|
|
712
|
-
type: Optional
|
|
713
|
-
}] }, { type: undefined, decorators: [{
|
|
714
|
-
type: Inject,
|
|
715
|
-
args: [GRANITE_CLIENT_INPUT]
|
|
716
|
-
}, {
|
|
717
|
-
type: Optional
|
|
718
|
-
}] }, { type: undefined, decorators: [{
|
|
719
|
-
type: Inject,
|
|
720
|
-
args: [GRANITE_CLIENT_OUTPUT]
|
|
721
|
-
}, {
|
|
722
|
-
type: Optional
|
|
723
|
-
}] }, { type: i2.GraniteMenuItemComponent, decorators: [{
|
|
724
|
-
type: Optional
|
|
725
|
-
}, {
|
|
726
|
-
type: Self
|
|
727
|
-
}] }, { type: i3.Directionality, decorators: [{
|
|
728
|
-
type: Optional
|
|
729
|
-
}] }, { type: i4.FocusMonitor }, { type: undefined, decorators: [{
|
|
730
|
-
type: Inject,
|
|
731
|
-
args: [DOCUMENT]
|
|
732
|
-
}] }], propDecorators: { menu: [{
|
|
733
|
-
type: Input,
|
|
734
|
-
args: ['graniteMenuTriggerFor']
|
|
735
|
-
}], openOnClick: [{
|
|
736
|
-
type: Input
|
|
737
|
-
}] } });
|
|
738
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS10cmlnZ2VyLWZvci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL2dyYW5pdGUtY29tcG9uZW50cy9zcmMvbGliL21lbnUvbWVudS10cmlnZ2VyLWZvci5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLE1BQU0sRUFDTixLQUFLLEVBR0wsUUFBUSxFQUNSLElBQUksRUFFSixnQkFBZ0IsR0FDakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTNDLE9BQU8sRUFDTCxZQUFZLEVBRVosK0JBQStCLEdBQ2hDLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3hFLE9BQU8sRUFHTCxPQUFPLEVBQ1AsYUFBYSxHQUtkLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXJELE9BQU8sRUFDTCxhQUFhLEVBQ2IsU0FBUyxFQUNULEtBQUssRUFFTCxFQUFFLElBQUksWUFBWSxFQUNsQixZQUFZLEdBQ2IsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFaEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2pELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pFLE9BQU8sRUFBbUIsa0JBQWtCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFbkUsNkNBQTZDO0FB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QUFrQjs7MEJBQ3pCLFFBQVE7OzBCQUtSLE1BQU07MkJBQUMsb0JBQW9COzswQkFDM0IsUUFBUTs7MEJBSVIsTUFBTTsyQkFBQyxxQkFBcUI7OzBCQUM1QixRQUFROzswQkFXUixRQUFROzswQkFBSSxJQUFJOzswQkFFaEIsUUFBUTs7MEJBR1IsTUFBTTsyQkFBQyxRQUFRO3lDQXZFbEIsSUFBSTtzQkFESCxLQUFLO3VCQUFDLHVCQUF1QjtnQkFHckIsV0FBVztzQkFBbkIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgU2VsZixcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0NvbnRhaW5lclJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbmltcG9ydCB7XG4gIEZvY3VzTW9uaXRvcixcbiAgRm9jdXNPcmlnaW4sXG4gIGlzRmFrZU1vdXNlZG93bkZyb21TY3JlZW5SZWFkZXIsXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IERpcmVjdGlvbmFsaXR5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2JpZGknO1xuaW1wb3J0IHsgbm9ybWFsaXplUGFzc2l2ZUxpc3RlbmVyT3B0aW9ucyB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wbGF0Zm9ybSc7XG5pbXBvcnQge1xuICBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3ksXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxuICBPdmVybGF5LFxuICBPdmVybGF5Q29uZmlnLFxuICBPdmVybGF5UmVmLFxuICBQb3NpdGlvblN0cmF0ZWd5LFxuICBTY3JvbGxTdHJhdGVneSxcbiAgVmVydGljYWxDb25uZWN0aW9uUG9zLFxufSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XG5pbXBvcnQgeyBUZW1wbGF0ZVBvcnRhbCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wb3J0YWwnO1xuXG5pbXBvcnQge1xuICBhc2FwU2NoZWR1bGVyLFxuICBmcm9tRXZlbnQsXG4gIG1lcmdlLFxuICBPYnNlcnZhYmxlLFxuICBvZiBhcyBvYnNlcnZhYmxlT2YsXG4gIFN1YnNjcmlwdGlvbixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWxheSwgZmlsdGVyLCB0YWtlLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IF9NZW51QmFzZUNvbXBvbmVudCB9IGZyb20gJy4vbWVudS1iYXNlJztcbmltcG9ydCB7IEdyYW5pdGVNZW51SXRlbUNvbXBvbmVudCB9IGZyb20gJy4vbWVudS1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDbG9zZWRFdmVudFR5cGUsIEdSQU5JVEVfTUVOVV9QQU5FTCB9IGZyb20gJy4vbWVudS1wYW5lbCc7XG5cbi8vI3JlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuaW1wb3J0IHtcbiAgQ2xpZW50SW5wdXRJbnRlcmZhY2UsXG4gIENsaWVudE91dHB1dEludGVyZmFjZSxcbiAgR1JBTklURV9DTElFTlRfSU5QVVQsXG4gIEdSQU5JVEVfQ0xJRU5UX09VVFBVVCxcbiAgT3V0cHV0RGV2aWNlVHlwZXMsXG59IGZyb20gJy4uL2NvcmUvY2xpZW50LWVudmlyb25tZW50JztcbmltcG9ydCB7IHRocm93R3Jhbml0ZU1lbnVNaXNzaW5nRXJyb3IgfSBmcm9tICcuL21lbnUtZXJyb3JzJztcblxuLyoqIE9wdGlvbnMgZm9yIGJpbmRpbmcgYSBwYXNzaXZlIGV2ZW50IGxpc3RlbmVyLiAqL1xuY29uc3QgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zID0gbm9ybWFsaXplUGFzc2l2ZUxpc3RlbmVyT3B0aW9ucyh7XG4gIHBhc3NpdmU6IHRydWUsXG59KTtcbi8vI2VuZHJlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuXG4vKipcbiAqIERpcmVjdGl2ZSB1c2VkIHRvIHR1cm4gYSBidXR0b24gZWxlbWVudCBpbnRvIGEgKHBvcHVwKSBtZW51IHRyaWdnZXJcbiAqXG4gKiBTdHJpcHBlZC1kb3duIHZlcnNpb24gb2YgQW5ndWxhciBNYXRlcmlhbCdzIG1lbnUgdHJpZ2dlciBkaXJlY3RpdmUgKC4uLi9tZW51L21lbnUtdHJpZ2dlci50cylcbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiBgW2dyYW5pdGVNZW51VHJpZ2dlckZvcl1gLFxuICBleHBvcnRBczogJ2dyYW5pdGVNZW51VHJpZ2dlckZvcicsXG4gIGhvc3Q6IHtcbiAgICBjbGFzczogJ2dyYW5pdGUtbWVudS10cmlnZ2VyJywgLy8gUmVxdWlyZWQgZm9yIHRlc3QgaGFybmVzcyBob3N0IHNlbGVjdG9yXG4gICAgJ2FyaWEtaGFzcG9wdXAnOiAndHJ1ZScsXG4gICAgJ1thdHRyLmFyaWEtZXhwYW5kZWRdJzogJ2lzTWVudU9wZW5lZCB8fCBudWxsJyxcbiAgICAnW2F0dHIuYXJpYS1jb250cm9sc10nOiAnaXNNZW51T3BlbmVkID8gbWVudS5wYW5lbElkIDogbnVsbCcsXG4gICAgJyhtb3VzZWRvd24pJzogJ19oYW5kbGVNb3VzZWRvd24oJGV2ZW50KScsXG4gICAgJyhrZXlkb3duKSc6ICdfaGFuZGxlS2V5ZG93bigkZXZlbnQpJyxcbiAgICAnKGNsaWNrKSc6ICdfaGFuZGxlQ2xpY2soJGV2ZW50KScsXG4gIH0sXG59KVxuZXhwb3J0IGNsYXNzIEdyYW5pdGVNZW51VHJpZ2dlckZvckRpcmVjdGl2ZVxuICBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzXG57XG4gIC8qKiBSZWZlcmVuY2VzIHRoZSBtZW51IGluc3RhbmNlIHRoYXQgdGhlIHRyaWdnZXIgaXMgYXNzb2NpYXRlZCB3aXRoLiAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L25vLWlucHV0LXJlbmFtZVxuICBASW5wdXQoJ2dyYW5pdGVNZW51VHJpZ2dlckZvcicpXG4gIG1lbnU6IF9NZW51QmFzZUNvbXBvbmVudDtcblxuICBASW5wdXQoKSBvcGVuT25DbGljaz86IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBhc3NvY2lhdGVkIG1lbnUgaXMgb3BlbiAqL1xuICBpc01lbnVPcGVuZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvLyBUcmFja2luZyBpbnB1dCB0eXBlIGlzIG5lY2Vzc2FyeSBzbyBpdCdzIHBvc3NpYmxlIHRvIG9ubHkgYXV0by1mb2N1c1xuICAvLyB0aGUgZmlyc3QgaXRlbSBvZiB0aGUgbGlzdCB3aGVuIHRoZSBtZW51IGlzIG9wZW5lZCB2aWEgdGhlIGtleWJvYXJkXG4gIHByaXZhdGUgb3BlbmVkQnk6ICdtb3VzZScgfCAndG91Y2gnIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBfaG92ZXJTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG4gIHByaXZhdGUgX21lbnVDbG9zZVN1YnNjcmlwdGlvbiA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcbiAgcHJpdmF0ZSBfY2xvc2luZ0FjdGlvbnNTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG5cbiAgcHJpdmF0ZSBfcG9ydGFsOiBUZW1wbGF0ZVBvcnRhbCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9vdmVybGF5UmVmOiBPdmVybGF5UmVmIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgX2RvY3VtZW50PzogRG9jdW1lbnQ7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cbiAgLy8gLS0tIEhlcmUgYmUgcG9vciBtYW4ncyB0b3VjaCBnZXN0dXJlcyAtLS0gLy9cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggSGFtbWVyIG9yIG90aGVyIGdlc3R1cmUgbGlicmFyeVxuXG4gIHByaXZhdGUgX3RvdWNoU3RhcnRUaW1lOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoVGltZVRha2VuOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoU3RhcnRYOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoU3RhcnRZOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoQ3VycmVudFg6IG51bWJlcjtcbiAgcHJpdmF0ZSBfdG91Y2hDdXJyZW50WTogbnVtYmVyO1xuICBwcml2YXRlIF90b3VjaFRyYW5zbGF0ZVg6IG51bWJlcjtcbiAgcHJpdmF0ZSBfdG91Y2hMb2NrZWRYOiBib29sZWFuIHwgbnVsbDtcbiAgcHJpdmF0ZSBfdG91Y2hNYXhYOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoVG91Y2hpbmdFbGVtZW50OiBib29sZWFuID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfb3ZlcmxheTogT3ZlcmxheSxcbiAgICBwcml2YXRlIF9lbGVtZW50OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIF92aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgIHByaXZhdGUgX2NoYW5nZURldGVjdGlvblJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG5cbiAgICAvKiogSWYgdGhpcyBpcyBhIF9zdWJtZW51XyB0cmlnZ2VyLCBpdCB3aWxsIGhhdmUgYSBwYXJlbnQgbWVudSAqL1xuICAgIEBJbmplY3QoR1JBTklURV9NRU5VX1BBTkVMKVxuICAgIEBPcHRpb25hbCgpXG4gICAgcHJpdmF0ZSBfcGFyZW50TWVudTogX01lbnVCYXNlQ29tcG9uZW50LFxuXG4gICAgLy8jcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgLyoqIENsaWVudCBpbnB1dCBkZXZpY2UgaW5mb3JtYXRpb24gKi9cbiAgICBASW5qZWN0KEdSQU5JVEVfQ0xJRU5UX0lOUFVUKVxuICAgIEBPcHRpb25hbCgpXG4gICAgcHJpdmF0ZSBfY2xpZW50SW5wdXQ6IENsaWVudElucHV0SW50ZXJmYWNlLFxuXG4gICAgLyoqIENsaWVudCBvdXRwdXQgZGV2aWNlIGluZm9ybWF0aW9uICovXG4gICAgQEluamVjdChHUkFOSVRFX0NMSUVOVF9PVVRQVVQpXG4gICAgQE9wdGlvbmFsKClcbiAgICBwcml2YXRlIF9jbGllbnRPdXRwdXQ6IENsaWVudE91dHB1dEludGVyZmFjZSxcbiAgICAvLyNlbmRyZWdpb24gLS0tIFRvdWNoIGRldmljZSBjdXN0b21pemF0aW9ucyAtLS1cblxuICAgIC8qKlxuICAgICAqIElmIHRoaXMgaXMgYSBfc3VibWVudV8gdHJpZ2dlciwgdGhlcmUgc2hvdWxkIGJlIGEgY29ycmVzcG9uZGluZyBtZW51XG4gICAgICogaXRlbSBkaXJlY3RpdmUgcHJlc2VudCBhcyB3ZWxsOlxuICAgICAqXG4gICAgICogICAgIDxidXR0b24gZ3Jhbml0ZU1lbnVJdGVtIFtncmFuaXRlTWVudVRyaWdnZXJGb3JdPVwiLi4uXCI+XG4gICAgICogICAgICAgICAgICAgICAgICAgXi0tIFRoaXMgb25lXG4gICAgICovXG4gICAgQE9wdGlvbmFsKCkgQFNlbGYoKSBwcml2YXRlIF9tZW51SXRlbUluc3RhbmNlOiBHcmFuaXRlTWVudUl0ZW1Db21wb25lbnQsXG5cbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIF9kaXI6IERpcmVjdGlvbmFsaXR5LFxuICAgIHByaXZhdGUgX2ZvY3VzTW9uaXRvcjogRm9jdXNNb25pdG9yLFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvZXhwbGljaXQtbW9kdWxlLWJvdW5kYXJ5LXR5cGVzXG4gICAgQEluamVjdChET0NVTUVOVCkgZG9jdW1lbnQ/OiBhbnlcbiAgKSB7XG4gICAgX2VsZW1lbnQubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgdGhpcy5faGFuZGxlVG91Y2hTdGFydCxcbiAgICAgIHBhc3NpdmVFdmVudExpc3RlbmVyT3B0aW9uc1xuICAgICk7XG5cbiAgICBpZiAoX21lbnVJdGVtSW5zdGFuY2UpIHtcbiAgICAgIF9tZW51SXRlbUluc3RhbmNlLl90cmlnZ2Vyc1N1Ym1lbnUgPSB0aGlzLnRyaWdnZXJzU3VibWVudSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2RvY3VtZW50ID0gZG9jdW1lbnQgYXMgRG9jdW1lbnQ7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXMubWVudSkge1xuICAgICAgdGhpcy5faGFuZGxlTWVudUNoYW5nZSgpO1xuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpOiB2b2lkIHtcbiAgICAvLyByZW1vdmVkIGNoZWNrTWVudSBoZXJlIHRvIGF2b2lkIGVycm9ycyBpbiBkeW5hbWljYWxseSBnZW5hcmF0ZWQgbWVudXNcbiAgICAvLyBtZW51IGlzIGNoZWNrZWQgd2hlbiBvcGVuaW5nIHRoZSBtZW51XG4gICAgLy8gdGhpcy5fY2hlY2tNZW51KCk7XG4gICAgdGhpcy5faGFuZGxlSG92ZXIoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICAvLyNyZWdpb24gLS0tIFRvdWNoIGRldmljZSBjdXN0b21pemF0aW9ucyAtLS1cbiAgICAgIHRoaXMucmVtb3ZlT3ZlcmxheUxpc3RlbmVycygpO1xuICAgICAgLy8jZW5kcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgICB0aGlzLl9vdmVybGF5UmVmLmRpc3Bvc2UoKTtcbiAgICAgIHRoaXMuX292ZXJsYXlSZWYgPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgdGhpcy5faGFuZGxlVG91Y2hTdGFydCxcbiAgICAgIHBhc3NpdmVFdmVudExpc3RlbmVyT3B0aW9uc1xuICAgICk7XG5cbiAgICB0aGlzLl9ob3ZlclN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX21lbnVDbG9zZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX2Nsb3NpbmdBY3Rpb25zU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvKiogSGFuZGxlcyBjaGFuZ2Ugb2YgYXNzb2NpYXRlZCBtZW51ICovXG4gIF9oYW5kbGVNZW51Q2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMuX21lbnVDbG9zZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuXG4gICAgLy8gQ2xvc2UgdGhlIG1lbnUgb3ZlcmxheSB3aGVuIHRoZSBtZW51IGl0c2VsZiBzYXlzIGl0IHdhbnRzIHRvIGJlIGNsb3NlZFxuICAgIGlmICh0aGlzLm1lbnUpIHtcbiAgICAgIGNvbnN0IGNsb3NlZCA9IHRoaXMubWVudS5jbG9zZWQgYXMgT2JzZXJ2YWJsZTxDbG9zZWRFdmVudFR5cGU+O1xuXG4gICAgICB0aGlzLl9tZW51Q2xvc2VTdWJzY3JpcHRpb24gPSBjbG9zZWQuc3Vic2NyaWJlKChyZWFzb24pID0+IHtcbiAgICAgICAgLy8jcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgICAgIGlmICh0aGlzLm1lbnUuX2lzQ2xvc2luZykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1lbnUuX2lzQ2xvc2luZyA9IHRydWU7XG5cbiAgICAgICAgLy8gR2V0IHJpZCBvZiB0aGUgbWVudSBhbmQgdGVsbCBhbnkgcGFyZW50IHRvIHJlc3RvcmUgaXRzIHBvc2l0aW9uXG4gICAgICAgIGlmICh0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAndG91Y2gnKSB7XG4gICAgICAgICAgLy8gRmlyc3Qgd2Ugd2FpdCBmb3IgYW55IHJ1bm5pbmcgYW5pbWF0aW9uIHRvIGNvbXBsZXRlXG4gICAgICAgICAgY29uc3QgcnVubmluZ0FuaW1hdGlvbkRvbmU6IE9ic2VydmFibGU8YW55PiA9IHRoaXMubWVudS5faXNBbmltYXRpbmdcbiAgICAgICAgICAgID8gdGhpcy5tZW51Ll9hbmltYXRpb25Eb25lXG4gICAgICAgICAgICA6IG9ic2VydmFibGVPZihbbnVsbF0pO1xuXG4gICAgICAgICAgcnVubmluZ0FuaW1hdGlvbkRvbmVcbiAgICAgICAgICAgIC5waXBlKHRha2UoMSksIGRlbGF5KDAsIGFzYXBTY2hlZHVsZXIpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuYW5pbWF0ZUNsb3NlTWVudShyZWFzb24gIT09ICdrZXlkb3duJywgcmVhc29uID09PSAnY2xpY2snKTtcbiAgICAgICAgICAgICAgdGhpcy5tZW51Ll9hbmltYXRpb25Eb25lXG4gICAgICAgICAgICAgICAgLnBpcGUodGFrZSgxKSwgZGVsYXkoMCwgYXNhcFNjaGVkdWxlcikpXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9kZXN0cm95TWVudSgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vI2VuZHJlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lNZW51KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBhIGNsaWNrIGNsb3NlZCB0aGUgbWVudSwgd2Ugc2hvdWxkIGNsb3NlIHRoZSBlbnRpcmUgY2hhaW4gb2YgbmVzdGVkIG1lbnVzLlxuICAgICAgICBpZiAoKHJlYXNvbiA9PT0gJ2NsaWNrJyB8fCByZWFzb24gPT09ICd0YWInKSAmJiB0aGlzLl9wYXJlbnRNZW51KSB7XG4gICAgICAgICAgdGhpcy5fcGFyZW50TWVudS5jbG9zZWQuZW1pdChyZWFzb24pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBpc09wZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNNZW51T3BlbmVkO1xuICB9XG5cbiAgLyoqIE9wZW4gdGhlIGFzc29jaWF0ZWQgbWVudSAqL1xuICBvcGVuTWVudSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc01lbnVPcGVuZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5vcGVuZWRFdmVudCgpO1xuXG4gICAgdGhpcy5fY2hlY2tNZW51KCk7XG5cbiAgICB0aGlzLm1lbnUucGFyZW50TWVudSA9IHRoaXMudHJpZ2dlcnNTdWJtZW51KClcbiAgICAgID8gdGhpcy5fcGFyZW50TWVudVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgdGhpcy5tZW51LmRpcmVjdGlvbiA9IHRoaXMuX2Rpci52YWx1ZSA9PT0gJ3J0bCcgPyAncnRsJyA6ICdsdHInO1xuXG4gICAgaWYgKHRoaXMuX3BhcmVudE1lbnUpIHtcbiAgICAgIC8vIE1lbnUgdHJpZ2dlcnMgaW5oZXJpdCB0YXJnZXQgZGV2aWNlIHR5cGVzIGZyb20gdGhlaXIgcGFyZW50LlxuICAgICAgLy8gVWx0aW1hdGVseSBpdCBpcyB0aGUgcm9vdCB0cmlnZ2VyIHRoYXQgZGV0ZXJtaW5lcyBkZXZpY2UgdHlwZXMgZm9yXG4gICAgICAvLyB0aGUgd2hvbGUgbWVudSBoaWVyYXJjaHkuXG4gICAgICB0aGlzLl9jbGllbnRJbnB1dCA9IHRoaXMuX3BhcmVudE1lbnUuX2NsaWVudElucHV0O1xuICAgICAgdGhpcy5fY2xpZW50T3V0cHV0ID0gdGhpcy5fcGFyZW50TWVudS5fY2xpZW50T3V0cHV0O1xuICAgIH1cblxuICAgIC8vI3JlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuICAgIC8vIE1ha2UgdGhlIG1lbnUgd2UncmUgYWJvdXQgdG8gb3BlbiB1c2UgdGhlIHNhbWUgZGV2aWNlcyBhcyB0aGUgdHJpZ2dlclxuICAgIHRoaXMubWVudS5fc2V0RGV2aWNlKHRoaXMuX2NsaWVudElucHV0LCB0aGlzLl9jbGllbnRPdXRwdXQpO1xuXG4gICAgaWYgKHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcpIHtcbiAgICAgIHRoaXMubWVudS5zaG93QmFja0J1dHRvbiA9ICEhdGhpcy5fcGFyZW50TWVudTtcbiAgICAgIHRoaXMubWVudS5fdXBkYXRlU2hvd1RpdGxlKCk7XG5cbiAgICAgIGlmICghdGhpcy5tZW51LmNsb3NlTGFiZWwpIHtcbiAgICAgICAgdGhpcy5tZW51LmNsb3NlTGFiZWwgPSB0aGlzLl9wYXJlbnRNZW51Py5jbG9zZUxhYmVsO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm1lbnUuc2hvd0Nsb3NlQnV0dG9uID0gISF0aGlzLm1lbnUuY2xvc2VMYWJlbDtcbiAgICB9XG4gICAgdGhpcy5tZW51Ll9pc0Nsb3NpbmcgPSBmYWxzZTtcblxuICAgIGNvbnN0IHBhbmVsQ2xhc3M6IHN0cmluZ1tdID0gW107XG4gICAgaWYgKHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcpIHtcbiAgICAgIHBhbmVsQ2xhc3MucHVzaCgnZ3Jhbml0ZS1vdmVybGF5LXBhbmUtZmlsbC13aWR0aC1ib3R0b20nKTtcbiAgICB9XG5cbiAgICAvLyBzZXR0aW5nIHNjcm9sbFN0cmF0ZWd5IG9wdGlvbnMgdG8gb3ZlcmxheVxuICAgIGNvbnN0IHNjcm9sbFN0cmF0ZWd5ID0gdGhpcy5zZXRTY3JvbGxTdHJhdGVneVRvT3ZlcnlsYXkoXG4gICAgICB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlLFxuICAgICAgdGhpcy5tZW51LnNjcm9sbFN0cmF0ZWd5XG4gICAgKTtcblxuICAgIGNvbnN0IGhhc0JhY2tkcm9wID1cbiAgICAgIHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcgJiYgIXRoaXMudHJpZ2dlcnNTdWJtZW51KCk7XG4gICAgLy8jZW5kcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG5cbiAgICAvLyBDcmVhdGUgYW4gb3ZlcmxheSB0byBzdHVmZiB0aGUgbWVudSAocG9ydGFsKSBpbnRvIGJlbG93XG4gICAgaWYgKCF0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICBjb25zdCBjb25maWcgPSBuZXcgT3ZlcmxheUNvbmZpZyh7XG4gICAgICAgIHBvc2l0aW9uU3RyYXRlZ3k6IHRoaXMuX3Bvc2l0aW9uU3RyYXRlZ3koKSxcbiAgICAgICAgYmFja2Ryb3BDbGFzczogJ2dyYW5pdGUtb3ZlcmxheS1kYXJrLWdsYXNzLWJhY2tkcm9wJyxcbiAgICAgICAgc2Nyb2xsU3RyYXRlZ3ksXG4gICAgICAgIGRpcmVjdGlvbjogdGhpcy5fZGlyLFxuICAgICAgICBwYW5lbENsYXNzLFxuICAgICAgICBoYXNCYWNrZHJvcCxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gdGhpcy5fb3ZlcmxheS5jcmVhdGUoY29uZmlnKTtcblxuICAgICAgLy8jcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgICAvLyBBZGQgdG91Y2ggbGlzdGVuZXIgZm9yIHN1Ym1lbnUgYmFjayBwYW4vc3dpcGVcbiAgICAgIGlmICh0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAndG91Y2gnKSB7XG4gICAgICAgIHRoaXMuYWRkT3ZlcmxheUxpc3RlbmVycygpO1xuICAgICAgfVxuICAgICAgLy8jZW5kcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlc2V0IGFuaW1hdGlvbiBzdGF0ZSBmb3IgcmV1c2VkIG92ZXJsYXlzXG4gICAgICBpZiAodGhpcy5fY2xpZW50T3V0cHV0LmRldmljZSA9PT0gJ3RvdWNoJykge1xuICAgICAgICB0aGlzLm1lbnUuX3BhbmVsQW5pbWF0aW9uU3RhdGUgPSAndm9pZCc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIHBvcnRhbCBmcm9tIGFzc29jaWF0ZWQgbWVudSdzIHRlbXBsYXRlXG4gICAgaWYgKCF0aGlzLl9wb3J0YWwgfHwgdGhpcy5fcG9ydGFsLnRlbXBsYXRlUmVmICE9PSB0aGlzLm1lbnUudGVtcGxhdGVSZWYpIHtcbiAgICAgIHRoaXMuX3BvcnRhbCA9IG5ldyBUZW1wbGF0ZVBvcnRhbChcbiAgICAgICAgdGhpcy5tZW51LnRlbXBsYXRlUmVmLFxuICAgICAgICB0aGlzLl92aWV3Q29udGFpbmVyUmVmXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEF0dGFjaCBtZW51IHBvcnRhbCB0byBvdmVybGF5IHJlZiAod2hpY2ggaXMgYSBwb3J0YWwgb3V0bGV0KVxuICAgIHRoaXMuX292ZXJsYXlSZWYuYXR0YWNoKHRoaXMuX3BvcnRhbCk7XG5cbiAgICAvLyBTdWJzY3JpYmUgdG8gc3RyZWFtIHRoYXQgZW1pdHMgd2hlbmV2ZXIgYW4gYWN0aW9uIHRoYXQgc2hvdWxkIGNsb3NlIHRoZSBtZW51IG9jY3Vyc1xuICAgIHRoaXMuX2Nsb3NpbmdBY3Rpb25zU3Vic2NyaXB0aW9uID0gdGhpcy5fbWVudUNsb3NpbmdBY3Rpb25zKCkuc3Vic2NyaWJlKFxuICAgICAgKCkgPT4gdGhpcy5jbG9zZU1lbnUoKVxuICAgICk7XG5cbiAgICB0aGlzLmFuaW1hdGVPcGVuTWVudSgpO1xuXG4gICAgdGhpcy5fc2V0SXNNZW51T3Blbih0cnVlKTtcbiAgICB0aGlzLm1lbnUuZm9jdXNGaXJzdEl0ZW0odGhpcy5vcGVuZWRCeSB8fCAncHJvZ3JhbScpO1xuICB9XG5cbiAgLyoqIEVtaXRzIGFuIGV2ZW50dHlwZSB3aGVuIHRoZSBtZW51IGlzIG9wZW5lZCAqL1xuICBvcGVuZWRFdmVudCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5vcGVuZWRCeSA9PT0gJ3RvdWNoJyB8fCB0aGlzLm9wZW5lZEJ5ID09PSAnbW91c2UnKSB7XG4gICAgICB0aGlzLm1lbnUub3BlbmVkLmVtaXQoJ2NsaWNrJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVudS5vcGVuZWQuZW1pdCgna2V5ZG93bicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSBtZW51IHRyaWdnZXJzIGEgc3ViLW1lbnUgb3IgYSB0b3AtbGV2ZWwgb25lLiAqL1xuICB0cmlnZ2Vyc1N1Ym1lbnUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKHRoaXMuX21lbnVJdGVtSW5zdGFuY2UgJiYgdGhpcy5fcGFyZW50TWVudSk7XG4gIH1cblxuICAvKiogVG9nZ2xlcyB0aGUgbWVudSBiZXR3ZWVuIHRoZSBvcGVuIGFuZCBjbG9zZWQgc3RhdGVzLiAqL1xuICB0b2dnbGVNZW51KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzTWVudU9wZW5lZCkge1xuICAgICAgdGhpcy5jbG9zZU1lbnUoKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMub3Blbk9uQ2xpY2spIHtcbiAgICAgIHRoaXMub3Blbk1lbnUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xvc2UgdGhlIGFzc29jaWF0ZWQgbWVudSAqL1xuICBjbG9zZU1lbnUoKTogdm9pZCB7XG4gICAgdGhpcy5tZW51LmNsb3NlZC5lbWl0KCk7XG4gIH1cblxuICAvKipcbiAgICogRm9jdXNlcyB0aGUgbWVudSB0cmlnZ2VyLlxuICAgKiBAcGFyYW0gb3JpZ2luIFNvdXJjZSBvZiB0aGUgbWVudSB0cmlnZ2VyJ3MgZm9jdXMuXG4gICAqL1xuICBmb2N1cyhvcmlnaW46IEZvY3VzT3JpZ2luID0gJ3Byb2dyYW0nLCBvcHRpb25zPzogRm9jdXNPcHRpb25zKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2ZvY3VzTW9uaXRvcikge1xuICAgICAgdGhpcy5fZm9jdXNNb25pdG9yLmZvY3VzVmlhKHRoaXMuX2VsZW1lbnQsIG9yaWdpbiwgb3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudC5mb2N1cyhvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKiogRGV0YWNoIG1lbnUgcG9ydGFsIGZyb20gb3ZlcmxheSBhbmQgdXBkYXRlIG9wZW4gc3RhdGUgKi9cbiAgX2Rlc3Ryb3lNZW51KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5fb3ZlcmxheVJlZiB8fCAhdGhpcy5pc01lbnVPcGVuZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9jbG9zaW5nQWN0aW9uc1N1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX292ZXJsYXlSZWYuZGV0YWNoKCk7XG4gICAgdGhpcy5fcmVzdG9yZUZvY3VzKCk7XG4gICAgdGhpcy5tZW51Ll9yZXNldEFuaW1hdGlvbigpO1xuXG4gICAgdGhpcy5fc2V0SXNNZW51T3BlbihmYWxzZSk7XG4gIH1cblxuICAvKiogSGFuZGxlcyBtb3VzZSBwcmVzc2VzIG9uIHRoZSB0cmlnZ2VyLiAqL1xuICBfaGFuZGxlTW91c2Vkb3duKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCFpc0Zha2VNb3VzZWRvd25Gcm9tU2NyZWVuUmVhZGVyKGV2ZW50KSkge1xuICAgICAgaWYgKHRoaXMub3BlbmVkQnkgIT09ICd0b3VjaCcpIHtcbiAgICAgICAgLy8gU2luY2UgcmlnaHQgb3IgbWlkZGxlIGJ1dHRvbiBjbGlja3Mgd29uJ3QgdHJpZ2dlciB0aGUgYGNsaWNrYCBldmVudCxcbiAgICAgICAgLy8gd2Ugc2hvdWxkbid0IGNvbnNpZGVyIHRoZSBtZW51IGFzIG9wZW5lZCBieSBtb3VzZSBpbiB0aG9zZSBjYXNlcy5cbiAgICAgICAgdGhpcy5vcGVuZWRCeSA9IGV2ZW50LmJ1dHRvbiA9PT0gMCA/ICdtb3VzZScgOiBudWxsO1xuICAgICAgfVxuXG4gICAgICAvLyBTaW5jZSBjbGlja2luZyBvbiB0aGUgdHJpZ2dlciB3b24ndCBjbG9zZSB0aGUgbWVudSBpZiBpdCBvcGVucyBhIHN1Yi1tZW51LFxuICAgICAgLy8gd2Ugc2hvdWxkIHByZXZlbnQgZm9jdXMgZnJvbSBtb3Zpbmcgb250byBpdCB2aWEgY2xpY2sgdG8gYXZvaWQgdGhlXG4gICAgICAvLyBoaWdobGlnaHQgZnJvbSBsaW5nZXJpbmcgb24gdGhlIG1lbnUgaXRlbS5cbiAgICAgIGlmICh0aGlzLnRyaWdnZXJzU3VibWVudSgpICYmICF0aGlzLl90b2dnbGVPblN1Ym1lbnVDbGljaygpKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIEhhbmRsZXMga2V5IHByZXNzZXMgb24gdGhlIHRyaWdnZXIuICovXG4gIF9oYW5kbGVLZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3Qga2V5ID0gZXZlbnQua2V5O1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKSAmJlxuICAgICAgKChrZXkgPT09ICdBcnJvd1JpZ2h0JyAmJiB0aGlzLl9kaXIudmFsdWUgPT09ICdsdHInKSB8fFxuICAgICAgICAoa2V5ID09PSAnQXJyb3dMZWZ0JyAmJiB0aGlzLl9kaXIudmFsdWUgPT09ICdydGwnKSlcbiAgICApIHtcbiAgICAgIHRoaXMub3Blbk1lbnUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogSGFuZGxlcyBjbGljayBldmVudHMgb24gdGhlIHRyaWdnZXIuICovXG4gIF9oYW5kbGVDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRyaWdnZXJzU3VibWVudSgpKSB7XG4gICAgICAvLyBTdG9wIGV2ZW50IHByb3BhZ2F0aW9uIHRvIGF2b2lkIGNsb3NpbmcgdGhlIHBhcmVudCBtZW51LlxuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIHRoaXMuX3RvZ2dsZU9uU3VibWVudUNsaWNrKCkgPyB0aGlzLnRvZ2dsZU1lbnUoKSA6IHRoaXMub3Blbk1lbnUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy50b2dnbGVNZW51KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdG91Y2ggc3RhcnQgZXZlbnRzIG9uIHRoZSB0cmlnZ2VyLlxuICAgKiBOZWVkcyB0byBiZSBhbiBhcnJvdyBmdW5jdGlvbiBzbyB3ZSBjYW4gZWFzaWx5IHVzZSBhZGRFdmVudExpc3RlbmVyIGFuZCByZW1vdmVFdmVudExpc3RlbmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlVG91Y2hTdGFydCA9ICgpID0+IHtcbiAgICB0aGlzLm9wZW5lZEJ5ID0gJ3RvdWNoJztcbiAgfTtcblxuICAvKiogSGFuZGxlcyB0aGUgY2FzZXMgd2hlcmUgdGhlIHVzZXIgaG92ZXJzIG92ZXIgdGhlIHRyaWdnZXIuICovXG4gIHByaXZhdGUgX2hhbmRsZUhvdmVyKCkge1xuICAgIC8vIFN1YnNjcmliZSB0byBjaGFuZ2VzIGluIHRoZSBob3ZlcmVkIGl0ZW0gaW4gb3JkZXIgdG8gdG9nZ2xlIHRoZSBwYW5lbC5cbiAgICBpZiAoIXRoaXMudHJpZ2dlcnNTdWJtZW51KCkgfHwgIXRoaXMuX3BhcmVudE1lbnUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9ob3ZlclN1YnNjcmlwdGlvbiA9IHRoaXMuX3BhcmVudE1lbnVcbiAgICAgIC5faG92ZXJlZCgpXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKCgpID0+IHRoaXMuX29wZW5PbkhvdmVyKCkpLFxuICAgICAgICAvLyBTaW5jZSB3ZSBtaWdodCBoYXZlIG11bHRpcGxlIGNvbXBldGluZyB0cmlnZ2VycyBmb3IgdGhlIHNhbWUgbWVudSAoZS5nLiBhIHN1Yi1tZW51XG4gICAgICAgIC8vIHdpdGggZGlmZmVyZW50IGRhdGEgYW5kIHRyaWdnZXJzKSwgd2UgaGF2ZSB0byBkZWxheSBpdCBieSBhIHRpY2sgdG8gZW5zdXJlIHRoYXRcbiAgICAgICAgLy8gaXQgd29uJ3QgYmUgY2xvc2VkIGltbWVkaWF0ZWx5IGFmdGVyIGl0IGlzIG9wZW5lZC5cbiAgICAgICAgZmlsdGVyKFxuICAgICAgICAgIChhY3RpdmUpID0+IGFjdGl2ZSA9PT0gdGhpcy5fbWVudUl0ZW1JbnN0YW5jZSAvKiYmICFhY3RpdmUuZGlzYWJsZWQqL1xuICAgICAgICApLFxuICAgICAgICBkZWxheSgwLCBhc2FwU2NoZWR1bGVyKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMub3BlbmVkQnkgPSAnbW91c2UnO1xuXG4gICAgICAgIC8vIElmIHRoZSBzYW1lIG1lbnUgaXMgdXNlZCBiZXR3ZWVuIG11bHRpcGxlIHRyaWdnZXJzLCBpdCBtaWdodCBzdGlsbCBiZSBhbmltYXRpbmdcbiAgICAgICAgLy8gd2hpbGUgdGhlIG5ldyB0cmlnZ2VyIHRyaWVzIHRvIHJlLW9wZW4gaXQuIFdhaXQgZm9yIHRoZSBhbmltYXRpb24gdG8gZmluaXNoXG4gICAgICAgIC8vIGJlZm9yZSBkb2luZyBzby4gQWxzbyBpbnRlcnJ1cHQgaWYgdGhlIHVzZXIgbW92ZXMgdG8gYW5vdGhlciBpdGVtLlxuICAgICAgICBpZiAodGhpcy5tZW51IGluc3RhbmNlb2YgX01lbnVCYXNlQ29tcG9uZW50ICYmIHRoaXMubWVudS5faXNBbmltYXRpbmcpIHtcbiAgICAgICAgICAvLyBXZSBuZWVkIHRoZSBgZGVsYXkoMClgIGhlcmUgaW4gb3JkZXIgdG8gYXZvaWRcbiAgICAgICAgICAvLyAnY2hhbmdlZCBhZnRlciBjaGVja2VkJyBlcnJvcnMgaW4gc29tZSBjYXNlcy4gU2VlIEFuZ3VsYXIgTWF0ZXJpYWwgIzEyMTk0LlxuICAgICAgICAgIHRoaXMubWVudS5fYW5pbWF0aW9uRG9uZVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgIHRha2UoMSksXG4gICAgICAgICAgICAgIGRlbGF5KDAsIGFzYXBTY2hlZHVsZXIpLFxuICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fcGFyZW50TWVudS5faG92ZXJlZCgpKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLm9wZW5NZW51KCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMub3Blbk1lbnUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzdG9yZXMgZm9jdXMgdG8gdGhlIGVsZW1lbnQgdGhhdCB3YXMgZm9jdXNlZCBiZWZvcmUgdGhlIG1lbnUgd2FzIG9wZW4uXG4gICAqIENvdWxkIGJlIHRoZSByb290IHRyaWdnZXIgYnV0dG9uIG9yIGEgc3VibWVudSB0cmlnZ2VyIGl0ZW1cbiAgICovXG4gIHByaXZhdGUgX3Jlc3RvcmVGb2N1cygpIHtcbiAgICAvLyBXZSBzaG91bGQgcmVzZXQgZm9jdXMgaWYgdGhlIHVzZXIgaXMgbmF2aWdhdGluZyB1c2luZyBhIGtleWJvYXJkIG9yXG4gICAgLy8gaWYgd2UgaGF2ZSBhIHRvcC1sZXZlbCB0cmlnZ2VyIHdoaWNoIG1pZ2h0IGNhdXNlIGZvY3VzIHRvIGJlIGxvc3RcbiAgICAvLyB3aGVuIGNsaWNraW5nIG91dHNpZGUgb2YgdGhlIG1lbnUuXG4gICAgaWYgKCF0aGlzLm9wZW5lZEJ5KSB7XG4gICAgICAvLyBOb3RlIHRoYXQgdGhlIGZvY3VzIHN0eWxlIHdpbGwgc2hvdyB1cCBib3RoIGZvciBgcHJvZ3JhbWAgYW5kXG4gICAgICAvLyBga2V5Ym9hcmRgIHNvIHdlIGRvbid0IGhhdmUgdG8gc3BlY2lmeSB3aGljaCBvbmUgaXQgaXMuXG4gICAgICB0aGlzLmZvY3VzKCk7XG4gICAgfSBlbHNlIGlmICghdGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKSkge1xuICAgICAgdGhpcy5mb2N1cyh0aGlzLm9wZW5lZEJ5KTtcbiAgICB9XG5cbiAgICB0aGlzLm9wZW5lZEJ5ID0gbnVsbDtcbiAgfVxuXG4gIC8vIFNldCBzdGF0ZSByYXRoZXIgdGhhbiB0b2dnbGUgdG8gc3VwcG9ydCB0cmlnZ2VycyBzaGFyaW5nIGEgbWVudVxuICBwcml2YXRlIF9zZXRJc01lbnVPcGVuKGlzT3BlbjogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzTWVudU9wZW5lZCAhPT0gaXNPcGVuKSB7XG4gICAgICB0aGlzLl9jaGFuZ2VEZXRlY3Rpb25SZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pc01lbnVPcGVuZWQgPSBpc09wZW47XG5cbiAgICBpZiAodGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKSkge1xuICAgICAgdGhpcy5fbWVudUl0ZW1JbnN0YW5jZS5faGlnaGxpZ2h0ZWQgPVxuICAgICAgICBpc09wZW4gJiYgdGhpcy5fY2xpZW50T3V0cHV0LmRldmljZSAhPT0gJ3RvdWNoJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgY2hlY2tzIHRoYXQgYSB2YWxpZCBpbnN0YW5jZSBvZiBNZW51Q29tcG9uZW50IGhhcyBiZWVuIHBhc3NlZCBpbnRvXG4gICAqIGdyYW5pdGVNZW51VHJpZ2dlckZvci4gSWYgbm90LCBhbiBleGNlcHRpb24gaXMgdGhyb3duLlxuICAgKi9cbiAgcHJpdmF0ZSBfY2hlY2tNZW51KCkge1xuICAgIGlmICghdGhpcy5tZW51KSB7XG4gICAgICB0aHJvd0dyYW5pdGVNZW51TWlzc2luZ0Vycm9yKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3RyYXRlZ3kgZm9yIHBvc2l0aW9uaW5nIHRoZSBvdmVybGF5IGZvciBkZXNrdG9wIGRldmljZXM6XG4gICAqIFBsYWNlIGFkamFjZW50IHRvIHRoZSB0cmlnZ2VyIGJ1dHRvbiAocHJlZmVyYWJseSBpbW1lZGlhdGVseSBiZWxvdylcbiAgICogaW4gb3JkZXIgdG8gc2hvdyBhcyBtdWNoIG9mIHRoZSBtZW51IGFzIHBvc3NpYmxlLlxuICAgKi9cbiAgcHJpdmF0ZSBfZGVza3RvcFBvc2l0aW9uU3RyYXRlZ3koKTogUG9zaXRpb25TdHJhdGVneSB7XG4gICAgY29uc3QgcG9zaXRpb25TdHJhdGVneTogRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5ID0gdGhpcy5fb3ZlcmxheVxuICAgICAgLnBvc2l0aW9uKClcbiAgICAgIC5mbGV4aWJsZUNvbm5lY3RlZFRvKHRoaXMuX2VsZW1lbnQpXG4gICAgICAud2l0aExvY2tlZFBvc2l0aW9uKClcbiAgICAgIC53aXRoVHJhbnNmb3JtT3JpZ2luT24oJy5ncmFuaXRlLW1lbnUnKTtcblxuICAgIHRoaXMuX3NldFBvc2l0aW9uKHBvc2l0aW9uU3RyYXRlZ3kpO1xuICAgIHJldHVybiBwb3NpdGlvblN0cmF0ZWd5O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGFwcHJvcHJpYXRlIHBvc2l0aW9ucyBvbiBhIHBvc2l0aW9uIHN0cmF0ZWd5XG4gICAqIHNvIHRoZSBvdmVybGF5IGNvbm5lY3RzIHdpdGggdGhlIHRyaWdnZXIgY29ycmVjdGx5LlxuICAgKiBAcGFyYW0gcG9zaXRpb25TdHJhdGVneSBTdHJhdGVneSB3aG9zZSBwb3NpdGlvbiB0byB1cGRhdGUuXG4gICAqL1xuICBwcml2YXRlIF9zZXRQb3NpdGlvbihwb3NpdGlvblN0cmF0ZWd5OiBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kpIHtcbiAgICBjb25zdCBNRU5VX1BBTkVMX1RPUF9QQURESU5HID0gMDtcblxuICAgIGxldCBbb3JpZ2luWCwgb3JpZ2luRmFsbGJhY2tYXTogSG9yaXpvbnRhbENvbm5lY3Rpb25Qb3NbXSA9XG4gICAgICB0aGlzLm1lbnUueFBvc2l0aW9uID09PSAnYmVmb3JlJyA/IFsnZW5kJywgJ3N0YXJ0J10gOiBbJ3N0YXJ0JywgJ2VuZCddO1xuXG4gICAgY29uc3QgW292ZXJsYXlZLCBvdmVybGF5RmFsbGJhY2tZXTogVmVydGljYWxDb25uZWN0aW9uUG9zW10gPVxuICAgICAgdGhpcy5tZW51LnlQb3NpdGlvbiA9PT0gJ2Fib3ZlJyA/IFsnYm90dG9tJywgJ3RvcCddIDogWyd0b3AnLCAnYm90dG9tJ107XG5cbiAgICBsZXQgW29yaWdpblksIG9yaWdpbkZhbGxiYWNrWV0gPSBbb3ZlcmxheVksIG92ZXJsYXlGYWxsYmFja1ldO1xuICAgIGxldCBbb3ZlcmxheVgsIG92ZXJsYXlGYWxsYmFja1hdID0gW29yaWdpblgsIG9yaWdpbkZhbGxiYWNrWF07XG4gICAgbGV0IG9mZnNldFkgPSAwO1xuXG4gICAgaWYgKHRoaXMudHJpZ2dlcnNTdWJtZW51KCkpIHtcbiAgICAgIC8vIFdoZW4gdGhlIG1lbnUgaXMgYSBzdWItbWVudSwgaXQgc2hvdWxkIGFsd2F5cyBhbGlnbiBpdHNlbGZcbiAgICAgIC8vIHRvIHRoZSBlZGdlcyBvZiB0aGUgdHJpZ2dlciwgaW5zdGVhZCBvZiBvdmVybGFwcGluZyBpdC5cbiAgICAgIG92ZXJsYXlGYWxsYmFja1ggPSBvcmlnaW5YID1cbiAgICAgICAgdGhpcy5tZW51LnhQb3NpdGlvbiA9PT0gJ2JlZm9yZScgPyAnc3RhcnQnIDogJ2VuZCc7XG4gICAgICBvcmlnaW5GYWxsYmFja1ggPSBvdmVybGF5WCA9IG9yaWdpblggPT09ICdlbmQnID8gJ3N0YXJ0JyA6ICdlbmQnO1xuICAgICAgb2Zmc2V0WSA9XG4gICAgICAgIG92ZXJsYXlZID09PSAnYm90dG9tJ1xuICAgICAgICAgID8gTUVOVV9QQU5FTF9UT1BfUEFERElOR1xuICAgICAgICAgIDogLU1FTlVfUEFORUxfVE9QX1BBRERJTkc7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9yaWdpblkgPSBvdmVybGF5WSA9PT0gJ3RvcCcgPyAnYm90dG9tJyA6ICd0b3AnO1xuICAgICAgb3JpZ2luRmFsbGJhY2tZID0gb3ZlcmxheUZhbGxiYWNrWSA9PT0gJ3RvcCcgPyAnYm90dG9tJyA6ICd0b3AnO1xuICAgIH1cblxuICAgIHBvc2l0aW9uU3RyYXRlZ3kud2l0aFBvc2l0aW9ucyhbXG4gICAgICB7IG9yaWdpblgsIG9yaWdpblksIG92ZXJsYXlYLCBvdmVybGF5WSwgb2Zmc2V0WSB9LFxuICAgICAge1xuICAgICAgICBvcmlnaW5YOiBvcmlnaW5GYWxsYmFja1gsXG4gICAgICAgIG9yaWdpblksXG4gICAgICAgIG92ZXJsYXlYOiBvdmVybGF5RmFsbGJhY2tYLFxuICAgICAgICBvdmVybGF5WSxcbiAgICAgICAgb2Zmc2V0WSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG9yaWdpblgsXG4gICAgICAgIG9yaWdpblk6IG9yaWdpbkZhbGxiYWNrWSxcbiAgICAgICAgb3ZlcmxheVgsXG4gICAgICAgIG92ZXJsYXlZOiBvdmVybGF5RmFsbGJhY2tZLFxuICAgICAgICBvZmZzZXRZOiAtb2Zmc2V0WSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG9yaWdpblg6IG9yaWdpbkZhbGxiYWNrWCxcbiAgICAgICAgb3JpZ2luWTogb3JpZ2luRmFsbGJhY2tZLFxuICAgICAgICBvdmVybGF5WDogb3ZlcmxheUZhbGxiYWNrWCxcbiAgICAgICAgb3ZlcmxheVk6IG92ZXJsYXlGYWxsYmFja1ksXG4gICAgICAgIG9mZnNldFk6IC1vZmZzZXRZLFxuICAgICAgfSxcbiAgICBdKTtcbiAgfVxuXG4gIC8qKiBSZXR1cm5zIGEgc3RyZWFtIHRoYXQgZW1pdHMgd2hlbmV2ZXIgYW4gYWN0aW9uIHRoYXQgc2hvdWxkIGNsb3NlIHRoZSBtZW51IG9jY3Vycy4gKi9cbiAgcHJpdmF0ZSBfbWVudUNsb3NpbmdBY3Rpb25zKCkge1xuICAgIGNvbnN0IGRldGFjaG1lbnRzID0gdGhpcy5fb3ZlcmxheVJlZj8uZGV0YWNobWVudHMoKTtcbiAgICBjb25zdCBwYXJlbnRDbG9zZSA9IHRoaXMuX3BhcmVudE1lbnVcbiAgICAgID8gdGhpcy5fcGFyZW50TWVudS5jbG9zZWRcbiAgICAgIDogb2JzZXJ2YWJsZU9mPENsb3NlZEV2ZW50VHlwZT4obnVsbCk7XG5cbiAgICBjb25zdCBob3ZlciA9XG4gICAgICB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAnZGVza3RvcCcgJiYgdGhpcy5fcGFyZW50TWVudVxuICAgICAgICA/IHRoaXMuX3BhcmVudE1lbnUuX2hvdmVyZWQoKS5waXBlKFxuICAgICAgICAgICAgZmlsdGVyKChpdGVtKSA9PiBpdGVtICE9PSB0aGlzLl9tZW51SXRlbUluc3RhbmNlKSxcbiAgICAgICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLmlzTWVudU9wZW5lZClcbiAgICAgICAgICApXG4gICAgICAgIDogb2JzZXJ2YWJsZU9mPENsb3NlZEV2ZW50VHlwZT4obnVsbCk7XG5cbiAgICAvLyBOb3RlOiBRdWljayBmaXguIEZlYXR1cmUgcmVwb3J0ZWRseSBleGlzdHMgaW4gQ0RLIGZvciBBbmd1bGFyIDEwXG4gICAgLy8gRmlsdGVyIHRvIHByZXZlbnQgY2xvc2luZyB3aGVuIGFuaW1hdGluZyBhZGRlZCB0aG91Z2guIEFwcGxpZWQgdG9cbiAgICAvLyByb290IG1lbnUgb25seS5cbiAgICBjb25zdCBvdXRzaWRlQ2xpY2sgPSAhdGhpcy5fcGFyZW50TWVudVxuICAgICAgPyBmcm9tRXZlbnQ8TW91c2VFdmVudD4odGhpcy5fZG9jdW1lbnQsICdjbGljaycpLnBpcGUoXG4gICAgICAgICAgZmlsdGVyKFxuICAgICAgICAgICAgKGU6IE1vdXNlRXZlbnQpID0+XG4gICAgICAgICAgICAgIChlLnRhcmdldCBhcyBIVE1MRWxlbWVudCkgIT09IHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCAmJlxuICAgICAgICAgICAgICAoZS50YXJnZXQgYXMgSFRNTEVsZW1lbnQpLmNsb3Nlc3QoJy5ncmFuaXRlLW1lbnUnKSA9PT0gbnVsbFxuICAgICAgICAgICksXG4gICAgICAgICAgZmlsdGVyKCgpID0+ICF0aGlzLm1lbnUuX2lzQW5pbWF0aW5nKVxuICAgICAgICApXG4gICAgICA6IG9ic2VydmFibGVPZjxNb3VzZUV2ZW50IHwgbnVsbD4obnVsbCk7XG5cbiAgICByZXR1cm4gbWVyZ2UoZGV0YWNobWVudHMsIGhvdmVyLCBwYXJlbnRDbG9zZSwgb3V0c2lkZUNsaWNrKS5waXBlKFxuICAgICAgZmlsdGVyKChldmVudCkgPT4gZXZlbnQgIT09IG51bGwpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGF1dG9tYXRpY2FsbHkgb3BlbiBzdWJtZW51cyBvbiBob3Zlci4gVGhpcyBpcyB0cnVlIHdoZW4gc2hvd2luZ1xuICAgKiBkZXNrdG9wIG1lbnVzIGFuZCBoYXZpbmcgbW91c2Ugc3VwcG9ydC5cbiAgICovXG4gIHByaXZhdGUgX29wZW5PbkhvdmVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICAodGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKVxuICAgICAgICA/IHRoaXMuX3BhcmVudE1lbnUub3Blbk9uSG92ZXJcbiAgICAgICAgOiB0aGlzLm1lbnUub3Blbk9uSG92ZXIpICYmXG4gICAgICB0aGlzLl9wYXJlbnRNZW51Ll9jbGllbnRPdXRwdXQ/LmRldmljZSA9PT0gJ2Rlc2t0b3AnICYmXG4gICAgICB0aGlzLl9wYXJlbnRNZW51Ll9jbGllbnRJbnB1dD8uZGV2aWNlcy5pbmNsdWRlcygnbW91c2UnKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0byB0b2dnbGUgc3VibWVudXMgb24gY2xpY2suIFRoaXMgaXMgdHJ1ZSB3aGVuIHNob3dpbmcgZGVza3RvcCBtZW51c1xuICAgKiB3aXRob3V0IG1vdXNlIHN1cHBvcnQuIFdoaWNoLCBieSB0aGUgd2F5LCBpcyBub3QgYSBncmVhdCBpZGVhIHRvIGJlZ2luIHdpdGguXG4gICAqL1xuICBwcml2YXRlIF90b2dnbGVPblN1Ym1lbnVDbGljaygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgISh0aGlzLnRyaWdnZXJzU3VibWVudSgpXG4gICAgICAgID8gdGhpcy5fcGFyZW50TWVudS5vcGVuT25Ib3ZlclxuICAgICAgICA6IHRoaXMubWVudS5vcGVuT25Ib3ZlcikgfHxcbiAgICAgICh0aGlzLl9wYXJlbnRNZW51Ll9jbGllbnRPdXRwdXQ/LmRldmljZSA9PT0gJ2Rlc2t0b3AnICYmXG4gICAgICAgICF0aGlzLl9wYXJlbnRNZW51Ll9jbGllbnRJbnB1dD8uZGV2aWNlcy5pbmNsdWRlcygnbW91c2UnKSlcbiAgICApO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuICAvLyAtLS0gSGVyZSBiZSB0b3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tIC8vXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvKiogU2V0IGFuaW1hdGlvbiBzdGF0ZSB0byBicmluZyBhIG5ld2x5IG9wZW5lZCBtZW51IGludG8gdmlldyAqL1xuICBwcml2YXRlIGFuaW1hdGVPcGVuTWVudSgpIHtcbiAgICB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAndG91Y2gnXG4gICAgICA/IHRoaXMuYW5pbWF0ZVRvdWNoT3Blbk1lbnUoKVxuICAgICAgOiB0aGlzLm1lbnUuX3N0YXJ0QW5pbWF0aW9uKCk7XG4gIH1cblxuICBwcml2YXRlIGFuaW1hdGVUb3VjaE9wZW5NZW51KCkge1xuICAgIGlmICh0aGlzLnRyaWdnZXJzU3VibWVudSgpKSB7XG4gICAgICAvLyBTbGlkZSBuZXdseSBvcGVuZWQgc3ViIG1lbnUgaW50byB2aWV3IGZyb20gdGhlIHNpZGUsXG4gICAgICAvLyBwdXNoaW5nIGFueSBwYXJlbnQgbWVudSBvdXQgb2YgdmlldyBvbiB0aGUgb3RoZXIgc2lkZVxuICAgICAgdGhpcy5tZW51Ll9zdGFydFRvdWNoU3VibWVudUVudGVyQW5pbWF0aW9uKCk7XG4gICAgICB0aGlzLl9wYXJlbnRNZW51Ll9zdGFydFRvdWNoSGlkZUFuaW1hdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTbGlkZSByb290IG1lbnUgaW50byB2aWV3IGZyb20gYmVsb3dcbiAgICAgIHRoaXMubWVudS5fc3RhcnRUb3VjaFJvb3RFbnRlckFuaW1hdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTZXQgYW5pbWF0aW9uIHN0YXRlIHRvIGNsb3NlIHRoZSBhY3RpdmUgbWVudSAqL1xuICBwcml2YXRlIGFuaW1hdGVDbG9zZU1lbnUodG9CZWxvdzogYm9vbGVhbiwgd2l0aERlbGF5OiBib29sZWFuKSB7XG4gICAgdGhpcy5fY2xpZW50T3V0cHV0LmRldmljZSA9PT0gJ3RvdWNoJ1xuICAgICAgPyB0aGlzLl9hbmltYXRlVG91Y2hDbG9zZU1lbnUodG9CZWxvdywgd2l0aERlbGF5KVxuICAgICAgOiB0aGlzLl9wYXJlbnRNZW51Ll9yZXNldEFuaW1hdGlvbigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfYW5pbWF0ZVRvdWNoQ2xvc2VNZW51KHRvQmVsb3c6IGJvb2xlYW4sIHdpdGhEZWxheTogYm9vbGVhbikge1xuICAgIGlmICh0b0JlbG93KSB7XG4gICAgICAvLyBTbGlkZSBtZW51IG91dCBvZiB2aWV3IGJlbG93IHRoZSB2aWV3cG9ydFxuICAgICAgd2l0aERlbGF5XG4gICAgICAgID8gdGhpcy5tZW51Ll9zdGFydFRvdWNoQ2xvc2VEb3duQW5pbWF0aW9uV2l0aERlbGF5KClcbiAgICAgICAgOiB0aGlzLm1lbnUuX3N0YXJ0VG91Y2hDbG9zZURvd25BbmltYXRpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU2xpZGUgdGhlIGNsb3NlZCBtZW51IG91dCBvZiB2aWV3IHRvIHRoZSBzaWRlXG4gICAgICAvLyBhbmQgc2xpZGUgYW55IHBhcmVudCBtZW51IGJhY2sgaW50byB2aWV3XG4gICAgICB0aGlzLm1lbnUuX3N0YXJ0VG91Y2hDbG9zZVNpZGVBbmltYXRpb24oKTtcbiAgICAgIHRoaXMuX3BhcmVudE1lbnU/Ll9zdGFydFRvdWNoU3VibWVudUVudGVyQW5pbWF0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldCBhbmltYXRpb24gc3RhdGUgdG8gcGxhY2UgdGhlIG1lbnUgYW5kIGFueSBwYXJlbnQgYXQgdGhlIGdpdmVuXG4gICAqIGhvcml6b250YWwgcG9zaXRpb24sIGkuZS4gZm9sbG93aW5nIHRvdWNoIHBhbiBtb3ZlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIHhPZmZzZXQgSG9yaXpvbnRhbCBvZmZzZXRcbiAgICovXG4gIHByaXZhdGUgYW5pbWF0ZVNldE1lbnVQb3NpdGlvbih4T2Zmc2V0OiBudW1iZXIpIHtcbiAgICB0aGlzLm1lbnUuX3N0YXJ0VG91Y2hQYW5BbmltYXRpb24oeE9mZnNldCk7XG4gICAgaWYgKHRoaXMuX3BhcmVudE1lbnUpIHtcbiAgICAgIHRoaXMuX3BhcmVudE1lbnUuX3N0YXJ0VG91Y2hIaWRlUGFuQW5pbWF0aW9uKHhPZmZzZXQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHN0cmF0ZWd5IGZvciBwb3NpdGlvbmluZyB0aGUgb3ZlcmxheSBkZXBlbmRpbmcgb24gd2hhdCB0eXBlIG9mXG4gICAqIGRldmljZSB0aGUgbWVudSBpcyBiZWluZyBzaG93biBvblxuICAgKi9cbiAgcHJpdmF0ZSBfcG9zaXRpb25TdHJhdGVneSgpOiBQb3NpdGlvblN0cmF0ZWd5IHtcbiAgICByZXR1cm4gdGhpcy5fY2xpZW50T3V0cHV0LmRldmljZSA9PT0gJ3RvdWNoJ1xuICAgICAgPyB0aGlzLl90b3VjaFBvc2l0aW9uU3RyYXRlZ3koKVxuICAgICAgOiB0aGlzLl9kZXNrdG9wUG9zaXRpb25TdHJhdGVneSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3RyYXRlZ3kgZm9yIHBvc2l0aW9uaW5nIHRoZSBvdmVybGF5IGZvciB0b3VjaCBkZXZpY2VzOlxuICAgKiBQbGFjZSBjZW50ZXJlZCBhdCB0aGUgYm90dG9tIG9mIHRoZSBzY3JlZW4uXG4gICAqL1xuICBwcml2YXRlIF90b3VjaFBvc2l0aW9uU3RyYXRlZ3koKTogUG9zaXRpb25TdHJhdGVneSB7XG4gICAgcmV0dXJuIHRoaXMuX292ZXJsYXkucG9zaXRpb24oKS5nbG9iYWwoKTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG4gIC8vIC0tLSBIZXJlIGJlIHBvb3IgbWFuJ3MgdG91Y2ggZ2VzdHVyZXMgLS0tIC8vXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbiAgLy8gVE9ETzogUmVwbGFjZSB3aXRoIEhhbW1lciBvciBvdGhlciBnZXN0dXJlIGxpYnJhcnlcblxuICAvKipcbiAgICogSGFuZGxlcyB0b3VjaCBzdGFydCBldmVudHMgb24gdGhlIG92ZXJsYXkgaG9zdCBlbGVtZW50ICh3cmFwcGVyKS5cbiAgICogTmVlZHMgdG8gYmUgYW4gYXJyb3cgZnVuY3Rpb24gc28gd2UgY2FuIGVhc2lseSB1c2UgYWRkRXZlbnRMaXN0ZW5lciBhbmQgcmVtb3ZlRXZlbnRMaXN0ZW5lci5cbiAgICovXG4gIHByaXZhdGUgX2hhbmRsZU92ZXJsYXlUb3VjaFN0YXJ0ID0gKGV2ZW50OiBUb3VjaEV2ZW50KSA9PiB7XG4gICAgaWYgKHRoaXMubWVudS5faXNBbmltYXRpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl90b3VjaFN0YXJ0VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuXG4gICAgdGhpcy5fdG91Y2hTdGFydFggPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRYO1xuICAgIHRoaXMuX3RvdWNoU3RhcnRZID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0uY2xpZW50WTtcbiAgICB0aGlzLl90b3VjaEN1cnJlbnRYID0gdGhpcy5fdG91Y2hTdGFydFg7XG4gICAgdGhpcy5fdG91Y2hDdXJyZW50WSA9IHRoaXMuX3RvdWNoU3RhcnRZO1xuICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA9IDA7XG4gICAgdGhpcy5fdG91Y2hNYXhYID1cbiAgICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG4gICAgdGhpcy5fdG91Y2hMb2NrZWRYID0gbnVsbDtcbiAgICB0aGlzLl90b3VjaFRvdWNoaW5nRWxlbWVudCA9IHRydWU7XG4gIH07XG5cbiAgcHJpdmF0ZSBfaGFuZGxlT3ZlcmxheVRvdWNoTW92ZSA9IChldmVudDogVG91Y2hFdmVudCkgPT4ge1xuICAgIGlmICghdGhpcy5fdG91Y2hUb3VjaGluZ0VsZW1lbnQgfHwgdGhpcy5tZW51Ll9pc0FuaW1hdGluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl90b3VjaExvY2tlZFgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl90b3VjaEN1cnJlbnRYID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0uY2xpZW50WDtcbiAgICB0aGlzLl90b3VjaEN1cnJlbnRZID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0uY2xpZW50WTtcblxuICAgIC8vIExvY2sgWC1heGlzIHBhbiBpZiBpbml0aWF0aW5nIHBhbiBvbiBZLWF4aXNcbiAgICBpZiAodGhpcy5fdG91Y2hMb2NrZWRYID09PSBudWxsKSB7XG4gICAgICBjb25zdCBkeSA9IE1hdGguYWJzKHRoaXMuX3RvdWNoQ3VycmVudFkgLSB0aGlzLl90b3VjaFN0YXJ0WSk7XG4gICAgICBjb25zdCBkeCA9IE1hdGguYWJzKHRoaXMuX3RvdWNoQ3VycmVudFggLSB0aGlzLl90b3VjaFN0YXJ0WCk7XG4gICAgICBpZiAoZHggPiAxMCB8fCBkeSA+IDEwKSB7XG4gICAgICAgIHRoaXMuX3RvdWNoTG9ja2VkWCA9IGR5ID4gZHg7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZXN0cmljdCB0byByaWdodCBwYW4vc3dpcGUgYW5kIG1ha2UgbWVudSBtb3ZlbWVudCBleHRyZW1lbHkgc2xvdyB3aGVuXG4gICAgLy8gbW92ZWQgcGFzdCBhbGxvd2VkIGxpbWl0cy5cbiAgICBjb25zdCBtZW51TWFyZ2luID0gMTY7XG4gICAgdGhpcy5fdG91Y2hUcmFuc2xhdGVYID0gdGhpcy5fdG91Y2hDdXJyZW50WCAtIHRoaXMuX3RvdWNoU3RhcnRYO1xuXG4gICAgaWYgKHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA8IDApIHtcbiAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA9IHRoaXMuZWFzZU91dEV4cG8oXG4gICAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCxcbiAgICAgICAgMCxcbiAgICAgICAgLW1lbnVNYXJnaW4gLyAyLFxuICAgICAgICB0aGlzLl90b3VjaE1heFggKiAtNFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLl9wYXJlbnRNZW51KSB7XG4gICAgICB0aGlzLl90b3VjaFRyYW5zbGF0ZVggPSB0aGlzLmVhc2VPdXRFeHBvKFxuICAgICAgICB0aGlzLl90b3VjaFRyYW5zbGF0ZVgsXG4gICAgICAgIDAsXG4gICAgICAgIG1lbnVNYXJnaW4gLyAyLFxuICAgICAgICB0aGlzLl90b3VjaE1heFggKiA0XG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fdG91Y2hUcmFuc2xhdGVYID4gdGhpcy5fdG91Y2hNYXhYKSB7XG4gICAgICB0aGlzLl90b3VjaFRyYW5zbGF0ZVggPSB0aGlzLmVhc2VPdXRFeHBvKFxuICAgICAgICB0aGlzLl90b3VjaFRyYW5zbGF0ZVggLSB0aGlzLl90b3VjaE1heFgsXG4gICAgICAgIHRoaXMuX3RvdWNoTWF4WCxcbiAgICAgICAgbWVudU1hcmdpbiAvIDIsXG4gICAgICAgIHRoaXMuX3RvdWNoTWF4WCAqIDRcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gU2V0IG5ldyBzdWIgbWVudSBwb3NpdGlvbiBhbmQgdGVsbCBhbnkgcGFyZW50IHRvIGZvbGxvdztcbiAgICB0aGlzLmFuaW1hdGVTZXRNZW51UG9zaXRpb24odGhpcy5fdG91Y2hUcmFuc2xhdGVYKTtcbiAgfTtcblxuICBwcml2YXRlIF9oYW5kbGVPdmVybGF5VG91Y2hFbmQgPSAoKSA9PiB7XG4gICAgaWYgKCF0aGlzLl90b3VjaFRvdWNoaW5nRWxlbWVudCB8fCB0aGlzLm1lbnUuX2lzQW5pbWF0aW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fdG91Y2hUcmFuc2xhdGVYID0gdGhpcy5fdG91Y2hDdXJyZW50WCAtIHRoaXMuX3RvdWNoU3RhcnRYO1xuICAgIGlmICh0aGlzLl90b3VjaFRyYW5zbGF0ZVggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl90b3VjaFRvdWNoaW5nRWxlbWVudCA9IGZhbHNlO1xuICAgIHRoaXMuX3RvdWNoVGltZVRha2VuID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSB0aGlzLl90b3VjaFN0YXJ0VGltZTtcblxuICAgIGNvbnN0IHN3aXBlTWluRGlzdGFuY2UgPSAxMDtcbiAgICBjb25zdCBzd2lwZU1pblRpbWUgPSA1MDtcbiAgICBjb25zdCBzd2lwZU1heFRpbWUgPSAzMDA7XG5cbiAgICBjb25zdCBwYW5uZWRIYWxmd2F5UmlnaHQgPSB0aGlzLl90b3VjaFRyYW5zbGF0ZVggPiB0aGlzLl90b3VjaE1heFggLyAyO1xuICAgIGNvbnN0IHN3aXBlZFJpZ2h0ID1cbiAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA+IHRoaXMuX3RvdWNoTWF4WCAvIHN3aXBlTWluRGlzdGFuY2UgJiZcbiAgICAgIHRoaXMuX3RvdWNoVGltZVRha2VuID4gc3dpcGVNaW5UaW1lICYmXG4gICAgICB0aGlzLl90b3VjaFRpbWVUYWtlbiA8IHN3aXBlTWF4VGltZTtcblxuICAgIGlmICghIXRoaXMuX3BhcmVudE1lbnUgJiYgKHN3aXBlZFJpZ2h0IHx8IHBhbm5lZEhhbGZ3YXlSaWdodCkpIHtcbiAgICAgIC8vIENsb3NlIHN1Ym1lbnUga2V5ZG93bi1zdHlsZTogY2xvc2Ugb25seSB0aGlzIG1lbnUgYW5kIGxlYXZlIHBhcmVudHMgb3BlblxuICAgICAgdGhpcy5tZW51LmNsb3NlZC5lbWl0KCdrZXlkb3duJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFBhbiBlbmRlZCBidXQgdGhlIG1lbnUgd2FzIG5vdCBtb3ZlZCBmYXIgZW5vdWdoLiBSZXNldCBtZW51cyB0b1xuICAgICAgLy8gd2hlcmUgdGhleSB3ZXJlIGJlZm9yZSBwYW5uaW5nIHN0YXJlZC5cbiAgICAgIHRoaXMuYW5pbWF0ZU9wZW5NZW51KCk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBSZW1vdmUgdG91Y2ggZGV2aWNlIHBhbi9zd2lwZSBsaXN0ZW5lcnMgZnJvbSBvdmVybGF5IGhvc3QgZWxlbWVudFxuICAgKi9cbiAgcHJpdmF0ZSBhZGRPdmVybGF5TGlzdGVuZXJzKCkge1xuICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICd0b3VjaHN0YXJ0JyxcbiAgICAgIHRoaXMuX2hhbmRsZU92ZXJsYXlUb3VjaFN0YXJ0LFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcblxuICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICd0b3VjaG1vdmUnLFxuICAgICAgdGhpcy5faGFuZGxlT3ZlcmxheVRvdWNoTW92ZSxcbiAgICAgIHBhc3NpdmVFdmVudExpc3RlbmVyT3B0aW9uc1xuICAgICk7XG5cbiAgICB0aGlzLl9vdmVybGF5UmVmLmhvc3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAndG91Y2hlbmQnLFxuICAgICAgdGhpcy5faGFuZGxlT3ZlcmxheVRvdWNoRW5kLFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdG91Y2ggZGV2aWNlIHBhbi9zd2lwZSBsaXN0ZW5lcnMgZnJvbSBvdmVybGF5IGhvc3QgZWxlbWVudFxuICAgKi9cbiAgcHJpdmF0ZSByZW1vdmVPdmVybGF5TGlzdGVuZXJzKCkge1xuICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICd0b3VjaHN0YXJ0JyxcbiAgICAgIHRoaXMuX2hhbmRsZU92ZXJsYXlUb3VjaFN0YXJ0LFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcblxuICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICd0b3VjaG1vdmUnLFxuICAgICAgdGhpcy5faGFuZGxlT3ZlcmxheVRvdWNoTW92ZSxcbiAgICAgIHBhc3NpdmVFdmVudExpc3RlbmVyT3B0aW9uc1xuICAgICk7XG5cbiAgICB0aGlzLl9vdmVybGF5UmVmLmhvc3RFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAndG91Y2hlbmQnLFxuICAgICAgdGhpcy5faGFuZGxlT3ZlcmxheVRvdWNoRW5kLFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFuZGFyZCBleHBvbmVudGlhbCBlYXNlIG91dCBmdW5jdGlvblxuICAgKlxuICAgKiBAcGFyYW0gY3VycmVudCBDdXJyZW50IHZhbHVlXG4gICAqIEBwYXJhbSBvZmZzZXQgT2Zmc2V0IHZhbHVlLCB0byB3aGljaCBjYWxjdWxhdGVkIHZhbHVlIHdpbGwgYmUgYWRkZWRcbiAgICogQHBhcmFtIHRhcmdldCBUaGUgdGFyZ2V0IHZhbHVlXG4gICAqIEBwYXJhbSBlbmQgVmFsdWUgdG8gd2hpY2ggY3VycmVudCB2YWx1ZSBpcyBjb21wYXJlZFxuICAgKi9cbiAgcHJpdmF0ZSBlYXNlT3V0RXhwbyhcbiAgICBjdXJyZW50OiBudW1iZXIsXG4gICAgb2Zmc2V0OiBudW1iZXIsXG4gICAgdGFyZ2V0OiBudW1iZXIsXG4gICAgZW5kOiBudW1iZXJcbiAgKTogbnVtYmVyIHtcbiAgICByZXR1cm4gY3VycmVudCA9PT0gZW5kXG4gICAgICA/IG9mZnNldCArIHRhcmdldFxuICAgICAgOiB0YXJnZXQgKiAoLU1hdGgucG93KDIsICgtMTAgKiBjdXJyZW50KSAvIGVuZCkgKyAxKSArIG9mZnNldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBzY3JvbGwgc3RyYXRlZ3kgZm9yIHRoZSBvdmVybGF5IGJhc2VkIG9uIHRoZSBjbGllbnQgb3V0cHV0IGRldmljZSBhbmQgbWVudSBzY3JvbGwgc3RyYXRlZ3kgaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSB7T3V0cHV0RGV2aWNlVHlwZXN9IGNsaWVudE91dHB1dERldmljZSAtIFRoZSB0eXBlIG9mIGNsaWVudCBvdXRwdXQgZGV2aWNlIChlLmcuLCAndG91Y2gnKS5cbiAgICogQHBhcmFtIHsncmVwb3NpdGlvbicgfCAnY2xvc2UnfSBtZW51U2Nyb2xsU3RyYXRlZ3lJbnB1dCAtIFRoZSBzY3JvbGwgc3RyYXRlZ3kgaW5wdXQgZm9yIHRoZSBtZW51LlxuICAgKiBAcmV0dXJucyB7U2Nyb2xsU3RyYXRlZ3l9IFRoZSBhcHByb3ByaWF0ZSBzY3JvbGwgc3RyYXRlZ3kgZm9yIHRoZSBvdmVybGF5LlxuICAgKi9cbiAgcHJpdmF0ZSBzZXRTY3JvbGxTdHJhdGVneVRvT3ZlcnlsYXkoXG4gICAgY2xpZW50T3V0cHV0RGV2aWNlOiBPdXRwdXREZXZpY2VUeXBlcyxcbiAgICBtZW51U2Nyb2xsU3RyYXRlZ3lJbnB1dDogJ3JlcG9zaXRpb24nIHwgJ2Nsb3NlJ1xuICApOiBTY3JvbGxTdHJhdGVneSB7XG4gICAgaWYgKGNsaWVudE91dHB1dERldmljZSA9PT0gJ3RvdWNoJykge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG1lbnVTY3JvbGxTdHJhdGVneUlucHV0ID09PSAnY2xvc2UnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vdmVybGF5LnNjcm9sbFN0cmF0ZWdpZXMuY2xvc2UoKTtcbiAgICAgIH0gZWxzZSBpZiAobWVudVNjcm9sbFN0cmF0ZWd5SW5wdXQgPT09ICdyZXBvc2l0aW9uJykge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3ZlcmxheS5zY3JvbGxTdHJhdGVnaWVzLnJlcG9zaXRpb24oKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
|