Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>10.0.1-beta07</Version>
<Version>10.0.1-beta08</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
21 changes: 20 additions & 1 deletion src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,17 @@ public partial class PdfReader
public string? MoreButtonIcon { get; set; }

/// <summary>
/// 点击下载按钮回调方法 默认 null 使用组件内置下载功能
/// 点击下载按钮回调方法 默认 null
/// </summary>
[Parameter]
public Func<Task>? OnDownloadAsync { get; set; }

/// <summary>
/// 正在打印回调方法 默认 null
/// </summary>
[Parameter]
public Func<Task>? OnPrintingAsync { get; set; }

private string? ClassString => CssBuilder.Default("bb-pdf-reader")
.AddClassFromAttributes(AdditionalAttributes)
.Build();
Expand Down Expand Up @@ -347,4 +353,17 @@ public async Task PageChanged(uint pageIndex)
await OnPageChangedAsync(pageIndex);
}
}

/// <summary>
/// 正在打印回调方法
/// </summary>
/// <returns></returns>
[JSInvokable]
public async Task Printing()
{
if (OnPrintingAsync != null)
{
await OnPrintingAsync();
}
}
}
41 changes: 40 additions & 1 deletion src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const addEventListener = (el, pdfViewer, eventBus, invoke, options) => {
}

if (options.triggerPagesInit === true) {
await invoke.invokeMethodAsync("pagesInit", numPages);
await invoke.invokeMethodAsync("PagesInit", numPages);
}
});

Expand All @@ -139,6 +139,12 @@ const addEventListener = (el, pdfViewer, eventBus, invoke, options) => {
if (options.triggerPagesLoaded === true) {
await invoke.invokeMethodAsync("PagesLoaded", e.pagesCount);
}

const controls = el.querySelector(".bb-view-controls");
EventHandler.on(controls, "click", ".bb-view-print", e => {
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The event handler callback function is missing the async keyword but uses await on line 146. This will cause a syntax error. The arrow function on line 144 should be declared as async (e) => { instead of e => {.

Suggested change
EventHandler.on(controls, "click", ".bb-view-print", e => {
EventHandler.on(controls, "click", ".bb-view-print", async e => {

Copilot uses AI. Check for mistakes.
printPdf(options.url);
Comment on lines +144 to +145
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The event handler uses await but is not marked async, which will cause a syntax error.

In the pagesloaded handler, the EventHandler.on callback is defined as e => { ... } but contains await invoke.invokeMethodAsync("Printing");, which is invalid in non-async functions and will cause a syntax error. Make the callback async e => { ... } or remove await and handle the returned promise explicitly.

await invoke.invokeMethodAsync("Printing");
});
Comment on lines +144 to +147
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The print event handler should follow the same pattern as other callbacks in this file by checking if the feature is enabled via an options flag. Add a TriggerPrinting option check similar to how triggerPagesInit, triggerPagesLoaded, and triggerPageChanged are used (see lines 129, 139, 169). This prevents unnecessary event handler registration and callback invocations when OnPrintingAsync is null.

Suggested change
EventHandler.on(controls, "click", ".bb-view-print", e => {
printPdf(options.url);
await invoke.invokeMethodAsync("Printing");
});
if (options.triggerPrinting === true) {
EventHandler.on(controls, "click", ".bb-view-print", async e => {
printPdf(options.url);
await invoke.invokeMethodAsync("Printing");
});
}

Copilot uses AI. Check for mistakes.
})
Comment on lines 139 to 148
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Null handling for .bb-view-controls should be added before wiring event listeners.

If .bb-view-controls is missing, el.querySelector(".bb-view-controls") returns null, and passing that into EventHandler.on will likely throw. Please guard this with a null check (e.g. if (controls) { EventHandler.on(...); }) so layouts without controls don’t cause runtime errors.

Suggested change
if (options.triggerPagesLoaded === true) {
await invoke.invokeMethodAsync("PagesLoaded", e.pagesCount);
}
const controls = el.querySelector(".bb-view-controls");
EventHandler.on(controls, "click", ".bb-view-print", e => {
printPdf(options.url);
await invoke.invokeMethodAsync("Printing");
});
})
if (options.triggerPagesLoaded === true) {
await invoke.invokeMethodAsync("PagesLoaded", e.pagesCount);
}
const controls = el.querySelector(".bb-view-controls");
if (controls) {
EventHandler.on(controls, "click", ".bb-view-print", async e => {
printPdf(options.url);
await invoke.invokeMethodAsync("Printing");
});
}
})

Comment on lines +142 to 148
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The print event handler is registered inside the 'pagesloaded' event callback. This means the handler will be registered multiple times if the PDF is reloaded, causing the print function and callback to be invoked multiple times on each print click. Consider registering this handler once in the main addEventListener function body, similar to how the minus/plus button handlers are registered on lines 197-198.

Suggested change
const controls = el.querySelector(".bb-view-controls");
EventHandler.on(controls, "click", ".bb-view-print", e => {
printPdf(options.url);
await invoke.invokeMethodAsync("Printing");
});
})
});
// Register print button click handler once
const controls = el.querySelector(".bb-view-controls");
if (controls) {
EventHandler.on(controls, "click", ".bb-view-print", async e => {
printPdf(options.url);
await invoke.invokeMethodAsync("Printing");
});
}

Copilot uses AI. Check for mistakes.

eventBus.on("pagechanging", async evt => {
Expand Down Expand Up @@ -276,6 +282,31 @@ const makeThumb = async page => {
return canvas;
}

const printPdf = url => {
let iframe = document.querySelector(".bb-view-print-iframe");
if (iframe) {
iframe.remove();
}

iframe = document.createElement("iframe");
iframe.classList = "bb-view-print-iframe";
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting classList directly to a string is incorrect. The classList property is a read-only DOMTokenList. Use iframe.classList.add("bb-view-print-iframe") instead, or use iframe.className = "bb-view-print-iframe" to set the class attribute.

Suggested change
iframe.classList = "bb-view-print-iframe";
iframe.className = "bb-view-print-iframe";

Copilot uses AI. Check for mistakes.
iframe.style.position = "fixed";
iframe.style.right = "100%";
iframe.style.bottom = "100%";
iframe.src = url;

iframe.onload = () => {
iframe.contentWindow.addEventListener('afterprint', function () {
document.body.removeChild(iframe);
});

iframe.contentWindow.focus();
iframe.contentWindow.print();
};

document.body.appendChild(iframe);
}

export function dispose(id) {
Data.remove(id);

Expand Down Expand Up @@ -304,5 +335,13 @@ export function dispose(id) {
if (thumbnailsContainer) {
EventHandler.off(thumbnailsContainer, "click");
}

const controls = el.querySelector(".bb-view-controls");
EventHandler.off(controls, "click");

const iframe = document.querySelector('.bb-view-print-iframe');
if (iframe) {
iframe.remove();
}
}
}
Loading