From cc7858b536da589e577de5b74839df637d8b05e7 Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Mon, 26 Oct 2026 10:51:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=89=B9=E9=87=8F=E8=BD=AC=E6=8D=A2=E5=8F=8A?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=89=93=E5=BC=80=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/webui/ofdgo.js | 43 +++++++++++++++++++++++++------------- assets/webui/ofdgo_util.js | 16 +++++++------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/assets/webui/ofdgo.js b/assets/webui/ofdgo.js index 6f897b0..e1148e6 100644 --- a/assets/webui/ofdgo.js +++ b/assets/webui/ofdgo.js @@ -1920,7 +1920,7 @@ function handleKeyDown(event) { } if (nativeHost && (event.ctrlKey || event.metaKey) && (key === "Tab" || key.toLowerCase() === "w")) { event.preventDefault(); - if (document.body.hasAttribute("data-busy") || documentDialogs?.applicationOpen() || formDialogOpen() && !documentTab().print?.context) return; + if (document.body.hasAttribute("data-busy") || documentDialogs?.applicationOpen() || formDialogOpen() && !documentTab().print?.context && !batchElements.Panel.open) return; if (key.toLowerCase() === "w") closeTab(documentTab()); else { const count = workspace.tabs.length, index = workspace.tabs.indexOf(documentTab()); @@ -5135,7 +5135,7 @@ function resizeViewer() { async function boot() { documentDialogs = new DocumentDialogs({document, titlebar: el.documentTitleBar, targets: () => [...document.body.children].filter(node => node !== el.documentTitleBar)}); - for (const panel of document.querySelectorAll("dialog.form-dialog")) if (panel !== el.printPanel) documentDialogs.register(panel); + for (const panel of document.querySelectorAll("dialog.form-dialog")) if (panel !== el.printPanel) documentDialogs.register(panel, {persistent: panel === batchElements.Panel}); documentDialogs.setOwner(documentTab()); const openSeq = state.openSeq; setBusy(true, "正在准备引擎", 8, STATUS.engine); @@ -5749,17 +5749,20 @@ async function openOFD(file, remote = null, handle = file?.handle) { tab.state.fileName = file.name || remote?.name || STATUS.opening; tab.status = STATUS.opening; workspace.tabs.push(tab); - setBusy(true, "正在读取文档", 10, STATUS.opening, tab); - await activateDocumentTab(tab); - if (workspace.active === tab && !previous.state.doc && !previous.opening && !previous.state.dirty && !previous.error) { - workspace.tabs.splice(workspace.tabs.indexOf(previous), 1); - await releaseDocumentTab(previous); - } - renderDocumentTabs(); const current = () => !tab.closed && tab.opening === request; let accepted = false; let originalSource = null; try { + setBusy(true, "正在读取文档", 10, STATUS.opening, tab); + await activateDocumentTab(tab); + if (!current()) return; + const previousIndex = workspace.tabs.indexOf(previous); + if (previousIndex >= 0 && workspace.active === tab && !previous.state.doc && !previous.opening && !previous.state.dirty && !previous.error) { + workspace.tabs.splice(previousIndex, 1); + await releaseDocumentTab(previous); + } + renderDocumentTabs(); + if (!current()) return; const downloaded = remote ? await downloadRemoteDocument(remote, tab, request.controller) : null; if (!current()) return; await ensureTabEngine(tab); @@ -9692,6 +9695,7 @@ function startBatchWorker() { const slot = { worker, error: null }; batch.workers.add(slot); const fail = async error => { + slot.cancel = null; slot.error = error; worker.terminate(); reject(error); @@ -9705,10 +9709,11 @@ function startBatchWorker() { request.reject(error); } }; + slot.cancel = () => fail(new DOMException("已取消转换", "AbortError")); worker.onerror = event => fail(new Error(event.message || "转换引擎异常")); worker.onmessageerror = () => fail(new Error("转换数据传递失败")); worker.onmessage = async ({ data }) => { - if (data.type === "ready") { resolve(slot); return; } + if (data.type === "ready") { slot.cancel = null; resolve(slot); return; } if (data.type === "exit") { fail(new Error(data.error)); return; } if (data.type === "progress") { if (!batch.canceled) batchElements.Status.textContent = { download: "正在下载", compile: "正在编译", start: "正在启动" }[data.phase] || "正在准备"; @@ -9743,7 +9748,16 @@ function cancelBatch() { batchElements.Cancel.disabled = true; batch.progress = null; batchElements.Status.textContent = "正在取消"; - if (batch.unlocking) finishCredentials(null); + const request = batch.unlocking; + if (request && request.tab.credentials === request) { + if (request === credentialRequest) finishCredentials(null); + else { + request.tab.credentials = null; + documentDialogs.closeFor(request.tab, el.credentialsPanel); + request.resolve(null); + } + } + for (const slot of batch.workers) slot.cancel?.(); for (const [id, request] of batch.requests) request.slot.worker.postMessage({ type: "cancel", id }); } @@ -9858,9 +9872,10 @@ async function runBatch() { options.credentials?.keyPassword?.fill(0); const unlock = batch.credentials.then(async () => { if (batch.canceled) throw new DOMException("已取消转换", "AbortError"); - batch.unlocking = true; - try { return await requestCredentials(code, state.openSeq, err.code === "pdfPassword"); } - finally { batch.unlocking = false; } + const credentials = requestCredentials(code, state.openSeq, err.code === "pdfPassword"); + batch.unlocking = documentTab().credentials; + try { return await credentials; } + finally { batch.unlocking = null; } }); batch.credentials = unlock.then(() => {}, () => {}); options.credentials = await unlock; diff --git a/assets/webui/ofdgo_util.js b/assets/webui/ofdgo_util.js index fa0ea70..69c6094 100644 --- a/assets/webui/ofdgo_util.js +++ b/assets/webui/ofdgo_util.js @@ -30,9 +30,9 @@ export class DocumentDialogs { root.defaultView.addEventListener("resize", () => this.paint()); } - register(panel, { shared = true } = {}) { + register(panel, { shared = true, persistent = false } = {}) { if (this.records.has(panel)) return panel; - const record = { show: panel.show.bind(panel), showModal: panel.showModal.bind(panel), close: panel.close.bind(panel), owner: null, application: false, shared, clicks: new WeakMap(), initial: shared ? this.snapshot(panel) : null }; + const record = { show: panel.show.bind(panel), showModal: panel.showModal.bind(panel), close: panel.close.bind(panel), owner: null, application: false, shared, clicks: new WeakMap(), initial: shared && !persistent ? this.snapshot(panel) : null }; this.records.set(panel, record); panel.showModal = panel.show = () => this.openFor(this.owner, panel); panel.close = value => { @@ -125,7 +125,7 @@ export class DocumentDialogs { this.unpaint(); if (value !== undefined) panel.returnValue = String(value); panel.removeAttribute("open"); - if (this.records.get(panel).shared) entry.snapshot = this.snapshot(panel); + if (this.records.get(panel).initial) entry.snapshot = this.snapshot(panel); } const result = value === undefined ? visible ? panel.returnValue : entry.snapshot?.returnValue ?? panel.returnValue : String(value); state.stack = state.stack.filter(value => value !== panel); @@ -151,8 +151,8 @@ export class DocumentDialogs { for (const [panel, entry] of this.current(tab)?.entries || []) { const record = this.records.get(panel); if (record.application || record.owner !== tab) continue; - if (record.shared) entry.snapshot = this.snapshot(panel); - else { + if (record.initial) entry.snapshot = this.snapshot(panel); + else if (!record.shared) { entry.focus = panel.contains(this.document.activeElement) ? this.document.activeElement : null; panel.remove(); } @@ -172,8 +172,8 @@ export class DocumentDialogs { for (const [panel, entry] of state.entries) { const record = this.records.get(panel); if (record.application) continue; - if (record.shared) this.applySnapshot(entry.snapshot, panel); - else this.document.body.append(panel); + if (record.initial) this.applySnapshot(entry.snapshot, panel); + else if (!record.shared) this.document.body.append(panel); record.owner = tab; } for (const [panel, entry] of state.entries) { @@ -205,7 +205,7 @@ export class DocumentDialogs { continue; } if (record.application || record.owner !== tab) continue; - this.applySnapshot(record.initial, panel); + if (record.initial) this.applySnapshot(record.initial, panel); record.owner = null; } state?.entries.clear();