UNPKG

@nativescript-community/ui-collectionview

Version:

Allows you to easily add a collection view (grid list view) to your projects. Supports vertical and horizontal modes, templating, and more.

417 lines 53 kB
import { ChangeDetectionStrategy, Component, ContentChild, Directive, ElementRef, EventEmitter, Host, HostListener, Inject, Input, IterableDiffers, NgZone, Output, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core'; import { CLog, CLogTypes, CollectionView, ListViewViewTypes } from '@nativescript-community/ui-collectionview'; import { DetachedLoader, NativeScriptRendererFactory, extractSingleViewRecursive, isListLikeIterable, registerElement } from '@nativescript/angular'; import { LayoutBase, ObservableArray, Trace } from '@nativescript/core'; import * as i0 from "@angular/core"; import * as i1 from "@nativescript/angular"; const _c0 = ["loader"]; registerElement('CollectionView', () => CollectionView); const NG_VIEW = '_ngViewRef'; export class ItemContext { $implicit; item; index; even; odd; constructor($implicit, item, index, even, odd) { this.$implicit = $implicit; this.item = item; this.index = index; this.even = even; this.odd = odd; } } export class CollectionViewComponent { _elementRef; _iterableDiffers; _renderer; _ngZone; get nativeElement() { return this._collectionView; } get listView() { return this._collectionView; } loader; setupItemView = new EventEmitter(); itemTemplateQuery; autoReuseViews = false; detachedLoaderFactory() { const ref = this.loader.createComponent(DetachedLoader, { index: 0 }); this.loader.detach(0); this._loaders.push(ref); return ref; } get itemTemplate() { return this._itemTemplate; } set itemTemplate(value) { this._itemTemplate = value; this._collectionView.refresh(); } get items() { return this._items; } set items(value) { this._items = value; let needDiffer = true; if (value instanceof ObservableArray) { needDiffer = false; } if (needDiffer && !this._differ && isListLikeIterable(value)) { this._differ = this._iterableDiffers.find(this._items).create((_index, item) => item); } this._collectionView.items = this._items; } _collectionView; _items; _differ; _itemTemplate; _templateMap; _loaders; constructor(_elementRef, _iterableDiffers, _renderer, _ngZone) { this._elementRef = _elementRef; this._iterableDiffers = _iterableDiffers; this._renderer = _renderer; this._ngZone = _ngZone; this._collectionView = _elementRef.nativeElement; this._collectionView.on(CollectionView.itemLoadingEvent, this.onItemLoading, this); this._collectionView.itemViewLoader = this.itemViewLoader; this._loaders = []; } itemViewLoader = (viewType) => this._ngZone.run(() => { switch (viewType) { case ListViewViewTypes.ItemView: if (this._itemTemplate && this.loader) { const typedView = this.getOrCreate(this._itemTemplate); return typedView; } break; } return null; }); ngAfterContentInit() { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'CollectionView.ngAfterContentInit()'); } this.setItemTemplates(); } ngOnDestroy() { this._collectionView.off(CollectionView.itemLoadingEvent, this.onItemLoading, this); this._collectionView = null; this._loaders.forEach((l) => l.destroy()); this._loaders = null; this.viewToLoader = null; this.viewToTemplate = null; this.viewPool = null; this._items = null; this._differ = null; this._itemTemplate = null; if (this._templateMap) { this._templateMap.clear(); } this._templateMap = null; } ngDoCheck() { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'ngDoCheck() - execute differ? ' + this._differ); } if (this._differ) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'ngDoCheck() - execute differ'); } const changes = this._differ.diff(this._items); if (changes) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'ngDoCheck() - refresh'); } this.refresh(); } } } registerTemplate(key, template) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'registerTemplate for key: ' + key); } if (!this._templateMap) { this._templateMap = new Map(); } const keyedTemplate = { key, createView: this.getItemTemplateViewFactory(template) }; this._templateMap.set(key, keyedTemplate); } onItemLoading(args) { if (!args.view && !this.itemTemplate) { return; } if (!this.items) return; const index = args.index; const items = args.object.items; const currentItem = typeof items.getItem === 'function' ? items.getItem(index) : items[index]; let viewRef; if (Trace.isEnabled()) { CLog(CLogTypes.info, `onItemLoading: ${index} - Reusing existing view`); } viewRef = args.view[NG_VIEW]; // Getting angular view from original element (in cases when ProxyViewContainer // is used NativeScript internally wraps it in a StackLayout) if (!viewRef && args.view instanceof LayoutBase && args.view.getChildrenCount() > 0) { viewRef = args.view.getChildAt(0)[NG_VIEW]; } if (!viewRef && Trace.isEnabled()) { if (Trace.isEnabled()) { CLog(CLogTypes.info, `ViewReference not found for item ${index}. View recycling is not working`); } } if (!viewRef) { if (Trace.isEnabled()) { CLog(CLogTypes.info, `onItemLoading: ${index} - Creating view from template`); } viewRef = this.loader.createEmbeddedView(this.itemTemplate, new ItemContext(), 0); args.view = getItemViewRoot(viewRef); args.view[NG_VIEW] = viewRef; } this.setupViewRef(viewRef, currentItem, index); this.detectChangesOnChild(viewRef, index); } onItemRecyclingInternal(args) { if (!args.view) { return; } let ngView = args.view[NG_VIEW]; // Getting angular view from original element (in cases when ProxyViewContainer // is used NativeScript internally wraps it in a StackLayout) if (!ngView && args.view instanceof LayoutBase && args.view.getChildrenCount() > 0) { ngView = args.view.getChildAt(0)[NG_VIEW]; } // console.log('recycling', args.view); if (ngView) { ngView.detach(); } } onItemDisposingInternal(args) { if (!args.view) { return; } let ngView = args.view[NG_VIEW]; // Getting angular view from original element (in cases when ProxyViewContainer // is used NativeScript internally wraps it in a StackLayout) if (!ngView && args.view instanceof LayoutBase && args.view.getChildrenCount() > 0) { ngView = args.view.getChildAt(0)[NG_VIEW]; } if (ngView) { ngView.detach(); this.storeViewRef(ngView); } } setupViewRef(view, data, index) { const context = view.context; context.$implicit = data; context.item = data; context.index = index; context.even = index % 2 === 0; context.odd = !context.even; this.setupItemView.next({ context, data, index, view }); } getItemTemplateViewFactory(template) { return () => { const viewRef = this.loader.createEmbeddedView(template, new ItemContext(), 0); const resultView = getItemViewRoot(viewRef); resultView[NG_VIEW] = viewRef; return resultView; }; } viewPool = new Map(); storeViewRef(viewRef) { const templateRef = this.viewToTemplate.get(viewRef); if (templateRef) { const scrap = this.viewPool.get(templateRef); if (scrap) { if (scrap.scrapHead.size >= scrap.scrapSize) { viewRef.destroy(); this.viewToLoader.get(viewRef)?.destroy(); } else { scrap.scrapHead.add(viewRef); } } } } viewToTemplate = new WeakMap(); viewToLoader = new WeakMap(); getOrCreate(templateRef) { return this._ngZone.run(() => { let viewRef = this.getView(templateRef); if (!viewRef) { const loader = this.detachedLoaderFactory(); // viewRef = this.loader.createEmbeddedView(templateRef, new ItemContext(), 0); viewRef = loader.instance.vc.createEmbeddedView(templateRef, new ItemContext(), 0); this.viewToLoader.set(viewRef, loader); this.viewToTemplate.set(viewRef, templateRef); } viewRef.detach(); const resultView = getItemViewRoot(viewRef); resultView[NG_VIEW] = viewRef; resultView.reusable = this.autoReuseViews; return resultView; }); } getView(templateRef) { const pool = this.getViewPool(templateRef); while (pool.scrapHead.size > 0) { const viewRef = pool.scrapHead.values().next().value; pool.scrapHead.delete(viewRef); if (!viewRef.destroyed) { return viewRef; } } return null; } getViewPool(templateRef) { if (!this.viewPool.has(templateRef)) { this.viewPool.set(templateRef, { scrapSize: this.autoReuseViews ? Infinity : 0, scrapHead: new Set() }); } return this.viewPool.get(templateRef); } setItemTemplates() { // The itemTemplateQuery may be changed after list items are added that contain <template> inside, // so cache and use only the original template to avoid errors. this.itemTemplate = this.itemTemplateQuery; if (this._templateMap) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'Setting templates'); } const templates = []; this._templateMap.forEach((value) => { templates.push(value); }); this._collectionView.itemTemplates = templates; } else { // If the map was not initialized this means that there are no named templates, so we register the default one. this._collectionView.itemTemplate = this.getItemTemplateViewFactory(this.itemTemplate); } } detectChangesOnChild(viewRef, index) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'Manually detect changes in child: ' + index); } viewRef.markForCheck(); viewRef.detectChanges(); } refresh() { if (this._collectionView) { this._collectionView.refresh(); } } static ɵfac = function CollectionViewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CollectionViewComponent)(i0.ɵɵdirectiveInject(ElementRef), i0.ɵɵdirectiveInject(IterableDiffers), i0.ɵɵdirectiveInject(NativeScriptRendererFactory), i0.ɵɵdirectiveInject(NgZone)); }; static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CollectionViewComponent, selectors: [["CollectionView"]], contentQueries: function CollectionViewComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) { i0.ɵɵcontentQuery(dirIndex, TemplateRef, 7, TemplateRef); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.itemTemplateQuery = _t.first); } }, viewQuery: function CollectionViewComponent_Query(rf, ctx) { if (rf & 1) { i0.ɵɵviewQuery(_c0, 7, ViewContainerRef); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.loader = _t.first); } }, hostBindings: function CollectionViewComponent_HostBindings(rf, ctx) { if (rf & 1) { i0.ɵɵlistener("itemLoading", function CollectionViewComponent_itemLoading_HostBindingHandler($event) { return ctx.onItemLoading($event); })("itemRecycling", function CollectionViewComponent_itemRecycling_HostBindingHandler($event) { return ctx.onItemRecyclingInternal($event); })("itemDisposing", function CollectionViewComponent_itemDisposing_HostBindingHandler($event) { return ctx.onItemDisposingInternal($event); }); } }, inputs: { autoReuseViews: "autoReuseViews", itemTemplate: "itemTemplate", items: "items" }, outputs: { setupItemView: "setupItemView" }, decls: 3, vars: 0, consts: [["loader", ""]], template: function CollectionViewComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "DetachedContainer"); i0.ɵɵelement(1, "Placeholder", null, 0); i0.ɵɵelementEnd(); } }, encapsulation: 2, changeDetection: 0 }); } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CollectionViewComponent, [{ type: Component, args: [{ selector: 'CollectionView', template: ` <DetachedContainer> <Placeholder #loader></Placeholder> </DetachedContainer> `, changeDetection: ChangeDetectionStrategy.OnPush }] }], () => [{ type: i0.ElementRef, decorators: [{ type: Inject, args: [ElementRef] }] }, { type: i0.IterableDiffers, decorators: [{ type: Inject, args: [IterableDiffers] }] }, { type: i1.NativeScriptRendererFactory, decorators: [{ type: Inject, args: [NativeScriptRendererFactory] }] }, { type: i0.NgZone, decorators: [{ type: Inject, args: [NgZone] }] }], { loader: [{ type: ViewChild, args: ['loader', { read: ViewContainerRef, static: true }] }], setupItemView: [{ type: Output }], itemTemplateQuery: [{ type: ContentChild, args: [TemplateRef, { read: TemplateRef, static: true }] }], autoReuseViews: [{ type: Input }], itemTemplate: [{ type: Input }], items: [{ type: Input }], onItemLoading: [{ type: HostListener, args: ['itemLoading', ['$event']] }], onItemRecyclingInternal: [{ type: HostListener, args: ['itemRecycling', ['$event']] }], onItemDisposingInternal: [{ type: HostListener, args: ['itemDisposing', ['$event']] }] }); })(); (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CollectionViewComponent, { className: "CollectionViewComponent", filePath: "collectionview-comp.ts", lineNumber: 53 }); })(); export function getItemViewRoot(viewRef, rootLocator = extractSingleViewRecursive) { const rootView = rootLocator(viewRef.rootNodes, 0); return rootView; } export class TemplateKeyDirective { templateRef; collectionView; constructor(templateRef, collectionView) { this.templateRef = templateRef; this.collectionView = collectionView; } set cvTemplateKey(value) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'cvTemplateKey: ' + value); } if (this.collectionView && this.templateRef) { this.collectionView.registerTemplate(value.toLowerCase(), this.templateRef); } } static ɵfac = function TemplateKeyDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TemplateKeyDirective)(i0.ɵɵdirectiveInject(i0.TemplateRef), i0.ɵɵdirectiveInject(CollectionViewComponent, 1)); }; static ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: TemplateKeyDirective, selectors: [["", "cvTemplateKey", ""]], inputs: { cvTemplateKey: "cvTemplateKey" } }); } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TemplateKeyDirective, [{ type: Directive, args: [{ selector: '[cvTemplateKey]' }] }], () => [{ type: i0.TemplateRef }, { type: CollectionViewComponent, decorators: [{ type: Host }] }], { cvTemplateKey: [{ type: Input }] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbnZpZXctY29tcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb2xsZWN0aW9udmlldy9hbmd1bGFyL2NvbGxlY3Rpb252aWV3LWNvbXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVILHVCQUF1QixFQUN2QixTQUFTLEVBRVQsWUFBWSxFQUNaLFNBQVMsRUFFVCxVQUFVLEVBRVYsWUFBWSxFQUNaLElBQUksRUFDSixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFFTCxlQUFlLEVBQ2YsTUFBTSxFQUVOLE1BQU0sRUFDTixXQUFXLEVBQ1gsU0FBUyxFQUNULGdCQUFnQixFQUNuQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQStCLGlCQUFpQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDNUksT0FBTyxFQUFFLGNBQWMsRUFBRSwyQkFBMkIsRUFBRSwwQkFBMEIsRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNySixPQUFPLEVBQWlCLFVBQVUsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFRLE1BQU0sb0JBQW9CLENBQUM7Ozs7QUFFN0YsZUFBZSxDQUFDLGdCQUFnQixFQUFFLEdBQUcsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBRXhELE1BQU0sT0FBTyxHQUFHLFlBQVksQ0FBQztBQUU3QixNQUFNLE9BQU8sV0FBVztJQUNEO0lBQXdCO0lBQW1CO0lBQXVCO0lBQXVCO0lBQTVHLFlBQW1CLFNBQWUsRUFBUyxJQUFVLEVBQVMsS0FBYyxFQUFTLElBQWMsRUFBUyxHQUFhO1FBQXRHLGNBQVMsR0FBVCxTQUFTLENBQU07UUFBUyxTQUFJLEdBQUosSUFBSSxDQUFNO1FBQVMsVUFBSyxHQUFMLEtBQUssQ0FBUztRQUFTLFNBQUksR0FBSixJQUFJLENBQVU7UUFBUyxRQUFHLEdBQUgs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V0FBNkIsRUFBa0IsY0FBdUM7UUFBdEYsZ0JBQVcsR0FBWCxXQUFXLENBQWtCO1FBQWtCLG1CQUFjLEdBQWQsY0FBYyxDQUF5QjtJQUFHLENBQUM7SUFFOUcsSUFDSSxhQUFhLENBQUMsS0FBVTtRQUN4QixJQUFJLEtBQUssQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxDQUFDO1FBQ3BELENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzFDLElBQUksQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNoRixDQUFDO0lBQ0wsQ0FBQzs4R0FYUSxvQkFBb0I7NkRBQXBCLG9CQUFvQjs7aUZBQXBCLG9CQUFvQjtjQURoQyxTQUFTO2VBQUMsRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUU7O3NCQUVjLElBQUk7cUJBR3BELGFBQWE7a0JBRGhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIEFmdGVyQ29udGVudEluaXQsXG4gICAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gICAgQ29tcG9uZW50LFxuICAgIENvbXBvbmVudFJlZixcbiAgICBDb250ZW50Q2hpbGQsXG4gICAgRGlyZWN0aXZlLFxuICAgIERvQ2hlY2ssXG4gICAgRWxlbWVudFJlZixcbiAgICBFbWJlZGRlZFZpZXdSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIEhvc3QsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIEluamVjdCxcbiAgICBJbnB1dCxcbiAgICBJdGVyYWJsZURpZmZlcixcbiAgICBJdGVyYWJsZURpZmZlcnMsXG4gICAgTmdab25lLFxuICAgIE9uRGVzdHJveSxcbiAgICBPdXRwdXQsXG4gICAgVGVtcGxhdGVSZWYsXG4gICAgVmlld0NoaWxkLFxuICAgIFZpZXdDb250YWluZXJSZWZcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDTG9nLCBDTG9nVHlwZXMsIENvbGxlY3Rpb25WaWV3LCBDb2xsZWN0aW9uVmlld0l0ZW1FdmVudERhdGEsIExpc3RWaWV3Vmlld1R5cGVzIH0gZnJvbSAnQG5hdGl2ZXNjcmlwdC1jb21tdW5pdHkvdWktY29sbGVjdGlvbnZpZXcnO1xuaW1wb3J0IHsgRGV0YWNoZWRMb2FkZXIsIE5hdGl2ZVNjcmlwdFJlbmRlcmVyRmFjdG9yeSwgZXh0cmFjdFNpbmdsZVZpZXdSZWN1cnNpdmUsIGlzTGlzdExpa2VJdGVyYWJsZSwgcmVnaXN0ZXJFbGVtZW50IH0gZnJvbSAnQG5hdGl2ZXNjcmlwdC9hbmd1bGFyJztcbmltcG9ydCB7IEtleWVkVGVtcGxhdGUsIExheW91dEJhc2UsIE9ic2VydmFibGVBcnJheSwgVHJhY2UsIFZpZXcgfSBmcm9tICdAbmF0aXZlc2NyaXB0L2NvcmUnO1xuXG5yZWdpc3RlckVsZW1lbnQoJ0NvbGxlY3Rpb25WaWV3JywgKCkgPT4gQ29sbGVjdGlvblZpZXcpO1xuXG5jb25zdCBOR19WSUVXID0gJ19uZ1ZpZXdSZWYnO1xuXG5leHBvcnQgY2xhc3MgSXRlbUNvbnRleHQge1xuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyAkaW1wbGljaXQ/OiBhbnksIHB1YmxpYyBpdGVtPzogYW55LCBwdWJsaWMgaW5kZXg/OiBudW1iZXIsIHB1YmxpYyBldmVuPzogYm9vbGVhbiwgcHVibGljIG9kZD86IGJvb2xlYW4pIHt9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2V0dXBJdGVtVmlld0FyZ3Mge1xuICAgIHZpZXc6IEVtYmVkZGVkVmlld1JlZjxhbnk+O1xuICAgIGRhdGE6IGFueTtcbiAgICBpbmRleDogbnVtYmVyO1xuICAgIGNvbnRleHQ6IEl0ZW1Db250ZXh0O1xufVxuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ0NvbGxlY3Rpb25WaWV3JyxcbiAgICB0ZW1wbGF0ZTogYFxuICAgICAgICA8RGV0YWNoZWRDb250YWluZXI+XG4gICAgICAgICAgICA8UGxhY2Vob2xkZXIgI2xvYWRlcj48L1BsYWNlaG9sZGVyPlxuICAgICAgICA8L0RldGFjaGVkQ29udGFpbmVyPlxuICAgIGAsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvblZpZXdDb21wb25lbnQgaW1wbGVtZW50cyBEb0NoZWNrLCBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQge1xuICAgIHB1YmxpYyBnZXQgbmF0aXZlRWxlbWVudCgpOiBhbnkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29sbGVjdGlvblZpZXc7XG4gICAgfVxuICAgIHB1YmxpYyBnZXQgbGlzdFZpZXcoKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbGxlY3Rpb25WaWV3O1xuICAgIH1cblxuICAgIEBWaWV3Q2hpbGQoJ2xvYWRlcicsIHsgcmVhZDogVmlld0NvbnRhaW5lclJlZiwgc3RhdGljOiB0cnVlIH0pIHB1YmxpYyBsb2FkZXI6IFZpZXdDb250YWluZXJSZWY7XG4gICAgQE91dHB1dCgpIHB1YmxpYyBzZXR1cEl0ZW1WaWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxTZXR1cEl0ZW1WaWV3QXJncz4oKTtcbiAgICBAQ29udGVudENoaWxkKFRlbXBsYXRlUmVmLCB7IHJlYWQ6IFRlbXBsYXRlUmVmLCBzdGF0aWM6IHRydWUgfSkgcHVibGljIGl0ZW1UZW1wbGF0ZVF1ZXJ5OiBUZW1wbGF0ZVJlZjxJdGVtQ29udGV4dD47XG5cbiAgICBASW5wdXQoKSBhdXRvUmV1c2VWaWV3cyA9IGZhbHNlO1xuXG4gICAgZGV0YWNoZWRMb2FkZXJGYWN0b3J5KCkge1xuICAgICAgICBjb25zdCByZWYgPSB0aGlzLmxvYWRlci5jcmVhdGVDb21wb25lbnQoRGV0YWNoZWRMb2FkZXIsIHtcbiAgICAgICAgICAgIGluZGV4OiAwXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmxvYWRlci5kZXRhY2goMCk7XG4gICAgICAgIHRoaXMuX2xvYWRlcnMucHVzaChyZWYpO1xuICAgICAgICByZXR1cm4gcmVmO1xuICAgIH1cblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGdldCBpdGVtVGVtcGxhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pdGVtVGVtcGxhdGU7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgaXRlbVRlbXBsYXRlKHZhbHVlOiBhbnkpIHtcbiAgICAgICAgdGhpcy5faXRlbVRlbXBsYXRlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuX2NvbGxlY3Rpb25WaWV3LnJlZnJlc2goKTtcbiAgICB9XG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2V0IGl0ZW1zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXRlbXM7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgaXRlbXModmFsdWU6IGFueSkge1xuICAgICAgICB0aGlzLl9pdGVtcyA9IHZhbHVlO1xuICAgICAgICBsZXQgbmVlZERpZmZlciA9IHRydWU7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE9ic2VydmFibGVBcnJheSkge1xuICAgICAgICAgICAgbmVlZERpZmZlciA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZWVkRGlmZmVyICYmICF0aGlzLl9kaWZmZXIgJiYgaXNMaXN0TGlrZUl0ZXJhYmxlKHZhbHVlKSkge1xuICAgICAgICAgICAgdGhpcy5fZGlmZmVyID0gdGhpcy5faXRlcmFibGVEaWZmZXJzLmZpbmQodGhpcy5faXRlbXMpLmNyZWF0ZSgoX2luZGV4LCBpdGVtKSA9PiBpdGVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NvbGxlY3Rpb25WaWV3Lml0ZW1zID0gdGhpcy5faXRlbXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfY29sbGVjdGlvblZpZXc6IENvbGxlY3Rpb25WaWV3O1xuICAgIHByaXZhdGUgX2l0ZW1zOiBhbnk7XG4gICAgcHJpdmF0ZSBfZGlmZmVyOiBJdGVyYWJsZURpZmZlcjxLZXllZFRlbXBsYXRlPjtcbiAgICBwcml2YXRlIF9pdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPEl0ZW1Db250ZXh0PjtcbiAgICBwcml2YXRlIF90ZW1wbGF0ZU1hcDogTWFwPHN0cmluZywgS2V5ZWRUZW1wbGF0ZT47XG4gICAgcHJpdmF0ZSBfbG9hZGVyczogQ29tcG9uZW50UmVmPERldGFjaGVkTG9hZGVyPltdO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIEBJbmplY3QoRWxlbWVudFJlZikgcHJpdmF0ZSBfZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgQEluamVjdChJdGVyYWJsZURpZmZlcnMpIHByaXZhdGUgX2l0ZXJhYmxlRGlmZmVyczogSXRlcmFibGVEaWZmZXJzLFxuICAgICAgICBASW5qZWN0KE5hdGl2ZVNjcmlwdFJlbmRlcmVyRmFjdG9yeSkgcHJpdmF0ZSBfcmVuZGVyZXI6IE5hdGl2ZVNjcmlwdFJlbmRlcmVyRmFjdG9yeSxcbiAgICAgICAgQEluamVjdChOZ1pvbmUpIHByaXZhdGUgX25nWm9uZTogTmdab25lXG4gICAgKSB7XG4gICAgICAgIHRoaXMuX2NvbGxlY3Rpb25WaWV3ID0gX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcblxuICAgICAgICB0aGlzLl9jb2xsZWN0aW9uVmlldy5vbihDb2xsZWN0aW9uVmlldy5pdGVtTG9hZGluZ0V2ZW50LCB0aGlzLm9uSXRlbUxvYWRpbmcsIHRoaXMpO1xuICAgICAgICB0aGlzLl9jb2xsZWN0aW9uVmlldy5pdGVtVmlld0xvYWRlciA9IHRoaXMuaXRlbVZpZXdMb2FkZXI7XG4gICAgICAgIHRoaXMuX2xvYWRlcnMgPSBbXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGl0ZW1WaWV3TG9hZGVyID0gKHZpZXdUeXBlKSA9PlxuICAgICAgICB0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIHN3aXRjaCAodmlld1R5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIExpc3RWaWV3Vmlld1R5cGVzLkl0ZW1WaWV3OlxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5faXRlbVRlbXBsYXRlICYmIHRoaXMubG9hZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0eXBlZFZpZXcgPSB0aGlzLmdldE9yQ3JlYXRlKHRoaXMuX2l0ZW1UZW1wbGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZWRWaWV3O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0pO1xuXG4gICAgcHVibGljIG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcbiAgICAgICAgaWYgKFRyYWNlLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICBDTG9nKENMb2dUeXBlcy5pbmZvLCAnQ29sbGVjdGlvblZpZXcubmdBZnRlckNvbnRlbnRJbml0KCknKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldEl0ZW1UZW1wbGF0ZXMoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuX2NvbGxlY3Rpb25WaWV3Lm9mZihDb2xsZWN0aW9uVmlldy5pdGVtTG9hZGluZ0V2ZW50LCB0aGlzLm9uSXRlbUxvYWRpbmcsIHRoaXMpO1xuICAgICAgICB0aGlzLl9jb2xsZWN0aW9uVmlldyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2xvYWRlcnMuZm9yRWFjaCgobCkgPT4gbC5kZXN0cm95KCkpO1xuICAgICAgICB0aGlzLl9sb2FkZXJzID0gbnVsbDtcbiAgICAgICAgdGhpcy52aWV3VG9Mb2FkZXIgPSBudWxsO1xuICAgICAgICB0aGlzLnZpZXdUb1RlbXBsYXRlID0gbnVsbDtcbiAgICAgICAgdGhpcy52aWV3UG9vbCA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5faXRlbXMgPSBudWxsO1xuICAgICAgICB0aGlzLl9kaWZmZXIgPSBudWxsO1xuICAgICAgICB0aGlzLl9pdGVtVGVtcGxhdGUgPSBudWxsO1xuICAgICAgICBpZiAodGhpcy5fdGVtcGxhdGVNYXApIHtcbiAgICAgICAgICAgIHRoaXMuX3RlbXBsYXRlTWFwLmNsZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdGVtcGxhdGVNYXAgPSBudWxsO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ0RvQ2hlY2soKSB7XG4gICAgICAgIGlmIChUcmFjZS5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgQ0xvZyhDTG9nVHlwZXMuaW5mbywgJ25nRG9DaGVjaygpIC0gZXhlY3V0ZSBkaWZmZXI/ICcgKyB0aGlzLl9kaWZmZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9kaWZmZXIpIHtcbiAgICAgICAgICAgIGlmIChUcmFjZS5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgIENMb2coQ0xvZ1R5cGVzLmluZm8sICduZ0RvQ2hlY2soKSAtIGV4ZWN1dGUgZGlmZmVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjaGFuZ2VzID0gdGhpcy5fZGlmZmVyLmRpZmYodGhpcy5faXRlbXMpO1xuICAgICAgICAgICAgaWYgKGNoYW5nZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoVHJhY2UuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgQ0xvZyhDTG9nVHlwZXMuaW5mbywgJ25nRG9DaGVjaygpIC0gcmVmcmVzaCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyByZWdpc3RlclRlbXBsYXRlKGtleTogc3RyaW5nLCB0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8SXRlbUNvbnRleHQ+KSB7XG4gICAgICAgIGlmIChUcmFjZS5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgQ0xvZyhDTG9nVHlwZXMuaW5mbywgJ3JlZ2lzdGVyVGVtcGxhdGUgZm9yIGtleTogJyArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl90ZW1wbGF0ZU1hcCkge1xuICAgICAgICAgICAgdGhpcy5fdGVtcGxhdGVNYXAgPSBuZXcgTWFwPHN0cmluZywgS2V5ZWRUZW1wbGF0ZT4oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGtleWVkVGVtcGxhdGUgPSB7XG4gICAgICAgICAgICBrZXksXG4gICAgICAgICAgICBjcmVhdGVWaWV3OiB0aGlzLmdldEl0ZW1UZW1wbGF0ZVZpZXdGYWN0b3J5KHRlbXBsYXRlKVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuX3RlbXBsYXRlTWFwLnNldChrZXksIGtleWVkVGVtcGxhdGUpO1xuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2l0ZW1Mb2FkaW5nJywgWyckZXZlbnQnXSlcbiAgICBwdWJsaWMgb25JdGVtTG9hZGluZyhhcmdzOiBDb2xsZWN0aW9uVmlld0l0ZW1FdmVudERhdGEpIHtcbiAgICAgICAgaWYgKCFhcmdzLnZpZXcgJiYgIXRoaXMuaXRlbVRlbXBsYXRlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLml0ZW1zKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGluZGV4ID0gYXJncy5pbmRleDtcbiAgICAgICAgY29uc3QgaXRlbXMgPSAoYXJncy5vYmplY3QgYXMgYW55KS5pdGVtcztcbiAgICAgICAgY29uc3QgY3VycmVudEl0ZW0gPSB0eXBlb2YgaXRlbXMuZ2V0SXRlbSA9PT0gJ2Z1bmN0aW9uJyA/IGl0ZW1zLmdldEl0ZW0oaW5kZXgpIDogaXRlbXNbaW5kZXhdO1xuICAgICAgICBsZXQgdmlld1JlZjogRW1iZWRkZWRWaWV3UmVmPEl0ZW1Db250ZXh0PjtcblxuICAgICAgICBpZiAoVHJhY2UuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIENMb2coQ0xvZ1R5cGVzLmluZm8sIGBvbkl0ZW1Mb2FkaW5nOiAke2luZGV4fSAtIFJldXNpbmcgZXhpc3Rpbmcgdmlld2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdmlld1JlZiA9IGFyZ3Mudmlld1tOR19WSUVXXTtcbiAgICAgICAgLy8gR2V0dGluZyBhbmd1bGFyIHZpZXcgZnJvbSBvcmlnaW5hbCBlbGVtZW50IChpbiBjYXNlcyB3aGVuIFByb3h5Vmlld0NvbnRhaW5lclxuICAgICAgICAvLyBpcyB1c2VkIE5hdGl2ZVNjcmlwdCBpbnRlcm5hbGx5IHdyYXBzIGl0IGluIGEgU3RhY2tMYXlvdXQpXG4gICAgICAgIGlmICghdmlld1JlZiAmJiBhcmdzLnZpZXcgaW5zdGFuY2VvZiBMYXlvdXRCYXNlICYmIGFyZ3Mudmlldy5nZXRDaGlsZHJlbkNvdW50KCkgPiAwKSB7XG4gICAgICAgICAgICB2aWV3UmVmID0gYXJncy52aWV3LmdldENoaWxkQXQoMClbTkdfVklFV107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXZpZXdSZWYgJiYgVHJhY2UuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIGlmIChUcmFjZS5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgIENMb2coQ0xvZ1R5cGVzLmluZm8sIGBWaWV3UmVmZXJlbmNlIG5vdCBmb3VuZCBmb3IgaXRlbSAke2luZGV4fS4gVmlldyByZWN5Y2xpbmcgaXMgbm90IHdvcmtpbmdgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdmlld1JlZikge1xuICAgICAgICAgICAgaWYgKFRyYWNlLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICAgICAgQ0xvZyhDTG9nVHlwZXMuaW5mbywgYG9uSXRlbUxvYWRpbmc6ICR7aW5kZXh9IC0gQ3JlYXRpbmcgdmlldyBmcm9tIHRlbXBsYXRlYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZpZXdSZWYgPSB0aGlzLmxvYWRlci5jcmVhdGVFbWJlZGRlZFZpZXcodGhpcy5pdGVtVGVtcGxhdGUsIG5ldyBJdGVtQ29udGV4dCgpLCAwKTtcbiAgICAgICAgICAgIGFyZ3MudmlldyA9IGdldEl0ZW1WaWV3Um9vdCh2aWV3UmVmKTtcbiAgICAgICAgICAgIGFyZ3Mudmlld1tOR19WSUVXXSA9IHZpZXdSZWY7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldHVwVmlld1JlZih2aWV3UmVmLCBjdXJyZW50SXRlbSwgaW5kZXgpO1xuXG4gICAgICAgIHRoaXMuZGV0ZWN0Q2hhbmdlc09uQ2hpbGQodmlld1JlZiwgaW5kZXgpO1xuICAgIH1cbiAgICBASG9zdExpc3RlbmVyKCdpdGVtUmVjeWNsaW5nJywgWyckZXZlbnQnXSlcbiAgICBwdWJsaWMgb25JdGVtUmVjeWNsaW5nSW50ZXJuYWwoYXJnczogYW55KSB7XG4gICAgICAgIGlmICghYXJncy52aWV3KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IG5nVmlldzogRW1iZWRkZWRWaWV3UmVmPGFueT4gPSBhcmdzLnZpZXdbTkdfVklFV107XG5cbiAgICAgICAgLy8gR2V0dGluZyBhbmd1bGFyIHZpZXcgZnJvbSBvcmlnaW5hbCBlbGVtZW50IChpbiBjYXNlcyB3aGVuIFByb3h5Vmlld0NvbnRhaW5lclxuICAgICAgICAvLyBpcyB1c2VkIE5hdGl2ZVNjcmlwdCBpbnRlcm5hbGx5IHdyYXBzIGl0IGluIGEgU3RhY2tMYXlvdXQpXG4gICAgICAgIGlmICghbmdWaWV3ICYmIGFyZ3MudmlldyBpbnN0YW5jZW9mIExheW91dEJhc2UgJiYgYXJncy52aWV3LmdldENoaWxkcmVuQ291bnQoKSA+IDApIHtcbiAgICAgICAgICAgIG5nVmlldyA9IGFyZ3Mudmlldy5nZXRDaGlsZEF0KDApW05HX1ZJRVddO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdyZWN5Y2xpbmcnLCBhcmdzLnZpZXcpO1xuXG4gICAgICAgIGlmIChuZ1ZpZXcpIHtcbiAgICAgICAgICAgIG5nVmlldy5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2l0ZW1EaXNwb3NpbmcnLCBbJyRldmVudCddKVxuICAgIHB1YmxpYyBvbkl0ZW1EaXNwb3NpbmdJbnRlcm5hbChhcmdzOiBhbnkpIHtcbiAgICAgICAgaWYgKCFhcmdzLnZpZXcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbmdWaWV3OiBFbWJlZGRlZFZpZXdSZWY8YW55PiA9IGFyZ3Mudmlld1tOR19WSUVXXTtcblxuICAgICAgICAvLyBHZXR0aW5nIGFuZ3VsYXIgdmlldyBmcm9tIG9yaWdpbmFsIGVsZW1lbnQgKGluIGNhc2VzIHdoZW4gUHJveHlWaWV3Q29udGFpbmVyXG4gICAgICAgIC8vIGlzIHVzZWQgTmF0aXZlU2NyaXB0IGludGVybmFsbHkgd3JhcHMgaXQgaW4gYSBTdGFja0xheW91dClcbiAgICAgICAgaWYgKCFuZ1ZpZXcgJiYgYXJncy52aWV3IGluc3RhbmNlb2YgTGF5b3V0QmFzZSAmJiBhcmdzLnZpZXcuZ2V0Q2hpbGRyZW5Db3VudCgpID4gMCkge1xuICAgICAgICAgICAgbmdWaWV3ID0gYXJncy52aWV3LmdldENoaWxkQXQoMClbTkdfVklFV107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmdWaWV3KSB7XG4gICAgICAgICAgICBuZ1ZpZXcuZGV0YWNoKCk7XG4gICAgICAgICAgICB0aGlzLnN0b3JlVmlld1JlZihuZ1ZpZXcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHNldHVwVmlld1JlZih2aWV3OiBFbWJlZGRlZFZpZXdSZWY8SXRlbUNvbnRleHQ+LCBkYXRhOiBhbnksIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHZpZXcuY29udGV4dDtcbiAgICAgICAgY29udGV4dC4kaW1wbGljaXQgPSBkYXRhO1xuICAgICAgICBjb250ZXh0Lml0ZW0gPSBkYXRhO1xuICAgICAgICBjb250ZXh0LmluZGV4ID0gaW5kZXg7XG4gICAgICAgIGNvbnRleHQuZXZlbiA9IGluZGV4ICUgMiA9PT0gMDtcbiAgICAgICAgY29udGV4dC5vZGQgPSAhY29udGV4dC5ldmVuO1xuXG4gICAgICAgIHRoaXMuc2V0dXBJdGVtVmlldy5uZXh0KHtcbiAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICB2aWV3XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRJdGVtVGVtcGxhdGVWaWV3RmFjdG9yeSh0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8SXRlbUNvbnRleHQ+KTogKCkgPT4gVmlldyB7XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB2aWV3UmVmID0gdGhpcy5sb2FkZXIuY3JlYXRlRW1iZWRkZWRWaWV3KHRlbXBsYXRlLCBuZXcgSXRlbUNvbnRleHQoKSwgMCk7XG4gICAgICAgICAgICBjb25zdCByZXN1bHRWaWV3ID0gZ2V0SXRlbVZpZXdSb290KHZpZXdSZWYpO1xuICAgICAgICAgICAgcmVzdWx0Vmlld1tOR19WSUVXXSA9IHZpZXdSZWY7XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHRWaWV3O1xuICAgICAgICB9O1xuICAgIH1cbiAgICB2aWV3UG9vbCA9IG5ldyBNYXA8XG4gICAgICAgIFRlbXBsYXRlUmVmPEl0ZW1Db250ZXh0PixcbiAgICAgICAge1xuICAgICAgICAgICAgc2NyYXBTaXplOiBudW1iZXI7XG4gICAgICAgICAgICBzY3JhcEhlYWQ6IFNldDxFbWJlZGRlZFZpZXdSZWY8SXRlbUNvbnRleHQ+PjtcbiAgICAgICAgfVxuICAgID4oKTtcbiAgICBwcml2YXRlIHN0b3JlVmlld1JlZih2aWV3UmVmOiBFbWJlZGRlZFZpZXdSZWY8YW55Pikge1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZVJlZiA9IHRoaXMudmlld1RvVGVtcGxhdGUuZ2V0KHZpZXdSZWYpO1xuICAgICAgICBpZiAodGVtcGxhdGVSZWYpIHtcbiAgICAgICAgICAgIGNvbnN0IHNjcmFwID0gdGhpcy52aWV3UG9vbC5nZXQodGVtcGxhdGVSZWYpO1xuICAgICAgICAgICAgaWYgKHNjcmFwKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNjcmFwLnNjcmFwSGVhZC5zaXplID49IHNjcmFwLnNjcmFwU2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICB2aWV3UmVmLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3VG9Mb2FkZXIuZ2V0KHZpZXdSZWYpPy5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2NyYXAuc2NyYXBIZWFkLmFkZCh2aWV3UmVmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmlld1RvVGVtcGxhdGUgPSBuZXcgV2Vha01hcDxFbWJlZGRlZFZpZXdSZWY8YW55PiwgVGVtcGxhdGVSZWY8YW55Pj4oKTtcbiAgICB2aWV3VG9Mb2FkZXIgPSBuZXcgV2Vha01hcDxFbWJlZGRlZFZpZXdSZWY8YW55PiwgQ29tcG9uZW50UmVmPERldGFjaGVkTG9hZGVyPj4oKTtcblxuICAgIHByaXZhdGUgZ2V0T3JDcmVhdGUodGVtcGxhdGVSZWY6IFRlbXBsYXRlUmVmPEl0ZW1Db250ZXh0Pikge1xuICAgICAgICByZXR1cm4gdGhpcy5fbmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICBsZXQgdmlld1JlZiA9IHRoaXMuZ2V0Vmlldyh0ZW1wbGF0ZVJlZik7XG4gICAgICAgICAgICBpZiAoIXZpZXdSZWYpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsb2FkZXIgPSB0aGlzLmRldGFjaGVkTG9hZGVyRmFjdG9yeSgpO1xuICAgICAgICAgICAgICAgIC8vIHZpZXdSZWYgPSB0aGlzLmxvYWRlci5jcmVhdGVFbWJlZGRlZFZpZXcodGVtcGxhdGVSZWYsIG5ldyBJdGVtQ29udGV4dCgpLCAwKTtcbiAgICAgICAgICAgICAgICB2aWV3UmVmID0gbG9hZGVyLmluc3RhbmNlLnZjLmNyZWF0ZUVtYmVkZGVkVmlldyh0ZW1wbGF0ZVJlZiwgbmV3IEl0ZW1Db250ZXh0KCksIDApO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1RvTG9hZGVyLnNldCh2aWV3UmVmLCBsb2FkZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1RvVGVtcGxhdGUuc2V0KHZpZXdSZWYsIHRlbXBsYXRlUmVmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZpZXdSZWYuZGV0YWNoKCk7XG4gICAgICAgICAgICBjb25zdCByZXN1bHRWaWV3ID0gZ2V0SXRlbVZpZXdSb290KHZpZXdSZWYpO1xuICAgICAgICAgICAgcmVzdWx0Vmlld1tOR19WSUVXXSA9IHZpZXdSZWY7XG4gICAgICAgICAgICByZXN1bHRWaWV3LnJldXNhYmxlID0gdGhpcy5hdXRvUmV1c2VWaWV3cztcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRWaWV3O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcHJpdmF0ZSBnZXRWaWV3KHRlbXBsYXRlUmVmOiBUZW1wbGF0ZVJlZjxJdGVtQ29udGV4dD4pIHtcbiAgICAgICAgY29uc3QgcG9vbCA9IHRoaXMuZ2V0Vmlld1Bvb2wodGVtcGxhdGVSZWYpO1xuICAgICAgICB3aGlsZSAocG9vbC5zY3JhcEhlYWQuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHZpZXdSZWY6IEVtYmVkZGVkVmlld1JlZjxJdGVtQ29udGV4dD4gPSBwb29sLnNjcmFwSGVhZC52YWx1ZXMoKS5uZXh0KCkudmFsdWU7XG4gICAgICAgICAgICBwb29sLnNjcmFwSGVhZC5kZWxldGUodmlld1JlZik7XG4gICAgICAgICAgICBpZiAoIXZpZXdSZWYuZGVzdHJveWVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXdSZWY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRWaWV3UG9vbCh0ZW1wbGF0ZVJlZjogVGVtcGxhdGVSZWY8SXRlbUNvbnRleHQ+KSB7XG4gICAgICAgIGlmICghdGhpcy52aWV3UG9vbC5oYXModGVtcGxhdGVSZWYpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdQb29sLnNldCh0ZW1wbGF0ZVJlZiwge1xuICAgICAgICAgICAgICAgIHNjcmFwU2l6ZTogdGhpcy5hdXRvUmV1c2VWaWV3cyA/IEluZmluaXR5IDogMCxcbiAgICAgICAgICAgICAgICBzY3JhcEhlYWQ6IG5ldyBTZXQ8RW1iZWRkZWRWaWV3UmVmPEl0ZW1Db250ZXh0Pj4oKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMudmlld1Bvb2wuZ2V0KHRlbXBsYXRlUmVmKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldEl0ZW1UZW1wbG