From 12aaada9822cfd1b7722f4c5232c9d0d221f9009 Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Wed, 28 Oct 2026 20:00:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E7=BC=96=E8=BE=91=E8=83=BD=E5=8A=9B):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AD=97=E5=8F=B7=E9=97=B4=E8=B7=9D=E5=AD=97?= =?UTF-8?q?=E4=BD=93=E7=AD=89=E6=8F=90=E4=BA=A4=E4=B8=A2=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/webui/ofdgo.js | 77 +++++++++++++++++++++----------------- assets/webui/ofdgo_font.js | 15 +++++++- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/assets/webui/ofdgo.js b/assets/webui/ofdgo.js index d408910..fe88644 100644 --- a/assets/webui/ofdgo.js +++ b/assets/webui/ofdgo.js @@ -702,14 +702,14 @@ const fontManager = new FontManager({ const fontPicker = new FontPicker(el.textFont, el.textFontToggle, el.textFontList, changeTextFont, loadEditorFonts); const textFormatButtons = [...document.querySelectorAll("[data-text-format]")]; const textBackground = document.querySelector("#textBackground"); -const editorColors = new Map(); +const editorInputs = new Map(); const annotationFields = Object.fromEntries(["CreateForm", "CreateCancel", "Content", "Old", "Font", "Text", "TextRow", "Image", "ImageRow", "Author", "LinkKind", "Address", "AddressRow", "Target", "TargetRow", "X", "Y", "Width", "Height", "Angle", "Opacity", "Tile", "Placement", "PlacementLabel", "Pick", "Scope", "Pages"].map(key => [key, document.querySelector(`#annotation${key}`)])); el.editorTools.addEventListener("scroll", () => fontPicker.position()); const canvasEditor = new CanvasEditor(el.viewerPanel, { textControls: [el.textAlign, el.textFont, el.textFontToggle, el.textFontAdd, el.textFontList, el.textSize, el.textColor, el.textLineHeight, el.textSpacing, el.textWrap, el.paragraphButton, el.paragraphPanel, textBackground, ...textFormatButtons, el.undoButton, el.redoButton, el.saveButton, el.saveAsButton, el.fontInput, document.querySelector("#textReflow")], keepTextFocus: () => fontPicker.open || el.closePanel.open || el.paragraphPanel.open || canvasEditor.input?.fontDialog, - prepareTextCommit: flushEditorColors, + prepareTextCommit: flushEditorInputs, onTextFormat: changeRangeFormat, onRichInput: ensureRichInput, textClipboardScope: () => `${documentTab().id}:${documentContentKey(state)}:${state.editorInfo?.revision ?? ""}`, @@ -868,14 +868,14 @@ editorClick(el.editObjectButton, () => { editCanvasObject(canvasEditor.selected); } }); -el.textSize.addEventListener("change", () => changeTextStyle(false)); -bindEditorColor(el.textColor, () => changeTextStyle(true)); +bindEditorInput(el.textSize, () => changeTextStyle(false)); +bindEditorInput(el.textColor, () => changeTextStyle(true)); for (const button of textFormatButtons) button.addEventListener("click", () => changeRangeFormat(button.dataset.textFormat)); -bindEditorColor(textBackground, value => changeRangeFormat("background", value)); -document.addEventListener("pointerdown", flushEditorColors, true); +bindEditorInput(textBackground, value => changeRangeFormat("background", value)); +document.addEventListener("pointerdown", flushEditorInputs, true); editorClick(el.textWrap, () => changeParagraph(!currentTextStyle().wrap), true); el.textAlign.addEventListener("change", () => changeTextAlignment()); -el.textLineHeight.addEventListener("change", () => changeParagraph(undefined, "lineHeight")); +bindEditorInput(el.textLineHeight, () => changeParagraph(undefined, "lineHeight")); editorClick(el.paragraphButton, () => { const item = currentTextStyle(); for (const key of ["leftIndent", "rightIndent", "firstLineIndent"]) { @@ -1210,7 +1210,7 @@ el.paragraphForm.addEventListener("submit", async event => { if (isForegroundDocument(tab) && el.paragraphPanel.open) el.paragraphStatus.textContent = error.message; } }); -el.textSpacing.addEventListener("change", () => changeParagraph(undefined, "letterSpacing")); +bindEditorInput(el.textSpacing, () => changeParagraph(undefined, "letterSpacing")); el.shapeWidth.addEventListener("focus", () => { el.shapeWidth.defaultValue = el.shapeWidth.value; }); for (const input of [el.textSize, el.shapeWidth, el.textLineHeight, el.textSpacing]) { input.addEventListener("keydown", (event) => { @@ -1220,6 +1220,9 @@ for (const input of [el.textSize, el.shapeWidth, el.textLineHeight, el.textSpaci event.stopPropagation(); if (event.repeat) return; if (event.key === "Escape") { + const control = editorInputs.get(input); + control.pending = null; + control.handled = true; updateObjectControls(canvasEditor.selected, true); if (input === el.shapeWidth && canvasEditor.selected?.type !== "PathObject") { input.value = input.defaultValue; @@ -1306,10 +1309,10 @@ editorClick(el.eraseButton, () => toggleDrawingTool(el.eraseMode.value)); el.eraseMode.addEventListener("change", () => { if (canvasEditor.tool.startsWith("erase-")) canvasEditor.setTool(el.eraseMode.value); }); -for (const input of [el.shapeFill, el.shapeStroke, el.shapeWidth]) { +for (const input of [el.shapeFill, el.shapeStroke]) { input.addEventListener("change", changeShapeStyle); } -for (const input of [el.shapeFillColor, el.shapeStrokeColor]) bindEditorColor(input, () => changeShapeStyle({ target: input })); +for (const input of [el.shapeFillColor, el.shapeStrokeColor, el.shapeWidth]) bindEditorInput(input, () => changeShapeStyle({ target: input })); el.addPageButton.addEventListener("change", async () => { const action = el.addPageButton.value; el.addPageButton.value = ""; @@ -2840,6 +2843,10 @@ function detachDocumentView() { settings.sequence++; fontBinding.sequence++; fontPicker.close(); + fontPicker.changing = null; + for (const [input, control] of editorInputs) { + editorInputs.set(input, { ...control, pending: null, task: null, handled: true }); + } canvasEditor.cancelNudge(); canvasEditor.clear(); canvasEditor.setTool(""); @@ -3009,8 +3016,8 @@ async function releaseDocumentTab(tab) { if (!prepared && workspace.objectClipboard === clipboard) workspace.objectClipboard = null; } tab.closed = true; - for (const color of editorColors.values()) { - if (color.pending?.tab === tab) { color.pending = null; color.handled = true; } + for (const control of editorInputs.values()) { + if (control.pending?.tab === tab) { control.pending = null; control.handled = true; } } tab.print?.destroy(); tab.print = null; @@ -4215,43 +4222,45 @@ async function reflowCanvasText() { updateObjectControls(canvasEditor.selected, true); } -function bindEditorColor(input, change) { - const color = { input, change, pending: null, task: null, handled: false }; - editorColors.set(input, color); +function bindEditorInput(input, change) { + editorInputs.set(input, { input, change, pending: null, task: null, handled: false }); const remember = () => { - color.pending = { value: input.value, tab: documentTab(), content: documentContentKey(state), editing: canvasEditor.input, selected: canvasEditor.selected }; - color.handled = false; + const control = editorInputs.get(input); + control.pending = { value: input.value, tab: documentTab(), content: documentContentKey(state), editing: canvasEditor.input, selected: canvasEditor.selected }; + control.handled = false; }; input.addEventListener("input", remember); input.addEventListener("change", () => { + const control = editorInputs.get(input); let task; - if (!color.handled) { - if (!color.pending) remember(); - task = flushEditorColor(color); + if (!control.handled) { + if (!control.pending) remember(); + task = flushEditorInput(control); } - color.handled = false; + control.handled = false; return task; }); } -function flushEditorColor(color) { - if (color.task || !color.pending) return color.task; - color.task = (async () => { - while (color.pending) { - const pending = color.pending; - color.pending = null; - color.handled = true; +function flushEditorInput(control) { + if (control.task || !control.pending) return control.task; + control.task = (async () => { + while (control.pending) { + const pending = control.pending; + control.pending = null; + control.handled = true; if (!isForegroundDocument(pending.tab) || pending.content !== documentContentKey(state) || pending.editing !== canvasEditor.input || pending.selected !== canvasEditor.selected) continue; - color.input.value = pending.value; - await color.change(pending.value); + control.input.value = pending.value; + await control.change(pending.value); } - })().finally(() => { color.task = null; }); - return color.task; + })().finally(() => { control.task = null; }); + return control.task; } -function flushEditorColors() { - const tasks = [...editorColors.values()].map(flushEditorColor).filter(Boolean); +function flushEditorInputs(event) { + const tasks = [...editorInputs.values()].filter(control => !event || !control.input.contains(event.target)) + .map(flushEditorInput).concat(fontPicker.prepareCommit(event)).filter(Boolean); return tasks.length ? Promise.all(tasks) : null; } diff --git a/assets/webui/ofdgo_font.js b/assets/webui/ofdgo_font.js index 9c24574..d2cbdab 100644 --- a/assets/webui/ofdgo_font.js +++ b/assets/webui/ofdgo_font.js @@ -131,7 +131,10 @@ export class FontPicker { const changed = this.value !== String(index); this.value = String(index); this.close(); - if (changed) return this.onChange(); + if (changed) { + const task = this.changing = Promise.resolve(this.onChange()); + return task.finally(() => { if (this.changing === task) this.changing = null; }); + } } commitExact() { @@ -140,7 +143,15 @@ export class FontPicker { && [font.fullName, font.name, font.postscriptName, ...(font.names || [])].some(name => name?.toLocaleLowerCase() === value); const selected = Number(this.value); const index = matches(this.fonts[selected]) ? selected : this.fonts.findIndex(matches); - if (index >= 0) this.choose(index); + if (index >= 0) return this.choose(index); + } + + prepareCommit(event) { + if (this.open && (!event || ![this.input, this.toggle, this.list].some(node => node.contains(event.target)))) { + this.commitExact(); + this.close(); + } + return this.changing; } close() {