[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 { ArrayDataSource, isDataSource, _RecycleViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY, } from '@angular/cdk/collections';
|
---|
| 9 | import { Directive, Inject, Input, IterableDiffers, NgZone, SkipSelf, TemplateRef, ViewContainerRef, } from '@angular/core';
|
---|
| 10 | import { coerceNumberProperty } from '@angular/cdk/coercion';
|
---|
| 11 | import { Subject, of as observableOf, isObservable } from 'rxjs';
|
---|
| 12 | import { pairwise, shareReplay, startWith, switchMap, takeUntil } from 'rxjs/operators';
|
---|
| 13 | import { CdkVirtualScrollViewport } from './virtual-scroll-viewport';
|
---|
| 14 | /** Helper to extract the offset of a DOM Node in a certain direction. */
|
---|
| 15 | function getOffset(orientation, direction, node) {
|
---|
| 16 | const el = node;
|
---|
| 17 | if (!el.getBoundingClientRect) {
|
---|
| 18 | return 0;
|
---|
| 19 | }
|
---|
| 20 | const rect = el.getBoundingClientRect();
|
---|
| 21 | if (orientation === 'horizontal') {
|
---|
| 22 | return direction === 'start' ? rect.left : rect.right;
|
---|
| 23 | }
|
---|
| 24 | return direction === 'start' ? rect.top : rect.bottom;
|
---|
| 25 | }
|
---|
| 26 | /**
|
---|
| 27 | * A directive similar to `ngForOf` to be used for rendering data inside a virtual scrolling
|
---|
| 28 | * container.
|
---|
| 29 | */
|
---|
| 30 | export class CdkVirtualForOf {
|
---|
| 31 | constructor(
|
---|
| 32 | /** The view container to add items to. */
|
---|
| 33 | _viewContainerRef,
|
---|
| 34 | /** The template to use when stamping out new items. */
|
---|
| 35 | _template,
|
---|
| 36 | /** The set of available differs. */
|
---|
| 37 | _differs,
|
---|
| 38 | /** The strategy used to render items in the virtual scroll viewport. */
|
---|
| 39 | _viewRepeater,
|
---|
| 40 | /** The virtual scrolling viewport that these items are being rendered in. */
|
---|
| 41 | _viewport, ngZone) {
|
---|
| 42 | this._viewContainerRef = _viewContainerRef;
|
---|
| 43 | this._template = _template;
|
---|
| 44 | this._differs = _differs;
|
---|
| 45 | this._viewRepeater = _viewRepeater;
|
---|
| 46 | this._viewport = _viewport;
|
---|
| 47 | /** Emits when the rendered view of the data changes. */
|
---|
| 48 | this.viewChange = new Subject();
|
---|
| 49 | /** Subject that emits when a new DataSource instance is given. */
|
---|
| 50 | this._dataSourceChanges = new Subject();
|
---|
| 51 | /** Emits whenever the data in the current DataSource changes. */
|
---|
| 52 | this.dataStream = this._dataSourceChanges
|
---|
| 53 | .pipe(
|
---|
| 54 | // Start off with null `DataSource`.
|
---|
| 55 | startWith(null),
|
---|
| 56 | // Bundle up the previous and current data sources so we can work with both.
|
---|
| 57 | pairwise(),
|
---|
| 58 | // Use `_changeDataSource` to disconnect from the previous data source and connect to the
|
---|
| 59 | // new one, passing back a stream of data changes which we run through `switchMap` to give
|
---|
| 60 | // us a data stream that emits the latest data from whatever the current `DataSource` is.
|
---|
| 61 | switchMap(([prev, cur]) => this._changeDataSource(prev, cur)),
|
---|
| 62 | // Replay the last emitted data when someone subscribes.
|
---|
| 63 | shareReplay(1));
|
---|
| 64 | /** The differ used to calculate changes to the data. */
|
---|
| 65 | this._differ = null;
|
---|
| 66 | /** Whether the rendered data should be updated during the next ngDoCheck cycle. */
|
---|
| 67 | this._needsUpdate = false;
|
---|
| 68 | this._destroyed = new Subject();
|
---|
| 69 | this.dataStream.subscribe(data => {
|
---|
| 70 | this._data = data;
|
---|
| 71 | this._onRenderedDataChange();
|
---|
| 72 | });
|
---|
| 73 | this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe(range => {
|
---|
| 74 | this._renderedRange = range;
|
---|
| 75 | ngZone.run(() => this.viewChange.next(this._renderedRange));
|
---|
| 76 | this._onRenderedDataChange();
|
---|
| 77 | });
|
---|
| 78 | this._viewport.attach(this);
|
---|
| 79 | }
|
---|
| 80 | /** The DataSource to display. */
|
---|
| 81 | get cdkVirtualForOf() {
|
---|
| 82 | return this._cdkVirtualForOf;
|
---|
| 83 | }
|
---|
| 84 | set cdkVirtualForOf(value) {
|
---|
| 85 | this._cdkVirtualForOf = value;
|
---|
| 86 | if (isDataSource(value)) {
|
---|
| 87 | this._dataSourceChanges.next(value);
|
---|
| 88 | }
|
---|
| 89 | else {
|
---|
| 90 | // If value is an an NgIterable, convert it to an array.
|
---|
| 91 | this._dataSourceChanges.next(new ArrayDataSource(isObservable(value) ? value : Array.from(value || [])));
|
---|
| 92 | }
|
---|
| 93 | }
|
---|
| 94 | /**
|
---|
| 95 | * The `TrackByFunction` to use for tracking changes. The `TrackByFunction` takes the index and
|
---|
| 96 | * the item and produces a value to be used as the item's identity when tracking changes.
|
---|
| 97 | */
|
---|
| 98 | get cdkVirtualForTrackBy() {
|
---|
| 99 | return this._cdkVirtualForTrackBy;
|
---|
| 100 | }
|
---|
| 101 | set cdkVirtualForTrackBy(fn) {
|
---|
| 102 | this._needsUpdate = true;
|
---|
| 103 | this._cdkVirtualForTrackBy = fn ?
|
---|
| 104 | (index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item) :
|
---|
| 105 | undefined;
|
---|
| 106 | }
|
---|
| 107 | /** The template used to stamp out new elements. */
|
---|
| 108 | set cdkVirtualForTemplate(value) {
|
---|
| 109 | if (value) {
|
---|
| 110 | this._needsUpdate = true;
|
---|
| 111 | this._template = value;
|
---|
| 112 | }
|
---|
| 113 | }
|
---|
| 114 | /**
|
---|
| 115 | * The size of the cache used to store templates that are not being used for re-use later.
|
---|
| 116 | * Setting the cache size to `0` will disable caching. Defaults to 20 templates.
|
---|
| 117 | */
|
---|
| 118 | get cdkVirtualForTemplateCacheSize() {
|
---|
| 119 | return this._viewRepeater.viewCacheSize;
|
---|
| 120 | }
|
---|
| 121 | set cdkVirtualForTemplateCacheSize(size) {
|
---|
| 122 | this._viewRepeater.viewCacheSize = coerceNumberProperty(size);
|
---|
| 123 | }
|
---|
| 124 | /**
|
---|
| 125 | * Measures the combined size (width for horizontal orientation, height for vertical) of all items
|
---|
| 126 | * in the specified range. Throws an error if the range includes items that are not currently
|
---|
| 127 | * rendered.
|
---|
| 128 | */
|
---|
| 129 | measureRangeSize(range, orientation) {
|
---|
| 130 | if (range.start >= range.end) {
|
---|
| 131 | return 0;
|
---|
| 132 | }
|
---|
| 133 | if ((range.start < this._renderedRange.start || range.end > this._renderedRange.end) &&
|
---|
| 134 | (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
---|
| 135 | throw Error(`Error: attempted to measure an item that isn't rendered.`);
|
---|
| 136 | }
|
---|
| 137 | // The index into the list of rendered views for the first item in the range.
|
---|
| 138 | const renderedStartIndex = range.start - this._renderedRange.start;
|
---|
| 139 | // The length of the range we're measuring.
|
---|
| 140 | const rangeLen = range.end - range.start;
|
---|
| 141 | // Loop over all the views, find the first and land node and compute the size by subtracting
|
---|
| 142 | // the top of the first node from the bottom of the last one.
|
---|
| 143 | let firstNode;
|
---|
| 144 | let lastNode;
|
---|
| 145 | // Find the first node by starting from the beginning and going forwards.
|
---|
| 146 | for (let i = 0; i < rangeLen; i++) {
|
---|
| 147 | const view = this._viewContainerRef.get(i + renderedStartIndex);
|
---|
| 148 | if (view && view.rootNodes.length) {
|
---|
| 149 | firstNode = lastNode = view.rootNodes[0];
|
---|
| 150 | break;
|
---|
| 151 | }
|
---|
| 152 | }
|
---|
| 153 | // Find the last node by starting from the end and going backwards.
|
---|
| 154 | for (let i = rangeLen - 1; i > -1; i--) {
|
---|
| 155 | const view = this._viewContainerRef.get(i + renderedStartIndex);
|
---|
| 156 | if (view && view.rootNodes.length) {
|
---|
| 157 | lastNode = view.rootNodes[view.rootNodes.length - 1];
|
---|
| 158 | break;
|
---|
| 159 | }
|
---|
| 160 | }
|
---|
| 161 | return firstNode && lastNode ?
|
---|
| 162 | getOffset(orientation, 'end', lastNode) - getOffset(orientation, 'start', firstNode) : 0;
|
---|
| 163 | }
|
---|
| 164 | ngDoCheck() {
|
---|
| 165 | if (this._differ && this._needsUpdate) {
|
---|
| 166 | // TODO(mmalerba): We should differentiate needs update due to scrolling and a new portion of
|
---|
| 167 | // this list being rendered (can use simpler algorithm) vs needs update due to data actually
|
---|
| 168 | // changing (need to do this diff).
|
---|
| 169 | const changes = this._differ.diff(this._renderedItems);
|
---|
| 170 | if (!changes) {
|
---|
| 171 | this._updateContext();
|
---|
| 172 | }
|
---|
| 173 | else {
|
---|
| 174 | this._applyChanges(changes);
|
---|
| 175 | }
|
---|
| 176 | this._needsUpdate = false;
|
---|
| 177 | }
|
---|
| 178 | }
|
---|
| 179 | ngOnDestroy() {
|
---|
| 180 | this._viewport.detach();
|
---|
| 181 | this._dataSourceChanges.next(undefined);
|
---|
| 182 | this._dataSourceChanges.complete();
|
---|
| 183 | this.viewChange.complete();
|
---|
| 184 | this._destroyed.next();
|
---|
| 185 | this._destroyed.complete();
|
---|
| 186 | this._viewRepeater.detach();
|
---|
| 187 | }
|
---|
| 188 | /** React to scroll state changes in the viewport. */
|
---|
| 189 | _onRenderedDataChange() {
|
---|
| 190 | if (!this._renderedRange) {
|
---|
| 191 | return;
|
---|
| 192 | }
|
---|
| 193 | this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end);
|
---|
| 194 | if (!this._differ) {
|
---|
| 195 | // Use a wrapper function for the `trackBy` so any new values are
|
---|
| 196 | // picked up automatically without having to recreate the differ.
|
---|
| 197 | this._differ = this._differs.find(this._renderedItems).create((index, item) => {
|
---|
| 198 | return this.cdkVirtualForTrackBy ? this.cdkVirtualForTrackBy(index, item) : item;
|
---|
| 199 | });
|
---|
| 200 | }
|
---|
| 201 | this._needsUpdate = true;
|
---|
| 202 | }
|
---|
| 203 | /** Swap out one `DataSource` for another. */
|
---|
| 204 | _changeDataSource(oldDs, newDs) {
|
---|
| 205 | if (oldDs) {
|
---|
| 206 | oldDs.disconnect(this);
|
---|
| 207 | }
|
---|
| 208 | this._needsUpdate = true;
|
---|
| 209 | return newDs ? newDs.connect(this) : observableOf();
|
---|
| 210 | }
|
---|
| 211 | /** Update the `CdkVirtualForOfContext` for all views. */
|
---|
| 212 | _updateContext() {
|
---|
| 213 | const count = this._data.length;
|
---|
| 214 | let i = this._viewContainerRef.length;
|
---|
| 215 | while (i--) {
|
---|
| 216 | const view = this._viewContainerRef.get(i);
|
---|
| 217 | view.context.index = this._renderedRange.start + i;
|
---|
| 218 | view.context.count = count;
|
---|
| 219 | this._updateComputedContextProperties(view.context);
|
---|
| 220 | view.detectChanges();
|
---|
| 221 | }
|
---|
| 222 | }
|
---|
| 223 | /** Apply changes to the DOM. */
|
---|
| 224 | _applyChanges(changes) {
|
---|
| 225 | this._viewRepeater.applyChanges(changes, this._viewContainerRef, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record, currentIndex), (record) => record.item);
|
---|
| 226 | // Update $implicit for any items that had an identity change.
|
---|
| 227 | changes.forEachIdentityChange((record) => {
|
---|
| 228 | const view = this._viewContainerRef.get(record.currentIndex);
|
---|
| 229 | view.context.$implicit = record.item;
|
---|
| 230 | });
|
---|
| 231 | // Update the context variables on all items.
|
---|
| 232 | const count = this._data.length;
|
---|
| 233 | let i = this._viewContainerRef.length;
|
---|
| 234 | while (i--) {
|
---|
| 235 | const view = this._viewContainerRef.get(i);
|
---|
| 236 | view.context.index = this._renderedRange.start + i;
|
---|
| 237 | view.context.count = count;
|
---|
| 238 | this._updateComputedContextProperties(view.context);
|
---|
| 239 | }
|
---|
| 240 | }
|
---|
| 241 | /** Update the computed properties on the `CdkVirtualForOfContext`. */
|
---|
| 242 | _updateComputedContextProperties(context) {
|
---|
| 243 | context.first = context.index === 0;
|
---|
| 244 | context.last = context.index === context.count - 1;
|
---|
| 245 | context.even = context.index % 2 === 0;
|
---|
| 246 | context.odd = !context.even;
|
---|
| 247 | }
|
---|
| 248 | _getEmbeddedViewArgs(record, index) {
|
---|
| 249 | // Note that it's important that we insert the item directly at the proper index,
|
---|
| 250 | // rather than inserting it and the moving it in place, because if there's a directive
|
---|
| 251 | // on the same node that injects the `ViewContainerRef`, Angular will insert another
|
---|
| 252 | // comment node which can throw off the move when it's being repeated for all items.
|
---|
| 253 | return {
|
---|
| 254 | templateRef: this._template,
|
---|
| 255 | context: {
|
---|
| 256 | $implicit: record.item,
|
---|
| 257 | // It's guaranteed that the iterable is not "undefined" or "null" because we only
|
---|
| 258 | // generate views for elements if the "cdkVirtualForOf" iterable has elements.
|
---|
| 259 | cdkVirtualForOf: this._cdkVirtualForOf,
|
---|
| 260 | index: -1,
|
---|
| 261 | count: -1,
|
---|
| 262 | first: false,
|
---|
| 263 | last: false,
|
---|
| 264 | odd: false,
|
---|
| 265 | even: false
|
---|
| 266 | },
|
---|
| 267 | index,
|
---|
| 268 | };
|
---|
| 269 | }
|
---|
| 270 | }
|
---|
| 271 | CdkVirtualForOf.decorators = [
|
---|
| 272 | { type: Directive, args: [{
|
---|
| 273 | selector: '[cdkVirtualFor][cdkVirtualForOf]',
|
---|
| 274 | providers: [
|
---|
| 275 | { provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy },
|
---|
| 276 | ]
|
---|
| 277 | },] }
|
---|
| 278 | ];
|
---|
| 279 | CdkVirtualForOf.ctorParameters = () => [
|
---|
| 280 | { type: ViewContainerRef },
|
---|
| 281 | { type: TemplateRef },
|
---|
| 282 | { type: IterableDiffers },
|
---|
| 283 | { type: _RecycleViewRepeaterStrategy, decorators: [{ type: Inject, args: [_VIEW_REPEATER_STRATEGY,] }] },
|
---|
| 284 | { type: CdkVirtualScrollViewport, decorators: [{ type: SkipSelf }] },
|
---|
| 285 | { type: NgZone }
|
---|
| 286 | ];
|
---|
| 287 | CdkVirtualForOf.propDecorators = {
|
---|
| 288 | cdkVirtualForOf: [{ type: Input }],
|
---|
| 289 | cdkVirtualForTrackBy: [{ type: Input }],
|
---|
| 290 | cdkVirtualForTemplate: [{ type: Input }],
|
---|
| 291 | cdkVirtualForTemplateCacheSize: [{ type: Input }]
|
---|
| 292 | };
|
---|
| 293 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1mb3Itb2YuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY2RrL3Njcm9sbGluZy92aXJ0dWFsLWZvci1vZi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQ0wsZUFBZSxFQUlmLFlBQVksRUFDWiw0QkFBNEIsRUFDNUIsdUJBQXVCLEdBRXhCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUNMLFNBQVMsRUFHVCxNQUFNLEVBQ04sS0FBSyxFQUlMLGVBQWUsRUFFZixNQUFNLEVBRU4sUUFBUSxFQUNSLFdBQVcsRUFFWCxnQkFBZ0IsR0FDakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLG9CQUFvQixFQUFjLE1BQU0sdUJBQXVCLENBQUM7QUFDeEUsT0FBTyxFQUFhLE9BQU8sRUFBRSxFQUFFLElBQUksWUFBWSxFQUFFLFlBQVksRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUMzRSxPQUFPLEVBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBRXRGLE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBd0JuRSx5RUFBeUU7QUFDekUsU0FBUyxTQUFTLENBQUMsV0FBc0MsRUFBRSxTQUEwQixFQUFFLElBQVU7SUFDL0YsTUFBTSxFQUFFLEdBQUcsSUFBZSxDQUFDO0lBQzNCLElBQUksQ0FBQyxFQUFFLENBQUMscUJBQXFCLEVBQUU7UUFDN0IsT0FBTyxDQUFDLENBQUM7S0FDVjtJQUNELE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBRXhDLElBQUksV0FBVyxLQUFLLFlBQVksRUFBRTtRQUNoQyxPQUFPLFNBQVMsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxD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M0IsT0FBTyxFQUFFO2dCQUNQLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSTtnQkFDdEIsaUZBQWlGO2dCQUNqRiw4RUFBOEU7Z0JBQzlFLGVBQWUsRUFBRSxJQUFJLENBQUMsZ0JBQWlCO2dCQUN2QyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNULEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQ1QsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsR0FBRyxFQUFFLEtBQUs7Z0JBQ1YsSUFBSSxFQUFFLEtBQUs7YUFDWjtZQUNELEtBQUs7U0FDTixDQUFDO0lBQ0osQ0FBQzs7O1lBM1NGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsa0NBQWtDO2dCQUM1QyxTQUFTLEVBQUU7b0JBQ1QsRUFBQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsUUFBUSxFQUFFLDRCQUE0QixFQUFDO2lCQUMzRTthQUNGOzs7WUF0REMsZ0JBQWdCO1lBRmhCLFdBQVc7WUFMWCxlQUFlO1lBYmYsNEJBQTRCLHVCQWlMdkIsTUFBTSxTQUFDLHVCQUF1QjtZQXZKN0Isd0JBQXdCLHVCQTBKekIsUUFBUTtZQXJLYixNQUFNOzs7OEJBcUVMLEtBQUs7bUNBcUJMLEtBQUs7b0NBYUwsS0FBSzs2Q0FZTCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7XG4gIEFycmF5RGF0YVNvdXJjZSxcbiAgQ29sbGVjdGlvblZpZXdlcixcbiAgRGF0YVNvdXJjZSxcbiAgTGlzdFJhbmdlLFxuICBpc0RhdGFTb3VyY2UsXG4gIF9SZWN5Y2xlVmlld1JlcGVhdGVyU3RyYXRlZ3ksXG4gIF9WSUVXX1JFUEVBVEVSX1NUUkFURUdZLFxuICBfVmlld1JlcGVhdGVySXRlbUluc2VydEFyZ3MsXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQge1xuICBEaXJlY3RpdmUsXG4gIERvQ2hlY2ssXG4gIEVtYmVkZGVkVmlld1JlZixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgSXRlcmFibGVDaGFuZ2VSZWNvcmQsXG4gIEl0ZXJhYmxlQ2hhbmdlcyxcbiAgSXRlcmFibGVEaWZmZXIsXG4gIEl0ZXJhYmxlRGlmZmVycyxcbiAgTmdJdGVyYWJsZSxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIFNraXBTZWxmLFxuICBUZW1wbGF0ZVJlZixcbiAgVHJhY2tCeUZ1bmN0aW9uLFxuICBWaWV3Q29udGFpbmVyUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Y29lcmNlTnVtYmVyUHJvcGVydHksIE51bWJlcklucHV0fSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBTdWJqZWN0LCBvZiBhcyBvYnNlcnZhYmxlT2YsIGlzT2JzZXJ2YWJsZX0gZnJvbSAncnhqcyc7XG5pbXBvcnQge3BhaXJ3aXNlLCBzaGFyZVJlcGxheSwgc3RhcnRXaXRoLCBzd2l0Y2hNYXAsIHRha2VVbnRpbH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtDZGtWaXJ0dWFsU2Nyb2xsUmVwZWF0ZXJ9IGZyb20gJy4vdmlydHVhbC1zY3JvbGwtcmVwZWF0ZXInO1xuaW1wb3J0IHtDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnR9IGZyb20gJy4vdmlydHVhbC1zY3JvbGwtdmlld3BvcnQnO1xuXG5cbi8qKiBUaGUgY29udGV4dCBmb3IgYW4gaXRlbSByZW5kZXJlZCBieSBgQ2RrVmlydHVhbEZvck9mYCAqL1xuZXhwb3J0IHR5cGUgQ2RrVmlydHVhbEZvck9mQ29udGV4dDxUPiA9IHtcbiAgLyoqIFRoZSBpdGVtIHZhbHVlLiAqL1xuICAkaW1wbGljaXQ6IFQ7XG4gIC8qKiBUaGUgRGF0YVNvdXJjZSwgT2JzZXJ2YWJsZSwgb3IgTmdJdGVyYWJsZSB0aGF0IHdhcyBwYXNzZWQgdG8gKmNka1ZpcnR1YWxGb3IuICovXG4gIGNka1ZpcnR1YWxGb3JPZjogRGF0YVNvdXJjZTxUPiB8IE9ic2VydmFibGU8VFtdPiB8IE5nSXRlcmFibGU8VD47XG4gIC8qKiBUaGUgaW5kZXggb2YgdGhlIGl0ZW0gaW4gdGhlIERhdGFTb3VyY2UuICovXG4gIGluZGV4OiBudW1iZXI7XG4gIC8qKiBUaGUgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBEYXRhU291cmNlLiAqL1xuICBjb3VudDogbnVtYmVyO1xuICAvKiogV2hldGhlciB0aGlzIGlzIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBEYXRhU291cmNlLiAqL1xuICBmaXJzdDogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhpcyBpcyB0aGUgbGFzdCBpdGVtIGluIHRoZSBEYXRhU291cmNlLiAqL1xuICBsYXN0OiBib29sZWFuO1xuICAvKiogV2hldGhlciB0aGUgaW5kZXggaXMgZXZlbi4gKi9cbiAgZXZlbjogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhlIGluZGV4IGlzIG9kZC4gKi9cbiAgb2RkOiBib29sZWFuO1xufTtcblxuXG4vKiogSGVscGVyIHRvIGV4dHJhY3QgdGhlIG9mZnNldCBvZiBhIERPTSBOb2RlIGluIGEgY2VydGFpbiBkaXJlY3Rpb24uICovXG5mdW5jdGlvbiBnZXRPZmZzZXQob3JpZW50YXRpb246ICdob3Jpem9udGFsJyB8ICd2ZXJ0aWNhbCcsIGRpcmVjdGlvbjogJ3N0YXJ0JyB8ICdlbmQnLCBub2RlOiBOb2RlKSB7XG4gIGNvbnN0IGVsID0gbm9kZSBhcyBFbGVtZW50O1xuICBpZiAoIWVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICBpZiAob3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgIHJldHVybiBkaXJlY3Rpb24gPT09ICdzdGFydCcgPyByZWN0LmxlZnQgOiByZWN0LnJpZ2h0O1xuICB9XG5cbiAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gJ3N0YXJ0JyA/IHJlY3QudG9wIDogcmVjdC5ib3R0b207XG59XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgc2ltaWxhciB0byBgbmdGb3JPZmAgdG8gYmUgdXNlZCBmb3IgcmVuZGVyaW5nIGRhdGEgaW5zaWRlIGEgdmlydHVhbCBzY3JvbGxpbmdcbiAqIGNvbnRhaW5lci5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2Nka1ZpcnR1YWxGb3JdW2Nka1ZpcnR1YWxGb3JPZl0nLFxuICBwcm92aWRlcnM6IFtcbiAgICB7cHJvdmlkZTogX1ZJRVdfUkVQRUFURVJfU1RSQVRFR1ksIHVzZUNsYXNzOiBfUmVjeWNsZVZpZXdSZXBlYXRlclN0cmF0ZWd5fSxcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBDZGtWaXJ0dWFsRm9yT2Y8VD4gaW1wbGVtZW50c1xuICAgIENka1ZpcnR1YWxTY3JvbGxSZXBlYXRlcjxUPiwgQ29sbGVjdGlvblZpZXdlciwgRG9DaGVjaywgT25EZXN0cm95IHtcbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHJlbmRlcmVkIHZpZXcgb2YgdGhlIGRhdGEgY2hhbmdlcy4gKi9cbiAgcmVhZG9ubHkgdmlld0NoYW5nZSA9IG5ldyBTdWJqZWN0PExpc3RSYW5nZT4oKTtcblxuICAvKiogU3ViamVjdCB0aGF0IGVtaXRzIHdoZW4gYSBuZXcgRGF0YVNvdXJjZSBpbnN0YW5jZSBpcyBnaXZlbi4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfZGF0YVNvdXJjZUNoYW5nZXMgPSBuZXcgU3ViamVjdDxEYXRhU291cmNlPFQ+PigpO1xuXG4gIC8qKiBUaGUgRGF0YVNvdXJjZSB0byBkaXNwbGF5LiAqL1xuICBASW5wdXQoKVxuICBnZXQgY2RrVmlydHVhbEZvck9mKCk6IERhdGFTb3VyY2U8VD4gfCBPYnNlcnZhYmxlPFRbXT4gfCBOZ0l0ZXJhYmxlPFQ+IHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2Nka1ZpcnR1YWxGb3JPZjtcbiAgfVxuICBzZXQgY2RrVmlydHVhbEZvck9mKHZhbHVlOiBEYXRhU291cmNlPFQ+IHwgT2JzZXJ2YWJsZTxUW10+IHwgTmdJdGVyYWJsZTxUPiB8IG51bGwgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9jZGtWaXJ0dWFsRm9yT2YgPSB2YWx1ZTtcbiAgICBpZiAoaXNEYXRhU291cmNlKHZhbHVlKSkge1xuICAgICAgdGhpcy5fZGF0YVNvdXJjZUNoYW5nZXMubmV4dCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHZhbHVlIGlzIGFuIGFuIE5nSXRlcmFibGUsIGNvbnZlcnQgaXQgdG8gYW4gYXJyYXkuXG4gICAgICB0aGlzLl9kYXRhU291cmNlQ2hhbmdlcy5uZXh0KG5ldyBBcnJheURhdGFTb3VyY2U8VD4oXG4gICAgICAgICAgaXNPYnNlcnZhYmxlKHZhbHVlKSA/IHZhbHVlIDogQXJyYXkuZnJvbSh2YWx1ZSB8fCBbXSkpKTtcbiAgICB9XG4gIH1cblxuICBfY2RrVmlydHVhbEZvck9mOiBEYXRhU291cmNlPFQ+IHwgT2JzZXJ2YWJsZTxUW10+IHwgTmdJdGVyYWJsZTxUPiB8IG51bGwgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIFRoZSBgVHJhY2tCeUZ1bmN0aW9uYCB0byB1c2UgZm9yIHRyYWNraW5nIGNoYW5nZXMuIFRoZSBgVHJhY2tCeUZ1bmN0aW9uYCB0YWtlcyB0aGUgaW5kZXggYW5kXG4gICAqIHRoZSBpdGVtIGFuZCBwcm9kdWNlcyBhIHZhbHVlIHRvIGJlIHVzZWQgYXMgdGhlIGl0ZW0ncyBpZGVudGl0eSB3aGVuIHRyYWNraW5nIGNoYW5nZXMuXG4gICAqL1xuICBASW5wdXQoKVxuICBnZXQgY2RrVmlydHVhbEZvclRyYWNrQnkoKTogVHJhY2tCeUZ1bmN0aW9uPFQ+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fY2RrVmlydHVhbEZvclRyYWNrQnk7XG4gIH1cbiAgc2V0IGNka1ZpcnR1YWxGb3JUcmFja0J5KGZuOiBUcmFja0J5RnVuY3Rpb248VD4gfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9uZWVkc1VwZGF0ZSA9IHRydWU7XG4gICAgdGhpcy5fY2RrVmlydHVhbEZvclRyYWNrQnkgPSBmbiA/XG4gICAgICAgIChpbmRleCwgaXRlbSkgPT4gZm4oaW5kZXggKyAodGhpcy5fcmVuZGVyZWRSYW5nZSA/IHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQgOiAwKSwgaXRlbSkgOlxuICAgICAgICB1bmRlZmluZWQ7XG4gIH1cbiAgcHJpdmF0ZSBfY2RrVmlydHVhbEZvclRyYWNrQnk6IFRyYWNrQnlGdW5jdGlvbjxUPiB8IHVuZGVmaW5lZDtcblxuICAvKiogVGhlIHRlbXBsYXRlIHVzZWQgdG8gc3RhbXAgb3V0IG5ldyBlbGVtZW50cy4gKi9cbiAgQElucHV0KClcbiAgc2V0IGNka1ZpcnR1YWxGb3JUZW1wbGF0ZSh2YWx1ZTogVGVtcGxhdGVSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4pIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuX25lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzaXplIG9mIHRoZSBjYWNoZSB1c2VkIHRvIHN0b3JlIHRlbXBsYXRlcyB0aGF0IGFyZSBub3QgYmVpbmcgdXNlZCBmb3IgcmUtdXNlIGxhdGVyLlxuICAgKiBTZXR0aW5nIHRoZSBjYWNoZSBzaXplIHRvIGAwYCB3aWxsIGRpc2FibGUgY2FjaGluZy4gRGVmYXVsdHMgdG8gMjAgdGVtcGxhdGVzLlxuICAgKi9cbiAgQElucHV0KClcbiAgZ2V0IGNka1ZpcnR1YWxGb3JUZW1wbGF0ZUNhY2hlU2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlld1JlcGVhdGVyLnZpZXdDYWNoZVNpemU7XG4gIH1cbiAgc2V0IGNka1ZpcnR1YWxGb3JUZW1wbGF0ZUNhY2hlU2l6ZShzaXplOiBudW1iZXIpIHtcbiAgICB0aGlzLl92aWV3UmVwZWF0ZXIudmlld0NhY2hlU2l6ZSA9IGNvZXJjZU51bWJlclByb3BlcnR5KHNpemUpO1xuICB9XG5cbiAgLyoqIEVtaXRzIHdoZW5ldmVyIHRoZSBkYXRhIGluIHRoZSBjdXJyZW50IERhdGFTb3VyY2UgY2hhbmdlcy4gKi9cbiAgcmVhZG9ubHkgZGF0YVN0cmVhbTogT2JzZXJ2YWJsZTxyZWFkb25seSBUW10+ID0gdGhpcy5fZGF0YVNvdXJjZUNoYW5nZXNcbiAgLnBpcGUoXG4gICAgICAvLyBTdGFydCBvZmYgd2l0aCBudWxsIGBEYXRhU291cmNlYC5cbiAgICAgIHN0YXJ0V2l0aChudWxsKSxcbiAgICAgIC8vIEJ1bmRsZSB1cCB0aGUgcHJldmlvdXMgYW5kIGN1cnJlbnQgZGF0YSBzb3VyY2VzIHNvIHdlIGNhbiB3b3JrIHdpdGggYm90aC5cbiAgICAgIHBhaXJ3aXNlKCksXG4gICAgICAvLyBVc2UgYF9jaGFuZ2VEYXRhU291cmNlYCB0byBkaXNjb25uZWN0IGZyb20gdGhlIHByZXZpb3VzIGRhdGEgc291cmNlIGFuZCBjb25uZWN0IHRvIHRoZVxuICAgICAgLy8gbmV3IG9uZSwgcGFzc2luZyBiYWNrIGEgc3RyZWFtIG9mIGRhdGEgY2hhbmdlcyB3aGljaCB3ZSBydW4gdGhyb3VnaCBgc3dpdGNoTWFwYCB0byBnaXZlXG4gICAgICAvLyB1cyBhIGRhdGEgc3RyZWFtIHRoYXQgZW1pdHMgdGhlIGxhdGVzdCBkYXRhIGZyb20gd2hhdGV2ZXIgdGhlIGN1cnJlbnQgYERhdGFTb3VyY2VgIGlzLlxuICAgICAgc3dpdGNoTWFwKChbcHJldiwgY3VyXSkgPT4gdGhpcy5fY2hhbmdlRGF0YVNvdXJjZShwcmV2LCBjdXIpKSxcbiAgICAgIC8vIFJlcGxheSB0aGUgbGFzdCBlbWl0dGVkIGRhdGEgd2hlbiBzb21lb25lIHN1YnNjcmliZXMuXG4gICAgICBzaGFyZVJlcGxheSgxKSk7XG5cbiAgLyoqIFRoZSBkaWZmZXIgdXNlZCB0byBjYWxjdWxhdGUgY2hhbmdlcyB0byB0aGUgZGF0YS4gKi9cbiAgcHJpdmF0ZSBfZGlmZmVyOiBJdGVyYWJsZURpZmZlcjxUPiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUaGUgbW9zdCByZWNlbnQgZGF0YSBlbWl0dGVkIGZyb20gdGhlIERhdGFTb3VyY2UuICovXG4gIHByaXZhdGUgX2RhdGE6IHJlYWRvbmx5IFRbXTtcblxuICAvKiogVGhlIGN1cnJlbnRseSByZW5kZXJlZCBpdGVtcy4gKi9cbiAgcHJpdmF0ZSBfcmVuZGVyZWRJdGVtczogVFtdO1xuXG4gIC8qKiBUaGUgY3VycmVudGx5IHJlbmRlcmVkIHJhbmdlIG9mIGluZGljZXMuICovXG4gIHByaXZhdGUgX3JlbmRlcmVkUmFuZ2U6IExpc3RSYW5nZTtcblxuICAvKiogV2hldGhlciB0aGUgcmVuZGVyZWQgZGF0YSBzaG91bGQgYmUgdXBkYXRlZCBkdXJpbmcgdGhlIG5leHQgbmdEb0NoZWNrIGN5Y2xlLiAqL1xuICBwcml2YXRlIF9uZWVkc1VwZGF0ZSA9IGZhbHNlO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3llZCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICAvKiogVGhlIHZpZXcgY29udGFpbmVyIHRvIGFkZCBpdGVtcyB0by4gKi9cbiAgICAgIHByaXZhdGUgX3ZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG4gICAgICAvKiogVGhlIHRlbXBsYXRlIHRvIHVzZSB3aGVuIHN0YW1waW5nIG91dCBuZXcgaXRlbXMuICovXG4gICAgICBwcml2YXRlIF90ZW1wbGF0ZTogVGVtcGxhdGVSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4sXG4gICAgICAvKiogVGhlIHNldCBvZiBhdmFpbGFibGUgZGlmZmVycy4gKi9cbiAgICAgIHByaXZhdGUgX2RpZmZlcnM6IEl0ZXJhYmxlRGlmZmVycyxcbiAgICAgIC8qKiBUaGUgc3RyYXRlZ3kgdXNlZCB0byByZW5kZXIgaXRlbXMgaW4gdGhlIHZpcnR1YWwgc2Nyb2xsIHZpZXdwb3J0LiAqL1xuICAgICAgQEluamVjdChfVklFV19SRVBFQVRFUl9TVFJBVEVHWSlcbiAgICAgIHByaXZhdGUgX3ZpZXdSZXBlYXRlcjogX1JlY3ljbGVWaWV3UmVwZWF0ZXJTdHJhdGVneTxULCBULCBDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PixcbiAgICAgIC8qKiBUaGUgdmlydHVhbCBzY3JvbGxpbmcgdmlld3BvcnQgdGhhdCB0aGVzZSBpdGVtcyBhcmUgYmVpbmcgcmVuZGVyZWQgaW4uICovXG4gICAgICBAU2tpcFNlbGYoKSBwcml2YXRlIF92aWV3cG9ydDogQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LFxuICAgICAgbmdab25lOiBOZ1pvbmUpIHtcbiAgICB0aGlzLmRhdGFTdHJlYW0uc3Vic2NyaWJlKGRhdGEgPT4ge1xuICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gICAgICB0aGlzLl9vblJlbmRlcmVkRGF0YUNoYW5nZSgpO1xuICAgIH0pO1xuICAgIHRoaXMuX3ZpZXdwb3J0LnJlbmRlcmVkUmFuZ2VTdHJlYW0ucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSkuc3Vic2NyaWJlKHJhbmdlID0+IHtcbiAgICAgIHRoaXMuX3JlbmRlcmVkUmFuZ2UgPSByYW5nZTtcbiAgICAgIG5nWm9uZS5ydW4oKCkgPT4gdGhpcy52aWV3Q2hhbmdlLm5leHQodGhpcy5fcmVuZGVyZWRSYW5nZSkpO1xuICAgICAgdGhpcy5fb25SZW5kZXJlZERhdGFDaGFuZ2UoKTtcbiAgICB9KTtcbiAgICB0aGlzLl92aWV3cG9ydC5hdHRhY2godGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogTWVhc3VyZXMgdGhlIGNvbWJpbmVkIHNpemUgKHdpZHRoIGZvciBob3Jpem9udGFsIG9yaWVudGF0aW9uLCBoZWlnaHQgZm9yIHZlcnRpY2FsKSBvZiBhbGwgaXRlbXNcbiAgICogaW4gdGhlIHNwZWNpZmllZCByYW5nZS4gVGhyb3dzIGFuIGVycm9yIGlmIHRoZSByYW5nZSBpbmNsdWRlcyBpdGVtcyB0aGF0IGFyZSBub3QgY3VycmVudGx5XG4gICAqIHJlbmRlcmVkLlxuICAgKi9cbiAgbWVhc3VyZVJhbmdlU2l6ZShyYW5nZTogTGlzdFJhbmdlLCBvcmllbnRhdGlvbjogJ2hvcml6b250YWwnIHwgJ3ZlcnRpY2FsJyk6IG51bWJlciB7XG4gICAgaWYgKHJhbmdlLnN0YXJ0ID49IHJhbmdlLmVuZCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmICgocmFuZ2Uuc3RhcnQgPCB0aGlzLl9yZW5kZXJlZFJhbmdlLnN0YXJ0IHx8IHJhbmdlLmVuZCA+IHRoaXMuX3JlbmRlcmVkUmFuZ2UuZW5kKSAmJlxuICAgICAgKHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8IG5nRGV2TW9kZSkpIHtcbiAgICAgIHRocm93IEVycm9yKGBFcnJvcjogYXR0ZW1wdGVkIHRvIG1lYXN1cmUgYW4gaXRlbSB0aGF0IGlzbid0IHJlbmRlcmVkLmApO1xuICAgIH1cblxuICAgIC8vIFRoZSBpbmRleCBpbnRvIHRoZSBsaXN0IG9mIHJlbmRlcmVkIHZpZXdzIGZvciB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgcmFuZ2UuXG4gICAgY29uc3QgcmVuZGVyZWRTdGFydEluZGV4ID0gcmFuZ2Uuc3RhcnQgLSB0aGlzLl9yZW5kZXJlZFJhbmdlLnN0YXJ0O1xuICAgIC8vIFRoZSBsZW5ndGggb2YgdGhlIHJhbmdlIHdlJ3JlIG1lYXN1cmluZy5cbiAgICBjb25zdCByYW5nZUxlbiA9IHJhbmdlLmVuZCAtIHJhbmdlLnN0YXJ0O1xuXG4gICAgLy8gTG9vcCBvdmVyIGFsbCB0aGUgdmlld3MsIGZpbmQgdGhlIGZpcnN0IGFuZCBsYW5kIG5vZGUgYW5kIGNvbXB1dGUgdGhlIHNpemUgYnkgc3VidHJhY3RpbmdcbiAgICAvLyB0aGUgdG9wIG9mIHRoZSBmaXJzdCBub2RlIGZyb20gdGhlIGJvdHRvbSBvZiB0aGUgbGFzdCBvbmUuXG4gICAgbGV0IGZpcnN0Tm9kZTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgbGV0IGxhc3ROb2RlOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZDtcblxuICAgIC8vIEZpbmQgdGhlIGZpcnN0IG5vZGUgYnkgc3RhcnRpbmcgZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCBnb2luZyBmb3J3YXJkcy5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmdlTGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLl92aWV3Q29udGFpbmVyUmVmLmdldChpICsgcmVuZGVyZWRTdGFydEluZGV4KSBhc1xuICAgICAgICAgIEVtYmVkZGVkVmlld1JlZjxDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PiB8IG51bGw7XG4gICAgICBpZiAodmlldyAmJiB2aWV3LnJvb3ROb2Rlcy5sZW5ndGgpIHtcbiAgICAgICAgZmlyc3ROb2RlID0gbGFzdE5vZGUgPSB2aWV3LnJvb3ROb2Rlc1swXTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmluZCB0aGUgbGFzdCBub2RlIGJ5IHN0YXJ0aW5nIGZyb20gdGhlIGVuZCBhbmQgZ29pbmcgYmFja3dhcmRzLlxuICAgIGZvciAobGV0IGkgPSByYW5nZUxlbiAtIDE7IGkgPiAtMTsgaS0tKSB7XG4gICAgICBjb25zdCB2aWV3ID0gdGhpcy5fdmlld0NvbnRhaW5lclJlZi5nZXQoaSArIHJlbmRlcmVkU3RhcnRJbmRleCkgYXNcbiAgICAgICAgICBFbWJlZGRlZFZpZXdSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4gfCBudWxsO1xuICAgICAgaWYgKHZpZXcgJiYgdmlldy5yb290Tm9kZXMubGVuZ3RoKSB7XG4gICAgICAgIGxhc3ROb2RlID0gdmlldy5yb290Tm9kZXNbdmlldy5yb290Tm9kZXMubGVuZ3RoIC0gMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaXJzdE5vZGUgJiYgbGFzdE5vZGUgP1xuICAgICAgICBnZXRPZmZzZXQob3JpZW50YXRpb24sICdlbmQnLCBsYXN0Tm9kZSkgLSBnZXRPZmZzZXQob3JpZW50YXRpb24sICdzdGFydCcsIGZpcnN0Tm9kZSkgOiAwO1xuICB9XG5cbiAgbmdEb0NoZWNrKCkge1xuICAgIGlmICh0aGlzLl9kaWZmZXIgJiYgdGhpcy5fbmVlZHNVcGRhdGUpIHtcbiAgICAgIC8vIFRPRE8obW1hbGVyYmEpOiBXZSBzaG91bGQgZGlmZmVyZW50aWF0ZSBuZWVkcyB1cGRhdGUgZHVlIHRvIHNjcm9sbGluZyBhbmQgYSBuZXcgcG9ydGlvbiBvZlxuICAgICAgLy8gdGhpcyBsaXN0IGJlaW5nIHJlbmRlcmVkIChjYW4gdXNlIHNpbXBsZXIgYWxnb3JpdGhtKSB2cyBuZWVkcyB1cGRhdGUgZHVlIHRvIGRhdGEgYWN0dWFsbHlcbiAgICAgIC8vIGNoYW5naW5nIChuZWVkIHRvIGRvIHRoaXMgZGlmZikuXG4gICAgICBjb25zdCBjaGFuZ2VzID0gdGhpcy5fZGlmZmVyLmRpZmYodGhpcy5fcmVuZGVyZWRJdGVtcyk7XG4gICAgICBpZiAoIWNoYW5nZXMpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGV4dCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fYXBwbHlDaGFuZ2VzKGNoYW5nZXMpO1xuICAgICAgfVxuICAgICAgdGhpcy5fbmVlZHNVcGRhdGUgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl92aWV3cG9ydC5kZXRhY2goKTtcblxuICAgIHRoaXMuX2RhdGFTb3VyY2VDaGFuZ2VzLm5leHQodW5kZWZpbmVkISk7XG4gICAgdGhpcy5fZGF0YVNvdXJjZUNoYW5nZXMuY29tcGxldGUoKTtcbiAgICB0aGlzLnZpZXdDaGFuZ2UuY29tcGxldGUoKTtcblxuICAgIHRoaXMuX2Rlc3Ryb3llZC5uZXh0KCk7XG4gICAgdGhpcy5fZGVzdHJveWVkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5fdmlld1JlcGVhdGVyLmRldGFjaCgpO1xuICB9XG5cbiAgLyoqIFJlYWN0IHRvIHNjcm9sbCBzdGF0ZSBjaGFuZ2VzIGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBfb25SZW5kZXJlZERhdGFDaGFuZ2UoKSB7XG4gICAgaWYgKCF0aGlzLl9yZW5kZXJlZFJhbmdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX3JlbmRlcmVkSXRlbXMgPSB0aGlzLl9kYXRhLnNsaWNlKHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQsIHRoaXMuX3JlbmRlcmVkUmFuZ2UuZW5kKTtcbiAgICBpZiAoIXRoaXMuX2RpZmZlcikge1xuICAgICAgLy8gVXNlIGEgd3JhcHBlciBmdW5jdGlvbiBmb3IgdGhlIGB0cmFja0J5YCBzbyBhbnkgbmV3IHZhbHVlcyBhcmVcbiAgICAgIC8vIHBpY2tlZCB1cCBhdXRvbWF0aWNhbGx5IHdpdGhvdXQgaGF2aW5nIHRvIHJlY3JlYXRlIHRoZSBkaWZmZXIuXG4gICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodGhpcy5fcmVuZGVyZWRJdGVtcykuY3JlYXRlKChpbmRleCwgaXRlbSkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jZGtWaXJ0dWFsRm9yVHJhY2tCeSA/IHRoaXMuY2RrVmlydHVhbEZvclRyYWNrQnkoaW5kZXgsIGl0ZW0pIDogaXRlbTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLl9uZWVkc1VwZGF0ZSA9IHRydWU7XG4gIH1cblxuICAvKiogU3dhcCBvdXQgb25lIGBEYXRhU291cmNlYCBmb3IgYW5vdGhlci4gKi9cbiAgcHJpdmF0ZSBfY2hhbmdlRGF0YVNvdXJjZShvbGREczogRGF0YVNvdXJjZTxUPiB8IG51bGwsIG5ld0RzOiBEYXRhU291cmNlPFQ+IHwgbnVsbCk6XG4gICAgICBPYnNlcnZhYmxlPHJlYWRvbmx5IFRbXT4ge1xuXG4gICAgaWYgKG9sZERzKSB7XG4gICAgICBvbGREcy5kaXNjb25uZWN0KHRoaXMpO1xuICAgIH1cblxuICAgIHRoaXMuX25lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgICByZXR1cm4gbmV3RHMgPyBuZXdEcy5jb25uZWN0KHRoaXMpIDogb2JzZXJ2YWJsZU9mKCk7XG4gIH1cblxuICAvKiogVXBkYXRlIHRoZSBgQ2RrVmlydHVhbEZvck9mQ29udGV4dGAgZm9yIGFsbCB2aWV3cy4gKi9cbiAgcHJpdmF0ZSBfdXBkYXRlQ29udGV4dCgpIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX2RhdGEubGVuZ3RoO1xuICAgIGxldCBpID0gdGhpcy5fdmlld0NvbnRhaW5lclJlZi5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgY29uc3QgdmlldyA9IHRoaXMuX3ZpZXdDb250YWluZXJSZWYuZ2V0KGkpIGFzIEVtYmVkZGVkVmlld1JlZjxDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PjtcbiAgICAgIHZpZXcuY29udGV4dC5pbmRleCA9IHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQgKyBpO1xuICAgICAgdmlldy5jb250ZXh0LmNvdW50ID0gY291bnQ7XG4gICAgICB0aGlzLl91cGRhdGVDb21wdXRlZENvbnRleHRQcm9wZXJ0aWVzKHZpZXcuY29udGV4dCk7XG4gICAgICB2aWV3LmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQXBwbHkgY2hhbmdlcyB0byB0aGUgRE9NLiAqL1xuICBwcml2YXRlIF9hcHBseUNoYW5nZXMoY2hhbmdlczogSXRlcmFibGVDaGFuZ2VzPFQ+KSB7XG4gICAgdGhpcy5fdmlld1JlcGVhdGVyLmFwcGx5Q2hhbmdlcyhcbiAgICAgICAgY2hhbmdlcyxcbiAgICAgICAgdGhpcy5fdmlld0NvbnRhaW5lclJlZixcbiAgICAgICAgKHJlY29yZDogSXRlcmFibGVDaGFuZ2VSZWNvcmQ8VD4sXG4gICAgICAgICBfYWRqdXN0ZWRQcmV2aW91c0luZGV4OiBudW1iZXIgfCBudWxsLFxuICAgICAgICAgY3VycmVudEluZGV4OiBudW1iZXIgfCBudWxsKSA9PiB0aGlzLl9nZXRFbWJlZGRlZFZpZXdBcmdzKHJlY29yZCwgY3VycmVudEluZGV4ISksXG4gICAgICAgIChyZWNvcmQpID0+IHJlY29yZC5pdGVtKTtcblxuICAgIC8vIFVwZGF0ZSAkaW1wbGljaXQgZm9yIGFueSBpdGVtcyB0aGF0IGhhZCBhbiBpZGVudGl0eSBjaGFuZ2UuXG4gICAgY2hhbmdlcy5mb3JFYWNoSWRlbnRpdHlDaGFuZ2UoKHJlY29yZDogSXRlcmFibGVDaGFuZ2VSZWNvcmQ8VD4pID0+IHtcbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLl92aWV3Q29udGFpbmVyUmVmLmdldChyZWNvcmQuY3VycmVudEluZGV4ISkgYXNcbiAgICAgICAgICBFbWJlZGRlZFZpZXdSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj47XG4gICAgICB2aWV3LmNvbnRleHQuJGltcGxpY2l0ID0gcmVjb3JkLml0ZW07XG4gICAgfSk7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGNvbnRleHQgdmFyaWFibGVzIG9uIGFsbCBpdGVtcy5cbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX2RhdGEubGVuZ3RoO1xuICAgIGxldCBpID0gdGhpcy5fdmlld0NvbnRhaW5lclJlZi5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgY29uc3QgdmlldyA9IHRoaXMuX3ZpZXdDb250YWluZXJSZWYuZ2V0KGkpIGFzIEVtYmVkZGVkVmlld1JlZjxDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PjtcbiAgICAgIHZpZXcuY29udGV4dC5pbmRleCA9IHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQgKyBpO1xuICAgICAgdmlldy5jb250ZXh0LmNvdW50ID0gY291bnQ7XG4gICAgICB0aGlzLl91cGRhdGVDb21wdXRlZENvbnRleHRQcm9wZXJ0aWVzKHZpZXcuY29udGV4dCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFVwZGF0ZSB0aGUgY29tcHV0ZWQgcHJvcGVydGllcyBvbiB0aGUgYENka1ZpcnR1YWxGb3JPZkNvbnRleHRgLiAqL1xuICBwcml2YXRlIF91cGRhdGVDb21wdXRlZENvbnRleHRQcm9wZXJ0aWVzKGNvbnRleHQ6IENka1ZpcnR1YWxGb3JPZkNvbnRleHQ8YW55Pikge1xuICAgIGNvbnRleHQuZmlyc3QgPSBjb250ZXh0LmluZGV4ID09PSAwO1xuICAgIGNvbnRleHQubGFzdCA9IGNvbnRleHQuaW5kZXggPT09IGNvbnRleHQuY291bnQgLSAxO1xuICAgIGNvbnRleHQuZXZlbiA9IGNvbnRleHQuaW5kZXggJSAyID09PSAwO1xuICAgIGNvbnRleHQub2RkID0gIWNvbnRleHQuZXZlbjtcbiAgfVxuXG4gIHByaXZhdGUgX2dldEVtYmVkZGVkVmlld0FyZ3MocmVjb3JkOiBJdGVyYWJsZUNoYW5nZVJlY29yZDxUPiwgaW5kZXg6IG51bWJlcik6XG4gICAgICBfVmlld1JlcGVhdGVySXRlbUluc2VydEFyZ3M8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4ge1xuICAgIC8vIE5vdGUgdGhhdCBpdCdzIGltcG9ydGFudCB0aGF0IHdlIGluc2VydCB0aGUgaXRlbSBkaXJlY3RseSBhdCB0aGUgcHJvcGVyIGluZGV4LFxuICAgIC8vIHJhdGhlciB0aGFuIGluc2VydGluZyBpdCBhbmQgdGhlIG1vdmluZyBpdCBpbiBwbGFjZSwgYmVjYXVzZSBpZiB0aGVyZSdzIGEgZGlyZWN0aXZlXG4gICAgLy8gb24gdGhlIHNhbWUgbm9kZSB0aGF0IGluamVjdHMgdGhlIGBWaWV3Q29udGFpbmVyUmVmYCwgQW5ndWxhciB3aWxsIGluc2VydCBhbm90aGVyXG4gICAgLy8gY29tbWVudCBub2RlIHdoaWNoIGNhbiB0aHJvdyBvZmYgdGhlIG1vdmUgd2hlbiBpdCdzIGJlaW5nIHJlcGVhdGVkIGZvciBhbGwgaXRlbXMuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRlbXBsYXRlUmVmOiB0aGlzLl90ZW1wbGF0ZSxcbiAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgJGltcGxpY2l0OiByZWNvcmQuaXRlbSxcbiAgICAgICAgLy8gSXQncyBndWFyYW50ZWVkIHRoYXQgdGhlIGl0ZXJhYmxlIGlzIG5vdCBcInVuZGVmaW5lZFwiIG9yIFwibnVsbFwiIGJlY2F1c2Ugd2Ugb25seVxuICAgICAgICAvLyBnZW5lcmF0ZSB2aWV3cyBmb3IgZWxlbWVudHMgaWYgdGhlIFwiY2RrVmlydHVhbEZvck9mXCIgaXRlcmFibGUgaGFzIGVsZW1lbnRzLlxuICAgICAgICBjZGtWaXJ0dWFsRm9yT2Y6IHRoaXMuX2Nka1ZpcnR1YWxGb3JPZiEsXG4gICAgICAgIGluZGV4OiAtMSxcbiAgICAgICAgY291bnQ6IC0xLFxuICAgICAgICBmaXJzdDogZmFsc2UsXG4gICAgICAgIGxhc3Q6IGZhbHNlLFxuICAgICAgICBvZGQ6IGZhbHNlLFxuICAgICAgICBldmVuOiBmYWxzZVxuICAgICAgfSxcbiAgICAgIGluZGV4LFxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfY2RrVmlydHVhbEZvclRlbXBsYXRlQ2FjaGVTaXplOiBOdW1iZXJJbnB1dDtcbn1cbiJdfQ== |
---|