UNPKG

ng-cw-v12

Version:

Angular UI Component Library

282 lines (275 loc) 38.8 kB
import { Component, ViewChild, Input, HostListener } from '@angular/core'; import * as THREE from 'three'; import * as i0 from "@angular/core"; // ─── 顶点着色器 ───────────────────────────────────────────────────────────── const vertexShader = ` attribute vec3 position; attribute vec2 uv; varying vec2 vUv; void main() { vUv = uv; gl_Position = vec4(position, 1.0); } `; // ─── 片元着色器 ───────────────────────────────────────────────────────────── const fragmentShader = ` precision highp float; uniform float uTime; uniform vec3 uColor; uniform vec3 uResolution; uniform vec2 uMouse; uniform float uAmplitude; uniform float uSpeed; varying vec2 vUv; void main() { float mr = min(uResolution.x, uResolution.y); vec2 uv = (vUv.xy * 2.0 - 1.0) * uResolution.xy / mr; uv += (uMouse - vec2(0.5)) * uAmplitude; float d = -uTime * 0.5 * uSpeed; float a = 0.0; for (float i = 0.0; i < 8.0; ++i) { a += cos(i - d - a * uv.x); d += sin(uv.y * i + a); } d += uTime * 0.5 * uSpeed; vec3 col = vec3(cos(uv * vec2(d, a)) * 0.6 + 0.4, cos(a + d) * 0.5 + 0.5); col = cos(col * cos(vec3(d, a, 2.5)) * 0.5 + 0.5) * uColor; gl_FragColor = vec4(col, 1.0); } `; export class IridescenceBackgroundComponent { constructor(ngZone) { this.ngZone = ngZone; /** 颜色 [r, g, b] 数组(0-1) */ this.ncColor = [0.5, 0.6, 0.8]; /** 动画速度倍率(0-2) */ this.ncSpeed = 1.0; /** 鼠标驱动效应的振幅 */ this.ncAmplitude = 0.1; /** 是否响应鼠标操作 */ this._mouseReact = true; this.renderer = null; this.scene = null; this.camera = null; this.material = null; this.mesh = null; this.rafId = null; this.resizeRafId = null; this.isVisible = true; this.mousePos = new THREE.Vector2(0.5, 0.5); } set ncMouseReact(val) { this._mouseReact = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncMouseReact() { return this._mouseReact; } ngOnInit() { } ngAfterViewInit() { this.initWebGL(); } ngOnDestroy() { this.cleanup(); } ngOnChanges(changes) { if (!this.material) return; if (changes['ncColor']) { this.material.uniforms['uColor'].value.setRGB(this.ncColor[0], this.ncColor[1], this.ncColor[2]); } if (changes['ncSpeed']) { this.material.uniforms['uSpeed'].value = this.ncSpeed; } if (changes['ncAmplitude']) { this.material.uniforms['uAmplitude'].value = this.ncAmplitude; } } // ─── 初始化 WebGL ────────────────────────────────────────────────────────── initWebGL() { const container = this.containerRef.nativeElement; this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); this.renderer.setClearColor(0xffffff, 1); // 限定最大 dpr,避免在超高分辨率屏幕上性能过低 this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); container.appendChild(this.renderer.domElement); this.scene = new THREE.Scene(); this.camera = new THREE.Camera(); // 空相机,不使用投影矩阵 const geometry = new THREE.PlaneGeometry(2, 2); this.material = new THREE.RawShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: { uTime: { value: 0 }, uColor: { value: new THREE.Color(this.ncColor[0], this.ncColor[1], this.ncColor[2]) }, uResolution: { value: new THREE.Vector3() }, uMouse: { value: this.mousePos }, uAmplitude: { value: this.ncAmplitude }, uSpeed: { value: this.ncSpeed } } }); this.mesh = new THREE.Mesh(geometry, this.material); this.scene.add(this.mesh); this.setupResizeObserver(container); this.setupIntersectionObserver(container); this.resize(); this.ngZone.runOutsideAngular(() => { this.startAnimation(); }); } // ─── Resize 处理 ────────────────────────────────────────────────────────── resize() { const container = this.containerRef.nativeElement; if (!container || !this.renderer || !this.material) return; const width = container.offsetWidth; const height = container.offsetHeight; this.renderer.setSize(width, height); const canvas = this.renderer.domElement; this.material.uniforms['uResolution'].value.set(canvas.width, canvas.height, canvas.width / canvas.height); } setupResizeObserver(container) { this.resizeObserver = new ResizeObserver(() => { if (this.resizeRafId !== null) cancelAnimationFrame(this.resizeRafId); this.ngZone.runOutsideAngular(() => { this.resizeRafId = requestAnimationFrame(() => { this.resize(); this.resizeRafId = null; }); }); }); this.resizeObserver.observe(container); } // ─── 渲染循环 ───────────────────────────────────────────────────────────── startAnimation() { const update = (t) => { this.rafId = requestAnimationFrame(update); if (this.isVisible && this.renderer && this.scene && this.camera && this.material) { this.material.uniforms['uTime'].value = t * 0.001; this.renderer.render(this.scene, this.camera); } }; update(performance.now()); } stopAnimation() { if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; } } // ─── IntersectionObserver:不可见时暂停渲染以节省性能 ──────────────────── setupIntersectionObserver(container) { this.intersectionObserver = new IntersectionObserver(entries => { const entry = entries[0]; this.isVisible = entry.isIntersecting && entry.intersectionRatio > 0; }, { threshold: [0, 0.01, 0.1] }); this.intersectionObserver.observe(container); } // ─── 清理资源 ───────────────────────────────────────────────────────────── cleanup() { var _a, _b; this.stopAnimation(); if (this.resizeRafId !== null) { cancelAnimationFrame(this.resizeRafId); this.resizeRafId = null; } try { (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); } catch (e) { void 0; } try { (_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect(); } catch (e) { void 0; } if (this.renderer) { const canvas = this.renderer.domElement; if (canvas && canvas.parentNode) { canvas.parentNode.removeChild(canvas); } this.renderer.dispose(); } if (this.material) { this.material.dispose(); } if (this.mesh && this.mesh.geometry) { this.mesh.geometry.dispose(); } this.renderer = null; this.scene = null; this.camera = null; this.material = null; this.mesh = null; } // ─── HostListeners for Mouse Interaction ───────────────────────────────── onMouseMove(event) { if (!this.ncMouseReact || !this.material || !this.containerRef) return; const container = this.containerRef.nativeElement; const rect = container.getBoundingClientRect(); if (rect.width === 0 || rect.height === 0) return; // 检查是否在容器内 if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) { return; } const x = (event.clientX - rect.left) / rect.width; const y = 1.0 - (event.clientY - rect.top) / rect.height; // 更新 THREE.Vector2 this.mousePos.set(x, y); } onTouchMove(event) { if (!this.ncMouseReact || !this.material || !this.containerRef || event.touches.length === 0) return; const container = this.containerRef.nativeElement; const rect = container.getBoundingClientRect(); if (rect.width === 0 || rect.height === 0) return; const touch = event.touches[0]; // 检查是否在容器内 if (touch.clientX < rect.left || touch.clientX > rect.right || touch.clientY < rect.top || touch.clientY > rect.bottom) { return; } const x = (touch.clientX - rect.left) / rect.width; const y = 1.0 - (touch.clientY - rect.top) / rect.height; // 更新 THREE.Vector2 this.mousePos.set(x, y); } } IridescenceBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: IridescenceBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); IridescenceBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: IridescenceBackgroundComponent, selector: "nc-iridescence-background", inputs: { ncColor: "ncColor", ncSpeed: "ncSpeed", ncAmplitude: "ncAmplitude", ncMouseReact: "ncMouseReact" }, host: { listeners: { "mousemove": "onMouseMove($event)", "touchmove": "onTouchMove($event)" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-iridescence-canvas-container\"></div>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-iridescence-canvas-container{position:absolute;inset:0;z-index:0}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: IridescenceBackgroundComponent, decorators: [{ type: Component, args: [{ selector: 'nc-iridescence-background', templateUrl: './iridescence-background.component.html', styleUrls: ['./iridescence-background.component.less'] }] }], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{ type: ViewChild, args: ['container', { static: true }] }], ncColor: [{ type: Input }], ncSpeed: [{ type: Input }], ncAmplitude: [{ type: Input }], ncMouseReact: [{ type: Input }], onMouseMove: [{ type: HostListener, args: ['mousemove', ['$event']] }], onTouchMove: [{ type: HostListener, args: ['touchmove', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXJpZGVzY2VuY2UtYmFja2dyb3VuZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2lyaWRlc2NlbmNlLWJhY2tncm91bmQvaXJpZGVzY2VuY2UtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2lyaWRlc2NlbmNlLWJhY2tncm91bmQvaXJpZGVzY2VuY2UtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQU1ULFNBQVMsRUFFVCxLQUFLLEVBQ0wsWUFBWSxFQUViLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sS0FBSyxLQUFLLE1BQU0sT0FBTyxDQUFDOztBQUUvQiwwRUFBMEU7QUFDMUUsTUFBTSxZQUFZLEdBQUc7Ozs7Ozs7Ozs7Q0FVcEIsQ0FBQztBQUVGLDBFQUEwRTtBQUMxRSxNQUFNLGNBQWMsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0E2QnRCLENBQUM7QUFPRixNQUFNLE9BQU8sOEJBQThCO0lBZ0N6QyxZQUFvQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQTdCbEMsMkJBQTJCO1FBQ2xCLFlBQU8sR0FBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDN0Msa0JBQWtCO1FBQ1QsWUFBTyxHQUFXLEdBQUcsQ0FBQztRQUMvQixnQkFBZ0I7UUFDUCxnQkFBVyxHQUFXLEdBQUcsQ0FBQztRQUNuQyxlQUFlO1FBQ1AsZ0JBQVcsR0FBWSxJQUFJLENBQUM7UUFTNUIsYUFBUSxHQUErQixJQUFJLENBQUM7UUFDNUMsVUFBSyxHQUF1QixJQUFJLENBQUM7UUFDakMsV0FBTSxHQUF3QixJQUFJLENBQUM7UUFDbkMsYUFBUSxHQUFtQyxJQUFJLENBQUM7UUFDaEQsU0FBSSxH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QkFBOEI7a0JBTDFDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDJCQUEyQjtvQkFDckMsV0FBVyxFQUFFLHlDQUF5QztvQkFDdEQsU0FBUyxFQUFFLENBQUMseUNBQXlDLENBQUM7aUJBQ3ZEOzZGQUUyQyxZQUFZO3NCQUFyRCxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRy9CLE9BQU87c0JBQWYsS0FBSztnQkFFRyxPQUFPO3NCQUFmLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFJRixZQUFZO3NCQURmLEtBQUs7Z0JBMkxOLFdBQVc7c0JBRFYsWUFBWTt1QkFBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBeUJyQyxXQUFXO3NCQURWLFlBQVk7dUJBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgT25Jbml0LFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG4gIElucHV0LFxyXG4gIEhvc3RMaXN0ZW5lcixcclxuICBOZ1pvbmVcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xyXG5cclxuLy8g4pSA4pSA4pSAIOmhtueCueedgOiJsuWZqCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuY29uc3QgdmVydGV4U2hhZGVyID0gYFxyXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcclxuYXR0cmlidXRlIHZlYzIgdXY7XHJcblxyXG52YXJ5aW5nIHZlYzIgdlV2O1xyXG5cclxudm9pZCBtYWluKCkge1xyXG4gIHZVdiA9IHV2O1xyXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiwgMS4wKTtcclxufVxyXG5gO1xyXG5cclxuLy8g4pSA4pSA4pSAIOeJh+WFg+edgOiJsuWZqCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuY29uc3QgZnJhZ21lbnRTaGFkZXIgPSBgXHJcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuXHJcbnVuaWZvcm0gZmxvYXQgdVRpbWU7XHJcbnVuaWZvcm0gdmVjMyB1Q29sb3I7XHJcbnVuaWZvcm0gdmVjMyB1UmVzb2x1dGlvbjtcclxudW5pZm9ybSB2ZWMyIHVNb3VzZTtcclxudW5pZm9ybSBmbG9hdCB1QW1wbGl0dWRlO1xyXG51bmlmb3JtIGZsb2F0IHVTcGVlZDtcclxuXHJcbnZhcnlpbmcgdmVjMiB2VXY7XHJcblxyXG52b2lkIG1haW4oKSB7XHJcbiAgZmxvYXQgbXIgPSBtaW4odVJlc29sdXRpb24ueCwgdVJlc29sdXRpb24ueSk7XHJcbiAgdmVjMiB1diA9ICh2VXYueHkgKiAyLjAgLSAxLjApICogdVJlc29sdXRpb24ueHkgLyBtcjtcclxuXHJcbiAgdXYgKz0gKHVNb3VzZSAtIHZlYzIoMC41KSkgKiB1QW1wbGl0dWRlO1xyXG5cclxuICBmbG9hdCBkID0gLXVUaW1lICogMC41ICogdVNwZWVkO1xyXG4gIGZsb2F0IGEgPSAwLjA7XHJcbiAgZm9yIChmbG9hdCBpID0gMC4wOyBpIDwgOC4wOyArK2kpIHtcclxuICAgIGEgKz0gY29zKGkgLSBkIC0gYSAqIHV2LngpO1xyXG4gICAgZCArPSBzaW4odXYueSAqIGkgKyBhKTtcclxuICB9XHJcbiAgZCArPSB1VGltZSAqIDAuNSAqIHVTcGVlZDtcclxuICB2ZWMzIGNvbCA9IHZlYzMoY29zKHV2ICogdmVjMihkLCBhKSkgKiAwLjYgKyAwLjQsIGNvcyhhICsgZCkgKiAwLjUgKyAwLjUpO1xyXG4gIGNvbCA9IGNvcyhjb2wgKiBjb3ModmVjMyhkLCBhLCAyLjUpKSAqIDAuNSArIDAuNSkgKiB1Q29sb3I7XHJcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChjb2wsIDEuMCk7XHJcbn1cclxuYDtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmMtaXJpZGVzY2VuY2UtYmFja2dyb3VuZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2lyaWRlc2NlbmNlLWJhY2tncm91bmQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2lyaWRlc2NlbmNlLWJhY2tncm91bmQuY29tcG9uZW50Lmxlc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgSXJpZGVzY2VuY2VCYWNrZ3JvdW5kQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XHJcbiAgQFZpZXdDaGlsZCgnY29udGFpbmVyJywgeyBzdGF0aWM6IHRydWUgfSkgY29udGFpbmVyUmVmITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XHJcblxyXG4gIC8qKiDpopzoibIgW3IsIGcsIGJdIOaVsOe7hO+8iDAtMe+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jQ29sb3I6IG51bWJlcltdID0gWzAuNSwgMC42LCAwLjhdO1xyXG4gIC8qKiDliqjnlLvpgJ/luqblgI3njofvvIgwLTLvvIkgKi9cclxuICBASW5wdXQoKSBuY1NwZWVkOiBudW1iZXIgPSAxLjA7XHJcbiAgLyoqIOm8oOagh+mpseWKqOaViOW6lOeahOaMr+W5hSAqL1xyXG4gIEBJbnB1dCgpIG5jQW1wbGl0dWRlOiBudW1iZXIgPSAwLjE7XHJcbiAgLyoqIOaYr+WQpuWTjeW6lOm8oOagh+aTjeS9nCAqL1xyXG4gIHByaXZhdGUgX21vdXNlUmVhY3Q6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IG5jTW91c2VSZWFjdCh2YWw6IGJvb2xlYW4gfCBzdHJpbmcpIHtcclxuICAgIHRoaXMuX21vdXNlUmVhY3QgPSB2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBmYWxzZSAmJiB2YWwgIT09ICdmYWxzZSc7XHJcbiAgfVxyXG4gIGdldCBuY01vdXNlUmVhY3QoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5fbW91c2VSZWFjdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVuZGVyZXI6IFRIUkVFLldlYkdMUmVuZGVyZXIgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIHNjZW5lOiBUSFJFRS5TY2VuZSB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgY2FtZXJhOiBUSFJFRS5DYW1lcmEgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIG1hdGVyaWFsOiBUSFJFRS5SYXdTaGFkZXJNYXRlcmlhbCB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgbWVzaDogVEhSRUUuTWVzaCB8IG51bGwgPSBudWxsO1xyXG5cclxuICBwcml2YXRlIHJhZklkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIHJlc2l6ZVJhZklkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIHJlc2l6ZU9ic2VydmVyITogUmVzaXplT2JzZXJ2ZXI7XHJcbiAgcHJpdmF0ZSBpbnRlcnNlY3Rpb25PYnNlcnZlciE6IEludGVyc2VjdGlvbk9ic2VydmVyO1xyXG4gIHByaXZhdGUgaXNWaXNpYmxlID0gdHJ1ZTtcclxuICBwcml2YXRlIG1vdXNlUG9zID0gbmV3IFRIUkVFLlZlY3RvcjIoMC41LCAwLjUpO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5nWm9uZTogTmdab25lKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7IH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbml0V2ViR0woKTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgdGhpcy5jbGVhbnVwKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMubWF0ZXJpYWwpIHJldHVybjtcclxuXHJcbiAgICBpZiAoY2hhbmdlc1snbmNDb2xvciddKSB7XHJcbiAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VDb2xvciddLnZhbHVlLnNldFJHQih0aGlzLm5jQ29sb3JbMF0sIHRoaXMubmNDb2xvclsxXSwgdGhpcy5uY0NvbG9yWzJdKTtcclxuICAgIH1cclxuICAgIGlmIChjaGFuZ2VzWyduY1NwZWVkJ10pIHtcclxuICAgICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVNwZWVkJ10udmFsdWUgPSB0aGlzLm5jU3BlZWQ7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1snbmNBbXBsaXR1ZGUnXSkge1xyXG4gICAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWyd1QW1wbGl0dWRlJ10udmFsdWUgPSB0aGlzLm5jQW1wbGl0dWRlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIOWIneWni+WMliBXZWJHTCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgcHJpdmF0ZSBpbml0V2ViR0woKTogdm9pZCB7XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG5cclxuICAgIHRoaXMucmVuZGVyZXIgPSBuZXcgVEhSRUUuV2ViR0xSZW5kZXJlcih7IGFudGlhbGlhczogdHJ1ZSwgYWxwaGE6IHRydWUgfSk7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnNldENsZWFyQ29sb3IoMHhmZmZmZmYsIDEpO1xyXG4gICAgLy8g6ZmQ5a6a5pyA5aSnIGRwcu+8jOmBv+WFjeWcqOi2hemrmOWIhui+qOeOh+Wxj+W5leS4iuaAp+iDvei/h+S9jlxyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRQaXhlbFJhdGlvKE1hdGgubWluKHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLCAyKSk7XHJcblxyXG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG4gICAgdGhpcy5jYW1lcmEgPSBuZXcgVEhSRUUuQ2FtZXJhKCk7IC8vIOepuuebuOacuu+8jOS4jeS9v+eUqOaKleW9seefqemYtVxyXG5cclxuICAgIGNvbnN0IGdlb21ldHJ5ID0gbmV3IFRIUkVFLlBsYW5lR2VvbWV0cnkoMiwgMik7XHJcbiAgICB0aGlzLm1hdGVyaWFsID0gbmV3IFRIUkVFLlJhd1NoYWRlck1hdGVyaWFsKHtcclxuICAgICAgdmVydGV4U2hhZGVyOiB2ZXJ0ZXhTaGFkZXIsXHJcbiAgICAgIGZyYWdtZW50U2hhZGVyOiBmcmFnbWVudFNoYWRlcixcclxuICAgICAgdW5pZm9ybXM6IHtcclxuICAgICAgICB1VGltZTogeyB2YWx1ZTogMCB9LFxyXG4gICAgICAgIHVDb2xvcjogeyB2YWx1ZTogbmV3IFRIUkVFLkNvbG9yKHRoaXMubmNDb2xvclswXSwgdGhpcy5uY0NvbG9yWzFdLCB0aGlzLm5jQ29sb3JbMl0pIH0sXHJcbiAgICAgICAgdVJlc29sdXRpb246IHsgdmFsdWU6IG5ldyBUSFJFRS5WZWN0b3IzKCkgfSxcclxuICAgICAgICB1TW91c2U6IHsgdmFsdWU6IHRoaXMubW91c2VQb3MgfSxcclxuICAgICAgICB1QW1wbGl0dWRlOiB7IHZhbHVlOiB0aGlzLm5jQW1wbGl0dWRlIH0sXHJcbiAgICAgICAgdVNwZWVkOiB7IHZhbHVlOiB0aGlzLm5jU3BlZWQgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLm1lc2ggPSBuZXcgVEhSRUUuTWVzaChnZW9tZXRyeSwgdGhpcy5tYXRlcmlhbCk7XHJcbiAgICB0aGlzLnNjZW5lLmFkZCh0aGlzLm1lc2gpO1xyXG5cclxuICAgIHRoaXMuc2V0dXBSZXNpemVPYnNlcnZlcihjb250YWluZXIpO1xyXG4gICAgdGhpcy5zZXR1cEludGVyc2VjdGlvbk9ic2VydmVyKGNvbnRhaW5lcik7XHJcblxyXG4gICAgdGhpcy5yZXNpemUoKTtcclxuICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgdGhpcy5zdGFydEFuaW1hdGlvbigpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgUmVzaXplIOWkhOeQhiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgcHJpdmF0ZSByZXNpemUoKTogdm9pZCB7XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgaWYgKCFjb250YWluZXIgfHwgIXRoaXMucmVuZGVyZXIgfHwgIXRoaXMubWF0ZXJpYWwpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCB3aWR0aCA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aDtcclxuICAgIGNvbnN0IGhlaWdodCA9IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xyXG5cclxuICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudDtcclxuICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VSZXNvbHV0aW9uJ10udmFsdWUuc2V0KFxyXG4gICAgICBjYW52YXMud2lkdGgsXHJcbiAgICAgIGNhbnZhcy5oZWlnaHQsXHJcbiAgICAgIGNhbnZhcy53aWR0aCAvIGNhbnZhcy5oZWlnaHRcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwUmVzaXplT2JzZXJ2ZXIoY29udGFpbmVyOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLnJlc2l6ZVJhZklkICE9PSBudWxsKSBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJlc2l6ZVJhZklkKTtcclxuICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVzaXplUmFmSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5yZXNpemUoKTtcclxuICAgICAgICAgIHRoaXMucmVzaXplUmFmSWQgPSBudWxsO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lcik7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAg5riy5p+T5b6q546vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBwcml2YXRlIHN0YXJ0QW5pbWF0aW9uKCk6IHZvaWQge1xyXG4gICAgY29uc3QgdXBkYXRlID0gKHQ6IG51bWJlcikgPT4ge1xyXG4gICAgICB0aGlzLnJhZklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHVwZGF0ZSk7XHJcbiAgICAgIGlmICh0aGlzLmlzVmlzaWJsZSAmJiB0aGlzLnJlbmRlcmVyICYmIHRoaXMuc2NlbmUgJiYgdGhpcy5jYW1lcmEgJiYgdGhpcy5tYXRlcmlhbCkge1xyXG4gICAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VUaW1lJ10udmFsdWUgPSB0ICogMC4wMDE7XHJcbiAgICAgICAgdGhpcy5yZW5kZXJlci5yZW5kZXIodGhpcy5zY2VuZSwgdGhpcy5jYW1lcmEpO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgdXBkYXRlKHBlcmZvcm1hbmNlLm5vdygpKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RvcEFuaW1hdGlvbigpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnJhZklkICE9PSBudWxsKSB7XHJcbiAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmFmSWQpO1xyXG4gICAgICB0aGlzLnJhZklkID0gbnVsbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBJbnRlcnNlY3Rpb25PYnNlcnZlcu+8muS4jeWPr+ingeaXtuaaguWBnOa4suafk+S7peiKguecgeaAp+iDvSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgcHJpdmF0ZSBzZXR1cEludGVyc2VjdGlvbk9ic2VydmVyKGNvbnRhaW5lcjogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuICAgIHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIgPSBuZXcgSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoZW50cmllcyA9PiB7XHJcbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1swXTtcclxuICAgICAgdGhpcy5pc1Zpc2libGUgPSBlbnRyeS5pc0ludGVyc2VjdGluZyAmJiBlbnRyeS5pbnRlcnNlY3Rpb25SYXRpbyA+IDA7XHJcbiAgICB9LCB7IHRocmVzaG9sZDogWzAsIDAuMDEsIDAuMV0gfSk7XHJcbiAgICB0aGlzLmludGVyc2VjdGlvbk9ic2VydmVyLm9ic2VydmUoY29udGFpbmVyKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCDmuIXnkIbotYTmupAg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHByaXZhdGUgY2xlYW51cCgpOiB2b2lkIHtcclxuICAgIHRoaXMuc3RvcEFuaW1hdGlvbigpO1xyXG5cclxuICAgIGlmICh0aGlzLnJlc2l6ZVJhZklkICE9PSBudWxsKSB7XHJcbiAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmVzaXplUmFmSWQpO1xyXG4gICAgICB0aGlzLnJlc2l6ZVJhZklkID0gbnVsbDtcclxuICAgIH1cclxuICAgIHRyeSB7IHRoaXMucmVzaXplT2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTsgfSBjYXRjaCAoZSkgeyB2b2lkIDA7IH1cclxuICAgIHRyeSB7IHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTsgfSBjYXRjaCAoZSkgeyB2b2lkIDA7IH1cclxuXHJcbiAgICBpZiAodGhpcy5yZW5kZXJlcikge1xyXG4gICAgICBjb25zdCBjYW52YXMgPSB0aGlzLnJlbmRlcmVyLmRvbUVsZW1lbnQ7XHJcbiAgICAgIGlmIChjYW52YXMgJiYgY2FudmFzLnBhcmVudE5vZGUpIHtcclxuICAgICAgICBjYW52YXMucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChjYW52YXMpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMucmVuZGVyZXIuZGlzcG9zZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm1hdGVyaWFsKSB7XHJcbiAgICAgIHRoaXMubWF0ZXJpYWwuZGlzcG9zZSgpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMubWVzaCAmJiB0aGlzLm1lc2guZ2VvbWV0cnkpIHtcclxuICAgICAgdGhpcy5tZXNoLmdlb21ldHJ5LmRpc3Bvc2UoKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyID0gbnVsbDtcclxuICAgIHRoaXMuc2NlbmUgPSBudWxsO1xyXG4gICAgdGhpcy5jYW1lcmEgPSBudWxsO1xyXG4gICAgdGhpcy5tYXRlcmlhbCA9IG51bGw7XHJcbiAgICB0aGlzLm1lc2ggPSBudWxsO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIEhvc3RMaXN0ZW5lcnMgZm9yIE1vdXNlIEludGVyYWN0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBASG9zdExpc3RlbmVyKCdtb3VzZW1vdmUnLCBbJyRldmVudCddKVxyXG4gIG9uTW91c2VNb3ZlKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMubmNNb3VzZVJlYWN0IHx8ICF0aGlzLm1hdGVyaWFsIHx8ICF0aGlzLmNvbnRhaW5lclJlZikgcmV0dXJuO1xyXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuICAgIGNvbnN0IHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcbiAgICBpZiAocmVjdC53aWR0aCA9PT0gMCB8fCByZWN0LmhlaWdodCA9PT0gMCkgcmV0dXJuO1xyXG5cclxuICAgIC8vIOajgOafpeaYr+WQpuWcqOWuueWZqOWGhVxyXG4gICAgaWYgKFxyXG4gICAgICBldmVudC5jbGllbnRYIDwgcmVjdC5sZWZ0IHx8XHJcbiAgICAgIGV2ZW50LmNsaWVudFggPiByZWN0LnJpZ2h0IHx8XHJcbiAgICAgIGV2ZW50LmNsaWVudFkgPCByZWN0LnRvcCB8fFxyXG4gICAgICBldmVudC5jbGllbnRZID4gcmVjdC5ib3R0b21cclxuICAgICkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeCA9IChldmVudC5jbGllbnRYIC0gcmVjdC5sZWZ0KSAvIHJlY3Qud2lkdGg7XHJcbiAgICBjb25zdCB5ID0gMS4wIC0gKGV2ZW50LmNsaWVudFkgLSByZWN0LnRvcCkgLyByZWN0LmhlaWdodDtcclxuXHJcbiAgICAvLyDmm7TmlrAgVEhSRUUuVmVjdG9yMlxyXG4gICAgdGhpcy5tb3VzZVBvcy5zZXQoeCwgeSk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd0b3VjaG1vdmUnLCBbJyRldmVudCddKVxyXG4gIG9uVG91Y2hNb3ZlKGV2ZW50OiBUb3VjaEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMubmNNb3VzZVJlYWN0IHx8ICF0aGlzLm1hdGVyaWFsIHx8ICF0aGlzLmNvbnRhaW5lclJlZiB8fCBldmVudC50b3VjaGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuICAgIGNvbnN0IHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcbiAgICBpZiAocmVjdC53aWR0aCA9PT0gMCB8fCByZWN0LmhlaWdodCA9PT0gMCkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IHRvdWNoID0gZXZlbnQudG91Y2hlc1swXTtcclxuXHJcbiAgICAvLyDmo4Dmn6XmmK/lkKblnKjlrrnlmajlhoVcclxuICAgIGlmIChcclxuICAgICAgdG91Y2guY2xpZW50WCA8IHJlY3QubGVmdCB8fFxyXG4gICAgICB0b3VjaC5jbGllbnRYID4gcmVjdC5yaWdodCB8fFxyXG4gICAgICB0b3VjaC5jbGllbnRZIDwgcmVjdC50b3AgfHxcclxuICAgICAgdG91Y2guY2xpZW50WSA+IHJlY3QuYm90dG9tXHJcbiAgICApIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHggPSAodG91Y2guY2xpZW50WCAtIHJlY3QubGVmdCkgLyByZWN0LndpZHRoO1xyXG4gICAgY29uc3QgeSA9IDEuMCAtICh0b3VjaC5jbGllbnRZIC0gcmVjdC50b3ApIC8gcmVjdC5oZWlnaHQ7XHJcblxyXG4gICAgLy8g5pu05pawIFRIUkVFLlZlY3RvcjJcclxuICAgIHRoaXMubW91c2VQb3Muc2V0KHgsIHkpO1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2ICNjb250YWluZXIgY2xhc3M9XCJuYy1pcmlkZXNjZW5jZS1jYW52YXMtY29udGFpbmVyXCI+PC9kaXY+XHJcbjxkaXYgY2xhc3M9XCJuYy1jb250ZW50LXdyYXBwZXJcIj5cclxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuPC9kaXY+Il19