UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

143 lines • 23.3 kB
import { fromEvent, Subject } from 'rxjs'; import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; // This is an adapted version of the original FixedSizeVirtualScrollStrategy // https://github.com/angular/components/blob/master/src/cdk/scrolling/fixed-size-virtual-scroll.ts export class VirtualScrollWindowStrategy { constructor(itemSizePx, offsetSizePx, minBufferPx, maxBufferPx) { this._viewport = null; this._scrolledIndexChange = new Subject(); this.destroy = new Subject(); this._itemSizePx = itemSizePx; this._offsetSizePx = offsetSizePx; this._minBufferPx = minBufferPx; this._maxBufferPx = maxBufferPx; this.scrolledIndexChange = this._scrolledIndexChange.pipe(distinctUntilChanged()); this.destroy$ = this.destroy.asObservable(); } /** * Attaches this scroll strategy to a viewport. * @param viewport The viewport to attach this strategy to. */ attach(viewport) { this._viewport = viewport; this._updateTotalContentSize(); this._updateRenderedRange(); fromEvent(window, 'scroll') .pipe(takeUntil(this.destroy$), debounceTime(10)) .subscribe(() => { this._updateRenderedRange(); }); } /** Detaches this scroll strategy from the currently attached viewport. */ detach() { this._scrolledIndexChange.complete(); this._viewport = null; this.destroy.next(); this.destroy.complete(); } /** * Update the item size and buffer size. * @param itemSize The size of the items in the virtually scrolling list. * @param offsetSizePx The size of the offset (in pixels).. * @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more * @param maxBufferPx The amount of buffer (in pixels) to render when rendering more. */ updateItemAndBufferSize(itemSize, offsetSizePx, minBufferPx, maxBufferPx) { this._itemSizePx = itemSize; this._offsetSizePx = offsetSizePx; this._minBufferPx = minBufferPx; this._maxBufferPx = maxBufferPx; this._updateTotalContentSize(); this._updateRenderedRange(); } /** @docs-private Implemented as part of VirtualScrollStrategy. */ onContentScrolled() { this._updateRenderedRange(); } /** @docs-private Implemented as part of VirtualScrollStrategy. */ onDataLengthChanged() { this._updateTotalContentSize(); this._updateRenderedRange(); } /** @docs-private Implemented as part of VirtualScrollStrategy. */ onContentRendered() { /* no-op */ } /** @docs-private Implemented as part of VirtualScrollStrategy. */ onRenderedOffsetChanged() { /* no-op */ } /** * Scroll to the offset for the given index. * @param index The index of the element to scroll to. * @param behavior The ScrollBehavior to use when scrolling. */ scrollToIndex(index, behavior) { if (this._viewport) { this._viewport.scrollToOffset(index * this._itemSizePx, behavior); } } /** Update the viewport's total content size. */ _updateTotalContentSize() { if (!this._viewport) { return; } this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSizePx + this._offsetSizePx); this._viewport._changeDetectorRef.detectChanges(); setTimeout(() => { const children = this._viewport.elementRef.nativeElement.children[0].children; if (children.length > 0) { this._itemSizePx = children[0]?.clientHeight; this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSizePx + this._offsetSizePx); } }, 100); } /** Update the viewport's rendered range. */ _updateRenderedRange() { if (!this._viewport) { return; } // Use the window as a reference for viewPort size and offset const viewportSize = window.innerHeight; let scrollOffset = window.pageYOffset; const renderedRange = this._viewport.getRenderedRange(); const newRange = { start: renderedRange.start, end: renderedRange.end }; const dataLength = this._viewport.getDataLength(); // Prevent NaN as result when dividing by zero. let firstVisibleIndex = this._itemSizePx > 0 ? scrollOffset / this._itemSizePx : 0; // If user scrolls to the bottom of the list and data changes to a smaller list if (newRange.end > dataLength) { // We have to recalculate the first visible index based on new data length and viewport size. const maxVisibleItems = Math.ceil(viewportSize / this._itemSizePx); const newVisibleIndex = Math.max(0, Math.min(firstVisibleIndex, dataLength - maxVisibleItems)); // If first visible index changed we must update scroll offset to handle start/end buffers // Current range must also be adjusted to cover the new position (bottom of new list). if (firstVisibleIndex !== newVisibleIndex) { firstVisibleIndex = newVisibleIndex; scrollOffset = newVisibleIndex * this._itemSizePx; newRange.start = Math.floor(firstVisibleIndex); } newRange.end = Math.max(0, Math.min(dataLength, newRange.start + maxVisibleItems)); } const startBuffer = scrollOffset - newRange.start * this._itemSizePx; if (startBuffer < this._minBufferPx && newRange.start !== 0) { const expandStart = Math.ceil((this._maxBufferPx - startBuffer) / this._itemSizePx); newRange.start = Math.max(0, newRange.start - expandStart); newRange.end = Math.min(dataLength, Math.ceil(firstVisibleIndex + (viewportSize + this._minBufferPx) / this._itemSizePx)); } else { const endBuffer = newRange.end * this._itemSizePx - (scrollOffset + viewportSize); if (endBuffer < this._minBufferPx && newRange.end !== dataLength) { const expandEnd = Math.ceil((this._maxBufferPx - endBuffer) / this._itemSizePx); if (expandEnd > 0) { newRange.end = Math.min(dataLength, newRange.end + expandEnd); newRange.start = Math.max(0, Math.floor(firstVisibleIndex - this._minBufferPx / this._itemSizePx)); } } } this._viewport.setRenderedRange(newRange); this._viewport.setRenderedContentOffset(this._itemSizePx * newRange.start); this._scrolledIndexChange.next(Math.floor(firstVisibleIndex)); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1zY3JvbGwtd2luZG93LXN0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vY29yZS9jb21tb24vdmlydHVhbC1zY3JvbGwvdmlydHVhbC1zY3JvbGwtd2luZG93LXN0cmF0ZWd5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQWMsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFL0UsNEVBQTRFO0FBQzVFLG1HQUFtRztBQUNuRyxNQUFNLE9BQU8sMkJBQTJCO0lBZXRDLFlBQVksVUFBa0IsRUFBRSxZQUFvQixFQUFFLFdBQW1CLEVBQUUsV0FBbUI7UUFWdEYsY0FBUyxHQUFvQyxJQUFJLENBQUM7UUFPekMseUJBQW9CLEdBQUcsSUFBSSxPQUFPLEVBQVUsQ0FBQztRQUM3QyxZQUFPLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUc3QyxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQztRQUM5QixJQUFJLENBQUMsYUFBYSxHQUFHLFlBQVksQ0FBQztRQUNsQyxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztRQUNoQyxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztRQUVoQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLENBQUM7UUFDbEYsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzlDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsUUFBa0M7UUFDdkMsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7UUFDMUIsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7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SUFBSSxRQUFRLENBQUMsR0FBRyxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUNqRSxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ2hGLElBQUksU0FBUyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUNsQixRQUFRLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLENBQUM7b0JBQzlELFFBQVEsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDdkIsQ0FBQyxFQUNELElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQ3JFLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsU0FBUyxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDaEUsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LCBWaXJ0dWFsU2Nyb2xsU3RyYXRlZ3kgfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7IGZyb21FdmVudCwgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG4vLyBUaGlzIGlzIGFuIGFkYXB0ZWQgdmVyc2lvbiBvZiB0aGUgb3JpZ2luYWwgRml4ZWRTaXplVmlydHVhbFNjcm9sbFN0cmF0ZWd5XG4vLyBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9jb21wb25lbnRzL2Jsb2IvbWFzdGVyL3NyYy9jZGsvc2Nyb2xsaW5nL2ZpeGVkLXNpemUtdmlydHVhbC1zY3JvbGwudHNcbmV4cG9ydCBjbGFzcyBWaXJ0dWFsU2Nyb2xsV2luZG93U3RyYXRlZ3kgaW1wbGVtZW50cyBWaXJ0dWFsU2Nyb2xsU3RyYXRlZ3kge1xuICBzY3JvbGxlZEluZGV4Q2hhbmdlOiBPYnNlcnZhYmxlPG51bWJlcj47XG5cbiAgcHJpdmF0ZSBkZXN0cm95JDogT2JzZXJ2YWJsZTx2b2lkPjtcblxuICBwcml2YXRlIF92aWV3cG9ydDogQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0IHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBfaXRlbVNpemVQeDogbnVtYmVyO1xuICBwcml2YXRlIF9vZmZzZXRTaXplUHg6IG51bWJlcjtcbiAgcHJpdmF0ZSBfbWluQnVmZmVyUHg6IG51bWJlcjtcbiAgcHJpdmF0ZSBfbWF4QnVmZmVyUHg6IG51bWJlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9zY3JvbGxlZEluZGV4Q2hhbmdlID0gbmV3IFN1YmplY3Q8bnVtYmVyPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIGNvbnN0cnVjdG9yKGl0ZW1TaXplUHg6IG51bWJlciwgb2Zmc2V0U2l6ZVB4OiBudW1iZXIsIG1pbkJ1ZmZlclB4OiBudW1iZXIsIG1heEJ1ZmZlclB4OiBudW1iZXIpIHtcbiAgICB0aGlzLl9pdGVtU2l6ZVB4ID0gaXRlbVNpemVQeDtcbiAgICB0aGlzLl9vZmZzZXRTaXplUHggPSBvZmZzZXRTaXplUHg7XG4gICAgdGhpcy5fbWluQnVmZmVyUHggPSBtaW5CdWZmZXJQeDtcbiAgICB0aGlzLl9tYXhCdWZmZXJQeCA9IG1heEJ1ZmZlclB4O1xuXG4gICAgdGhpcy5zY3JvbGxlZEluZGV4Q2hhbmdlID0gdGhpcy5fc2Nyb2xsZWRJbmRleENoYW5nZS5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpO1xuICAgIHRoaXMuZGVzdHJveSQgPSB0aGlzLmRlc3Ryb3kuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKipcbiAgICogQXR0YWNoZXMgdGhpcyBzY3JvbGwgc3RyYXRlZ3kgdG8gYSB2aWV3cG9ydC5cbiAgICogQHBhcmFtIHZpZXdwb3J0IFRoZSB2aWV3cG9ydCB0byBhdHRhY2ggdGhpcyBzdHJhdGVneSB0by5cbiAgICovXG4gIGF0dGFjaCh2aWV3cG9ydDogQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0KSB7XG4gICAgdGhpcy5fdmlld3BvcnQgPSB2aWV3cG9ydDtcbiAgICB0aGlzLl91cGRhdGVUb3RhbENvbnRlbnRTaXplKCk7XG4gICAgdGhpcy5fdXBkYXRlUmVuZGVyZWRSYW5nZSgpO1xuXG4gICAgZnJvbUV2ZW50KHdpbmRvdywgJ3Njcm9sbCcpXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCksIGRlYm91bmNlVGltZSgxMCkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUmVuZGVyZWRSYW5nZSgpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKiogRGV0YWNoZXMgdGhpcyBzY3JvbGwgc3RyYXRlZ3kgZnJvbSB0aGUgY3VycmVudGx5IGF0dGFjaGVkIHZpZXdwb3J0LiAqL1xuICBkZXRhY2goKSB7XG4gICAgdGhpcy5fc2Nyb2xsZWRJbmRleENoYW5nZS5jb21wbGV0ZSgpO1xuICAgIHRoaXMuX3ZpZXdwb3J0ID0gbnVsbDtcblxuICAgIHRoaXMuZGVzdHJveS5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95LmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHRoZSBpdGVtIHNpemUgYW5kIGJ1ZmZlciBzaXplLlxuICAgKiBAcGFyYW0gaXRlbVNpemUgVGhlIHNpemUgb2YgdGhlIGl0ZW1zIGluIHRoZSB2aXJ0dWFsbHkgc2Nyb2xsaW5nIGxpc3QuXG4gICAqIEBwYXJhbSBvZmZzZXRTaXplUHggVGhlIHNpemUgb2YgdGhlIG9mZnNldCAoaW4gcGl4ZWxzKS4uXG4gICAqIEBwYXJhbSBtaW5CdWZmZXJQeCBUaGUgbWluaW11bSBhbW91bnQgb2YgYnVmZmVyIChpbiBwaXhlbHMpIGJlZm9yZSBuZWVkaW5nIHRvIHJlbmRlciBtb3JlXG4gICAqIEBwYXJhbSBtYXhCdWZmZXJQeCBUaGUgYW1vdW50IG9mIGJ1ZmZlciAoaW4gcGl4ZWxzKSB0byByZW5kZXIgd2hlbiByZW5kZXJpbmcgbW9yZS5cbiAgICovXG4gIHVwZGF0ZUl0ZW1BbmRCdWZmZXJTaXplKFxuICAgIGl0ZW1TaXplOiBudW1iZXIsXG4gICAgb2Zmc2V0U2l6ZVB4OiBudW1iZXIsXG4gICAgbWluQnVmZmVyUHg6IG51bWJlcixcbiAgICBtYXhCdWZmZXJQeDogbnVtYmVyXG4gICkge1xuICAgIHRoaXMuX2l0ZW1TaXplUHggPSBpdGVtU2l6ZTtcbiAgICB0aGlzLl9vZmZzZXRTaXplUHggPSBvZmZzZXRTaXplUHg7XG4gICAgdGhpcy5fbWluQnVmZmVyUHggPSBtaW5CdWZmZXJQeDtcbiAgICB0aGlzLl9tYXhCdWZmZXJQeCA9IG1heEJ1ZmZlclB4O1xuXG4gICAgdGhpcy5fdXBkYXRlVG90YWxDb250ZW50U2l6ZSgpO1xuICAgIHRoaXMuX3VwZGF0ZVJlbmRlcmVkUmFuZ2UoKTtcbiAgfVxuXG4gIC8qKiBAZG9jcy1wcml2YXRlIEltcGxlbWVudGVkIGFzIHBhcnQgb2YgVmlydHVhbFNjcm9sbFN0cmF0ZWd5LiAqL1xuICBvbkNvbnRlbnRTY3JvbGxlZCgpIHtcbiAgICB0aGlzLl91cGRhdGVSZW5kZXJlZFJhbmdlKCk7XG4gIH1cblxuICAvKiogQGRvY3MtcHJpdmF0ZSBJbXBsZW1lbnRlZCBhcyBwYXJ0IG9mIFZpcnR1YWxTY3JvbGxTdHJhdGVneS4gKi9cbiAgb25EYXRhTGVuZ3RoQ2hhbmdlZCgpIHtcbiAgICB0aGlzLl91cGRhdGVUb3RhbENvbnRlbnRTaXplKCk7XG4gICAgdGhpcy5fdXBkYXRlUmVuZGVyZWRSYW5nZSgpO1xuICB9XG5cbiAgLyoqIEBkb2NzLXByaXZhdGUgSW1wbGVtZW50ZWQgYXMgcGFydCBvZiBWaXJ0dWFsU2Nyb2xsU3RyYXRlZ3kuICovXG4gIG9uQ29udGVudFJlbmRlcmVkKCkge1xuICAgIC8qIG5vLW9wICovXG4gIH1cblxuICAvKiogQGRvY3MtcHJpdmF0ZSBJbXBsZW1lbnRlZCBhcyBwYXJ0IG9mIFZpcnR1YWxTY3JvbGxTdHJhdGVneS4gKi9cbiAgb25SZW5kZXJlZE9mZnNldENoYW5nZWQoKSB7XG4gICAgLyogbm8tb3AgKi9cbiAgfVxuXG4gIC8qKlxuICAgKiBTY3JvbGwgdG8gdGhlIG9mZnNldCBmb3IgdGhlIGdpdmVuIGluZGV4LlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHNjcm9sbCB0by5cbiAgICogQHBhcmFtIGJlaGF2aW9yIFRoZSBTY3JvbGxCZWhhdmlvciB0byB1c2Ugd2hlbiBzY3JvbGxpbmcuXG4gICAqL1xuICBzY3JvbGxUb0luZGV4KGluZGV4OiBudW1iZXIsIGJlaGF2aW9yOiBTY3JvbGxCZWhhdmlvcik6IHZvaWQge1xuICAgIGlmICh0aGlzLl92aWV3cG9ydCkge1xuICAgICAgdGhpcy5fdmlld3BvcnQuc2Nyb2xsVG9PZmZzZXQoaW5kZXggKiB0aGlzLl9pdGVtU2l6ZVB4LCBiZWhhdmlvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqIFVwZGF0ZSB0aGUgdmlld3BvcnQncyB0b3RhbCBjb250ZW50IHNpemUuICovXG4gIHByaXZhdGUgX3VwZGF0ZVRvdGFsQ29udGVudFNpemUoKSB7XG4gICAgaWYgKCF0aGlzLl92aWV3cG9ydCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3ZpZXdwb3J0LnNldFRvdGFsQ29udGVudFNpemUoXG4gICAgICB0aGlzLl92aWV3cG9ydC5nZXREYXRhTGVuZ3RoKCkgKiB0aGlzLl9pdGVtU2l6ZVB4ICsgdGhpcy5fb2Zmc2V0U2l6ZVB4XG4gICAgKTtcbiAgICAodGhpcy5fdmlld3BvcnQgYXMgYW55KS5fY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjb25zdCBjaGlsZHJlbiA9IHRoaXMuX3ZpZXdwb3J0LmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jaGlsZHJlblswXS5jaGlsZHJlbjtcbiAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMuX2l0ZW1TaXplUHggPSBjaGlsZHJlblswXT8uY2xpZW50SGVpZ2h0O1xuICAgICAgICB0aGlzLl92aWV3cG9ydC5zZXRUb3RhbENvbnRlbnRTaXplKFxuICAgICAgICAgIHRoaXMuX3ZpZXdwb3J0LmdldERhdGFMZW5ndGgoKSAqIHRoaXMuX2l0ZW1TaXplUHggKyB0aGlzLl9vZmZzZXRTaXplUHhcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9LCAxMDApO1xuICB9XG5cbiAgLyoqIFVwZGF0ZSB0aGUgdmlld3BvcnQncyByZW5kZXJlZCByYW5nZS4gKi9cbiAgcHJpdmF0ZSBfdXBkYXRlUmVuZGVyZWRSYW5nZSgpIHtcbiAgICBpZiAoIXRoaXMuX3ZpZXdwb3J0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVXNlIHRoZSB3aW5kb3cgYXMgYSByZWZlcmVuY2UgZm9yIHZpZXdQb3J0IHNpemUgYW5kIG9mZnNldFxuICAgIGNvbnN0IHZpZXdwb3J0U2l6ZSA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICBsZXQgc2Nyb2xsT2Zmc2V0ID0gd2luZG93LnBhZ2VZT2Zmc2V0O1xuXG4gICAgY29uc3QgcmVuZGVyZWRSYW5nZSA9IHRoaXMuX3ZpZXdwb3J0LmdldFJlbmRlcmVkUmFuZ2UoKTtcbiAgICBjb25zdCBuZXdSYW5nZSA9IHsgc3RhcnQ6IHJlbmRlcmVkUmFuZ2Uuc3RhcnQsIGVuZDogcmVuZGVyZWRSYW5nZS5lbmQgfTtcblxuICAgIGNvbnN0IGRhdGFMZW5ndGggPSB0aGlzLl92aWV3cG9ydC5nZXREYXRhTGVuZ3RoKCk7XG4gICAgLy8gUHJldmVudCBOYU4gYXMgcmVzdWx0IHdoZW4gZGl2aWRpbmcgYnkgemVyby5cbiAgICBsZXQgZmlyc3RWaXNpYmxlSW5kZXggPSB0aGlzLl9pdGVtU2l6ZVB4ID4gMCA/IHNjcm9sbE9mZnNldCAvIHRoaXMuX2l0ZW1TaXplUHggOiAwO1xuXG4gICAgLy8gSWYgdXNlciBzY3JvbGxzIHRvIHRoZSBib3R0b20gb2YgdGhlIGxpc3QgYW5kIGRhdGEgY2hhbmdlcyB0byBhIHNtYWxsZXIgbGlzdFxuICAgIGlmIChuZXdSYW5nZS5lbmQgPiBkYXRhTGVuZ3RoKSB7XG4gICAgICAvLyBXZSBoYXZlIHRvIHJlY2FsY3VsYXRlIHRoZSBmaXJzdCB2aXNpYmxlIGluZGV4IGJhc2VkIG9uIG5ldyBkYXRhIGxlbmd0aCBhbmQgdmlld3BvcnQgc2l6ZS5cbiAgICAgIGNvbnN0IG1heFZpc2libGVJdGVtcyA9IE1hdGguY2VpbCh2aWV3cG9ydFNpemUgLyB0aGlzLl9pdGVtU2l6ZVB4KTtcbiAgICAgIGNvbnN0IG5ld1Zpc2libGVJbmRleCA9IE1hdGgubWF4KFxuICAgICAgICAwLFxuICAgICAgICBNYXRoLm1pbihmaXJzdFZpc2libGVJbmRleCwgZGF0YUxlbmd0aCAtIG1heFZpc2libGVJdGVtcylcbiAgICAgICk7XG5cbiAgICAgIC8vIElmIGZpcnN0IHZpc2libGUgaW5kZXggY2hhbmdlZCB3ZSBtdXN0IHVwZGF0ZSBzY3JvbGwgb2Zmc2V0IHRvIGhhbmRsZSBzdGFydC9lbmQgYnVmZmVyc1xuICAgICAgLy8gQ3VycmVudCByYW5nZSBtdXN0IGFsc28gYmUgYWRqdXN0ZWQgdG8gY292ZXIgdGhlIG5ldyBwb3NpdGlvbiAoYm90dG9tIG9mIG5ldyBsaXN0KS5cbiAgICAgIGlmIChmaXJzdFZpc2libGVJbmRleCAhPT0gbmV3VmlzaWJsZUluZGV4KSB7XG4gICAgICAgIGZpcnN0VmlzaWJsZUluZGV4ID0gbmV3VmlzaWJsZUluZGV4O1xuICAgICAgICBzY3JvbGxPZmZzZXQgPSBuZXdWaXNpYmxlSW5kZXggKiB0aGlzLl9pdGVtU2l6ZVB4O1xuICAgICAgICBuZXdSYW5nZS5zdGFydCA9IE1hdGguZmxvb3IoZmlyc3RWaXNpYmxlSW5kZXgpO1xuICAgICAgfVxuXG4gICAgICBuZXdSYW5nZS5lbmQgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihkYXRhTGVuZ3RoLCBuZXdSYW5nZS5zdGFydCArIG1heFZpc2libGVJdGVtcykpO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YXJ0QnVmZmVyID0gc2Nyb2xsT2Zmc2V0IC0gbmV3UmFuZ2Uuc3RhcnQgKiB0aGlzLl9pdGVtU2l6ZVB4O1xuICAgIGlmIChzdGFydEJ1ZmZlciA8IHRoaXMuX21pbkJ1ZmZlclB4ICYmIG5ld1JhbmdlLnN0YXJ0ICE9PSAwKSB7XG4gICAgICBjb25zdCBleHBhbmRTdGFydCA9IE1hdGguY2VpbCgodGhpcy5fbWF4QnVmZmVyUHggLSBzdGFydEJ1ZmZlcikgLyB0aGlzLl9pdGVtU2l6ZVB4KTtcbiAgICAgIG5ld1JhbmdlLnN0YXJ0ID0gTWF0aC5tYXgoMCwgbmV3UmFuZ2Uuc3RhcnQgLSBleHBhbmRTdGFydCk7XG4gICAgICBuZXdSYW5nZS5lbmQgPSBNYXRoLm1pbihcbiAgICAgICAgZGF0YUxlbmd0aCxcbiAgICAgICAgTWF0aC5jZWlsKGZpcnN0VmlzaWJsZUluZGV4ICsgKHZpZXdwb3J0U2l6ZSArIHRoaXMuX21pbkJ1ZmZlclB4KSAvIHRoaXMuX2l0ZW1TaXplUHgpXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBlbmRCdWZmZXIgPSBuZXdSYW5nZS5lbmQgKiB0aGlzLl9pdGVtU2l6ZVB4IC0gKHNjcm9sbE9mZnNldCArIHZpZXdwb3J0U2l6ZSk7XG4gICAgICBpZiAoZW5kQnVmZmVyIDwgdGhpcy5fbWluQnVmZmVyUHggJiYgbmV3UmFuZ2UuZW5kICE9PSBkYXRhTGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGV4cGFuZEVuZCA9IE1hdGguY2VpbCgodGhpcy5fbWF4QnVmZmVyUHggLSBlbmRCdWZmZXIpIC8gdGhpcy5faXRlbVNpemVQeCk7XG4gICAgICAgIGlmIChleHBhbmRFbmQgPiAwKSB7XG4gICAgICAgICAgbmV3UmFuZ2UuZW5kID0gTWF0aC5taW4oZGF0YUxlbmd0aCwgbmV3UmFuZ2UuZW5kICsgZXhwYW5kRW5kKTtcbiAgICAgICAgICBuZXdSYW5nZS5zdGFydCA9IE1hdGgubWF4KFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIE1hdGguZmxvb3IoZmlyc3RWaXNpYmxlSW5kZXggLSB0aGlzLl9taW5CdWZmZXJQeCAvIHRoaXMuX2l0ZW1TaXplUHgpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3ZpZXdwb3J0LnNldFJlbmRlcmVkUmFuZ2UobmV3UmFuZ2UpO1xuICAgIHRoaXMuX3ZpZXdwb3J0LnNldFJlbmRlcmVkQ29udGVudE9mZnNldCh0aGlzLl9pdGVtU2l6ZVB4ICogbmV3UmFuZ2Uuc3RhcnQpO1xuICAgIHRoaXMuX3Njcm9sbGVkSW5kZXhDaGFuZ2UubmV4dChNYXRoLmZsb29yKGZpcnN0VmlzaWJsZUluZGV4KSk7XG4gIH1cbn1cbiJdfQ==