diff --git a/assets/webui/index.html b/assets/webui/index.html index 858ab5e..13fce55 100644 --- a/assets/webui/index.html +++ b/assets/webui/index.html @@ -32,6 +32,7 @@ +
diff --git a/assets/webui/ofdgo.css b/assets/webui/ofdgo.css index 7eb2f34..daf743c 100644 --- a/assets/webui/ofdgo.css +++ b/assets/webui/ofdgo.css @@ -739,10 +739,6 @@ body[data-hide-meta] .meta-panel { text-align: center; } -body[aria-busy="true"] .viewer-panel { - cursor: progress; -} - .app-footer { justify-content: space-between; border-top: 1px solid var(--line); diff --git a/assets/webui/ofdgo.js b/assets/webui/ofdgo.js index 8b5563c..e35f942 100644 --- a/assets/webui/ofdgo.js +++ b/assets/webui/ofdgo.js @@ -59,6 +59,7 @@ const state = { pageIndex: 0, scale: 1, fitMode: "width", + renderAnnotations: true, pageCache: new Map(), pageInFlight: new Set(), pageObserver: null, @@ -88,6 +89,7 @@ const el = { zoomLabel: document.querySelector("#zoomLabel"), fitButton: document.querySelector("#fitButton"), fitHeightButton: document.querySelector("#fitHeightButton"), + annotationButton: document.querySelector("#annotationButton"), pageExportFormat: document.querySelector("#pageExportFormat"), exportPageButton: document.querySelector("#exportPageButton"), exportButton: document.querySelector("#exportButton"), @@ -125,6 +127,7 @@ el.zoomOutButton.addEventListener("click", () => setScale(state.scale - 0.1)); el.zoomInButton.addEventListener("click", () => setScale(state.scale + 0.1)); el.fitButton.addEventListener("click", fitWidth); el.fitHeightButton.addEventListener("click", fitHeight); +el.annotationButton.addEventListener("click", toggleAnnotations); el.exportPageButton.addEventListener("click", exportCurrentPage); el.exportButton.addEventListener("click", exportPDF); el.pageInput.addEventListener("change", () => { @@ -524,9 +527,7 @@ function fontData(fonts) { function updateFontSummary() { const total = fontRecords().length; const enabled = fontRecords().filter((font) => font.enabled).length; - if (el.availableFontSummary) { - el.availableFontSummary.textContent = total ? `${enabled}/${total}` : "0"; - } + el.availableFontSummary.textContent = total ? `${enabled}/${total}` : "0"; } function createFontRecord(name, data, source) { @@ -660,15 +661,25 @@ async function applyFontChange(options = {}) { }); } +async function toggleAnnotations() { + state.renderAnnotations = !state.renderAnnotations; + updateAnnotationButton(); + if (!state.ofdBytes || !state.doc) { + return; + } + await openDocument({ + pageIndex: state.pageIndex, + fitMode: state.fitMode, + skipAutoFonts: true, + }); +} + function removeFont(id) { state.localFonts = state.localFonts.filter((font) => font.id !== id); state.userFonts = state.userFonts.filter((font) => font.id !== id); } function renderFontList() { - if (!el.fontList) { - return; - } el.fontList.replaceChildren(); const fonts = fontRecords(); if (!fonts.length) { @@ -753,9 +764,6 @@ function fontSourceText(source) { } function updateLocalFontButton() { - if (!el.localFontButton) { - return; - } const supported = canReadLocalFonts(); el.localFontButton.disabled = !supported; el.localFontButton.title = supported ? "授权读取浏览器可访问的系统字体" : "当前浏览器不支持读取系统字体"; @@ -786,7 +794,7 @@ async function openDocument(options = {}) { if (openSeq !== state.openSeq) { return; } - const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts()); + const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations); if (openSeq !== state.openSeq) { return; } @@ -1436,14 +1444,9 @@ function renderMeta() { } function renderDocumentFonts() { - if (!el.docFontList) { - return; - } const fonts = state.doc?.fonts || []; el.docFontList.replaceChildren(); - if (el.docFontSummary) { - el.docFontSummary.textContent = fontSummary(fonts); - } + el.docFontSummary.textContent = fontSummary(fonts); if (!fonts.length) { const empty = document.createElement("div"); empty.className = "font-empty"; @@ -1594,11 +1597,18 @@ function updateControls() { el.fitHeightButton.disabled = !hasDoc; el.fitButton.toggleAttribute("aria-pressed", hasDoc && state.fitMode === "width"); el.fitHeightButton.toggleAttribute("aria-pressed", hasDoc && state.fitMode === "height"); + updateAnnotationButton(); el.pageExportFormat.disabled = !hasDoc || !state.exportFormats.length; el.exportPageButton.disabled = !hasDoc || !state.exportFormats.length; el.exportButton.disabled = !hasDoc; } +function updateAnnotationButton() { + el.annotationButton.setAttribute("aria-pressed", String(state.renderAnnotations)); + el.annotationButton.title = state.renderAnnotations ? "关闭注解渲染" : "开启注解渲染"; + el.annotationButton.setAttribute("aria-label", el.annotationButton.title); +} + function setExportControlsDisabled(disabled) { el.exportButton.disabled = disabled; el.exportPageButton.disabled = disabled; diff --git a/internal/webui/wasm.go b/internal/webui/wasm.go index c000576..318d49a 100644 --- a/internal/webui/wasm.go +++ b/internal/webui/wasm.go @@ -79,22 +79,23 @@ func safeCall(fn func([]js.Value) (any, error), args []js.Value) (data any, err // 入参: args 浏览器参数 // 返回: any 文档信息, error 错误信息 func openDocument(args []js.Value) (any, error) { - if len(args) == 0 { - return nil, fmt.Errorf("missing ofd data") + if len(args) < 3 { + return nil, fmt.Errorf("missing open arguments") } data, err := bytesFromJS(args[0]) if err != nil { return nil, err } - fonts, err := fontsFromJS(jsArg(args, 1)) + fonts, err := fontsFromJS(args[1]) if err != nil { return nil, err } + renderAnnotations := args[2].Bool() if currentSession != nil { _ = currentSession.Close() currentSession = nil } - session, err := Open(data, OpenOptions{Fonts: fonts}) + session, err := Open(data, OpenOptions{Fonts: fonts, RenderAnnotations: renderAnnotations}) if err != nil { return nil, err } diff --git a/internal/webui/webui.go b/internal/webui/webui.go index f1701e4..7883112 100644 --- a/internal/webui/webui.go +++ b/internal/webui/webui.go @@ -29,7 +29,8 @@ import ( // OpenOptions 打开OFD文档选项 type OpenOptions struct { - Fonts []FontFile + Fonts []FontFile + RenderAnnotations bool } // FontFile 字体文件 @@ -144,6 +145,7 @@ func Open(data []byte, opts OpenOptions) (*Session, error) { } rendererOptions = append(rendererOptions, ofdgo.WithFontFS(fontFS)) } + rendererOptions = append(rendererOptions, ofdgo.WithAnnotations(opts.RenderAnnotations)) return &Session{Reader: reader, Renderer: ofdgo.NewRenderer(reader, rendererOptions...), doc: doc}, nil }