[6a3a178] | 1 | /**
|
---|
| 2 | * @license
|
---|
| 3 | * Copyright Google LLC All Rights Reserved.
|
---|
| 4 | *
|
---|
| 5 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 6 | * found in the LICENSE file at https://angular.io/license
|
---|
| 7 | */
|
---|
| 8 | import { Platform } from '@angular/cdk/platform';
|
---|
| 9 | import { BasePortalOutlet, CdkPortalOutlet, } from '@angular/cdk/portal';
|
---|
| 10 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, ViewChild, ViewEncapsulation, } from '@angular/core';
|
---|
| 11 | import { Subject } from 'rxjs';
|
---|
| 12 | import { take } from 'rxjs/operators';
|
---|
| 13 | import { matSnackBarAnimations } from './snack-bar-animations';
|
---|
| 14 | import { MatSnackBarConfig } from './snack-bar-config';
|
---|
| 15 | /**
|
---|
| 16 | * Internal component that wraps user-provided snack bar content.
|
---|
| 17 | * @docs-private
|
---|
| 18 | */
|
---|
| 19 | export class MatSnackBarContainer extends BasePortalOutlet {
|
---|
| 20 | constructor(_ngZone, _elementRef, _changeDetectorRef, _platform,
|
---|
| 21 | /** The snack bar configuration. */
|
---|
| 22 | snackBarConfig) {
|
---|
| 23 | super();
|
---|
| 24 | this._ngZone = _ngZone;
|
---|
| 25 | this._elementRef = _elementRef;
|
---|
| 26 | this._changeDetectorRef = _changeDetectorRef;
|
---|
| 27 | this._platform = _platform;
|
---|
| 28 | this.snackBarConfig = snackBarConfig;
|
---|
| 29 | /** The number of milliseconds to wait before announcing the snack bar's content. */
|
---|
| 30 | this._announceDelay = 150;
|
---|
| 31 | /** Whether the component has been destroyed. */
|
---|
| 32 | this._destroyed = false;
|
---|
| 33 | /** Subject for notifying that the snack bar has announced to screen readers. */
|
---|
| 34 | this._onAnnounce = new Subject();
|
---|
| 35 | /** Subject for notifying that the snack bar has exited from view. */
|
---|
| 36 | this._onExit = new Subject();
|
---|
| 37 | /** Subject for notifying that the snack bar has finished entering the view. */
|
---|
| 38 | this._onEnter = new Subject();
|
---|
| 39 | /** The state of the snack bar animations. */
|
---|
| 40 | this._animationState = 'void';
|
---|
| 41 | /**
|
---|
| 42 | * Attaches a DOM portal to the snack bar container.
|
---|
| 43 | * @deprecated To be turned into a method.
|
---|
| 44 | * @breaking-change 10.0.0
|
---|
| 45 | */
|
---|
| 46 | this.attachDomPortal = (portal) => {
|
---|
| 47 | this._assertNotAttached();
|
---|
| 48 | this._applySnackBarClasses();
|
---|
| 49 | return this._portalOutlet.attachDomPortal(portal);
|
---|
| 50 | };
|
---|
| 51 | // Use aria-live rather than a live role like 'alert' or 'status'
|
---|
| 52 | // because NVDA and JAWS have show inconsistent behavior with live roles.
|
---|
| 53 | if (snackBarConfig.politeness === 'assertive' && !snackBarConfig.announcementMessage) {
|
---|
| 54 | this._live = 'assertive';
|
---|
| 55 | }
|
---|
| 56 | else if (snackBarConfig.politeness === 'off') {
|
---|
| 57 | this._live = 'off';
|
---|
| 58 | }
|
---|
| 59 | else {
|
---|
| 60 | this._live = 'polite';
|
---|
| 61 | }
|
---|
| 62 | // Only set role for Firefox. Set role based on aria-live because setting role="alert" implies
|
---|
| 63 | // aria-live="assertive" which may cause issues if aria-live is set to "polite" above.
|
---|
| 64 | if (this._platform.FIREFOX) {
|
---|
| 65 | if (this._live === 'polite') {
|
---|
| 66 | this._role = 'status';
|
---|
| 67 | }
|
---|
| 68 | if (this._live === 'assertive') {
|
---|
| 69 | this._role = 'alert';
|
---|
| 70 | }
|
---|
| 71 | }
|
---|
| 72 | }
|
---|
| 73 | /** Attach a component portal as content to this snack bar container. */
|
---|
| 74 | attachComponentPortal(portal) {
|
---|
| 75 | this._assertNotAttached();
|
---|
| 76 | this._applySnackBarClasses();
|
---|
| 77 | return this._portalOutlet.attachComponentPortal(portal);
|
---|
| 78 | }
|
---|
| 79 | /** Attach a template portal as content to this snack bar container. */
|
---|
| 80 | attachTemplatePortal(portal) {
|
---|
| 81 | this._assertNotAttached();
|
---|
| 82 | this._applySnackBarClasses();
|
---|
| 83 | return this._portalOutlet.attachTemplatePortal(portal);
|
---|
| 84 | }
|
---|
| 85 | /** Handle end of animations, updating the state of the snackbar. */
|
---|
| 86 | onAnimationEnd(event) {
|
---|
| 87 | const { fromState, toState } = event;
|
---|
| 88 | if ((toState === 'void' && fromState !== 'void') || toState === 'hidden') {
|
---|
| 89 | this._completeExit();
|
---|
| 90 | }
|
---|
| 91 | if (toState === 'visible') {
|
---|
| 92 | // Note: we shouldn't use `this` inside the zone callback,
|
---|
| 93 | // because it can cause a memory leak.
|
---|
| 94 | const onEnter = this._onEnter;
|
---|
| 95 | this._ngZone.run(() => {
|
---|
| 96 | onEnter.next();
|
---|
| 97 | onEnter.complete();
|
---|
| 98 | });
|
---|
| 99 | }
|
---|
| 100 | }
|
---|
| 101 | /** Begin animation of snack bar entrance into view. */
|
---|
| 102 | enter() {
|
---|
| 103 | if (!this._destroyed) {
|
---|
| 104 | this._animationState = 'visible';
|
---|
| 105 | this._changeDetectorRef.detectChanges();
|
---|
| 106 | this._screenReaderAnnounce();
|
---|
| 107 | }
|
---|
| 108 | }
|
---|
| 109 | /** Begin animation of the snack bar exiting from view. */
|
---|
| 110 | exit() {
|
---|
| 111 | // Note: this one transitions to `hidden`, rather than `void`, in order to handle the case
|
---|
| 112 | // where multiple snack bars are opened in quick succession (e.g. two consecutive calls to
|
---|
| 113 | // `MatSnackBar.open`).
|
---|
| 114 | this._animationState = 'hidden';
|
---|
| 115 | // Mark this element with an 'exit' attribute to indicate that the snackbar has
|
---|
| 116 | // been dismissed and will soon be removed from the DOM. This is used by the snackbar
|
---|
| 117 | // test harness.
|
---|
| 118 | this._elementRef.nativeElement.setAttribute('mat-exit', '');
|
---|
| 119 | // If the snack bar hasn't been announced by the time it exits it wouldn't have been open
|
---|
| 120 | // long enough to visually read it either, so clear the timeout for announcing.
|
---|
| 121 | clearTimeout(this._announceTimeoutId);
|
---|
| 122 | return this._onExit;
|
---|
| 123 | }
|
---|
| 124 | /** Makes sure the exit callbacks have been invoked when the element is destroyed. */
|
---|
| 125 | ngOnDestroy() {
|
---|
| 126 | this._destroyed = true;
|
---|
| 127 | this._completeExit();
|
---|
| 128 | }
|
---|
| 129 | /**
|
---|
| 130 | * Waits for the zone to settle before removing the element. Helps prevent
|
---|
| 131 | * errors where we end up removing an element which is in the middle of an animation.
|
---|
| 132 | */
|
---|
| 133 | _completeExit() {
|
---|
| 134 | this._ngZone.onMicrotaskEmpty.pipe(take(1)).subscribe(() => {
|
---|
| 135 | this._onExit.next();
|
---|
| 136 | this._onExit.complete();
|
---|
| 137 | });
|
---|
| 138 | }
|
---|
| 139 | /** Applies the various positioning and user-configured CSS classes to the snack bar. */
|
---|
| 140 | _applySnackBarClasses() {
|
---|
| 141 | const element = this._elementRef.nativeElement;
|
---|
| 142 | const panelClasses = this.snackBarConfig.panelClass;
|
---|
| 143 | if (panelClasses) {
|
---|
| 144 | if (Array.isArray(panelClasses)) {
|
---|
| 145 | // Note that we can't use a spread here, because IE doesn't support multiple arguments.
|
---|
| 146 | panelClasses.forEach(cssClass => element.classList.add(cssClass));
|
---|
| 147 | }
|
---|
| 148 | else {
|
---|
| 149 | element.classList.add(panelClasses);
|
---|
| 150 | }
|
---|
| 151 | }
|
---|
| 152 | if (this.snackBarConfig.horizontalPosition === 'center') {
|
---|
| 153 | element.classList.add('mat-snack-bar-center');
|
---|
| 154 | }
|
---|
| 155 | if (this.snackBarConfig.verticalPosition === 'top') {
|
---|
| 156 | element.classList.add('mat-snack-bar-top');
|
---|
| 157 | }
|
---|
| 158 | }
|
---|
| 159 | /** Asserts that no content is already attached to the container. */
|
---|
| 160 | _assertNotAttached() {
|
---|
| 161 | if (this._portalOutlet.hasAttached() && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
---|
| 162 | throw Error('Attempting to attach snack bar content after content is already attached');
|
---|
| 163 | }
|
---|
| 164 | }
|
---|
| 165 | /**
|
---|
| 166 | * Starts a timeout to move the snack bar content to the live region so screen readers will
|
---|
| 167 | * announce it.
|
---|
| 168 | */
|
---|
| 169 | _screenReaderAnnounce() {
|
---|
| 170 | if (!this._announceTimeoutId) {
|
---|
| 171 | this._ngZone.runOutsideAngular(() => {
|
---|
| 172 | this._announceTimeoutId = setTimeout(() => {
|
---|
| 173 | const inertElement = this._elementRef.nativeElement.querySelector('[aria-hidden]');
|
---|
| 174 | const liveElement = this._elementRef.nativeElement.querySelector('[aria-live]');
|
---|
| 175 | if (inertElement && liveElement) {
|
---|
| 176 | // If an element in the snack bar content is focused before being moved
|
---|
| 177 | // track it and restore focus after moving to the live region.
|
---|
| 178 | let focusedElement = null;
|
---|
| 179 | if (this._platform.isBrowser &&
|
---|
| 180 | document.activeElement instanceof HTMLElement &&
|
---|
| 181 | inertElement.contains(document.activeElement)) {
|
---|
| 182 | focusedElement = document.activeElement;
|
---|
| 183 | }
|
---|
| 184 | inertElement.removeAttribute('aria-hidden');
|
---|
| 185 | liveElement.appendChild(inertElement);
|
---|
| 186 | focusedElement === null || focusedElement === void 0 ? void 0 : focusedElement.focus();
|
---|
| 187 | this._onAnnounce.next();
|
---|
| 188 | this._onAnnounce.complete();
|
---|
| 189 | }
|
---|
| 190 | }, this._announceDelay);
|
---|
| 191 | });
|
---|
| 192 | }
|
---|
| 193 | }
|
---|
| 194 | }
|
---|
| 195 | MatSnackBarContainer.decorators = [
|
---|
| 196 | { type: Component, args: [{
|
---|
| 197 | selector: 'snack-bar-container',
|
---|
| 198 | template: "<!-- Initially holds the snack bar content, will be empty after announcing to screen readers. -->\n<div aria-hidden=\"true\">\n <ng-template cdkPortalOutlet></ng-template>\n</div>\n\n<!-- Will receive the snack bar content from the non-live div, move will happen a short delay after opening -->\n<div [attr.aria-live]=\"_live\" [attr.role]=\"_role\"></div>\n",
|
---|
| 199 | // In Ivy embedded views will be change detected from their declaration place, rather than
|
---|
| 200 | // where they were stamped out. This means that we can't have the snack bar container be OnPush,
|
---|
| 201 | // because it might cause snack bars that were opened from a template not to be out of date.
|
---|
| 202 | // tslint:disable-next-line:validate-decorators
|
---|
| 203 | changeDetection: ChangeDetectionStrategy.Default,
|
---|
| 204 | encapsulation: ViewEncapsulation.None,
|
---|
| 205 | animations: [matSnackBarAnimations.snackBarState],
|
---|
| 206 | host: {
|
---|
| 207 | 'class': 'mat-snack-bar-container',
|
---|
| 208 | '[@state]': '_animationState',
|
---|
| 209 | '(@state.done)': 'onAnimationEnd($event)'
|
---|
| 210 | },
|
---|
| 211 | styles: [".mat-snack-bar-container{border-radius:4px;box-sizing:border-box;display:block;margin:24px;max-width:33vw;min-width:344px;padding:14px 16px;min-height:48px;transform-origin:center}.cdk-high-contrast-active .mat-snack-bar-container{border:solid 1px}.mat-snack-bar-handset{width:100%}.mat-snack-bar-handset .mat-snack-bar-container{margin:8px;max-width:100%;min-width:0;width:100%}\n"]
|
---|
| 212 | },] }
|
---|
| 213 | ];
|
---|
| 214 | MatSnackBarContainer.ctorParameters = () => [
|
---|
| 215 | { type: NgZone },
|
---|
| 216 | { type: ElementRef },
|
---|
| 217 | { type: ChangeDetectorRef },
|
---|
| 218 | { type: Platform },
|
---|
| 219 | { type: MatSnackBarConfig }
|
---|
| 220 | ];
|
---|
| 221 | MatSnackBarContainer.propDecorators = {
|
---|
| 222 | _portalOutlet: [{ type: ViewChild, args: [CdkPortalOutlet, { static: true },] }]
|
---|
| 223 | };
|
---|
[e29cc2e] | 224 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hY2stYmFyLWNvbnRhaW5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tYXRlcmlhbC9zbmFjay1iYXIvc25hY2stYmFyLWNvbnRhaW5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFJSCxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDL0MsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixlQUFlLEdBSWhCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUVULFVBQVUsRUFFVixNQUFNLEVBRU4sU0FBUyxFQUNULGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQWEsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ3pDLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwQyxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUM3RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQWlCckQ7OztHQUdHO0FBa0JILE1BQU0sT0FBTyxvQkFBcUIsU0FBUSxnQkFBZ0I7SUFtQ3hELFlBQ1UsT0FBZSxFQUNmLFdBQW9DLEVBQ3BDLGtCQUFxQyxFQUNyQyxTQUFtQjtJQUMzQixtQ0FBbUM7SUFDNUIsY0FBaUM7UUFFeEMsS0FBSyxFQUFFLENBQUM7UUFQQSxZQUFPLEdBQVAsT0FBTyxDQUFRO1FBQ2YsZ0JBQVcsR0FBWCxXQUFXLENBQXlCO1FBQ3BDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7UUFDckMsY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUVwQixtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUF2QzFDLG9GQUFvRjtRQUNuRSxtQkFBYyxHQUFXLEdBQUcsQ0FBQztRQUs5QyxnREFBZ0Q7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QUFFLHdCQUF3QjtpQkFDMUM7O2FBQ0Y7OztZQTdDQyxNQUFNO1lBRk4sVUFBVTtZQUhWLGlCQUFpQjtZQVZYLFFBQVE7WUF1QlIsaUJBQWlCOzs7NEJBa0R0QixTQUFTLFNBQUMsZUFBZSxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0FuaW1hdGlvbkV2ZW50fSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcbmltcG9ydCB7QXJpYUxpdmVQb2xpdGVuZXNzfSBmcm9tICdAYW5ndWxhci9jZGsvYTExeSc7XG5pbXBvcnQge1BsYXRmb3JtfSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xuaW1wb3J0IHtcbiAgQmFzZVBvcnRhbE91dGxldCxcbiAgQ2RrUG9ydGFsT3V0bGV0LFxuICBDb21wb25lbnRQb3J0YWwsXG4gIFRlbXBsYXRlUG9ydGFsLFxuICBEb21Qb3J0YWwsXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9wb3J0YWwnO1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbXBvbmVudFJlZixcbiAgRWxlbWVudFJlZixcbiAgRW1iZWRkZWRWaWV3UmVmLFxuICBOZ1pvbmUsXG4gIE9uRGVzdHJveSxcbiAgVmlld0NoaWxkLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHt0YWtlfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge21hdFNuYWNrQmFyQW5pbWF0aW9uc30gZnJvbSAnLi9zbmFjay1iYXItYW5pbWF0aW9ucyc7XG5pbXBvcnQge01hdFNuYWNrQmFyQ29uZmlnfSBmcm9tICcuL3NuYWNrLWJhci1jb25maWcnO1xuXG4vKipcbiAqIEludGVybmFsIGludGVyZmFjZSBmb3IgYSBzbmFjayBiYXIgY29udGFpbmVyLlxuICogQGRvY3MtcHJpdmF0ZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIF9TbmFja0JhckNvbnRhaW5lciB7XG4gIHNuYWNrQmFyQ29uZmlnOiBNYXRTbmFja0JhckNvbmZpZztcbiAgcmVhZG9ubHkgX29uQW5ub3VuY2U6IFN1YmplY3Q8YW55PjtcbiAgcmVhZG9ubHkgX29uRXhpdDogU3ViamVjdDxhbnk+O1xuICByZWFkb25seSBfb25FbnRlcjogU3ViamVjdDxhbnk+O1xuICBlbnRlcjogKCkgPT4gdm9pZDtcbiAgZXhpdDogKCkgPT4gT2JzZXJ2YWJsZTx2b2lkPjtcbiAgYXR0YWNoVGVtcGxhdGVQb3J0YWw6IDxDPihwb3J0YWw6IFRlbXBsYXRlUG9ydGFsPEM+KSA9PiBFbWJlZGRlZFZpZXdSZWY8Qz47XG4gIGF0dGFjaENvbXBvbmVudFBvcnRhbDogPFQ+KHBvcnRhbDogQ29tcG9uZW50UG9ydGFsPFQ+KSA9PiBDb21wb25lbnRSZWY8VD47XG59XG5cbi8qKlxuICogSW50ZXJuYWwgY29tcG9uZW50IHRoYXQgd3JhcHMgdXNlci1wcm92aWRlZCBzbmFjayBiYXIgY29udGVudC5cbiAqIEBkb2NzLXByaXZhdGVcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc25hY2stYmFyLWNvbnRhaW5lcicsXG4gIHRlbXBsYXRlVXJsOiAnc25hY2stYmFyLWNvbnRhaW5lci5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJ3NuYWNrLWJhci1jb250YWluZXIuY3NzJ10sXG4gIC8vIEluIEl2eSBlbWJlZGRlZCB2aWV3cyB3aWxsIGJlIGNoYW5nZSBkZXRlY3RlZCBmcm9tIHRoZWlyIGRlY2xhcmF0aW9uIHBsYWNlLCByYXRoZXIgdGhhblxuICAvLyB3aGVyZSB0aGV5IHdlcmUgc3RhbXBlZCBvdXQuIFRoaXMgbWVhbnMgdGhhdCB3ZSBjYW4ndCBoYXZlIHRoZSBzbmFjayBiYXIgY29udGFpbmVyIGJlIE9uUHVzaCxcbiAgLy8gYmVjYXVzZSBpdCBtaWdodCBjYXVzZSBzbmFjayBiYXJzIHRoYXQgd2VyZSBvcGVuZWQgZnJvbSBhIHRlbXBsYXRlIG5vdCB0byBiZSBvdXQgb2YgZGF0ZS5cbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnZhbGlkYXRlLWRlY29yYXRvcnNcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5EZWZhdWx0LFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBhbmltYXRpb25zOiBbbWF0U25hY2tCYXJBbmltYXRpb25zLnNuYWNrQmFyU3RhdGVdLFxuICBob3N0OiB7XG4gICAgJ2NsYXNzJzogJ21hdC1zbmFjay1iYXItY29udGFpbmVyJyxcbiAgICAnW0BzdGF0ZV0nOiAnX2FuaW1hdGlvblN0YXRlJyxcbiAgICAnKEBzdGF0ZS5kb25lKSc6ICdvbkFuaW1hdGlvbkVuZCgkZXZlbnQpJ1xuICB9LFxufSlcbmV4cG9ydCBjbGFzcyBNYXRTbmFja0JhckNvbnRhaW5lciBleHRlbmRzIEJhc2VQb3J0YWxPdXRsZXRcbiAgICBpbXBsZW1lbnRzIE9uRGVzdHJveSwgX1NuYWNrQmFyQ29udGFpbmVyIHtcbiAgLyoqIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGFubm91bmNpbmcgdGhlIHNuYWNrIGJhcidzIGNvbnRlbnQuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Fubm91bmNlRGVsYXk6IG51bWJlciA9IDE1MDtcblxuICAvKiogVGhlIHRpbWVvdXQgZm9yIGFubm91bmNpbmcgdGhlIHNuYWNrIGJhcidzIGNvbnRlbnQuICovXG4gIHByaXZhdGUgX2Fubm91bmNlVGltZW91dElkOiBudW1iZXI7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGNvbXBvbmVudCBoYXMgYmVlbiBkZXN0cm95ZWQuICovXG4gIHByaXZhdGUgX2Rlc3Ryb3llZCA9IGZhbHNlO1xuXG4gIC8qKiBUaGUgcG9ydGFsIG91dGxldCBpbnNpZGUgb2YgdGhpcyBjb250YWluZXIgaW50byB3aGljaCB0aGUgc25hY2sgYmFyIGNvbnRlbnQgd2lsbCBiZSBsb2FkZWQuICovXG4gIEBWaWV3Q2hpbGQoQ2RrUG9ydGFsT3V0bGV0LCB7c3RhdGljOiB0cnVlfSkgX3BvcnRhbE91dGxldDogQ2RrUG9ydGFsT3V0bGV0O1xuXG4gIC8qKiBTdWJqZWN0IGZvciBub3RpZnlpbmcgdGhhdCB0aGUgc25hY2sgYmFyIGhhcyBhbm5vdW5jZWQgdG8gc2NyZWVuIHJlYWRlcnMuICovXG4gIHJlYWRvbmx5IF9vbkFubm91bmNlOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3QoKTtcblxuICAvKiogU3ViamVjdCBmb3Igbm90aWZ5aW5nIHRoYXQgdGhlIHNuYWNrIGJhciBoYXMgZXhpdGVkIGZyb20gdmlldy4gKi9cbiAgcmVhZG9ubHkgX29uRXhpdDogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgLyoqIFN1YmplY3QgZm9yIG5vdGlmeWluZyB0aGF0IHRoZSBzbmFjayBiYXIgaGFzIGZpbmlzaGVkIGVudGVyaW5nIHRoZSB2aWV3LiAqL1xuICByZWFkb25seSBfb25FbnRlcjogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgLyoqIFRoZSBzdGF0ZSBvZiB0aGUgc25hY2sgYmFyIGFuaW1hdGlvbnMuICovXG4gIF9hbmltYXRpb25TdGF0ZSA9ICd2b2lkJztcblxuICAvKiogYXJpYS1saXZlIHZhbHVlIGZvciB0aGUgbGl2ZSByZWdpb24uICovXG4gIF9saXZlOiBBcmlhTGl2ZVBvbGl0ZW5lc3M7XG5cbiAgLyoqXG4gICAqIFJvbGUgb2YgdGhlIGxpdmUgcmVnaW9uLiBUaGlzIGlzIG9ubHkgZm9yIEZpcmVmb3ggYXMgdGhlcmUgaXMgYSBrbm93biBpc3N1ZSB3aGVyZSBGaXJlZm94ICtcbiAgICogSkFXUyBkb2VzIG5vdCByZWFkIG91dCBhcmlhLWxpdmUgbWVzc2FnZS5cbiAgICovXG4gIF9yb2xlPzogJ3N0YXR1cycgfCAnYWxlcnQnO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX25nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICAgIHByaXZhdGUgX2NoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIF9wbGF0Zm9ybTogUGxhdGZvcm0sXG4gICAgLyoqIFRoZSBzbmFjayBiYXIgY29uZmlndXJhdGlvbi4gKi9cbiAgICBwdWJsaWMgc25hY2tCYXJDb25maWc6IE1hdFNuYWNrQmFyQ29uZmlnKSB7XG5cbiAgICBzdXBlcigpO1xuXG4gICAgLy8gVXNlIGFyaWEtbGl2ZSByYXRoZXIgdGhhbiBhIGxpdmUgcm9sZSBsaWtlICdhbGVydCcgb3IgJ3N0YXR1cydcbiAgICAvLyBiZWNhdXNlIE5WREEgYW5kIEpBV1MgaGF2ZSBzaG93IGluY29uc2lzdGVudCBiZWhhdmlvciB3aXRoIGxpdmUgcm9sZXMuXG4gICAgaWYgKHNuYWNrQmFyQ29uZmlnLnBvbGl0ZW5lc3MgPT09ICdhc3NlcnRpdmUnICYmICFzbmFja0JhckNvbmZpZy5hbm5vdW5jZW1lbnRNZXNzYWdlKSB7XG4gICAgICB0aGlzLl9saXZlID0gJ2Fzc2VydGl2ZSc7XG4gICAgfSBlbHNlIGlmIChzbmFja0JhckNvbmZpZy5wb2xpdGVuZXNzID09PSAnb2ZmJykge1xuICAgICAgdGhpcy5fbGl2ZSA9ICdvZmYnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9saXZlID0gJ3BvbGl0ZSc7XG4gICAgfVxuXG4gICAgLy8gT25seSBzZXQgcm9sZSBmb3IgRmlyZWZveC4gU2V0IHJvbGUgYmFzZWQgb24gYXJpYS1saXZlIGJlY2F1c2Ugc2V0dGluZyByb2xlPVwiYWxlcnRcIiBpbXBsaWVzXG4gICAgLy8gYXJpYS1saXZlPVwiYXNzZXJ0aXZlXCIgd2hpY2ggbWF5IGNhdXNlIGlzc3VlcyBpZiBhcmlhLWxpdmUgaXMgc2V0IHRvIFwicG9saXRlXCIgYWJvdmUuXG4gICAgaWYgKHRoaXMuX3BsYXRmb3JtLkZJUkVGT1gpIHtcbiAgICAgIGlmICh0aGlzLl9saXZlID09PSAncG9saXRlJykge1xuICAgICAgICB0aGlzLl9yb2xlID0gJ3N0YXR1cyc7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5fbGl2ZSA9PT0gJ2Fzc2VydGl2ZScpIHtcbiAgICAgICAgdGhpcy5fcm9sZSA9ICdhbGVydCc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIEF0dGFjaCBhIGNvbXBvbmVudCBwb3J0YWwgYXMgY29udGVudCB0byB0aGlzIHNuYWNrIGJhciBjb250YWluZXIuICovXG4gIGF0dGFjaENvbXBvbmVudFBvcnRhbDxUPihwb3J0YWw6IENvbXBvbmVudFBvcnRhbDxUPik6IENvbXBvbmVudFJlZjxUPiB7XG4gICAgdGhpcy5fYXNzZXJ0Tm90QXR0YWNoZWQoKTtcbiAgICB0aGlzLl9hcHBseVNuYWNrQmFyQ2xhc3NlcygpO1xuICAgIHJldHVybiB0aGlzLl9wb3J0YWxPdXRsZXQuYXR0YWNoQ29tcG9uZW50UG9ydGFsKHBvcnRhbCk7XG4gIH1cblxuICAvKiogQXR0YWNoIGEgdGVtcGxhdGUgcG9ydGFsIGFzIGNvbnRlbnQgdG8gdGhpcyBzbmFjayBiYXIgY29udGFpbmVyLiAqL1xuICBhdHRhY2hUZW1wbGF0ZVBvcnRhbDxDPihwb3J0YWw6IFRlbXBsYXRlUG9ydGFsPEM+KTogRW1iZWRkZWRWaWV3UmVmPEM+IHtcbiAgICB0aGlzLl9hc3NlcnROb3RBdHRhY2hlZCgpO1xuICAgIHRoaXMuX2FwcGx5U25hY2tCYXJDbGFzc2VzKCk7XG4gICAgcmV0dXJuIHRoaXMuX3BvcnRhbE91dGxldC5hdHRhY2hUZW1wbGF0ZVBvcnRhbChwb3J0YWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGFjaGVzIGEgRE9NIHBvcnRhbCB0byB0aGUgc25hY2sgYmFyIGNvbnRhaW5lci5cbiAgICogQGRlcHJlY2F0ZWQgVG8gYmUgdHVybmVkIGludG8gYSBtZXRob2QuXG4gICAqIEBicmVha2luZy1jaGFuZ2UgMTAuMC4wXG4gICAqL1xuICBvdmVycmlkZSBhdHRhY2hEb21Qb3J0YWwgPSAocG9ydGFsOiBEb21Qb3J0YWwpID0+IHtcbiAgICB0aGlzLl9hc3NlcnROb3RBdHRhY2hlZCgpO1xuICAgIHRoaXMuX2FwcGx5U25hY2tCYXJDbGFzc2VzKCk7XG4gICAgcmV0dXJuIHRoaXMuX3BvcnRhbE91dGxldC5hdHRhY2hEb21Qb3J0YWwocG9ydGFsKTtcbiAgfVxuXG4gIC8qKiBIYW5kbGUgZW5kIG9mIGFuaW1hdGlvbnMsIHVwZGF0aW5nIHRoZSBzdGF0ZSBvZiB0aGUgc25hY2tiYXIuICovXG4gIG9uQW5pbWF0aW9uRW5kKGV2ZW50OiBBbmltYXRpb25FdmVudCkge1xuICAgIGNvbnN0IHtmcm9tU3RhdGUsIHRvU3RhdGV9ID0gZXZlbnQ7XG5cbiAgICBpZiAoKHRvU3RhdGUgPT09ICd2b2lkJyAmJiBmcm9tU3RhdGUgIT09ICd2b2lkJykgfHwgdG9TdGF0ZSA9PT0gJ2hpZGRlbicpIHtcbiAgICAgIHRoaXMuX2NvbXBsZXRlRXhpdCgpO1xuICAgIH1cblxuICAgIGlmICh0b1N0YXRlID09PSAndmlzaWJsZScpIHtcbiAgICAgIC8vIE5vdGU6IHdlIHNob3VsZG4ndCB1c2UgYHRoaXNgIGluc2lkZSB0aGUgem9uZSBjYWxsYmFjayxcbiAgICAgIC8vIGJlY2F1c2UgaXQgY2FuIGNhdXNlIGEgbWVtb3J5IGxlYWsuXG4gICAgICBjb25zdCBvbkVudGVyID0gdGhpcy5fb25FbnRlcjtcblxuICAgICAgdGhpcy5fbmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgIG9uRW50ZXIubmV4dCgpO1xuICAgICAgICBvbkVudGVyLmNvbXBsZXRlKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogQmVnaW4gYW5pbWF0aW9uIG9mIHNuYWNrIGJhciBlbnRyYW5jZSBpbnRvIHZpZXcuICovXG4gIGVudGVyKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5fZGVzdHJveWVkKSB7XG4gICAgICB0aGlzLl9hbmltYXRpb25TdGF0ZSA9ICd2aXNpYmxlJztcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHRoaXMuX3NjcmVlblJlYWRlckFubm91bmNlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJlZ2luIGFuaW1hdGlvbiBvZiB0aGUgc25hY2sgYmFyIGV4aXRpbmcgZnJvbSB2aWV3LiAqL1xuICBleGl0KCk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIC8vIE5vdGU6IHRoaXMgb25lIHRyYW5zaXRpb25zIHRvIGBoaWRkZW5gLCByYXRoZXIgdGhhbiBgdm9pZGAsIGluIG9yZGVyIHRvIGhhbmRsZSB0aGUgY2FzZVxuICAgIC8vIHdoZXJlIG11bHRpcGxlIHNuYWNrIGJhcnMgYXJlIG9wZW5lZCBpbiBxdWljayBzdWNjZXNzaW9uIChlLmcuIHR3byBjb25zZWN1dGl2ZSBjYWxscyB0b1xuICAgIC8vIGBNYXRTbmFja0Jhci5vcGVuYCkuXG4gICAgdGhpcy5fYW5pbWF0aW9uU3RhdGUgPSAnaGlkZGVuJztcblxuICAgIC8vIE1hcmsgdGhpcyBlbGVtZW50IHdpdGggYW4gJ2V4aXQnIGF0dHJpYnV0ZSB0byBpbmRpY2F0ZSB0aGF0IHRoZSBzbmFja2JhciBoYXNcbiAgICAvLyBiZWVuIGRpc21pc3NlZCBhbmQgd2lsbCBzb29uIGJlIHJlbW92ZWQgZnJvbSB0aGUgRE9NLiBUaGlzIGlzIHVzZWQgYnkgdGhlIHNuYWNrYmFyXG4gICAgLy8gdGVzdCBoYXJuZXNzLlxuICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21hdC1leGl0JywgJycpO1xuXG4gICAgLy8gSWYgdGhlIHNuYWNrIGJhciBoYXNuJ3QgYmVlbiBhbm5vdW5jZWQgYnkgdGhlIHRpbWUgaXQgZXhpdHMgaXQgd291bGRuJ3QgaGF2ZSBiZWVuIG9wZW5cbiAgICAvLyBsb25nIGVub3VnaCB0byB2aXN1YWxseSByZWFkIGl0IGVpdGhlciwgc28gY2xlYXIgdGhlIHRpbWVvdXQgZm9yIGFubm91bmNpbmcuXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuX2Fubm91bmNlVGltZW91dElkKTtcblxuICAgIHJldHVybiB0aGlzLl9vbkV4aXQ7XG4gIH1cblxuICAvKiogTWFrZXMgc3VyZSB0aGUgZXhpdCBjYWxsYmFja3MgaGF2ZSBiZWVuIGludm9rZWQgd2hlbiB0aGUgZWxlbWVudCBpcyBkZXN0cm95ZWQuICovXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuX2Rlc3Ryb3llZCA9IHRydWU7XG4gICAgdGhpcy5fY29tcGxldGVFeGl0KCk7XG4gIH1cblxuICAvKipcbiAgICogV2FpdHMgZm9yIHRoZSB6b25lIHRvIHNldHRsZSBiZWZvcmUgcmVtb3ZpbmcgdGhlIGVsZW1lbnQuIEhlbHBzIHByZXZlbnRcbiAgICogZXJyb3JzIHdoZXJlIHdlIGVuZCB1cCByZW1vdmluZyBhbiBlbGVtZW50IHdoaWNoIGlzIGluIHRoZSBtaWRkbGUgb2YgYW4gYW5pbWF0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBfY29tcGxldGVFeGl0KCkge1xuICAgIHRoaXMuX25nWm9uZS5vbk1pY3JvdGFza0VtcHR5LnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMuX29uRXhpdC5uZXh0KCk7XG4gICAgICB0aGlzLl9vbkV4aXQuY29tcGxldGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBBcHBsaWVzIHRoZSB2YXJpb3VzIHBvc2l0aW9uaW5nIGFuZCB1c2VyLWNvbmZpZ3VyZWQgQ1NTIGNsYXNzZXMgdG8gdGhlIHNuYWNrIGJhci4gKi9cbiAgcHJpdmF0ZSBfYXBwbHlTbmFja0JhckNsYXNzZXMoKSB7XG4gICAgY29uc3QgZWxlbWVudDogSFRNTEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgcGFuZWxDbGFzc2VzID0gdGhpcy5zbmFja0JhckNvbmZpZy5wYW5lbENsYXNzO1xuXG4gICAgaWYgKHBhbmVsQ2xhc3Nlcykge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFuZWxDbGFzc2VzKSkge1xuICAgICAgICAvLyBOb3RlIHRoYXQgd2UgY2FuJ3QgdXNlIGEgc3ByZWFkIGhlcmUsIGJlY2F1c2UgSUUgZG9lc24ndCBzdXBwb3J0IG11bHRpcGxlIGFyZ3VtZW50cy5cbiAgICAgICAgcGFuZWxDbGFzc2VzLmZvckVhY2goY3NzQ2xhc3MgPT4gZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNzc0NsYXNzKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQocGFuZWxDbGFzc2VzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5zbmFja0JhckNvbmZpZy5ob3Jpem9udGFsUG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ21hdC1zbmFjay1iYXItY2VudGVyJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc25hY2tCYXJDb25maWcudmVydGljYWxQb3NpdGlvbiA9PT0gJ3RvcCcpIHtcbiAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnbWF0LXNuYWNrLWJhci10b3AnKTtcbiAgICB9XG4gIH1cblxuICAvKiogQXNzZXJ0cyB0aGF0IG5vIGNvbnRlbnQgaXMgYWxyZWFkeSBhdHRhY2hlZCB0byB0aGUgY29udGFpbmVyLiAqL1xuICBwcml2YXRlIF9hc3NlcnROb3RBdHRhY2hlZCgpIHtcbiAgICBpZiAodGhpcy5fcG9ydGFsT3V0bGV0Lmhhc0F0dGFjaGVkKCkgJiYgKHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8IG5nRGV2TW9kZSkpIHtcbiAgICAgIHRocm93IEVycm9yKCdBdHRlbXB0aW5nIHRvIGF0dGFjaCBzbmFjayBiYXIgY29udGVudCBhZnRlciBjb250ZW50IGlzIGFscmVhZHkgYXR0YWNoZWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIGEgdGltZW91dCB0byBtb3ZlIHRoZSBzbmFjayBiYXIgY29udGVudCB0byB0aGUgbGl2ZSByZWdpb24gc28gc2NyZWVuIHJlYWRlcnMgd2lsbFxuICAgKiBhbm5vdW5jZSBpdC5cbiAgICovXG4gIHByaXZhdGUgX3NjcmVlblJlYWRlckFubm91bmNlKCkge1xuICAgIGlmICghdGhpcy5fYW5ub3VuY2VUaW1lb3V0SWQpIHtcbiAgICAgIHRoaXMuX25nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgIHRoaXMuX2Fubm91bmNlVGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgY29uc3QgaW5lcnRFbGVtZW50ID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ1thcmlhLWhpZGRlbl0nKTtcbiAgICAgICAgICBjb25zdCBsaXZlRWxlbWVudCA9IHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdbYXJpYS1saXZlXScpO1xuXG4gICAgICAgICAgaWYgKGluZXJ0RWxlbWVudCAmJiBsaXZlRWxlbWVudCkge1xuICAgICAgICAgICAgLy8gSWYgYW4gZWxlbWVudCBpbiB0aGUgc25hY2sgYmFyIGNvbnRlbnQgaXMgZm9jdXNlZCBiZWZvcmUgYmVpbmcgbW92ZWRcbiAgICAgICAgICAgIC8vIHRyYWNrIGl0IGFuZCByZXN0b3JlIGZvY3VzIGFmdGVyIG1vdmluZyB0byB0aGUgbGl2ZSByZWdpb24uXG4gICAgICAgICAgICBsZXQgZm9jdXNlZEVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgICBpZiAodGhpcy5fcGxhdGZvcm0uaXNCcm93c2VyICYmXG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ICYmXG4gICAgICAgICAgICAgICAgaW5lcnRFbGVtZW50LmNvbnRhaW5zKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgIGZvY3VzZWRFbGVtZW50ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaW5lcnRFbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKTtcbiAgICAgICAgICAgIGxpdmVFbGVtZW50LmFwcGVuZENoaWxkKGluZXJ0RWxlbWVudCk7XG4gICAgICAgICAgICBmb2N1c2VkRWxlbWVudD8uZm9jdXMoKTtcblxuICAgICAgICAgICAgdGhpcy5fb25Bbm5vdW5jZS5uZXh0KCk7XG4gICAgICAgICAgICB0aGlzLl9vbkFubm91bmNlLmNvbXBsZXRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCB0aGlzLl9hbm5vdW5jZURlbGF5KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuIl19 |
---|