@eternalheart/ngx-file-preview
Version:
A powerful Angular file preview component library supporting multiple file formats including images, videos, PDFs, Office documents, text files and more.
349 lines (337 loc) • 47.6 kB
JavaScript
import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BasePreviewComponent } from '../base-preview/base-preview.component';
import { PreviewIconComponent } from "../../components/preview-icon/preview-icon.component";
import { I18nPipe } from "../../i18n/i18n.pipe";
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class ImagePreviewComponent extends BasePreviewComponent {
constructor(el) {
super();
this.el = el;
this.minZoom = 0.1;
this.maxZoom = 5;
this.zoomStep = 0.1;
this.zoom = 1;
this.rotation = 0;
this.translateX = 0;
this.translateY = 0;
this.isDragging = false;
this.imageWidth = 0;
this.imageHeight = 0;
this.transformStyle = '';
this.dragStartX = 0;
this.dragStartY = 0;
}
ngAfterViewInit() {
this.updateTransformStyle();
}
async handleFileContent(content) {
}
updateTransformStyle() {
const transform = `translate(-50%, -50%)
translate(${this.translateX}px, ${this.translateY}px)
scale(${this.zoom})
rotate(${this.rotation}deg)`;
const transition = this.isDragging ? 'none' : 'transform 0.3s ease';
this.transformStyle = `transform: ${transform}; transition: ${transition};`;
this.cdr.markForCheck();
}
handleWheel(event) {
event.preventDefault();
if (!this.imageWrapper?.nativeElement)
return;
const delta = event.deltaY < 0 ? 1 : -1;
const zoomFactor = 1 + (delta * this.zoomStep);
const newZoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.zoom * zoomFactor));
if (newZoom !== this.zoom) {
const scale = newZoom / this.zoom;
this.translateX = this.translateX * scale;
this.translateY = this.translateY * scale;
this.zoom = newZoom;
this.updateTransformStyle();
}
}
startDrag(event) {
if (event.button !== 0)
return;
this.isDragging = true;
this.dragStartX = event.clientX - this.translateX;
this.dragStartY = event.clientY - this.translateY;
this.updateTransformStyle();
}
onDrag(event) {
if (!this.isDragging)
return;
event.preventDefault();
this.translateX = event.clientX - this.dragStartX;
this.translateY = event.clientY - this.dragStartY;
this.updateTransformStyle();
}
stopDrag() {
this.isDragging = false;
this.updateTransformStyle();
}
zoomIn() {
const newZoom = Math.min(this.maxZoom, this.zoom * (1 + this.zoomStep));
if (newZoom !== this.zoom) {
const scale = newZoom / this.zoom;
this.translateX = this.translateX * scale;
this.translateY = this.translateY * scale;
this.zoom = newZoom;
this.updateTransformStyle();
}
}
zoomOut() {
const newZoom = Math.max(this.minZoom, this.zoom / (1 + this.zoomStep));
if (newZoom !== this.zoom) {
const scale = newZoom / this.zoom;
this.translateX = this.translateX * scale;
this.translateY = this.translateY * scale;
this.zoom = newZoom;
this.updateTransformStyle();
}
}
rotate(angle) {
this.rotation += angle;
this.updateTransformStyle();
}
resetView() {
this.rotation = 0;
this.centerImage();
this.autoFit();
}
onImageLoad() {
if (this.previewImage?.nativeElement) {
const image = this.previewImage.nativeElement;
this.imageWidth = image.naturalWidth;
this.imageHeight = image.naturalHeight;
this.autoFit();
}
}
autoFit() {
if (!this.previewImage?.nativeElement)
return;
const image = this.previewImage.nativeElement;
const container = this.el.nativeElement;
const imageWidth = image.naturalWidth;
const imageHeight = image.naturalHeight;
const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight;
if (!imageWidth || !imageHeight || !containerWidth || !containerHeight)
return;
// 计算基于容器的缩放比例
const scaleX = containerWidth / imageWidth;
const scaleY = containerHeight / imageHeight;
// 取较小的缩放值,保证完整展示(等效 `object-fit: contain`)
const zoom = Math.min(scaleX, scaleY);
this.zoom = zoom > 0 ? zoom : 1;
setTimeout(() => this.updateTransformStyle());
}
originSize() {
this.zoom = 1;
setTimeout(() => this.updateTransformStyle());
}
centerImage() {
if (!this.imageWrapper?.nativeElement || !this.previewImage?.nativeElement)
return;
const wrapper = this.imageWrapper.nativeElement;
const image = this.previewImage.nativeElement;
const wrapperWidth = wrapper.clientWidth;
const wrapperHeight = wrapper.clientHeight;
const imageWidth = image.naturalWidth;
const imageHeight = image.naturalHeight;
if (!wrapperWidth || !wrapperHeight || !imageWidth || !imageHeight)
return;
const wrapperRatio = wrapperWidth / wrapperHeight;
const imageRatio = imageWidth / imageHeight;
// 计算缩放比例,确保图片完整展示
this.zoom = imageRatio > wrapperRatio
? wrapperWidth / imageWidth // 以宽度为基准缩放
: wrapperHeight / imageHeight; // 以高度为基准缩放
// 避免 zoom = 0
if (!this.zoom || this.zoom <= 0) {
this.zoom = 1;
}
// 居中图片
this.translateX = 0;
this.translateY = 0;
// 确保样式更新
setTimeout(() => this.updateTransformStyle());
}
download() {
if (!this.file?.url)
return;
const link = document.createElement('a');
link.href = this.file.url;
link.download = this.file.name || 'image';
link.target = '_blank';
link.rel = 'noopener noreferrer';
if (this.isExternalUrl(this.file.url)) {
const image = this.previewImage?.nativeElement;
if (!image)
return;
const canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
const ctx = canvas.getContext('2d');
if (!ctx)
return;
ctx.drawImage(image, 0, 0);
try {
canvas.toBlob((blob) => {
if (!blob)
return;
const url = URL.createObjectURL(blob);
link.href = url;
link.click();
URL.revokeObjectURL(url);
}, 'image/png');
}
catch (error) {
console.error('Failed to download image:', error);
window.open(this.file.url, '_blank');
}
}
else {
link.click();
}
}
isExternalUrl(url) {
try {
const currentOrigin = window.location.origin;
const urlOrigin = new URL(url, window.location.href).origin;
return currentOrigin !== urlOrigin;
}
catch {
return true;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ImagePreviewComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ImagePreviewComponent, isStandalone: true, selector: "ngx-image-preview", viewQueries: [{ propertyName: "imageWrapper", first: true, predicate: ["imageWrapper"], descendants: true }, { propertyName: "previewImage", first: true, predicate: ["previewImage"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
<div class="image-preview"
(mousedown)="startDrag($event)"
(mousemove)="onDrag($event)"
(mouseup)="stopDrag()"
(mouseleave)="stopDrag()"
(wheel)="handleWheel($event)">
<div class="image-wrapper"
#imageWrapper
[style]="transformStyle"
[class.is-moving]="isDragging">
<img #previewImage
[src]="file.url"
[style.display]="(isLoading|async) ? 'none' : 'block'"
(load)="onImageLoad()"
alt="preview"/>
</div>
<div class="image-info" *ngIf="!(isLoading|async)">
<span class="filename">{{ file.name }}</span>
<span class="dimensions">{{ imageWidth }} × {{ imageHeight }}</span>
</div>
<div class="toolbar" *ngIf="!(isLoading|async)">
<div class="tool-group">
<div class="control" (click)="zoomOut()" [class.disabled]="zoom <= minZoom">
<preview-icon [themeMode]="themeMode" name="zoom-out" [title]="'preview.toolbar.zoomOut'|i18n"></preview-icon>
</div>
<span class="zoom-text">{{ (zoom * 100).toFixed(0) }}%</span>
<div class="control" (click)="zoomIn()" [class.disabled]="zoom >= maxZoom">
<preview-icon [themeMode]="themeMode" name="zoom-in" [title]="'preview.toolbar.zoomIn'|i18n"></preview-icon>
</div>
</div>
<div class="divider"></div>
<div class="tool-group">
<div class="control" (click)="rotate(-90)">
<preview-icon [themeMode]="themeMode" name="rotate-90" [title]="'preview.toolbar.rotate-90'|i18n"></preview-icon>
</div>
<div class="control" (click)="rotate(90)">
<preview-icon [themeMode]="themeMode" name="rotate90" [title]="'preview.toolbar.rotate90'|i18n"></preview-icon>
</div>
</div>
<div class="divider"></div>
<div class="tool-group">
<div class="control" (click)="autoFit()">
<preview-icon [themeMode]="themeMode" name="auto-fit" [title]="'preview.toolbar.autoFit'|i18n"></preview-icon>
</div>
<div class="control" (click)="originSize()">
<preview-icon [themeMode]="themeMode" name="origin-size" [title]="'preview.toolbar.originSize'|i18n"></preview-icon>
</div>
<div class="control" (click)="resetView()">
<preview-icon [themeMode]="themeMode" name="reset" [title]="'preview.toolbar.reset'|i18n"></preview-icon>
</div>
<div class="control" (click)="download()">
<preview-icon [themeMode]="themeMode" name="download" [title]="'preview.toolbar.download'|i18n"></preview-icon>
</div>
</div>
</div>
</div>
`, isInline: true, styles: [":root{--nfp-primary-color: #177ddc;--nfp-primary-hover: #1890ff;--nfp-primary-active: #0050b3;--nfp-error-color: #d32029;--nfp-warning-color: #d89614;--nfp-success-color: #49aa19;--nfp-text-primary: rgba(0, 0, 0, .85);--nfp-text-secondary: rgba(0, 0, 0, .65);--nfp-text-disabled: rgba(0, 0, 0, .25);--nfp-bg-container: #ffffff;--nfp-bg-elevated: #fafafa;--nfp-bg-layout: #f0f2f5;--nfp-hover-bg: rgba(0, 0, 0, .04);--nfp-border-color: #d9d9d9;--nfp-split-color: rgba(0, 0, 0, .06);--nfp-scrollbar-bg: #ffffff;--nfp-scrollbar-thumb: #d9d9d9;--nfp-toolbar-bg: #fafafa;--nfp-toolbar-border: #d9d9d9;--nfp-toolbar-hover: rgba(0, 0, 0, .04);--nfp-toolbar-active: #e6f4ff;--nfp-preview-mask: rgba(0, 0, 0, .3);--nfp-preview-loading-bg: rgba(255, 255, 255, .8);--nfp-preview-toolbar-bg: rgba(0, 0, 0, .1);--nfp-theme-transition-duration: .3s}[data-nfp-theme=dark]{--nfp-primary-color: #177ddc;--nfp-primary-hover: #1890ff;--nfp-primary-active: #0050b3;--nfp-error-color: #a61d24;--nfp-warning-color: #d89614;--nfp-success-color: #49aa19;--nfp-text-primary: rgba(255, 255, 255, .85);--nfp-text-secondary: rgba(255, 255, 255, .65);--nfp-text-disabled: rgba(255, 255, 255, .25);--nfp-bg-container: #1a1a1a;--nfp-bg-elevated: #262626;--nfp-bg-layout: #141414;--nfp-hover-bg: rgba(255, 255, 255, .08);--nfp-border-color: #303030;--nfp-split-color: rgba(255, 255, 255, .12);--nfp-scrollbar-bg: #1a1a1a;--nfp-scrollbar-thumb: #404040;--nfp-toolbar-bg: #262626;--nfp-toolbar-border: #303030;--nfp-toolbar-hover: rgba(255, 255, 255, .08);--nfp-toolbar-active: #111b26;--nfp-preview-mask: rgba(0, 0, 0, .65);--nfp-preview-loading-bg: rgba(0, 0, 0, .8);--nfp-preview-toolbar-bg: rgba(0, 0, 0, .4);--nfp-theme-transition-duration: .3s}*{transition:background-color var(--nfp-theme-transition-duration) var(--theme-transition-timing),border-color var(--nfp-theme-transition-duration) var(--theme-transition-timing),color var(--nfp-theme-transition-duration) var(--theme-transition-timing)}.no-transition,.no-transition *{transition:none!important}\n", ":host{display:block;width:100%;height:100%}.image-preview{width:100%;height:100%;background:var(--nfp-bg-container);cursor:grab}.image-preview:active{cursor:grabbing}.image-preview .image-wrapper{position:absolute;top:50%;left:50%;transform-origin:center center;will-change:transform}.image-preview .image-wrapper.is-moving{transition:none!important}.image-preview .image-wrapper img{max-width:none;max-height:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;transform-origin:center center}.image-preview .toolbar{position:absolute;bottom:24px;left:50%;transform:translate(-50%);background:var(--nfp-bg-container);border-radius:24px;padding:8px 12px;display:flex;align-items:center;gap:4px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:0 2px 8px var(--nfp-preview-mask);color:var(--nfp-text-primary)}.image-preview .toolbar .tool-group{display:flex;align-items:center;gap:4px}.image-preview .toolbar .divider{width:1px;height:16px;background:var(--nfp-border-color);margin:0 8px}.image-preview .toolbar .control{min-width:24px;height:24px;display:flex;align-items:center;justify-content:center;color:var(--nfp-text-primary);cursor:pointer;border-radius:16px;transition:all .2s ease}.image-preview .toolbar .control:hover{background:var(--nfp-toolbar-hover)}.image-preview .toolbar .control.disabled{color:var(--nfp-text-disabled);cursor:not-allowed;pointer-events:none}.image-preview .toolbar .zoom-text{min-width:54px;text-align:center;color:var(--nfp-text-primary);font-size:13px;-webkit-user-select:none;user-select:none}.image-info{position:absolute;left:16px;bottom:16px;color:var(--nfp-text-primary);font-size:12px;-webkit-user-select:none;user-select:none;pointer-events:none;display:flex;flex-direction:column;gap:4px;text-shadow:0 1px 2px var(--nfp-preview-mask)}.image-info .filename{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.image-info .dimensions{font-family:monospace;opacity:.8;color:var(--nfp-text-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: PreviewIconComponent, selector: "preview-icon", inputs: ["name", "svg", "size", "color", "themeMode", "title", "cursor"] }, { kind: "pipe", type: I18nPipe, name: "i18n" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ImagePreviewComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-image-preview', standalone: true, imports: [CommonModule, PreviewIconComponent, I18nPipe], template: `
<div class="image-preview"
(mousedown)="startDrag($event)"
(mousemove)="onDrag($event)"
(mouseup)="stopDrag()"
(mouseleave)="stopDrag()"
(wheel)="handleWheel($event)">
<div class="image-wrapper"
#imageWrapper
[style]="transformStyle"
[class.is-moving]="isDragging">
<img #previewImage
[src]="file.url"
[style.display]="(isLoading|async) ? 'none' : 'block'"
(load)="onImageLoad()"
alt="preview"/>
</div>
<div class="image-info" *ngIf="!(isLoading|async)">
<span class="filename">{{ file.name }}</span>
<span class="dimensions">{{ imageWidth }} × {{ imageHeight }}</span>
</div>
<div class="toolbar" *ngIf="!(isLoading|async)">
<div class="tool-group">
<div class="control" (click)="zoomOut()" [class.disabled]="zoom <= minZoom">
<preview-icon [themeMode]="themeMode" name="zoom-out" [title]="'preview.toolbar.zoomOut'|i18n"></preview-icon>
</div>
<span class="zoom-text">{{ (zoom * 100).toFixed(0) }}%</span>
<div class="control" (click)="zoomIn()" [class.disabled]="zoom >= maxZoom">
<preview-icon [themeMode]="themeMode" name="zoom-in" [title]="'preview.toolbar.zoomIn'|i18n"></preview-icon>
</div>
</div>
<div class="divider"></div>
<div class="tool-group">
<div class="control" (click)="rotate(-90)">
<preview-icon [themeMode]="themeMode" name="rotate-90" [title]="'preview.toolbar.rotate-90'|i18n"></preview-icon>
</div>
<div class="control" (click)="rotate(90)">
<preview-icon [themeMode]="themeMode" name="rotate90" [title]="'preview.toolbar.rotate90'|i18n"></preview-icon>
</div>
</div>
<div class="divider"></div>
<div class="tool-group">
<div class="control" (click)="autoFit()">
<preview-icon [themeMode]="themeMode" name="auto-fit" [title]="'preview.toolbar.autoFit'|i18n"></preview-icon>
</div>
<div class="control" (click)="originSize()">
<preview-icon [themeMode]="themeMode" name="origin-size" [title]="'preview.toolbar.originSize'|i18n"></preview-icon>
</div>
<div class="control" (click)="resetView()">
<preview-icon [themeMode]="themeMode" name="reset" [title]="'preview.toolbar.reset'|i18n"></preview-icon>
</div>
<div class="control" (click)="download()">
<preview-icon [themeMode]="themeMode" name="download" [title]="'preview.toolbar.download'|i18n"></preview-icon>
</div>
</div>
</div>
</div>
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":root{--nfp-primary-color: #177ddc;--nfp-primary-hover: #1890ff;--nfp-primary-active: #0050b3;--nfp-error-color: #d32029;--nfp-warning-color: #d89614;--nfp-success-color: #49aa19;--nfp-text-primary: rgba(0, 0, 0, .85);--nfp-text-secondary: rgba(0, 0, 0, .65);--nfp-text-disabled: rgba(0, 0, 0, .25);--nfp-bg-container: #ffffff;--nfp-bg-elevated: #fafafa;--nfp-bg-layout: #f0f2f5;--nfp-hover-bg: rgba(0, 0, 0, .04);--nfp-border-color: #d9d9d9;--nfp-split-color: rgba(0, 0, 0, .06);--nfp-scrollbar-bg: #ffffff;--nfp-scrollbar-thumb: #d9d9d9;--nfp-toolbar-bg: #fafafa;--nfp-toolbar-border: #d9d9d9;--nfp-toolbar-hover: rgba(0, 0, 0, .04);--nfp-toolbar-active: #e6f4ff;--nfp-preview-mask: rgba(0, 0, 0, .3);--nfp-preview-loading-bg: rgba(255, 255, 255, .8);--nfp-preview-toolbar-bg: rgba(0, 0, 0, .1);--nfp-theme-transition-duration: .3s}[data-nfp-theme=dark]{--nfp-primary-color: #177ddc;--nfp-primary-hover: #1890ff;--nfp-primary-active: #0050b3;--nfp-error-color: #a61d24;--nfp-warning-color: #d89614;--nfp-success-color: #49aa19;--nfp-text-primary: rgba(255, 255, 255, .85);--nfp-text-secondary: rgba(255, 255, 255, .65);--nfp-text-disabled: rgba(255, 255, 255, .25);--nfp-bg-container: #1a1a1a;--nfp-bg-elevated: #262626;--nfp-bg-layout: #141414;--nfp-hover-bg: rgba(255, 255, 255, .08);--nfp-border-color: #303030;--nfp-split-color: rgba(255, 255, 255, .12);--nfp-scrollbar-bg: #1a1a1a;--nfp-scrollbar-thumb: #404040;--nfp-toolbar-bg: #262626;--nfp-toolbar-border: #303030;--nfp-toolbar-hover: rgba(255, 255, 255, .08);--nfp-toolbar-active: #111b26;--nfp-preview-mask: rgba(0, 0, 0, .65);--nfp-preview-loading-bg: rgba(0, 0, 0, .8);--nfp-preview-toolbar-bg: rgba(0, 0, 0, .4);--nfp-theme-transition-duration: .3s}*{transition:background-color var(--nfp-theme-transition-duration) var(--theme-transition-timing),border-color var(--nfp-theme-transition-duration) var(--theme-transition-timing),color var(--nfp-theme-transition-duration) var(--theme-transition-timing)}.no-transition,.no-transition *{transition:none!important}\n", ":host{display:block;width:100%;height:100%}.image-preview{width:100%;height:100%;background:var(--nfp-bg-container);cursor:grab}.image-preview:active{cursor:grabbing}.image-preview .image-wrapper{position:absolute;top:50%;left:50%;transform-origin:center center;will-change:transform}.image-preview .image-wrapper.is-moving{transition:none!important}.image-preview .image-wrapper img{max-width:none;max-height:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;transform-origin:center center}.image-preview .toolbar{position:absolute;bottom:24px;left:50%;transform:translate(-50%);background:var(--nfp-bg-container);border-radius:24px;padding:8px 12px;display:flex;align-items:center;gap:4px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:0 2px 8px var(--nfp-preview-mask);color:var(--nfp-text-primary)}.image-preview .toolbar .tool-group{display:flex;align-items:center;gap:4px}.image-preview .toolbar .divider{width:1px;height:16px;background:var(--nfp-border-color);margin:0 8px}.image-preview .toolbar .control{min-width:24px;height:24px;display:flex;align-items:center;justify-content:center;color:var(--nfp-text-primary);cursor:pointer;border-radius:16px;transition:all .2s ease}.image-preview .toolbar .control:hover{background:var(--nfp-toolbar-hover)}.image-preview .toolbar .control.disabled{color:var(--nfp-text-disabled);cursor:not-allowed;pointer-events:none}.image-preview .toolbar .zoom-text{min-width:54px;text-align:center;color:var(--nfp-text-primary);font-size:13px;-webkit-user-select:none;user-select:none}.image-info{position:absolute;left:16px;bottom:16px;color:var(--nfp-text-primary);font-size:12px;-webkit-user-select:none;user-select:none;pointer-events:none;display:flex;flex-direction:column;gap:4px;text-shadow:0 1px 2px var(--nfp-preview-mask)}.image-info .filename{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.image-info .dimensions{font-family:monospace;opacity:.8;color:var(--nfp-text-secondary)}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { imageWrapper: [{
type: ViewChild,
args: ['imageWrapper']
}], previewImage: [{
type: ViewChild,
args: ['previewImage']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtcHJldmlldy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL25neC1maWxlLXByZXZpZXcvc3JjL2xpYi9wcmV2aWV3LXR5cGVzL2ltYWdlLXByZXZpZXcvaW1hZ2UtcHJldmlldy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFnQix1QkFBdUIsRUFBRSxTQUFTLEVBQWMsU0FBUyxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3ZHLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM3QyxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSx3Q0FBd0MsQ0FBQztBQUM1RSxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxzREFBc0QsQ0FBQztBQUUxRixPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7OztBQTRFOUMsTUFBTSxPQUFPLHFCQUFzQixTQUFRLG9CQUFvQjtJQW9CN0QsWUFBb0IsRUFBYztRQUNoQyxLQUFLLEVBQUUsQ0FBQztRQURVLE9BQUUsR0FBRixFQUFFLENBQVk7UUFoQmYsWUFBTyxHQUFHLEdBQUcsQ0FBQztRQUNkLFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDZCxhQUFRLEdBQUcsR0FBRyxDQUFDO1FBRWhDLFNBQUksR0FBRyxDQUFDLENBQUM7UUFDVCxhQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsZUFBVSxHQUFHLENBQUMsQ0FBQztRQUNmLGVBQVUsR0FBRyxDQUFDLENBQUM7UUFDZixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ25CLGVBQVUsR0FBRyxDQUFDLENBQUM7UUFDZixnQkFBVyxHQUFHLENBQUMsQ0FBQztRQUNoQixtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUVaLGVBQVUsR0FBRyxDQUFDLENBQUM7UUFDZixlQUFVLEdBQUcsQ0FBQyxDQUFDO0lBSXZCLENBQUM7SUFFRCxlQUFlO1FB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SUFBSSxHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDO1lBQzVELE9BQU8sYUFBYSxLQUFLLFNBQVMsQ0FBQztRQUNyQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQzsrR0FuT1UscUJBQXFCO21HQUFyQixxQkFBcUIsaVRBdEV0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0RULDhnSUFoRVMsWUFBWSx3TEFBRSxvQkFBb0IsOEhBQUUsUUFBUTs7NEZBdUUzQyxxQkFBcUI7a0JBMUVqQyxTQUFTOytCQUNFLG1CQUFtQixjQUNqQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsUUFBUSxDQUFDLFlBQzdDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErRFQsbUJBS2dCLHVCQUF1QixDQUFDLE1BQU07K0VBR3BCLFlBQVk7c0JBQXRDLFNBQVM7dUJBQUMsY0FBYztnQkFDRSxZQUFZO3NCQUF0QyxTQUFTO3VCQUFDLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0FmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIFZpZXdDaGlsZH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NvbW1vbk1vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7QmFzZVByZXZpZXdDb21wb25lbnR9IGZyb20gJy4uL2Jhc2UtcHJldmlldy9iYXNlLXByZXZpZXcuY29tcG9uZW50JztcbmltcG9ydCB7UHJldmlld0ljb25Db21wb25lbnR9IGZyb20gXCIuLi8uLi9jb21wb25lbnRzL3ByZXZpZXctaWNvbi9wcmV2aWV3LWljb24uY29tcG9uZW50XCI7XG5pbXBvcnQge0ZpbGVSZWFkZXJSZXNwb25zZX0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzXCI7XG5pbXBvcnQge0kxOG5QaXBlfSBmcm9tIFwiLi4vLi4vaTE4bi9pMThuLnBpcGVcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWltYWdlLXByZXZpZXcnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBQcmV2aWV3SWNvbkNvbXBvbmVudCwgSTE4blBpcGVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJpbWFnZS1wcmV2aWV3XCJcbiAgICAgICAgIChtb3VzZWRvd24pPVwic3RhcnREcmFnKCRldmVudClcIlxuICAgICAgICAgKG1vdXNlbW92ZSk9XCJvbkRyYWcoJGV2ZW50KVwiXG4gICAgICAgICAobW91c2V1cCk9XCJzdG9wRHJhZygpXCJcbiAgICAgICAgIChtb3VzZWxlYXZlKT1cInN0b3BEcmFnKClcIlxuICAgICAgICAgKHdoZWVsKT1cImhhbmRsZVdoZWVsKCRldmVudClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbWFnZS13cmFwcGVyXCJcbiAgICAgICAgICAgI2ltYWdlV3JhcHBlclxuICAgICAgICAgICBbc3R5bGVdPVwidHJhbnNmb3JtU3R5bGVcIlxuICAgICAgICAgICBbY2xhc3MuaXMtbW92aW5nXT1cImlzRHJhZ2dpbmdcIj5cbiAgICAgICAgPGltZyAjcHJldmlld0ltYWdlXG4gICAgICAgICAgICAgW3NyY109XCJmaWxlLnVybFwiXG4gICAgICAgICAgICAgW3N0eWxlLmRpc3BsYXldPVwiKGlzTG9hZGluZ3xhc3luYykgPyAnbm9uZScgOiAnYmxvY2snXCJcbiAgICAgICAgICAgICAobG9hZCk9XCJvbkltYWdlTG9hZCgpXCJcbiAgICAgICAgICAgICBhbHQ9XCJwcmV2aWV3XCIvPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbWFnZS1pbmZvXCIgKm5nSWY9XCIhKGlzTG9hZGluZ3xhc3luYylcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlbmFtZVwiPnt7IGZpbGUubmFtZSB9fTwvc3Bhbj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJkaW1lbnNpb25zXCI+e3sgaW1hZ2VXaWR0aCB9fSDDlyB7eyBpbWFnZUhlaWdodCB9fTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwidG9vbGJhclwiICpuZ0lmPVwiIShpc0xvYWRpbmd8YXN5bmMpXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0b29sLWdyb3VwXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRyb2xcIiAoY2xpY2spPVwiem9vbU91dCgpXCIgW2NsYXNzLmRpc2FibGVkXT1cInpvb20gPD0gbWluWm9vbVwiPlxuICAgICAgICAgICAgPHByZXZpZXctaWNvbiBbdGhlbWVNb2RlXT1cInRoZW1lTW9kZVwiIG5hbWU9XCJ6b29tLW91dFwiIFt0aXRsZV09XCIncHJldmlldy50b29sYmFyLnpvb21PdXQnfGkxOG5cIj48L3ByZXZpZXctaWNvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInpvb20tdGV4dFwiPnt7ICh6b29tICogMTAwKS50b0ZpeGVkKDApIH19JTwvc3Bhbj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29udHJvbFwiIChjbGljayk9XCJ6b29tSW4oKVwiIFtjbGFzcy5kaXNhYmxlZF09XCJ6b29tID49IG1heFpvb21cIj5cbiAgICAgICAgICAgIDxwcmV2aWV3LWljb24gW3RoZW1lTW9kZV09XCJ0aGVtZU1vZGVcIiBuYW1lPVwiem9vbS1pblwiIFt0aXRsZV09XCIncHJldmlldy50b29sYmFyLnpvb21Jbid8aTE4blwiPjwvcHJldmlldy1pY29uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2aWRlclwiPjwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0b29sLWdyb3VwXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRyb2xcIiAoY2xpY2spPVwicm90YXRlKC05MClcIj5cbiAgICAgICAgICAgIDxwcmV2aWV3LWljb24gW3RoZW1lTW9kZV09XCJ0aGVtZU1vZGVcIiBuYW1lPVwicm90YXRlLTkwXCIgW3RpdGxlXT1cIidwcmV2aWV3LnRvb2xiYXIucm90YXRlLTkwJ3xpMThuXCI+PC9wcmV2aWV3LWljb24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRyb2xcIiAoY2xpY2spPVwicm90YXRlKDkwKVwiPlxuICAgICAgICAgICAgPHByZXZpZXctaWNvbiBbdGhlbWVNb2RlXT1cInRoZW1lTW9kZVwiIG5hbWU9XCJyb3RhdGU5MFwiIFt0aXRsZV09XCIncHJldmlldy50b29sYmFyLnJvdGF0ZTkwJ3xpMThuXCI+PC9wcmV2aWV3LWljb24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkaXZpZGVyXCI+PC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2wtZ3JvdXBcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29udHJvbFwiIChjbGljayk9XCJhdXRvRml0KClcIj5cbiAgICAgICAgICAgIDxwcmV2aWV3LWljb24gW3RoZW1lTW9kZV09XCJ0aGVtZU1vZGVcIiBuYW1lPVwiYXV0by1maXRcIiBbdGl0bGVdPVwiJ3ByZXZpZXcudG9vbGJhci5hdXRvRml0J3xpMThuXCI+PC9wcmV2aWV3LWljb24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRyb2xcIiAoY2xpY2spPVwib3JpZ2luU2l6ZSgpXCI+XG4gICAgICAgICAgICA8cHJldmlldy1pY29uIFt0aGVtZU1vZGVdPVwidGhlbWVNb2RlXCIgbmFtZT1cIm9yaWdpbi1zaXplXCIgW3RpdGxlXT1cIidwcmV2aWV3LnRvb2xiYXIub3JpZ2luU2l6ZSd8aTE4blwiPjwvcHJldmlldy1pY29uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb250cm9sXCIgKGNsaWNrKT1cInJlc2V0VmlldygpXCI+XG4gICAgICAgICAgICA8cHJldmlldy1pY29uIFt0aGVtZU1vZGVdPVwidGhlbWVNb2RlXCIgbmFtZT1cInJlc2V0XCIgW3RpdGxlXT1cIidwcmV2aWV3LnRvb2xiYXIucmVzZXQnfGkxOG5cIj48L3ByZXZpZXctaWNvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29udHJvbFwiIChjbGljayk9XCJkb3dubG9hZCgpXCI+XG4gICAgICAgICAgICA8cHJldmlldy1pY29uIFt0aGVtZU1vZGVdPVwidGhlbWVNb2RlXCIgbmFtZT1cImRvd25sb2FkXCIgW3RpdGxlXT1cIidwcmV2aWV3LnRvb2xiYXIuZG93bmxvYWQnfGkxOG5cIj48L3ByZXZpZXctaWNvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbXG4gICAgXCIuLi8uLi9zdHlsZXMvX3RoZW1lLnNjc3NcIixcbiAgICAnLi9pbWFnZS1wcmV2aWV3LmNvbXBvbmVudC5zY3NzJ1xuICBdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBJbWFnZVByZXZpZXdDb21wb25lbnQgZXh0ZW5kcyBCYXNlUHJldmlld0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xuICBAVmlld0NoaWxkKCdpbWFnZVdyYXBwZXInKSBpbWFnZVdyYXBwZXI/OiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgncHJldmlld0ltYWdlJykgcHJldmlld0ltYWdlPzogRWxlbWVudFJlZjxIVE1MSW1hZ2VFbGVtZW50PjtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbWluWm9vbSA9IDAuMTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IG1heFpvb20gPSA1O1xuICBwcml2YXRlIHJlYWRvbmx5IHpvb21TdGVwID0gMC4xO1xuXG4gIHpvb20gPSAxO1xuICByb3RhdGlvbiA9IDA7XG4gIHRyYW5zbGF0ZVggPSAwO1xuICB0cmFuc2xhdGVZID0gMDtcbiAgaXNEcmFnZ2luZyA9IGZhbHNlO1xuICBpbWFnZVdpZHRoID0gMDtcbiAgaW1hZ2VIZWlnaHQgPSAwO1xuICB0cmFuc2Zvcm1TdHlsZSA9ICcnO1xuXG4gIHByaXZhdGUgZHJhZ1N0YXJ0WCA9IDA7XG4gIHByaXZhdGUgZHJhZ1N0YXJ0WSA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBlbDogRWxlbWVudFJlZikge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy51cGRhdGVUcmFuc2Zvcm1TdHlsZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGhhbmRsZUZpbGVDb250ZW50KGNvbnRlbnQ6IEZpbGVSZWFkZXJSZXNwb25zZSkge1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVUcmFuc2Zvcm1TdHlsZSgpIHtcbiAgICBjb25zdCB0cmFuc2Zvcm0gPSBgdHJhbnNsYXRlKC01MCUsIC01MCUpXG4gICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlKCR7dGhpcy50cmFuc2xhdGVYfXB4LCAke3RoaXMudHJhbnNsYXRlWX1weClcbiAgICAgICAgICAgICAgICAgICAgICBzY2FsZSgke3RoaXMuem9vbX0pXG4gICAgICAgICAgICAgICAgICAgICAgcm90YXRlKCR7dGhpcy5yb3RhdGlvbn1kZWcpYDtcblxuICAgIGNvbnN0IHRyYW5zaXRpb24gPSB0aGlzLmlzRHJhZ2dpbmcgPyAnbm9uZScgOiAndHJhbnNmb3JtIDAuM3MgZWFzZSc7XG4gICAgdGhpcy50cmFuc2Zvcm1TdHlsZSA9IGB0cmFuc2Zvcm06ICR7dHJhbnNmb3JtfTsgdHJhbnNpdGlvbjogJHt0cmFuc2l0aW9ufTtgO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgaGFuZGxlV2hlZWwoZXZlbnQ6IFdoZWVsRXZlbnQpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGlmICghdGhpcy5pbWFnZVdyYXBwZXI/Lm5hdGl2ZUVsZW1lbnQpIHJldHVybjtcblxuICAgIGNvbnN0IGRlbHRhID0gZXZlbnQuZGVsdGFZIDwgMCA/IDEgOiAtMTtcbiAgICBjb25zdCB6b29tRmFjdG9yID0gMSArIChkZWx0YSAqIHRoaXMuem9vbVN0ZXApO1xuICAgIGNvbnN0IG5ld1pvb20gPSBNYXRoLm1heCh0aGlzLm1pblpvb20sIE1hdGgubWluKHRoaXMubWF4Wm9vbSwgdGhpcy56b29tICogem9vbUZhY3RvcikpO1xuXG4gICAgaWYgKG5ld1pvb20gIT09IHRoaXMuem9vbSkge1xuICAgICAgY29uc3Qgc2NhbGUgPSBuZXdab29tIC8gdGhpcy56b29tO1xuICAgICAgdGhpcy50cmFuc2xhdGVYID0gdGhpcy50cmFuc2xhdGVYICogc2NhbGU7XG4gICAgICB0aGlzLnRyYW5zbGF0ZVkgPSB0aGlzLnRyYW5zbGF0ZVkgKiBzY2FsZTtcbiAgICAgIHRoaXMuem9vbSA9IG5ld1pvb207XG4gICAgICB0aGlzLnVwZGF0ZVRyYW5zZm9ybVN0eWxlKCk7XG4gICAgfVxuICB9XG5cbiAgc3RhcnREcmFnKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LmJ1dHRvbiAhPT0gMCkgcmV0dXJuO1xuICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7XG4gICAgdGhpcy5kcmFnU3RhcnRYID0gZXZlbnQuY2xpZW50WCAtIHRoaXMudHJhbnNsYXRlWDtcbiAgICB0aGlzLmRyYWdTdGFydFkgPSBldmVudC5jbGllbnRZIC0gdGhpcy50cmFuc2xhdGVZO1xuICAgIHRoaXMudXBkYXRlVHJhbnNmb3JtU3R5bGUoKTtcbiAgfVxuXG4gIG9uRHJhZyhldmVudDogTW91c2VFdmVudCkge1xuICAgIGlmICghdGhpcy5pc0RyYWdnaW5nKSByZXR1cm47XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIHRoaXMudHJhbnNsYXRlWCA9IGV2ZW50LmNsaWVudFggLSB0aGlzLmRyYWdTdGFydFg7XG4gICAgdGhpcy50cmFuc2xhdGVZID0gZXZlbnQuY2xpZW50WSAtIHRoaXMuZHJhZ1N0YXJ0WTtcbiAgICB0aGlzLnVwZGF0ZVRyYW5zZm9ybVN0eWxlKCk7XG4gIH1cblxuICBzdG9wRHJhZygpIHtcbiAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICB0aGlzLnVwZGF0ZVRyYW5zZm9ybVN0eWxlKCk7XG4gIH1cblxuICB6b29tSW4oKSB7XG4gICAgY29uc3QgbmV3Wm9vbSA9IE1hdGgubWluKHRoaXMubWF4Wm9vbSwgdGhpcy56b29tICogKDEgKyB0aGlzLnpvb21TdGVwKSk7XG4gICAgaWYgKG5ld1pvb20gIT09IHRoaXMuem9vbSkge1xuICAgICAgY29uc3Qgc2NhbGUgPSBuZXdab29tIC8gdGhpcy56b29tO1xuICAgICAgdGhpcy50cmFuc2xhdGVYID0gdGhpcy50cmFuc2xhdGVYICogc2NhbGU7XG4gICAgICB0aGlzLnRyYW5zbGF0ZVkgPSB0aGlzLnRyYW5zbGF0ZVkgKiBzY2FsZTtcbiAgICAgIHRoaXMuem9vbSA9IG5ld1pvb207XG4gICAgICB0aGlzLnVwZGF0ZVRyYW5zZm9ybVN0eWxlKCk7XG4gICAgfVxuICB9XG5cbiAgem9vbU91dCgpIHtcbiAgICBjb25zdCBuZXdab29tID0gTWF0aC5tYXgodGhpcy5taW5ab29tLCB0aGlzLnpvb20gLyAoMSArIHRoaXMuem9vbVN0ZXApKTtcbiAgICBpZiAobmV3Wm9vbSAhPT0gdGhpcy56b29tKSB7XG4gICAgICBjb25zdCBzY2FsZSA9IG5ld1pvb20gLyB0aGlzLnpvb207XG4gICAgICB0aGlzLnRyYW5zbGF0ZVggPSB0aGlzLnRyYW5zbGF0ZVggKiBzY2FsZTtcbiAgICAgIHRoaXMudHJhbnNsYXRlWSA9IHRoaXMudHJhbnNsYXRlWSAqIHNjYWxlO1xuICAgICAgdGhpcy56b29tID0gbmV3Wm9vbTtcbiAgICAgIHRoaXMudXBkYXRlVHJhbnNmb3JtU3R5bGUoKTtcbiAgICB9XG4gIH1cblxuICByb3RhdGUoYW5nbGU6IG51bWJlcikge1xuICAgIHRoaXMucm90YXRpb24gKz0gYW5nbGU7XG4gICAgdGhpcy51cGRhdGVUcmFuc2Zvcm1TdHlsZSgpO1xuICB9XG5cbiAgcmVzZXRWaWV3KCkge1xuICAgIHRoaXMucm90YXRpb24gPSAwO1xuICAgIHRoaXMuY2VudGVySW1hZ2UoKTtcbiAgICB0aGlzLmF1dG9GaXQoKVxuICB9XG5cbiAgb25JbWFnZUxvYWQoKSB7XG4gICAgaWYgKHRoaXMucHJldmlld0ltYWdlPy5uYXRpdmVFbGVtZW50KSB7XG4gICAgICBjb25zdCBpbWFnZSA9IHRoaXMucHJldmlld0ltYWdlLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICB0aGlzLmltYWdlV2lkdGggPSBpbWFnZS5uYXR1cmFsV2lkdGg7XG4gICAgICB0aGlzLmltYWdlSGVpZ2h0ID0gaW1hZ2UubmF0dXJhbEhlaWdodDtcbiAgICAgIHRoaXMuYXV0b0ZpdCgpXG4gICAgfVxuICB9XG5cbiAgYXV0b0ZpdCgpIHtcbiAgICBpZiAoIXRoaXMucHJldmlld0ltYWdlPy5uYXRpdmVFbGVtZW50KSByZXR1cm47XG4gICAgY29uc3QgaW1hZ2UgPSB0aGlzLnByZXZpZXdJbWFnZS5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuZWwubmF0aXZlRWxlbWVudFxuICAgIGNvbnN0IGltYWdlV2lkdGggPSBpbWFnZS5uYXR1cmFsV2lkdGg7XG4gICAgY29uc3QgaW1hZ2VIZWlnaHQgPSBpbWFnZS5uYXR1cmFsSGVpZ2h0O1xuICAgIGNvbnN0IGNvbnRhaW5lcldpZHRoID0gY29udGFpbmVyLmNsaWVudFdpZHRoXG4gICAgY29uc3QgY29udGFpbmVySGVpZ2h0ID0gY29udGFpbmVyLmNsaWVudEhlaWdodFxuICAgIGlmICghaW1hZ2VXaWR0aCB8fCAhaW1hZ2VIZWlnaHQgfHwgIWNvbnRhaW5lcldpZHRoIHx8ICFjb250YWluZXJIZWlnaHQpIHJldHVybjtcbiAgICAvLyDorqHnrpfln7rkuo7lrrnlmajnmoTnvKnmlL7mr5TkvotcbiAgICBjb25zdCBzY2FsZVggPSBjb250YWluZXJXaWR0aCAvIGltYWdlV2lkdGg7XG4gICAgY29uc3Qgc2NhbGVZID0gY29udGFpbmVySGVpZ2h0IC8gaW1hZ2VIZWlnaHQ7XG4gICAgLy8g5Y+W6L6D5bCP55qE57yp5pS+5YC877yM5L+d6K+B5a6M5pW05bGV56S677yI562J5pWIIGBvYmplY3QtZml0OiBjb250YWluYO+8iVxuICAgIGNvbnN0IHpvb20gPSBNYXRoLm1pbihzY2FsZVgsIHNjYWxlWSk7XG4gICAgdGhpcy56b29tID0gem9vbSA+IDAgPyB6b29tIDogMTtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMudXBkYXRlVHJhbnNmb3JtU3R5bGUoKSk7XG4gIH1cblxuICBvcmlnaW5TaXplKCkge1xuICAgIHRoaXMuem9vbSA9IDE7XG4gICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnVwZGF0ZVRyYW5zZm9ybVN0eWxlKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBjZW50ZXJJbWFnZSgpIHtcbiAgICBpZiAoIXRoaXMuaW1hZ2VXcmFwcGVyPy5uYXRpdmVFbGVtZW50IHx8ICF0aGlzLnByZXZpZXdJbWFnZT8ubmF0aXZlRWxlbWVudCkgcmV0dXJuO1xuXG4gICAgY29uc3Qgd3JhcHBlciA9IHRoaXMuaW1hZ2VXcmFwcGVyLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgaW1hZ2UgPSB0aGlzLnByZXZpZXdJbWFnZS5uYXRpdmVFbGVtZW50O1xuXG4gICAgY29uc3Qgd3JhcHBlcldpZHRoID0gd3JhcHBlci5jbGllbnRXaWR0aDtcbiAgICBjb25zdCB3cmFwcGVySGVpZ2h0ID0gd3JhcHBlci5jbGllbnRIZWlnaHQ7XG4gICAgY29uc3QgaW1hZ2VXaWR0aCA9IGltYWdlLm5hdHVyYWxXaWR0aDtcbiAgICBjb25zdCBpbWFnZUhlaWdodCA9IGltYWdlLm5hdHVyYWxIZWlnaHQ7XG5cbiAgICBpZiAoIXdyYXBwZXJXaWR0aCB8fCAhd3JhcHBlckhlaWdodCB8fCAhaW1hZ2VXaWR0aCB8fCAhaW1hZ2VIZWlnaHQpIHJldHVybjtcblxuICAgIGNvbnN0IHdyYXBwZXJSYXRpbyA9IHdyYXBwZXJXaWR0aCAvIHdyYXBwZXJIZWlnaHQ7XG4gICAgY29uc3QgaW1hZ2VSYXRpbyA9IGltYWdlV2lkdGggLyBpbWFnZUhlaWdodDtcblxuICAgIC8vIOiuoeeul+e8qeaUvuavlOS+i++8jOehruS/neWbvueJh+WujOaVtOWxleekulxuICAgIHRoaXMuem9vbSA9IGltYWdlUmF0aW8gPiB3cmFwcGVyUmF0aW9cbiAgICAgID8gd3JhcHBlcldpZHRoIC8gaW1hZ2VXaWR0aCAgLy8g5Lul5a695bqm5Li65Z+65YeG57yp5pS+XG4gICAgICA6IHdyYXBwZXJIZWlnaHQgLyBpbWFnZUhlaWdodDsgLy8g5Lul6auY5bqm5Li65Z+65YeG57yp5pS+XG5cbiAgICAvLyDpgb/lhY0gem9vbSA9IDBcbiAgICBpZiAoIXRoaXMuem9vbSB8fCB0aGlzLnpvb20gPD0gMCkge1xuICAgICAgdGhpcy56b29tID0gMTtcbiAgICB9XG5cbiAgICAvLyDlsYXkuK3lm77niYdcbiAgICB0aGlzLnRyYW5zbGF0ZVggPSAwO1xuICAgIHRoaXMudHJhbnNsYXRlWSA9IDA7XG5cbiAgICAvLyDnoa7kv53moLflvI/mm7TmlrBcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMudXBkYXRlVHJhbnNmb3JtU3R5bGUoKSk7XG4gIH1cblxuICBkb3dubG9hZCgpIHtcbiAgICBpZiAoIXRoaXMuZmlsZT8udXJsKSByZXR1cm47XG5cbiAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgIGxpbmsuaHJlZiA9IHRoaXMuZmlsZS51cmw7XG4gICAgbGluay5kb3dubG9hZCA9IHRoaXMuZmlsZS5uYW1lIHx8ICdpbWFnZSc7XG4gICAgbGluay50YXJnZXQgPSAnX2JsYW5rJztcbiAgICBsaW5rLnJlbCA9ICdub29wZW5lciBub3JlZmVycmVyJztcblxuICAgIGlmICh0aGlzLmlzRXh0ZXJuYWxVcmwodGhpcy5maWxlLnVybCkpIHtcbiAgICAgIGNvbnN0IGltYWdlID0gdGhpcy5wcmV2aWV3SW1hZ2U/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICBpZiAoIWltYWdlKSByZXR1cm47XG5cbiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgY2FudmFzLndpZHRoID0gaW1hZ2UubmF0dXJhbFdpZHRoO1xuICAgICAgY2FudmFzLmhlaWdodCA9IGltYWdlLm5hdHVyYWxIZWlnaHQ7XG5cbiAgICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgaWYgKCFjdHgpIHJldHVybjtcblxuICAgICAgY3R4LmRyYXdJbWFnZShpbWFnZSwgMCwgMCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNhbnZhcy50b0Jsb2IoKGJsb2IpID0+IHtcbiAgICAgICAgICBpZiAoIWJsb2IpIHJldHVybjtcbiAgICAgICAgICBjb25zdCB1cmwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuICAgICAgICAgIGxpbmsuaHJlZiA9IHVybDtcbiAgICAgICAgICBsaW5rLmNsaWNrKCk7XG4gICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuICAgICAgICB9LCAnaW1hZ2UvcG5nJyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gZG93bmxvYWQgaW1hZ2U6JywgZXJyb3IpO1xuICAgICAgICB3aW5kb3cub3Blbih0aGlzLmZpbGUudXJsLCAnX2JsYW5rJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpbmsuY2xpY2soKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzRXh0ZXJuYWxVcmwodXJsOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY3VycmVudE9yaWdpbiA9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW47XG4gICAgICBjb25zdCB1cmxPcmlnaW4gPSBuZXcgVVJMKHVybCwgd2luZG93LmxvY2F0aW9uLmhyZWYpLm9yaWdpbjtcbiAgICAgIHJldHVybiBjdXJyZW50T3JpZ2luICE9PSB1cmxPcmlnaW47XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==