UNPKG

ngx-extended-pdf-viewer

Version:

Embedding PDF files in your Angular application. Highly configurable viewer including the toolbar, sidebar, and all the features you're used to.

181 lines 22.4 kB
import { Injectable } from '@angular/core'; import { pdfDefaultOptions } from '../options/pdf-default-options'; import * as i0 from "@angular/core"; /** * Pure Angular service for iOS Safari pinch-to-zoom optimization * Works by dynamically adjusting the maxCanvasPixels option during touch gestures * This approach is compatible with the existing mypdf.js MaxCanvasSize class */ export class IOSCanvasOptimizationService { ngZone; PDFViewerApplication; isInitialized = false; isPinching = false; cooldownTimer = null; originalMaxCanvasPixels; reducedMaxCanvasPixels; // Configuration cooldownDuration = 2000; // 2 seconds reductionFactor = 0.25; // Reduce to 25% during pinch iosMaxCanvasPixels = 5242880; // PDF.js iOS limit (5MP) constructor(ngZone) { this.ngZone = ngZone; // Store original canvas size this.originalMaxCanvasPixels = pdfDefaultOptions.maxCanvasPixels || this.getDefaultCanvasSize(); this.reducedMaxCanvasPixels = Math.min(this.originalMaxCanvasPixels * this.reductionFactor, this.iosMaxCanvasPixels); } /** * Initialize the service with PDFViewerApplication * Called from NgxExtendedPdfViewerComponent.initialize() */ initialize(pdfViewerApplication) { if (this.isInitialized || typeof window === 'undefined') return; this.PDFViewerApplication = pdfViewerApplication; this.ngZone.runOutsideAngular(() => { this.setupTouchListeners(); this.isInitialized = true; }); } getDefaultCanvasSize() { const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window); const isMobile = /Android|iPhone|iPad|iPod/.test(navigator.userAgent); if (isIOS || isMobile) { return this.iosMaxCanvasPixels; // Use PDF.js iOS limit } return 33554432; // PDF.js desktop default (32MP) } setupTouchListeners() { // Listen for pinch-to-zoom gestures window.addEventListener('touchstart', (e) => { if (e.touches.length === 2) { this.onPinchStart(); } }, { passive: true }); window.addEventListener('touchend', (e) => { if (e.touches.length < 2 && this.isPinching) { this.onPinchEnd(); } }, { passive: true }); window.addEventListener('touchcancel', () => { if (this.isPinching) { this.onPinchEnd(); } }, { passive: true }); } onPinchStart() { if (this.isPinching) return; this.isPinching = true; this.clearCooldown(); // Reduce canvas resolution immediately for smooth pinching this.updateCanvasSize(this.reducedMaxCanvasPixels); } onPinchEnd() { if (!this.isPinching) return; this.isPinching = false; this.startCooldown(); } startCooldown() { this.clearCooldown(); this.cooldownTimer = setTimeout(() => { // Restore full resolution after cooldown this.updateCanvasSize(this.originalMaxCanvasPixels); }, this.cooldownDuration); } clearCooldown() { if (this.cooldownTimer) { clearTimeout(this.cooldownTimer); this.cooldownTimer = null; } } updateCanvasSize(maxCanvasPixels) { // Update the pdfDefaultOptions to affect new renders pdfDefaultOptions.maxCanvasPixels = maxCanvasPixels; // Update existing PDF.js instances if available if (this.PDFViewerApplication) { // Update main viewer if (this.PDFViewerApplication.pdfViewer) { this.PDFViewerApplication.pdfViewer.maxCanvasPixels = maxCanvasPixels; } // Update thumbnail viewer if (this.PDFViewerApplication.pdfThumbnailViewer) { this.PDFViewerApplication.pdfThumbnailViewer.maxCanvasPixels = maxCanvasPixels; } // Trigger a gentle re-render of visible pages only during transitions // (not during active pinching to avoid performance issues) if (!this.isPinching) { setTimeout(() => this.triggerVisiblePageRerender(), 100); } } } triggerVisiblePageRerender() { if (!this.PDFViewerApplication?.pdfViewer) return; const pdfViewer = this.PDFViewerApplication.pdfViewer; // Only re-render currently visible pages to minimize performance impact pdfViewer._pages?.forEach((pageView) => { if (pageView && this.isPageVisible(pageView)) { // Gently trigger re-render by invalidating the current render if (pageView.renderingState === 3 /* FINISHED */) { pageView.reset(); // Let the normal rendering queue handle the re-render if (pdfViewer.renderingQueue) { pdfViewer.renderingQueue.renderView(pageView); } } } }); } isPageVisible(pageView) { if (!pageView?.div) return false; const rect = pageView.div.getBoundingClientRect(); const viewHeight = window.innerHeight || document.documentElement.clientHeight; const viewWidth = window.innerWidth || document.documentElement.clientWidth; return (rect.bottom >= 0 && rect.right >= 0 && rect.top <= viewHeight && rect.left <= viewWidth); } /** * Get current canvas size setting */ getCurrentCanvasSize() { return pdfDefaultOptions.maxCanvasPixels || this.originalMaxCanvasPixels; } /** * Check if currently in pinch mode */ isPinchingActive() { return this.isPinching; } /** * Manually override the canvas size (for advanced users) */ setCanvasSize(maxCanvasPixels) { this.originalMaxCanvasPixels = maxCanvasPixels; this.reducedMaxCanvasPixels = Math.min(maxCanvasPixels * this.reductionFactor, this.iosMaxCanvasPixels); if (!this.isPinching) { this.updateCanvasSize(maxCanvasPixels); } } /** * Cleanup when service is destroyed */ destroy() { this.clearCooldown(); this.isInitialized = false; // Touch listeners will be cleaned up when window is destroyed } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IOSCanvasOptimizationService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IOSCanvasOptimizationService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IOSCanvasOptimizationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i0.NgZone }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW9zLWNhbnZhcy1vcHRpbWl6YXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvc2VydmljZXMvaW9zLWNhbnZhcy1vcHRpbWl6YXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBRW5ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDOztBQUVuRTs7OztHQUlHO0FBSUgsTUFBTSxPQUFPLDRCQUE0QjtJQWFuQjtJQVpaLG9CQUFvQixDQUFvQztJQUN4RCxhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLFVBQVUsR0FBRyxLQUFLLENBQUM7SUFDbkIsYUFBYSxHQUFRLElBQUksQ0FBQztJQUMxQix1QkFBdUIsQ0FBUztJQUNoQyxzQkFBc0IsQ0FBUztJQUV2QyxnQkFBZ0I7SUFDQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsQ0FBQyxZQUFZO0lBQ3JDLGVBQWUsR0FBRyxJQUFJLENBQUMsQ0FBQyw2QkFBNkI7SUFDckQsa0JBQWtCLEdBQUcsT0FBTyxDQUFDLENBQUMseUJBQXlCO0lBRXhFLFlBQW9CLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2hDLDZCQUE2QjtRQUM3QixJQUFJLENBQUMsdUJBQXVCLEdBQUcsaUJBQWlCLENBQUMsZUFBZSxJQUFJLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQ2hHLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUNwQyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFDbkQsSUFBSSxDQUFDLGtCQUFrQixDQUN4QixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILFVBQVUsQ0FBQyxvQkFBMkM7UUFDcEQs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LElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3BCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsQ0FBQztTQUN4QztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILE9BQU87UUFDTCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDM0IsOERBQThEO0lBQ2hFLENBQUM7d0dBbk1VLDRCQUE0Qjs0R0FBNUIsNEJBQTRCLGNBRjNCLE1BQU07OzRGQUVQLDRCQUE0QjtrQkFIeEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBOZ1pvbmUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElQREZWaWV3ZXJBcHBsaWNhdGlvbiB9IGZyb20gJy4uL29wdGlvbnMvcGRmLXZpZXdlci1hcHBsaWNhdGlvbic7XG5pbXBvcnQgeyBwZGZEZWZhdWx0T3B0aW9ucyB9IGZyb20gJy4uL29wdGlvbnMvcGRmLWRlZmF1bHQtb3B0aW9ucyc7XG5cbi8qKlxuICogUHVyZSBBbmd1bGFyIHNlcnZpY2UgZm9yIGlPUyBTYWZhcmkgcGluY2gtdG8tem9vbSBvcHRpbWl6YXRpb25cbiAqIFdvcmtzIGJ5IGR5bmFtaWNhbGx5IGFkanVzdGluZyB0aGUgbWF4Q2FudmFzUGl4ZWxzIG9wdGlvbiBkdXJpbmcgdG91Y2ggZ2VzdHVyZXNcbiAqIFRoaXMgYXBwcm9hY2ggaXMgY29tcGF0aWJsZSB3aXRoIHRoZSBleGlzdGluZyBteXBkZi5qcyBNYXhDYW52YXNTaXplIGNsYXNzXG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIElPU0NhbnZhc09wdGltaXphdGlvblNlcnZpY2Uge1xuICBwcml2YXRlIFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgaXNJbml0aWFsaXplZCA9IGZhbHNlO1xuICBwcml2YXRlIGlzUGluY2hpbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBjb29sZG93blRpbWVyOiBhbnkgPSBudWxsO1xuICBwcml2YXRlIG9yaWdpbmFsTWF4Q2FudmFzUGl4ZWxzOiBudW1iZXI7XG4gIHByaXZhdGUgcmVkdWNlZE1heENhbnZhc1BpeGVsczogbnVtYmVyO1xuXG4gIC8vIENvbmZpZ3VyYXRpb25cbiAgcHJpdmF0ZSByZWFkb25seSBjb29sZG93bkR1cmF0aW9uID0gMjAwMDsgLy8gMiBzZWNvbmRzXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVkdWN0aW9uRmFjdG9yID0gMC4yNTsgLy8gUmVkdWNlIHRvIDI1JSBkdXJpbmcgcGluY2hcbiAgcHJpdmF0ZSByZWFkb25seSBpb3NNYXhDYW52YXNQaXhlbHMgPSA1MjQyODgwOyAvLyBQREYuanMgaU9TIGxpbWl0ICg1TVApXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSkge1xuICAgIC8vIFN0b3JlIG9yaWdpbmFsIGNhbnZhcyBzaXplXG4gICAgdGhpcy5vcmlnaW5hbE1heENhbnZhc1BpeGVscyA9IHBkZkRlZmF1bHRPcHRpb25zLm1heENhbnZhc1BpeGVscyB8fCB0aGlzLmdldERlZmF1bHRDYW52YXNTaXplKCk7XG4gICAgdGhpcy5yZWR1Y2VkTWF4Q2FudmFzUGl4ZWxzID0gTWF0aC5taW4oXG4gICAgICB0aGlzLm9yaWdpbmFsTWF4Q2FudmFzUGl4ZWxzICogdGhpcy5yZWR1Y3Rpb25GYWN0b3IsXG4gICAgICB0aGlzLmlvc01heENhbnZhc1BpeGVsc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgc2VydmljZSB3aXRoIFBERlZpZXdlckFwcGxpY2F0aW9uXG4gICAqIENhbGxlZCBmcm9tIE5neEV4dGVuZGVkUGRmVmlld2VyQ29tcG9uZW50LmluaXRpYWxpemUoKVxuICAgKi9cbiAgaW5pdGlhbGl6ZShwZGZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCB8fCB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykgcmV0dXJuO1xuXG4gICAgdGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbiA9IHBkZlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIHRoaXMuc2V0dXBUb3VjaExpc3RlbmVycygpO1xuICAgICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGVmYXVsdENhbnZhc1NpemUoKTogbnVtYmVyIHtcbiAgICBjb25zdCBpc0lPUyA9IC9pUGFkfGlQaG9uZXxpUG9kLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpICYmICEoJ01TU3RyZWFtJyBpbiB3aW5kb3cpO1xuICAgIGNvbnN0IGlzTW9iaWxlID0gL0FuZHJvaWR8aVBob25lfGlQYWR8aVBvZC8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICBcbiAgICBpZiAoaXNJT1MgfHwgaXNNb2JpbGUpIHtcbiAgICAgIHJldHVybiB0aGlzLmlvc01heENhbnZhc1BpeGVsczsgLy8gVXNlIFBERi5qcyBpT1MgbGltaXRcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIDMzNTU0NDMyOyAvLyBQREYuanMgZGVza3RvcCBkZWZhdWx0ICgzMk1QKVxuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cFRvdWNoTGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIC8vIExpc3RlbiBmb3IgcGluY2gtdG8tem9vbSBnZXN0dXJlc1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgKGUpID0+IHtcbiAgICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgIHRoaXMub25QaW5jaFN0YXJ0KCk7XG4gICAgICB9XG4gICAgfSwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgKGUpID0+IHtcbiAgICAgIGlmIChlLnRvdWNoZXMubGVuZ3RoIDwgMiAmJiB0aGlzLmlzUGluY2hpbmcpIHtcbiAgICAgICAgdGhpcy5vblBpbmNoRW5kKCk7XG4gICAgICB9XG4gICAgfSwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoY2FuY2VsJywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuaXNQaW5jaGluZykge1xuICAgICAgICB0aGlzLm9uUGluY2hFbmQoKTtcbiAgICAgIH1cbiAgICB9LCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gIH1cblxuICBwcml2YXRlIG9uUGluY2hTdGFydCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1BpbmNoaW5nKSByZXR1cm47XG5cbiAgICB0aGlzLmlzUGluY2hpbmcgPSB0cnVlO1xuICAgIHRoaXMuY2xlYXJDb29sZG93bigpO1xuICAgIFxuICAgIC8vIFJlZHVjZSBjYW52YXMgcmVzb2x1dGlvbiBpbW1lZGlhdGVseSBmb3Igc21vb3RoIHBpbmNoaW5nXG4gICAgdGhpcy51cGRhdGVDYW52YXNTaXplKHRoaXMucmVkdWNlZE1heENhbnZhc1BpeGVscyk7XG4gIH1cblxuICBwcml2YXRlIG9uUGluY2hFbmQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzUGluY2hpbmcpIHJldHVybjtcblxuICAgIHRoaXMuaXNQaW5jaGluZyA9IGZhbHNlO1xuICAgIHRoaXMuc3RhcnRDb29sZG93bigpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGFydENvb2xkb3duKCk6IHZvaWQge1xuICAgIHRoaXMuY2xlYXJDb29sZG93bigpO1xuICAgIHRoaXMuY29vbGRvd25UaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gUmVzdG9yZSBmdWxsIHJlc29sdXRpb24gYWZ0ZXIgY29vbGRvd25cbiAgICAgIHRoaXMudXBkYXRlQ2FudmFzU2l6ZSh0aGlzLm9yaWdpbmFsTWF4Q2FudmFzUGl4ZWxzKTtcbiAgICB9LCB0aGlzLmNvb2xkb3duRHVyYXRpb24pO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhckNvb2xkb3duKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNvb2xkb3duVGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmNvb2xkb3duVGltZXIpO1xuICAgICAgdGhpcy5jb29sZG93blRpbWVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUNhbnZhc1NpemUobWF4Q2FudmFzUGl4ZWxzOiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBVcGRhdGUgdGhlIHBkZkRlZmF1bHRPcHRpb25zIHRvIGFmZmVjdCBuZXcgcmVuZGVyc1xuICAgIHBkZkRlZmF1bHRPcHRpb25zLm1heENhbnZhc1BpeGVscyA9IG1heENhbnZhc1BpeGVscztcblxuICAgIC8vIFVwZGF0ZSBleGlzdGluZyBQREYuanMgaW5zdGFuY2VzIGlmIGF2YWlsYWJsZVxuICAgIGlmICh0aGlzLlBERlZpZXdlckFwcGxpY2F0aW9uKSB7XG4gICAgICAvLyBVcGRhdGUgbWFpbiB2aWV3ZXJcbiAgICAgIGlmICh0aGlzLlBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlcikge1xuICAgICAgICB0aGlzLlBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlci5tYXhDYW52YXNQaXhlbHMgPSBtYXhDYW52YXNQaXhlbHM7XG4gICAgICB9XG5cbiAgICAgIC8vIFVwZGF0ZSB0aHVtYm5haWwgdmlld2VyXG4gICAgICBpZiAodGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZUaHVtYm5haWxWaWV3ZXIpIHtcbiAgICAgICAgdGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZUaHVtYm5haWxWaWV3ZXIubWF4Q2FudmFzUGl4ZWxzID0gbWF4Q2FudmFzUGl4ZWxzO1xuICAgICAgfVxuXG4gICAgICAvLyBUcmlnZ2VyIGEgZ2VudGxlIHJlLXJlbmRlciBvZiB2aXNpYmxlIHBhZ2VzIG9ubHkgZHVyaW5nIHRyYW5zaXRpb25zXG4gICAgICAvLyAobm90IGR1cmluZyBhY3RpdmUgcGluY2hpbmcgdG8gYXZvaWQgcGVyZm9ybWFuY2UgaXNzdWVzKVxuICAgICAgaWYgKCF0aGlzLmlzUGluY2hpbmcpIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnRyaWdnZXJWaXNpYmxlUGFnZVJlcmVuZGVyKCksIDEwMCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB0cmlnZ2VyVmlzaWJsZVBhZ2VSZXJlbmRlcigpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuUERGVmlld2VyQXBwbGljYXRpb24/LnBkZlZpZXdlcikgcmV0dXJuO1xuXG4gICAgY29uc3QgcGRmVmlld2VyID0gdGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZWaWV3ZXI7XG4gICAgXG4gICAgLy8gT25seSByZS1yZW5kZXIgY3VycmVudGx5IHZpc2libGUgcGFnZXMgdG8gbWluaW1pemUgcGVyZm9ybWFuY2UgaW1wYWN0XG4gICAgcGRmVmlld2VyLl9wYWdlcz8uZm9yRWFjaCgocGFnZVZpZXc6IGFueSkgPT4ge1xuICAgICAgaWYgKHBhZ2VWaWV3ICYmIHRoaXMuaXNQYWdlVmlzaWJsZShwYWdlVmlldykpIHtcbiAgICAgICAgLy8gR2VudGx5IHRyaWdnZXIgcmUtcmVuZGVyIGJ5IGludmFsaWRhdGluZyB0aGUgY3VycmVudCByZW5kZXJcbiAgICAgICAgaWYgKHBhZ2VWaWV3LnJlbmRlcmluZ1N0YXRlID09PSAzIC8qIEZJTklTSEVEICovKSB7XG4gICAgICAgICAgcGFnZVZpZXcucmVzZXQoKTtcbiAgICAgICAgICAvLyBMZXQgdGhlIG5vcm1hbCByZW5kZXJpbmcgcXVldWUgaGFuZGxlIHRoZSByZS1yZW5kZXJcbiAgICAgICAgICBpZiAocGRmVmlld2VyLnJlbmRlcmluZ1F1ZXVlKSB7XG4gICAgICAgICAgICBwZGZWaWV3ZXIucmVuZGVyaW5nUXVldWUucmVuZGVyVmlldyhwYWdlVmlldyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGlzUGFnZVZpc2libGUocGFnZVZpZXc6IGFueSk6IGJvb2xlYW4ge1xuICAgIGlmICghcGFnZVZpZXc/LmRpdikgcmV0dXJuIGZhbHNlO1xuICAgIFxuICAgIGNvbnN0IHJlY3QgPSBwYWdlVmlldy5kaXYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3Qgdmlld0hlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIGNvbnN0IHZpZXdXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aDtcbiAgICBcbiAgICByZXR1cm4gKFxuICAgICAgcmVjdC5ib3R0b20gPj0gMCAmJlxuICAgICAgcmVjdC5yaWdodCA+PSAwICYmXG4gICAgICByZWN0LnRvcCA8PSB2aWV3SGVpZ2h0ICYmXG4gICAgICByZWN0LmxlZnQgPD0gdmlld1dpZHRoXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCBjYW52YXMgc2l6ZSBzZXR0aW5nXG4gICAqL1xuICBnZXRDdXJyZW50Q2FudmFzU2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiBwZGZEZWZhdWx0T3B0aW9ucy5tYXhDYW52YXNQaXhlbHMgfHwgdGhpcy5vcmlnaW5hbE1heENhbnZhc1BpeGVscztcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBjdXJyZW50bHkgaW4gcGluY2ggbW9kZVxuICAgKi9cbiAgaXNQaW5jaGluZ0FjdGl2ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc1BpbmNoaW5nO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hbnVhbGx5IG92ZXJyaWRlIHRoZSBjYW52YXMgc2l6ZSAoZm9yIGFkdmFuY2VkIHVzZXJzKVxuICAgKi9cbiAgc2V0Q2FudmFzU2l6ZShtYXhDYW52YXNQaXhlbHM6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMub3JpZ2luYWxNYXhDYW52YXNQaXhlbHMgPSBtYXhDYW52YXNQaXhlbHM7XG4gICAgdGhpcy5yZWR1Y2VkTWF4Q2FudmFzUGl4ZWxzID0gTWF0aC5taW4oXG4gICAgICBtYXhDYW52YXNQaXhlbHMgKiB0aGlzLnJlZHVjdGlvbkZhY3RvcixcbiAgICAgIHRoaXMuaW9zTWF4Q2FudmFzUGl4ZWxzXG4gICAgKTtcbiAgICBcbiAgICBpZiAoIXRoaXMuaXNQaW5jaGluZykge1xuICAgICAgdGhpcy51cGRhdGVDYW52YXNTaXplKG1heENhbnZhc1BpeGVscyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsZWFudXAgd2hlbiBzZXJ2aWNlIGlzIGRlc3Ryb3llZFxuICAgKi9cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmNsZWFyQ29vbGRvd24oKTtcbiAgICB0aGlzLmlzSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICAvLyBUb3VjaCBsaXN0ZW5lcnMgd2lsbCBiZSBjbGVhbmVkIHVwIHdoZW4gd2luZG93IGlzIGRlc3Ryb3llZFxuICB9XG59Il19