You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
46 KiB
315 lines
46 KiB
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
import { ArrayDataSource, isDataSource, _RecycleViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY, } from '@angular/cdk/collections';
|
|
import { Directive, Inject, Input, IterableDiffers, NgZone, SkipSelf, TemplateRef, ViewContainerRef, } from '@angular/core';
|
|
import { coerceNumberProperty } from '@angular/cdk/coercion';
|
|
import { Subject, of as observableOf, isObservable } from 'rxjs';
|
|
import { pairwise, shareReplay, startWith, switchMap, takeUntil } from 'rxjs/operators';
|
|
import { CdkVirtualScrollViewport } from './virtual-scroll-viewport';
|
|
/** Helper to extract the offset of a DOM Node in a certain direction. */
|
|
import * as ɵngcc0 from '@angular/core';
|
|
import * as ɵngcc1 from './virtual-scroll-viewport';
|
|
import * as ɵngcc2 from '@angular/cdk/collections';
|
|
function getOffset(orientation, direction, node) {
|
|
const el = node;
|
|
if (!el.getBoundingClientRect) {
|
|
return 0;
|
|
}
|
|
const rect = el.getBoundingClientRect();
|
|
if (orientation === 'horizontal') {
|
|
return direction === 'start' ? rect.left : rect.right;
|
|
}
|
|
return direction === 'start' ? rect.top : rect.bottom;
|
|
}
|
|
/**
|
|
* A directive similar to `ngForOf` to be used for rendering data inside a virtual scrolling
|
|
* container.
|
|
*/
|
|
export class CdkVirtualForOf {
|
|
constructor(
|
|
/** The view container to add items to. */
|
|
_viewContainerRef,
|
|
/** The template to use when stamping out new items. */
|
|
_template,
|
|
/** The set of available differs. */
|
|
_differs,
|
|
/** The strategy used to render items in the virtual scroll viewport. */
|
|
_viewRepeater,
|
|
/** The virtual scrolling viewport that these items are being rendered in. */
|
|
_viewport, ngZone) {
|
|
this._viewContainerRef = _viewContainerRef;
|
|
this._template = _template;
|
|
this._differs = _differs;
|
|
this._viewRepeater = _viewRepeater;
|
|
this._viewport = _viewport;
|
|
/** Emits when the rendered view of the data changes. */
|
|
this.viewChange = new Subject();
|
|
/** Subject that emits when a new DataSource instance is given. */
|
|
this._dataSourceChanges = new Subject();
|
|
/** Emits whenever the data in the current DataSource changes. */
|
|
this.dataStream = this._dataSourceChanges
|
|
.pipe(
|
|
// Start off with null `DataSource`.
|
|
startWith(null),
|
|
// Bundle up the previous and current data sources so we can work with both.
|
|
pairwise(),
|
|
// Use `_changeDataSource` to disconnect from the previous data source and connect to the
|
|
// new one, passing back a stream of data changes which we run through `switchMap` to give
|
|
// us a data stream that emits the latest data from whatever the current `DataSource` is.
|
|
switchMap(([prev, cur]) => this._changeDataSource(prev, cur)),
|
|
// Replay the last emitted data when someone subscribes.
|
|
shareReplay(1));
|
|
/** The differ used to calculate changes to the data. */
|
|
this._differ = null;
|
|
/** Whether the rendered data should be updated during the next ngDoCheck cycle. */
|
|
this._needsUpdate = false;
|
|
this._destroyed = new Subject();
|
|
this.dataStream.subscribe(data => {
|
|
this._data = data;
|
|
this._onRenderedDataChange();
|
|
});
|
|
this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe(range => {
|
|
this._renderedRange = range;
|
|
ngZone.run(() => this.viewChange.next(this._renderedRange));
|
|
this._onRenderedDataChange();
|
|
});
|
|
this._viewport.attach(this);
|
|
}
|
|
/** The DataSource to display. */
|
|
get cdkVirtualForOf() {
|
|
return this._cdkVirtualForOf;
|
|
}
|
|
set cdkVirtualForOf(value) {
|
|
this._cdkVirtualForOf = value;
|
|
if (isDataSource(value)) {
|
|
this._dataSourceChanges.next(value);
|
|
}
|
|
else {
|
|
// If value is an an NgIterable, convert it to an array.
|
|
this._dataSourceChanges.next(new ArrayDataSource(isObservable(value) ? value : Array.from(value || [])));
|
|
}
|
|
}
|
|
/**
|
|
* The `TrackByFunction` to use for tracking changes. The `TrackByFunction` takes the index and
|
|
* the item and produces a value to be used as the item's identity when tracking changes.
|
|
*/
|
|
get cdkVirtualForTrackBy() {
|
|
return this._cdkVirtualForTrackBy;
|
|
}
|
|
set cdkVirtualForTrackBy(fn) {
|
|
this._needsUpdate = true;
|
|
this._cdkVirtualForTrackBy = fn ?
|
|
(index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item) :
|
|
undefined;
|
|
}
|
|
/** The template used to stamp out new elements. */
|
|
set cdkVirtualForTemplate(value) {
|
|
if (value) {
|
|
this._needsUpdate = true;
|
|
this._template = value;
|
|
}
|
|
}
|
|
/**
|
|
* The size of the cache used to store templates that are not being used for re-use later.
|
|
* Setting the cache size to `0` will disable caching. Defaults to 20 templates.
|
|
*/
|
|
get cdkVirtualForTemplateCacheSize() {
|
|
return this._viewRepeater.viewCacheSize;
|
|
}
|
|
set cdkVirtualForTemplateCacheSize(size) {
|
|
this._viewRepeater.viewCacheSize = coerceNumberProperty(size);
|
|
}
|
|
/**
|
|
* Measures the combined size (width for horizontal orientation, height for vertical) of all items
|
|
* in the specified range. Throws an error if the range includes items that are not currently
|
|
* rendered.
|
|
*/
|
|
measureRangeSize(range, orientation) {
|
|
if (range.start >= range.end) {
|
|
return 0;
|
|
}
|
|
if ((range.start < this._renderedRange.start || range.end > this._renderedRange.end) &&
|
|
(typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
throw Error(`Error: attempted to measure an item that isn't rendered.`);
|
|
}
|
|
// The index into the list of rendered views for the first item in the range.
|
|
const renderedStartIndex = range.start - this._renderedRange.start;
|
|
// The length of the range we're measuring.
|
|
const rangeLen = range.end - range.start;
|
|
// Loop over all the views, find the first and land node and compute the size by subtracting
|
|
// the top of the first node from the bottom of the last one.
|
|
let firstNode;
|
|
let lastNode;
|
|
// Find the first node by starting from the beginning and going forwards.
|
|
for (let i = 0; i < rangeLen; i++) {
|
|
const view = this._viewContainerRef.get(i + renderedStartIndex);
|
|
if (view && view.rootNodes.length) {
|
|
firstNode = lastNode = view.rootNodes[0];
|
|
break;
|
|
}
|
|
}
|
|
// Find the last node by starting from the end and going backwards.
|
|
for (let i = rangeLen - 1; i > -1; i--) {
|
|
const view = this._viewContainerRef.get(i + renderedStartIndex);
|
|
if (view && view.rootNodes.length) {
|
|
lastNode = view.rootNodes[view.rootNodes.length - 1];
|
|
break;
|
|
}
|
|
}
|
|
return firstNode && lastNode ?
|
|
getOffset(orientation, 'end', lastNode) - getOffset(orientation, 'start', firstNode) : 0;
|
|
}
|
|
ngDoCheck() {
|
|
if (this._differ && this._needsUpdate) {
|
|
// TODO(mmalerba): We should differentiate needs update due to scrolling and a new portion of
|
|
// this list being rendered (can use simpler algorithm) vs needs update due to data actually
|
|
// changing (need to do this diff).
|
|
const changes = this._differ.diff(this._renderedItems);
|
|
if (!changes) {
|
|
this._updateContext();
|
|
}
|
|
else {
|
|
this._applyChanges(changes);
|
|
}
|
|
this._needsUpdate = false;
|
|
}
|
|
}
|
|
ngOnDestroy() {
|
|
this._viewport.detach();
|
|
this._dataSourceChanges.next(undefined);
|
|
this._dataSourceChanges.complete();
|
|
this.viewChange.complete();
|
|
this._destroyed.next();
|
|
this._destroyed.complete();
|
|
this._viewRepeater.detach();
|
|
}
|
|
/** React to scroll state changes in the viewport. */
|
|
_onRenderedDataChange() {
|
|
if (!this._renderedRange) {
|
|
return;
|
|
}
|
|
this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end);
|
|
if (!this._differ) {
|
|
// Use a wrapper function for the `trackBy` so any new values are
|
|
// picked up automatically without having to recreate the differ.
|
|
this._differ = this._differs.find(this._renderedItems).create((index, item) => {
|
|
return this.cdkVirtualForTrackBy ? this.cdkVirtualForTrackBy(index, item) : item;
|
|
});
|
|
}
|
|
this._needsUpdate = true;
|
|
}
|
|
/** Swap out one `DataSource` for another. */
|
|
_changeDataSource(oldDs, newDs) {
|
|
if (oldDs) {
|
|
oldDs.disconnect(this);
|
|
}
|
|
this._needsUpdate = true;
|
|
return newDs ? newDs.connect(this) : observableOf();
|
|
}
|
|
/** Update the `CdkVirtualForOfContext` for all views. */
|
|
_updateContext() {
|
|
const count = this._data.length;
|
|
let i = this._viewContainerRef.length;
|
|
while (i--) {
|
|
const view = this._viewContainerRef.get(i);
|
|
view.context.index = this._renderedRange.start + i;
|
|
view.context.count = count;
|
|
this._updateComputedContextProperties(view.context);
|
|
view.detectChanges();
|
|
}
|
|
}
|
|
/** Apply changes to the DOM. */
|
|
_applyChanges(changes) {
|
|
this._viewRepeater.applyChanges(changes, this._viewContainerRef, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record, currentIndex), (record) => record.item);
|
|
// Update $implicit for any items that had an identity change.
|
|
changes.forEachIdentityChange((record) => {
|
|
const view = this._viewContainerRef.get(record.currentIndex);
|
|
view.context.$implicit = record.item;
|
|
});
|
|
// Update the context variables on all items.
|
|
const count = this._data.length;
|
|
let i = this._viewContainerRef.length;
|
|
while (i--) {
|
|
const view = this._viewContainerRef.get(i);
|
|
view.context.index = this._renderedRange.start + i;
|
|
view.context.count = count;
|
|
this._updateComputedContextProperties(view.context);
|
|
}
|
|
}
|
|
/** Update the computed properties on the `CdkVirtualForOfContext`. */
|
|
_updateComputedContextProperties(context) {
|
|
context.first = context.index === 0;
|
|
context.last = context.index === context.count - 1;
|
|
context.even = context.index % 2 === 0;
|
|
context.odd = !context.even;
|
|
}
|
|
_getEmbeddedViewArgs(record, index) {
|
|
// Note that it's important that we insert the item directly at the proper index,
|
|
// rather than inserting it and the moving it in place, because if there's a directive
|
|
// on the same node that injects the `ViewContainerRef`, Angular will insert another
|
|
// comment node which can throw off the move when it's being repeated for all items.
|
|
return {
|
|
templateRef: this._template,
|
|
context: {
|
|
$implicit: record.item,
|
|
// It's guaranteed that the iterable is not "undefined" or "null" because we only
|
|
// generate views for elements if the "cdkVirtualForOf" iterable has elements.
|
|
cdkVirtualForOf: this._cdkVirtualForOf,
|
|
index: -1,
|
|
count: -1,
|
|
first: false,
|
|
last: false,
|
|
odd: false,
|
|
even: false
|
|
},
|
|
index,
|
|
};
|
|
}
|
|
}
|
|
CdkVirtualForOf.ɵfac = function CdkVirtualForOf_Factory(t) { return new (t || CdkVirtualForOf)(ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ViewContainerRef), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.TemplateRef), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.IterableDiffers), ɵngcc0.ɵɵdirectiveInject(_VIEW_REPEATER_STRATEGY), ɵngcc0.ɵɵdirectiveInject(ɵngcc1.CdkVirtualScrollViewport, 4), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.NgZone)); };
|
|
CdkVirtualForOf.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: CdkVirtualForOf, selectors: [["", "cdkVirtualFor", "", "cdkVirtualForOf", ""]], inputs: { cdkVirtualForOf: "cdkVirtualForOf", cdkVirtualForTrackBy: "cdkVirtualForTrackBy", cdkVirtualForTemplate: "cdkVirtualForTemplate", cdkVirtualForTemplateCacheSize: "cdkVirtualForTemplateCacheSize" }, features: [ɵngcc0.ɵɵProvidersFeature([
|
|
{ provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy },
|
|
])] });
|
|
CdkVirtualForOf.ctorParameters = () => [
|
|
{ type: ViewContainerRef },
|
|
{ type: TemplateRef },
|
|
{ type: IterableDiffers },
|
|
{ type: _RecycleViewRepeaterStrategy, decorators: [{ type: Inject, args: [_VIEW_REPEATER_STRATEGY,] }] },
|
|
{ type: CdkVirtualScrollViewport, decorators: [{ type: SkipSelf }] },
|
|
{ type: NgZone }
|
|
];
|
|
CdkVirtualForOf.propDecorators = {
|
|
cdkVirtualForOf: [{ type: Input }],
|
|
cdkVirtualForTrackBy: [{ type: Input }],
|
|
cdkVirtualForTemplate: [{ type: Input }],
|
|
cdkVirtualForTemplateCacheSize: [{ type: Input }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(CdkVirtualForOf, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: '[cdkVirtualFor][cdkVirtualForOf]',
|
|
providers: [
|
|
{ provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy },
|
|
]
|
|
}]
|
|
}], function () { return [{ type: ɵngcc0.ViewContainerRef }, { type: ɵngcc0.TemplateRef }, { type: ɵngcc0.IterableDiffers }, { type: ɵngcc2._RecycleViewRepeaterStrategy, decorators: [{
|
|
type: Inject,
|
|
args: [_VIEW_REPEATER_STRATEGY]
|
|
}] }, { type: ɵngcc1.CdkVirtualScrollViewport, decorators: [{
|
|
type: SkipSelf
|
|
}] }, { type: ɵngcc0.NgZone }]; }, { cdkVirtualForOf: [{
|
|
type: Input
|
|
}], cdkVirtualForTrackBy: [{
|
|
type: Input
|
|
}], cdkVirtualForTemplate: [{
|
|
type: Input
|
|
}], cdkVirtualForTemplateCacheSize: [{
|
|
type: Input
|
|
}] }); })();
|
|
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1mb3Itb2YuanMiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jZGsvc2Nyb2xsaW5nL3ZpcnR1YWwtZm9yLW9mLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFFSCxPQUFPLEVBQ0wsZUFBZSxFQUlmLFlBQVksRUFDWiw0QkFBNEIsRUFDNUIsdUJBQXVCLEdBRXhCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUNMLFNBQVMsRUFHVCxNQUFNLEVBQ04sS0FBSyxFQUlMLGVBQWUsRUFFZixNQUFNLEVBRU4sUUFBUSxFQUNSLFdBQVcsRUFFWCxnQkFBZ0IsR0FDakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLG9CQUFvQixFQUFjLE1BQU0sdUJBQXVCLENBQUM7QUFDeEUsT0FBTyxFQUFhLE9BQU8sRUFBRSxFQUFFLElBQUksWUFBWSxFQUFFLFlBQVksRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUMzRSxPQUFPLEVBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBRXRGLE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBd0JuRSx5RUFBeUU7Ozs7QUFDekUsU0FBUyxTQUFTLENBQUMsV0FBc0MsRUFBRSxTQUEwQixFQUFFLElBQVU7QUFDakcsSUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFlLENBQUM7QUFDN0IsSUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLHFCQUFxQixFQUFFO0FBQ2pDLFFBQUksT0FBTyxDQUFDLENBQUM7QUFDYixLQUFHO0FBQ0gsSUFBRSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMscUJBQXFCLEVBQUUsQ0FBQztBQUMxQyxJQUNFLElBQUksV0FBVyxLQUFLLFlBQVksRUFBRTtBQUNwQyxRQUFJLE9BQU8sU0FBUyxLQUFL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Qix1QkEwSnpCLFFBQVE7QUFBTyxZQXJLcEIsTUFBTTtBQUNQO0FBQUc7QUFFVSw4QkFrRVgsS0FBSztBQUNOLG1DQW9CQyxLQUFLO0FBQ04sb0NBWUMsS0FBSztBQUNOLDZDQVdDLEtBQUs7QUFDUDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztvQkFBRTtBQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7XG4gIEFycmF5RGF0YVNvdXJjZSxcbiAgQ29sbGVjdGlvblZpZXdlcixcbiAgRGF0YVNvdXJjZSxcbiAgTGlzdFJhbmdlLFxuICBpc0RhdGFTb3VyY2UsXG4gIF9SZWN5Y2xlVmlld1JlcGVhdGVyU3RyYXRlZ3ksXG4gIF9WSUVXX1JFUEVBVEVSX1NUUkFURUdZLFxuICBfVmlld1JlcGVhdGVySXRlbUluc2VydEFyZ3MsXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQge1xuICBEaXJlY3RpdmUsXG4gIERvQ2hlY2ssXG4gIEVtYmVkZGVkVmlld1JlZixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgSXRlcmFibGVDaGFuZ2VSZWNvcmQsXG4gIEl0ZXJhYmxlQ2hhbmdlcyxcbiAgSXRlcmFibGVEaWZmZXIsXG4gIEl0ZXJhYmxlRGlmZmVycyxcbiAgTmdJdGVyYWJsZSxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIFNraXBTZWxmLFxuICBUZW1wbGF0ZVJlZixcbiAgVHJhY2tCeUZ1bmN0aW9uLFxuICBWaWV3Q29udGFpbmVyUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Y29lcmNlTnVtYmVyUHJvcGVydHksIE51bWJlcklucHV0fSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBTdWJqZWN0LCBvZiBhcyBvYnNlcnZhYmxlT2YsIGlzT2JzZXJ2YWJsZX0gZnJvbSAncnhqcyc7XG5pbXBvcnQge3BhaXJ3aXNlLCBzaGFyZVJlcGxheSwgc3RhcnRXaXRoLCBzd2l0Y2hNYXAsIHRha2VVbnRpbH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtDZGtWaXJ0dWFsU2Nyb2xsUmVwZWF0ZXJ9IGZyb20gJy4vdmlydHVhbC1zY3JvbGwtcmVwZWF0ZXInO1xuaW1wb3J0IHtDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnR9IGZyb20gJy4vdmlydHVhbC1zY3JvbGwtdmlld3BvcnQnO1xuXG5cbi8qKiBUaGUgY29udGV4dCBmb3IgYW4gaXRlbSByZW5kZXJlZCBieSBgQ2RrVmlydHVhbEZvck9mYCAqL1xuZXhwb3J0IHR5cGUgQ2RrVmlydHVhbEZvck9mQ29udGV4dDxUPiA9IHtcbiAgLyoqIFRoZSBpdGVtIHZhbHVlLiAqL1xuICAkaW1wbGljaXQ6IFQ7XG4gIC8qKiBUaGUgRGF0YVNvdXJjZSwgT2JzZXJ2YWJsZSwgb3IgTmdJdGVyYWJsZSB0aGF0IHdhcyBwYXNzZWQgdG8gKmNka1ZpcnR1YWxGb3IuICovXG4gIGNka1ZpcnR1YWxGb3JPZjogRGF0YVNvdXJjZTxUPiB8IE9ic2VydmFibGU8VFtdPiB8IE5nSXRlcmFibGU8VD47XG4gIC8qKiBUaGUgaW5kZXggb2YgdGhlIGl0ZW0gaW4gdGhlIERhdGFTb3VyY2UuICovXG4gIGluZGV4OiBudW1iZXI7XG4gIC8qKiBUaGUgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBEYXRhU291cmNlLiAqL1xuICBjb3VudDogbnVtYmVyO1xuICAvKiogV2hldGhlciB0aGlzIGlzIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBEYXRhU291cmNlLiAqL1xuICBmaXJzdDogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhpcyBpcyB0aGUgbGFzdCBpdGVtIGluIHRoZSBEYXRhU291cmNlLiAqL1xuICBsYXN0OiBib29sZWFuO1xuICAvKiogV2hldGhlciB0aGUgaW5kZXggaXMgZXZlbi4gKi9cbiAgZXZlbjogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhlIGluZGV4IGlzIG9kZC4gKi9cbiAgb2RkOiBib29sZWFuO1xufTtcblxuXG4vKiogSGVscGVyIHRvIGV4dHJhY3QgdGhlIG9mZnNldCBvZiBhIERPTSBOb2RlIGluIGEgY2VydGFpbiBkaXJlY3Rpb24uICovXG5mdW5jdGlvbiBnZXRPZmZzZXQob3JpZW50YXRpb246ICdob3Jpem9udGFsJyB8ICd2ZXJ0aWNhbCcsIGRpcmVjdGlvbjogJ3N0YXJ0JyB8ICdlbmQnLCBub2RlOiBOb2RlKSB7XG4gIGNvbnN0IGVsID0gbm9kZSBhcyBFbGVtZW50O1xuICBpZiAoIWVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICBpZiAob3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgIHJldHVybiBkaXJlY3Rpb24gPT09ICdzdGFydCcgPyByZWN0LmxlZnQgOiByZWN0LnJpZ2h0O1xuICB9XG5cbiAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gJ3N0YXJ0JyA/IHJlY3QudG9wIDogcmVjdC5ib3R0b207XG59XG5cbi8qKlxuICogQSBkaXJlY3RpdmUgc2ltaWxhciB0byBgbmdGb3JPZmAgdG8gYmUgdXNlZCBmb3IgcmVuZGVyaW5nIGRhdGEgaW5zaWRlIGEgdmlydHVhbCBzY3JvbGxpbmdcbiAqIGNvbnRhaW5lci5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2Nka1ZpcnR1YWxGb3JdW2Nka1ZpcnR1YWxGb3JPZl0nLFxuICBwcm92aWRlcnM6IFtcbiAgICB7cHJvdmlkZTogX1ZJRVdfUkVQRUFURVJfU1RSQVRFR1ksIHVzZUNsYXNzOiBfUmVjeWNsZVZpZXdSZXBlYXRlclN0cmF0ZWd5fSxcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBDZGtWaXJ0dWFsRm9yT2Y8VD4gaW1wbGVtZW50c1xuICAgIENka1ZpcnR1YWxTY3JvbGxSZXBlYXRlcjxUPiwgQ29sbGVjdGlvblZpZXdlciwgRG9DaGVjaywgT25EZXN0cm95IHtcbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHJlbmRlcmVkIHZpZXcgb2YgdGhlIGRhdGEgY2hhbmdlcy4gKi9cbiAgcmVhZG9ubHkgdmlld0NoYW5nZSA9IG5ldyBTdWJqZWN0PExpc3RSYW5nZT4oKTtcblxuICAvKiogU3ViamVjdCB0aGF0IGVtaXRzIHdoZW4gYSBuZXcgRGF0YVNvdXJjZSBpbnN0YW5jZSBpcyBnaXZlbi4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfZGF0YVNvdXJjZUNoYW5nZXMgPSBuZXcgU3ViamVjdDxEYXRhU291cmNlPFQ+PigpO1xuXG4gIC8qKiBUaGUgRGF0YVNvdXJjZSB0byBkaXNwbGF5LiAqL1xuICBASW5wdXQoKVxuICBnZXQgY2RrVmlydHVhbEZvck9mKCk6IERhdGFTb3VyY2U8VD4gfCBPYnNlcnZhYmxlPFRbXT4gfCBOZ0l0ZXJhYmxlPFQ+IHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2Nka1ZpcnR1YWxGb3JPZjtcbiAgfVxuICBzZXQgY2RrVmlydHVhbEZvck9mKHZhbHVlOiBEYXRhU291cmNlPFQ+IHwgT2JzZXJ2YWJsZTxUW10+IHwgTmdJdGVyYWJsZTxUPiB8IG51bGwgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9jZGtWaXJ0dWFsRm9yT2YgPSB2YWx1ZTtcbiAgICBpZiAoaXNEYXRhU291cmNlKHZhbHVlKSkge1xuICAgICAgdGhpcy5fZGF0YVNvdXJjZUNoYW5nZXMubmV4dCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHZhbHVlIGlzIGFuIGFuIE5nSXRlcmFibGUsIGNvbnZlcnQgaXQgdG8gYW4gYXJyYXkuXG4gICAgICB0aGlzLl9kYXRhU291cmNlQ2hhbmdlcy5uZXh0KG5ldyBBcnJheURhdGFTb3VyY2U8VD4oXG4gICAgICAgICAgaXNPYnNlcnZhYmxlKHZhbHVlKSA/IHZhbHVlIDogQXJyYXkuZnJvbSh2YWx1ZSB8fCBbXSkpKTtcbiAgICB9XG4gIH1cblxuICBfY2RrVmlydHVhbEZvck9mOiBEYXRhU291cmNlPFQ+IHwgT2JzZXJ2YWJsZTxUW10+IHwgTmdJdGVyYWJsZTxUPiB8IG51bGwgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIFRoZSBgVHJhY2tCeUZ1bmN0aW9uYCB0byB1c2UgZm9yIHRyYWNraW5nIGNoYW5nZXMuIFRoZSBgVHJhY2tCeUZ1bmN0aW9uYCB0YWtlcyB0aGUgaW5kZXggYW5kXG4gICAqIHRoZSBpdGVtIGFuZCBwcm9kdWNlcyBhIHZhbHVlIHRvIGJlIHVzZWQgYXMgdGhlIGl0ZW0ncyBpZGVudGl0eSB3aGVuIHRyYWNraW5nIGNoYW5nZXMuXG4gICAqL1xuICBASW5wdXQoKVxuICBnZXQgY2RrVmlydHVhbEZvclRyYWNrQnkoKTogVHJhY2tCeUZ1bmN0aW9uPFQ+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fY2RrVmlydHVhbEZvclRyYWNrQnk7XG4gIH1cbiAgc2V0IGNka1ZpcnR1YWxGb3JUcmFja0J5KGZuOiBUcmFja0J5RnVuY3Rpb248VD4gfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9uZWVkc1VwZGF0ZSA9IHRydWU7XG4gICAgdGhpcy5fY2RrVmlydHVhbEZvclRyYWNrQnkgPSBmbiA/XG4gICAgICAgIChpbmRleCwgaXRlbSkgPT4gZm4oaW5kZXggKyAodGhpcy5fcmVuZGVyZWRSYW5nZSA/IHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQgOiAwKSwgaXRlbSkgOlxuICAgICAgICB1bmRlZmluZWQ7XG4gIH1cbiAgcHJpdmF0ZSBfY2RrVmlydHVhbEZvclRyYWNrQnk6IFRyYWNrQnlGdW5jdGlvbjxUPiB8IHVuZGVmaW5lZDtcblxuICAvKiogVGhlIHRlbXBsYXRlIHVzZWQgdG8gc3RhbXAgb3V0IG5ldyBlbGVtZW50cy4gKi9cbiAgQElucHV0KClcbiAgc2V0IGNka1ZpcnR1YWxGb3JUZW1wbGF0ZSh2YWx1ZTogVGVtcGxhdGVSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4pIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuX25lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzaXplIG9mIHRoZSBjYWNoZSB1c2VkIHRvIHN0b3JlIHRlbXBsYXRlcyB0aGF0IGFyZSBub3QgYmVpbmcgdXNlZCBmb3IgcmUtdXNlIGxhdGVyLlxuICAgKiBTZXR0aW5nIHRoZSBjYWNoZSBzaXplIHRvIGAwYCB3aWxsIGRpc2FibGUgY2FjaGluZy4gRGVmYXVsdHMgdG8gMjAgdGVtcGxhdGVzLlxuICAgKi9cbiAgQElucHV0KClcbiAgZ2V0IGNka1ZpcnR1YWxGb3JUZW1wbGF0ZUNhY2hlU2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlld1JlcGVhdGVyLnZpZXdDYWNoZVNpemU7XG4gIH1cbiAgc2V0IGNka1ZpcnR1YWxGb3JUZW1wbGF0ZUNhY2hlU2l6ZShzaXplOiBudW1iZXIpIHtcbiAgICB0aGlzLl92aWV3UmVwZWF0ZXIudmlld0NhY2hlU2l6ZSA9IGNvZXJjZU51bWJlclByb3BlcnR5KHNpemUpO1xuICB9XG5cbiAgLyoqIEVtaXRzIHdoZW5ldmVyIHRoZSBkYXRhIGluIHRoZSBjdXJyZW50IERhdGFTb3VyY2UgY2hhbmdlcy4gKi9cbiAgcmVhZG9ubHkgZGF0YVN0cmVhbTogT2JzZXJ2YWJsZTxyZWFkb25seSBUW10+ID0gdGhpcy5fZGF0YVNvdXJjZUNoYW5nZXNcbiAgLnBpcGUoXG4gICAgICAvLyBTdGFydCBvZmYgd2l0aCBudWxsIGBEYXRhU291cmNlYC5cbiAgICAgIHN0YXJ0V2l0aChudWxsKSxcbiAgICAgIC8vIEJ1bmRsZSB1cCB0aGUgcHJldmlvdXMgYW5kIGN1cnJlbnQgZGF0YSBzb3VyY2VzIHNvIHdlIGNhbiB3b3JrIHdpdGggYm90aC5cbiAgICAgIHBhaXJ3aXNlKCksXG4gICAgICAvLyBVc2UgYF9jaGFuZ2VEYXRhU291cmNlYCB0byBkaXNjb25uZWN0IGZyb20gdGhlIHByZXZpb3VzIGRhdGEgc291cmNlIGFuZCBjb25uZWN0IHRvIHRoZVxuICAgICAgLy8gbmV3IG9uZSwgcGFzc2luZyBiYWNrIGEgc3RyZWFtIG9mIGRhdGEgY2hhbmdlcyB3aGljaCB3ZSBydW4gdGhyb3VnaCBgc3dpdGNoTWFwYCB0byBnaXZlXG4gICAgICAvLyB1cyBhIGRhdGEgc3RyZWFtIHRoYXQgZW1pdHMgdGhlIGxhdGVzdCBkYXRhIGZyb20gd2hhdGV2ZXIgdGhlIGN1cnJlbnQgYERhdGFTb3VyY2VgIGlzLlxuICAgICAgc3dpdGNoTWFwKChbcHJldiwgY3VyXSkgPT4gdGhpcy5fY2hhbmdlRGF0YVNvdXJjZShwcmV2LCBjdXIpKSxcbiAgICAgIC8vIFJlcGxheSB0aGUgbGFzdCBlbWl0dGVkIGRhdGEgd2hlbiBzb21lb25lIHN1YnNjcmliZXMuXG4gICAgICBzaGFyZVJlcGxheSgxKSk7XG5cbiAgLyoqIFRoZSBkaWZmZXIgdXNlZCB0byBjYWxjdWxhdGUgY2hhbmdlcyB0byB0aGUgZGF0YS4gKi9cbiAgcHJpdmF0ZSBfZGlmZmVyOiBJdGVyYWJsZURpZmZlcjxUPiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUaGUgbW9zdCByZWNlbnQgZGF0YSBlbWl0dGVkIGZyb20gdGhlIERhdGFTb3VyY2UuICovXG4gIHByaXZhdGUgX2RhdGE6IHJlYWRvbmx5IFRbXTtcblxuICAvKiogVGhlIGN1cnJlbnRseSByZW5kZXJlZCBpdGVtcy4gKi9cbiAgcHJpdmF0ZSBfcmVuZGVyZWRJdGVtczogVFtdO1xuXG4gIC8qKiBUaGUgY3VycmVudGx5IHJlbmRlcmVkIHJhbmdlIG9mIGluZGljZXMuICovXG4gIHByaXZhdGUgX3JlbmRlcmVkUmFuZ2U6IExpc3RSYW5nZTtcblxuICAvKiogV2hldGhlciB0aGUgcmVuZGVyZWQgZGF0YSBzaG91bGQgYmUgdXBkYXRlZCBkdXJpbmcgdGhlIG5leHQgbmdEb0NoZWNrIGN5Y2xlLiAqL1xuICBwcml2YXRlIF9uZWVkc1VwZGF0ZSA9IGZhbHNlO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3llZCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICAvKiogVGhlIHZpZXcgY29udGFpbmVyIHRvIGFkZCBpdGVtcyB0by4gKi9cbiAgICAgIHByaXZhdGUgX3ZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG4gICAgICAvKiogVGhlIHRlbXBsYXRlIHRvIHVzZSB3aGVuIHN0YW1waW5nIG91dCBuZXcgaXRlbXMuICovXG4gICAgICBwcml2YXRlIF90ZW1wbGF0ZTogVGVtcGxhdGVSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4sXG4gICAgICAvKiogVGhlIHNldCBvZiBhdmFpbGFibGUgZGlmZmVycy4gKi9cbiAgICAgIHByaXZhdGUgX2RpZmZlcnM6IEl0ZXJhYmxlRGlmZmVycyxcbiAgICAgIC8qKiBUaGUgc3RyYXRlZ3kgdXNlZCB0byByZW5kZXIgaXRlbXMgaW4gdGhlIHZpcnR1YWwgc2Nyb2xsIHZpZXdwb3J0LiAqL1xuICAgICAgQEluamVjdChfVklFV19SRVBFQVRFUl9TVFJBVEVHWSlcbiAgICAgIHByaXZhdGUgX3ZpZXdSZXBlYXRlcjogX1JlY3ljbGVWaWV3UmVwZWF0ZXJTdHJhdGVneTxULCBULCBDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PixcbiAgICAgIC8qKiBUaGUgdmlydHVhbCBzY3JvbGxpbmcgdmlld3BvcnQgdGhhdCB0aGVzZSBpdGVtcyBhcmUgYmVpbmcgcmVuZGVyZWQgaW4uICovXG4gICAgICBAU2tpcFNlbGYoKSBwcml2YXRlIF92aWV3cG9ydDogQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LFxuICAgICAgbmdab25lOiBOZ1pvbmUpIHtcbiAgICB0aGlzLmRhdGFTdHJlYW0uc3Vic2NyaWJlKGRhdGEgPT4ge1xuICAgICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gICAgICB0aGlzLl9vblJlbmRlcmVkRGF0YUNoYW5nZSgpO1xuICAgIH0pO1xuICAgIHRoaXMuX3ZpZXdwb3J0LnJlbmRlcmVkUmFuZ2VTdHJlYW0ucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSkuc3Vic2NyaWJlKHJhbmdlID0+IHtcbiAgICAgIHRoaXMuX3JlbmRlcmVkUmFuZ2UgPSByYW5nZTtcbiAgICAgIG5nWm9uZS5ydW4oKCkgPT4gdGhpcy52aWV3Q2hhbmdlLm5leHQodGhpcy5fcmVuZGVyZWRSYW5nZSkpO1xuICAgICAgdGhpcy5fb25SZW5kZXJlZERhdGFDaGFuZ2UoKTtcbiAgICB9KTtcbiAgICB0aGlzLl92aWV3cG9ydC5hdHRhY2godGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogTWVhc3VyZXMgdGhlIGNvbWJpbmVkIHNpemUgKHdpZHRoIGZvciBob3Jpem9udGFsIG9yaWVudGF0aW9uLCBoZWlnaHQgZm9yIHZlcnRpY2FsKSBvZiBhbGwgaXRlbXNcbiAgICogaW4gdGhlIHNwZWNpZmllZCByYW5nZS4gVGhyb3dzIGFuIGVycm9yIGlmIHRoZSByYW5nZSBpbmNsdWRlcyBpdGVtcyB0aGF0IGFyZSBub3QgY3VycmVudGx5XG4gICAqIHJlbmRlcmVkLlxuICAgKi9cbiAgbWVhc3VyZVJhbmdlU2l6ZShyYW5nZTogTGlzdFJhbmdlLCBvcmllbnRhdGlvbjogJ2hvcml6b250YWwnIHwgJ3ZlcnRpY2FsJyk6IG51bWJlciB7XG4gICAgaWYgKHJhbmdlLnN0YXJ0ID49IHJhbmdlLmVuZCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmICgocmFuZ2Uuc3RhcnQgPCB0aGlzLl9yZW5kZXJlZFJhbmdlLnN0YXJ0IHx8IHJhbmdlLmVuZCA+IHRoaXMuX3JlbmRlcmVkUmFuZ2UuZW5kKSAmJlxuICAgICAgKHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8IG5nRGV2TW9kZSkpIHtcbiAgICAgIHRocm93IEVycm9yKGBFcnJvcjogYXR0ZW1wdGVkIHRvIG1lYXN1cmUgYW4gaXRlbSB0aGF0IGlzbid0IHJlbmRlcmVkLmApO1xuICAgIH1cblxuICAgIC8vIFRoZSBpbmRleCBpbnRvIHRoZSBsaXN0IG9mIHJlbmRlcmVkIHZpZXdzIGZvciB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgcmFuZ2UuXG4gICAgY29uc3QgcmVuZGVyZWRTdGFydEluZGV4ID0gcmFuZ2Uuc3RhcnQgLSB0aGlzLl9yZW5kZXJlZFJhbmdlLnN0YXJ0O1xuICAgIC8vIFRoZSBsZW5ndGggb2YgdGhlIHJhbmdlIHdlJ3JlIG1lYXN1cmluZy5cbiAgICBjb25zdCByYW5nZUxlbiA9IHJhbmdlLmVuZCAtIHJhbmdlLnN0YXJ0O1xuXG4gICAgLy8gTG9vcCBvdmVyIGFsbCB0aGUgdmlld3MsIGZpbmQgdGhlIGZpcnN0IGFuZCBsYW5kIG5vZGUgYW5kIGNvbXB1dGUgdGhlIHNpemUgYnkgc3VidHJhY3RpbmdcbiAgICAvLyB0aGUgdG9wIG9mIHRoZSBmaXJzdCBub2RlIGZyb20gdGhlIGJvdHRvbSBvZiB0aGUgbGFzdCBvbmUuXG4gICAgbGV0IGZpcnN0Tm9kZTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgbGV0IGxhc3ROb2RlOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZDtcblxuICAgIC8vIEZpbmQgdGhlIGZpcnN0IG5vZGUgYnkgc3RhcnRpbmcgZnJvbSB0aGUgYmVnaW5uaW5nIGFuZCBnb2luZyBmb3J3YXJkcy5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmdlTGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLl92aWV3Q29udGFpbmVyUmVmLmdldChpICsgcmVuZGVyZWRTdGFydEluZGV4KSBhc1xuICAgICAgICAgIEVtYmVkZGVkVmlld1JlZjxDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PiB8IG51bGw7XG4gICAgICBpZiAodmlldyAmJiB2aWV3LnJvb3ROb2Rlcy5sZW5ndGgpIHtcbiAgICAgICAgZmlyc3ROb2RlID0gbGFzdE5vZGUgPSB2aWV3LnJvb3ROb2Rlc1swXTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmluZCB0aGUgbGFzdCBub2RlIGJ5IHN0YXJ0aW5nIGZyb20gdGhlIGVuZCBhbmQgZ29pbmcgYmFja3dhcmRzLlxuICAgIGZvciAobGV0IGkgPSByYW5nZUxlbiAtIDE7IGkgPiAtMTsgaS0tKSB7XG4gICAgICBjb25zdCB2aWV3ID0gdGhpcy5fdmlld0NvbnRhaW5lclJlZi5nZXQoaSArIHJlbmRlcmVkU3RhcnRJbmRleCkgYXNcbiAgICAgICAgICBFbWJlZGRlZFZpZXdSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4gfCBudWxsO1xuICAgICAgaWYgKHZpZXcgJiYgdmlldy5yb290Tm9kZXMubGVuZ3RoKSB7XG4gICAgICAgIGxhc3ROb2RlID0gdmlldy5yb290Tm9kZXNbdmlldy5yb290Tm9kZXMubGVuZ3RoIC0gMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaXJzdE5vZGUgJiYgbGFzdE5vZGUgP1xuICAgICAgICBnZXRPZmZzZXQob3JpZW50YXRpb24sICdlbmQnLCBsYXN0Tm9kZSkgLSBnZXRPZmZzZXQob3JpZW50YXRpb24sICdzdGFydCcsIGZpcnN0Tm9kZSkgOiAwO1xuICB9XG5cbiAgbmdEb0NoZWNrKCkge1xuICAgIGlmICh0aGlzLl9kaWZmZXIgJiYgdGhpcy5fbmVlZHNVcGRhdGUpIHtcbiAgICAgIC8vIFRPRE8obW1hbGVyYmEpOiBXZSBzaG91bGQgZGlmZmVyZW50aWF0ZSBuZWVkcyB1cGRhdGUgZHVlIHRvIHNjcm9sbGluZyBhbmQgYSBuZXcgcG9ydGlvbiBvZlxuICAgICAgLy8gdGhpcyBsaXN0IGJlaW5nIHJlbmRlcmVkIChjYW4gdXNlIHNpbXBsZXIgYWxnb3JpdGhtKSB2cyBuZWVkcyB1cGRhdGUgZHVlIHRvIGRhdGEgYWN0dWFsbHlcbiAgICAgIC8vIGNoYW5naW5nIChuZWVkIHRvIGRvIHRoaXMgZGlmZikuXG4gICAgICBjb25zdCBjaGFuZ2VzID0gdGhpcy5fZGlmZmVyLmRpZmYodGhpcy5fcmVuZGVyZWRJdGVtcyk7XG4gICAgICBpZiAoIWNoYW5nZXMpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udGV4dCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fYXBwbHlDaGFuZ2VzKGNoYW5nZXMpO1xuICAgICAgfVxuICAgICAgdGhpcy5fbmVlZHNVcGRhdGUgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl92aWV3cG9ydC5kZXRhY2goKTtcblxuICAgIHRoaXMuX2RhdGFTb3VyY2VDaGFuZ2VzLm5leHQodW5kZWZpbmVkISk7XG4gICAgdGhpcy5fZGF0YVNvdXJjZUNoYW5nZXMuY29tcGxldGUoKTtcbiAgICB0aGlzLnZpZXdDaGFuZ2UuY29tcGxldGUoKTtcblxuICAgIHRoaXMuX2Rlc3Ryb3llZC5uZXh0KCk7XG4gICAgdGhpcy5fZGVzdHJveWVkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5fdmlld1JlcGVhdGVyLmRldGFjaCgpO1xuICB9XG5cbiAgLyoqIFJlYWN0IHRvIHNjcm9sbCBzdGF0ZSBjaGFuZ2VzIGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBfb25SZW5kZXJlZERhdGFDaGFuZ2UoKSB7XG4gICAgaWYgKCF0aGlzLl9yZW5kZXJlZFJhbmdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX3JlbmRlcmVkSXRlbXMgPSB0aGlzLl9kYXRhLnNsaWNlKHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQsIHRoaXMuX3JlbmRlcmVkUmFuZ2UuZW5kKTtcbiAgICBpZiAoIXRoaXMuX2RpZmZlcikge1xuICAgICAgLy8gVXNlIGEgd3JhcHBlciBmdW5jdGlvbiBmb3IgdGhlIGB0cmFja0J5YCBzbyBhbnkgbmV3IHZhbHVlcyBhcmVcbiAgICAgIC8vIHBpY2tlZCB1cCBhdXRvbWF0aWNhbGx5IHdpdGhvdXQgaGF2aW5nIHRvIHJlY3JlYXRlIHRoZSBkaWZmZXIuXG4gICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodGhpcy5fcmVuZGVyZWRJdGVtcykuY3JlYXRlKChpbmRleCwgaXRlbSkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jZGtWaXJ0dWFsRm9yVHJhY2tCeSA/IHRoaXMuY2RrVmlydHVhbEZvclRyYWNrQnkoaW5kZXgsIGl0ZW0pIDogaXRlbTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLl9uZWVkc1VwZGF0ZSA9IHRydWU7XG4gIH1cblxuICAvKiogU3dhcCBvdXQgb25lIGBEYXRhU291cmNlYCBmb3IgYW5vdGhlci4gKi9cbiAgcHJpdmF0ZSBfY2hhbmdlRGF0YVNvdXJjZShvbGREczogRGF0YVNvdXJjZTxUPiB8IG51bGwsIG5ld0RzOiBEYXRhU291cmNlPFQ+IHwgbnVsbCk6XG4gICAgICBPYnNlcnZhYmxlPHJlYWRvbmx5IFRbXT4ge1xuXG4gICAgaWYgKG9sZERzKSB7XG4gICAgICBvbGREcy5kaXNjb25uZWN0KHRoaXMpO1xuICAgIH1cblxuICAgIHRoaXMuX25lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgICByZXR1cm4gbmV3RHMgPyBuZXdEcy5jb25uZWN0KHRoaXMpIDogb2JzZXJ2YWJsZU9mKCk7XG4gIH1cblxuICAvKiogVXBkYXRlIHRoZSBgQ2RrVmlydHVhbEZvck9mQ29udGV4dGAgZm9yIGFsbCB2aWV3cy4gKi9cbiAgcHJpdmF0ZSBfdXBkYXRlQ29udGV4dCgpIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX2RhdGEubGVuZ3RoO1xuICAgIGxldCBpID0gdGhpcy5fdmlld0NvbnRhaW5lclJlZi5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgY29uc3QgdmlldyA9IHRoaXMuX3ZpZXdDb250YWluZXJSZWYuZ2V0KGkpIGFzIEVtYmVkZGVkVmlld1JlZjxDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PjtcbiAgICAgIHZpZXcuY29udGV4dC5pbmRleCA9IHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQgKyBpO1xuICAgICAgdmlldy5jb250ZXh0LmNvdW50ID0gY291bnQ7XG4gICAgICB0aGlzLl91cGRhdGVDb21wdXRlZENvbnRleHRQcm9wZXJ0aWVzKHZpZXcuY29udGV4dCk7XG4gICAgICB2aWV3LmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQXBwbHkgY2hhbmdlcyB0byB0aGUgRE9NLiAqL1xuICBwcml2YXRlIF9hcHBseUNoYW5nZXMoY2hhbmdlczogSXRlcmFibGVDaGFuZ2VzPFQ+KSB7XG4gICAgdGhpcy5fdmlld1JlcGVhdGVyLmFwcGx5Q2hhbmdlcyhcbiAgICAgICAgY2hhbmdlcyxcbiAgICAgICAgdGhpcy5fdmlld0NvbnRhaW5lclJlZixcbiAgICAgICAgKHJlY29yZDogSXRlcmFibGVDaGFuZ2VSZWNvcmQ8VD4sXG4gICAgICAgICBfYWRqdXN0ZWRQcmV2aW91c0luZGV4OiBudW1iZXIgfCBudWxsLFxuICAgICAgICAgY3VycmVudEluZGV4OiBudW1iZXIgfCBudWxsKSA9PiB0aGlzLl9nZXRFbWJlZGRlZFZpZXdBcmdzKHJlY29yZCwgY3VycmVudEluZGV4ISksXG4gICAgICAgIChyZWNvcmQpID0+IHJlY29yZC5pdGVtKTtcblxuICAgIC8vIFVwZGF0ZSAkaW1wbGljaXQgZm9yIGFueSBpdGVtcyB0aGF0IGhhZCBhbiBpZGVudGl0eSBjaGFuZ2UuXG4gICAgY2hhbmdlcy5mb3JFYWNoSWRlbnRpdHlDaGFuZ2UoKHJlY29yZDogSXRlcmFibGVDaGFuZ2VSZWNvcmQ8VD4pID0+IHtcbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLl92aWV3Q29udGFpbmVyUmVmLmdldChyZWNvcmQuY3VycmVudEluZGV4ISkgYXNcbiAgICAgICAgICBFbWJlZGRlZFZpZXdSZWY8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj47XG4gICAgICB2aWV3LmNvbnRleHQuJGltcGxpY2l0ID0gcmVjb3JkLml0ZW07XG4gICAgfSk7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGNvbnRleHQgdmFyaWFibGVzIG9uIGFsbCBpdGVtcy5cbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX2RhdGEubGVuZ3RoO1xuICAgIGxldCBpID0gdGhpcy5fdmlld0NvbnRhaW5lclJlZi5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgY29uc3QgdmlldyA9IHRoaXMuX3ZpZXdDb250YWluZXJSZWYuZ2V0KGkpIGFzIEVtYmVkZGVkVmlld1JlZjxDZGtWaXJ0dWFsRm9yT2ZDb250ZXh0PFQ+PjtcbiAgICAgIHZpZXcuY29udGV4dC5pbmRleCA9IHRoaXMuX3JlbmRlcmVkUmFuZ2Uuc3RhcnQgKyBpO1xuICAgICAgdmlldy5jb250ZXh0LmNvdW50ID0gY291bnQ7XG4gICAgICB0aGlzLl91cGRhdGVDb21wdXRlZENvbnRleHRQcm9wZXJ0aWVzKHZpZXcuY29udGV4dCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFVwZGF0ZSB0aGUgY29tcHV0ZWQgcHJvcGVydGllcyBvbiB0aGUgYENka1ZpcnR1YWxGb3JPZkNvbnRleHRgLiAqL1xuICBwcml2YXRlIF91cGRhdGVDb21wdXRlZENvbnRleHRQcm9wZXJ0aWVzKGNvbnRleHQ6IENka1ZpcnR1YWxGb3JPZkNvbnRleHQ8YW55Pikge1xuICAgIGNvbnRleHQuZmlyc3QgPSBjb250ZXh0LmluZGV4ID09PSAwO1xuICAgIGNvbnRleHQubGFzdCA9IGNvbnRleHQuaW5kZXggPT09IGNvbnRleHQuY291bnQgLSAxO1xuICAgIGNvbnRleHQuZXZlbiA9IGNvbnRleHQuaW5kZXggJSAyID09PSAwO1xuICAgIGNvbnRleHQub2RkID0gIWNvbnRleHQuZXZlbjtcbiAgfVxuXG4gIHByaXZhdGUgX2dldEVtYmVkZGVkVmlld0FyZ3MocmVjb3JkOiBJdGVyYWJsZUNoYW5nZVJlY29yZDxUPiwgaW5kZXg6IG51bWJlcik6XG4gICAgICBfVmlld1JlcGVhdGVySXRlbUluc2VydEFyZ3M8Q2RrVmlydHVhbEZvck9mQ29udGV4dDxUPj4ge1xuICAgIC8vIE5vdGUgdGhhdCBpdCdzIGltcG9ydGFudCB0aGF0IHdlIGluc2VydCB0aGUgaXRlbSBkaXJlY3RseSBhdCB0aGUgcHJvcGVyIGluZGV4LFxuICAgIC8vIHJhdGhlciB0aGFuIGluc2VydGluZyBpdCBhbmQgdGhlIG1vdmluZyBpdCBpbiBwbGFjZSwgYmVjYXVzZSBpZiB0aGVyZSdzIGEgZGlyZWN0aXZlXG4gICAgLy8gb24gdGhlIHNhbWUgbm9kZSB0aGF0IGluamVjdHMgdGhlIGBWaWV3Q29udGFpbmVyUmVmYCwgQW5ndWxhciB3aWxsIGluc2VydCBhbm90aGVyXG4gICAgLy8gY29tbWVudCBub2RlIHdoaWNoIGNhbiB0aHJvdyBvZmYgdGhlIG1vdmUgd2hlbiBpdCdzIGJlaW5nIHJlcGVhdGVkIGZvciBhbGwgaXRlbXMuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRlbXBsYXRlUmVmOiB0aGlzLl90ZW1wbGF0ZSxcbiAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgJGltcGxpY2l0OiByZWNvcmQuaXRlbSxcbiAgICAgICAgLy8gSXQncyBndWFyYW50ZWVkIHRoYXQgdGhlIGl0ZXJhYmxlIGlzIG5vdCBcInVuZGVmaW5lZFwiIG9yIFwibnVsbFwiIGJlY2F1c2Ugd2Ugb25seVxuICAgICAgICAvLyBnZW5lcmF0ZSB2aWV3cyBmb3IgZWxlbWVudHMgaWYgdGhlIFwiY2RrVmlydHVhbEZvck9mXCIgaXRlcmFibGUgaGFzIGVsZW1lbnRzLlxuICAgICAgICBjZGtWaXJ0dWFsRm9yT2Y6IHRoaXMuX2Nka1ZpcnR1YWxGb3JPZiEsXG4gICAgICAgIGluZGV4OiAtMSxcbiAgICAgICAgY291bnQ6IC0xLFxuICAgICAgICBmaXJzdDogZmFsc2UsXG4gICAgICAgIGxhc3Q6IGZhbHNlLFxuICAgICAgICBvZGQ6IGZhbHNlLFxuICAgICAgICBldmVuOiBmYWxzZVxuICAgICAgfSxcbiAgICAgIGluZGV4LFxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfY2RrVmlydHVhbEZvclRlbXBsYXRlQ2FjaGVTaXplOiBOdW1iZXJJbnB1dDtcbn1cbiJdfQ==
|