// Native Chromium PDF viewer using a single persistent iframe. class NativePdfViewer { constructor(frame, container) { this.frame = frame; this.container = container; this.generation = 0; this.currentKey = null; this.lastUrl = null; this.loadTimer = null; this._onLoad = null; this._createDOM(); } _createDOM() { this.loadingDiv = document.createElement("div"); this.loadingDiv.className = "native-pdf-loading"; this.loadingDiv.textContent = "Loading PDF\u2026"; this.container.appendChild(this.loadingDiv); this.errorDiv = document.createElement("div"); //this.errorDiv.className = "native-pdf-error"; this.errorMsg = document.createElement("div"); this.errorMsg.className = "native-pdf-error-msg"; this.errorDiv.appendChild(this.errorMsg); this.retryBtn = document.createElement("button"); this.retryBtn.className = "native-pdf-retry"; this.retryBtn.textContent = "Retry"; this.retryBtn.addEventListener("click", () => { if (this.lastUrl && this.currentKey) { this._navigate(this.lastUrl, this.currentKey, true); } }); this.errorDiv.appendChild(this.retryBtn); this.container.appendChild(this.errorDiv); } _showState(state) { this.loadingDiv.classList.toggle("is-visible", state === "loading"); this.errorDiv.classList.toggle("is-visible", state === "error"); } load(url, _byteSize, key) { this._navigate(url, key, false); } _navigate(url, key, force) { if (!force && key && key === this.currentKey) return; const generation = ++this.generation; this.currentKey = key; this.lastUrl = url; // Clear old error text, show loading badge this.errorMsg.textContent = ""; this._showState("loading"); // Shared hide function, idempotent per navigation const hideLoading = () => { if (generation !== this.generation) return; if (this.loadTimer) { clearTimeout(this.loadTimer); this.loadTimer = null; } this._showState("loaded"); }; // Optional early signal from iframe load event if (this._onLoad) this.frame.removeEventListener("load", this._onLoad); this._onLoad = hideLoading; this.frame.addEventListener("load", hideLoading, { once: true }); // Fallback: hide loading after 800ms regardless of load event if (this.loadTimer) clearTimeout(this.loadTimer); this.loadTimer = setTimeout(hideLoading, 800); this.frame.src = url; } destroy() { if (this.loadTimer) clearTimeout(this.loadTimer); if (this._onLoad) this.frame.removeEventListener("load", this._onLoad); this.generation = 0; this.frame.src = ""; this._showState("loading"); } } globalThis.NativePdfViewer = NativePdfViewer;