Skip to content

feat(PdfReader): add ShowPrint parameter#729

Merged
ArgoZhang merged 7 commits intomasterfrom
dev-page
Nov 27, 2025
Merged

feat(PdfReader): add ShowPrint parameter#729
ArgoZhang merged 7 commits intomasterfrom
dev-page

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Nov 27, 2025

Link issues

fixes #728

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Add configurable print visibility and enhanced zoom / fit controls to the PdfReader toolbar while updating fit mode handling and related UI/interop.

New Features:

  • Introduce a ShowPrint parameter to allow toggling visibility of the PdfReader print button.
  • Add a PdfReaderFitMode enum and public API to set the document fit mode, including UI controls for selecting common scale options.

Enhancements:

  • Refine the PdfReader toolbar layout and styling, including updated icons, fit controls, and a simplified overflow menu implementation.
  • Rename and clarify parameters related to two‑page view and page change callbacks for improved semantics.
  • Replace the boolean IsFitToPage flag with a FitMode value and update JS interop to use a generic scale setter instead of separate fit methods.
  • Remove the unused DownloadService injection from PdfReader.

Copilot AI review requested due to automatic review settings November 27, 2025 03:35
@bb-auto bb-auto Bot added the enhancement New feature or request label Nov 27, 2025
@bb-auto bb-auto Bot added this to the v9.2.0 milestone Nov 27, 2025
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Nov 27, 2025

Reviewer's Guide

Adds a configurable print button to the PdfReader component, replaces the boolean fit-to-page API with a more flexible PdfReaderFitMode enum, and refactors the toolbar UI/JS interop to support multiple fit modes and improved dropdown controls.

Sequence diagram for PdfReader fit mode change via toolbar

sequenceDiagram
    actor User
    participant PdfReaderComponent
    participant BlazorRenderer
    participant JsInterop as PdfReaderJsInterop
    participant PdfViewer as PdfJsPdfViewer

    User->>PdfReaderComponent: Click fit mode button
    PdfReaderComponent->>PdfReaderComponent: SetFitMode(mode)
    PdfReaderComponent->>BlazorRenderer: Request re-render
    BlazorRenderer->>PdfReaderComponent: OnAfterRenderAsync(firstRender=false)
    PdfReaderComponent->>PdfReaderComponent: Detect _fitMode != FitMode
    PdfReaderComponent->>PdfReaderComponent: _fitMode = FitMode
    PdfReaderComponent->>JsInterop: InvokeVoidAsync("setScaleValue", Id, FitMode.ToDescriptionString())
    JsInterop->>PdfViewer: setScaleValue(id, value)
    PdfViewer->>PdfViewer: pdfViewer.currentScaleValue = value
Loading

Class diagram for updated PdfReader component and PdfReaderFitMode enum

classDiagram
    class PdfReader {
        +bool ShowDownload
        +bool ShowPrint
        +bool EnableThumbnails
        +string? Url
        +uint CurrentPage
        +string? CurrentScale
        +PdfReaderFitMode FitMode
        +bool ShowTwoPagesOneView
        +bool EnableTwoPagesOneView
        +bool EnableMonitorDocumentState
        +string? MoreButtonIcon
        +Func~Task~? OnPagesInitAsync
        +Func~int,Task~? OnPagesLoadedAsync
        +Func~uint,Task~? OnPageChangedAsync
        +Func~Task~? OnDownloadAsync
        -string? ClassString
        -string? ToolbarClassString
        -string? ViewBodyString
        -string? _docTitle
        -PdfReaderFitMode _fitMode
        -uint _currentPage
        -string? _url
        -string? _currentScale
        -bool _enableTwoPagesOneView
        -bool _showTwoPagesOneViewButton
        -string? _twoPagesOneViewIcon
        +void SetFitMode(mode PdfReaderFitMode)
        +void RotateLeft()
        +void RotateRight()
        +Task OnDownload()
        +Task InvokeInitAsync()
        +Task OnAfterRenderAsync(firstRender bool)
        +void OnParametersSet()
    }

    class PdfReaderFitMode {
        <<enumeration>>
        PageWidth
        PageActual
        PageHeight
        PageFit
        Auto
    }

    PdfReader --> PdfReaderFitMode : uses
    PdfReader "1" o--> "1" PdfReaderFitMode : FitMode
Loading

File-Level Changes

Change Details Files
Introduce configurable print button visibility in PdfReader.
  • Add ShowPrint parameter with default true on the PdfReader component class.
  • Render the print icon conditionally based on ShowPrint in the toolbar controls.
  • Normalize print and download icons to use fixed-width Font Awesome classes for better alignment.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Replace IsFitToPage boolean API with PdfReaderFitMode enum and propagate through component and JS interop.
  • Add PdfReaderFitMode enum with description attributes for various PDF viewer scale modes.
  • Change IsFitToPage parameter to FitMode in the PdfReader component and adjust backing fields from bool to enum.
  • Update ViewBodyString CSS class binding and associated private state to use FitMode instead of IsFitToPage.
  • Update lifecycle logic in OnAfterRenderAsync and InvokeInitAsync to send FitMode to JS and call new setScaleValue interop instead of fitToPage/fitToWidth.
  • Replace FitToPage/FitToWidth methods with a single SetFitMode method that accepts a PdfReaderFitMode.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
src/components/BootstrapBlazor.PdfReader/PdfReaderFitMode.cs
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Refine toolbar layout and styling for scale controls, fit mode buttons, and the "more" menu.
  • Rework the zoom/scale section markup to use separate input and grouped buttons for fit-height/fit-width plus a dropdown of all fit modes.
  • Change the page title span to always show (remove d-none d-sm-block) and adjust structure around pagesCount and dividers.
  • Replace the Blazor Dropdown component for the more menu with a plain Bootstrap dropdown and adjust ShowTwoPagesOneViewButton parameter name to ShowTwoPagesOneView.
  • Update CSS to scope button styles, tweak paddings, margins, and background color, and add styles for the new scale input and toolbar layout.
  • Ensure appropriate use of Font Awesome fixed-width classes and dropdown toggle arrow removal for the controls dropdown.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css
Simplify JS interop for setting viewer scale and wiring fit mode on initialization.
  • Replace separate fitToWidth and fitToPage JS functions with a unified setScaleValue that accepts an arbitrary scale value string.
  • Change the init options and pagesinit handler to use fitMode instead of isFitToPage and set pdfViewer.currentScaleValue accordingly.
  • Remove unused AllowedScaleValues on the C# side and adjust interop calls to pass description string values of PdfReaderFitMode.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Minor API and dependency cleanups in PdfReader component.
  • Rename ShowTwoPagesOneViewButton parameter and backing field to ShowTwoPagesOneView and keep behavior the same.
  • Remove the injected DownloadService dependency that is no longer used by OnDownload.
  • Tighten icon defaults (MoreButtonIcon adds fa-fw) and keep OnPageChangedAsync XML doc in sync with behavior description.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
src/components/BootstrapBlazor.PdfReader/PdfReader.razor

Assessment against linked issues

Issue Objective Addressed Explanation
#728 Add a ShowPrint parameter to the PdfReader component that controls whether the print button is displayed in the toolbar.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and found some issues that need to be addressed.

  • In ViewBodyString, the fit-width CSS class is applied when FitMode == PdfReaderFitMode.PageHeight, which looks inverted relative to the intent and the .bb-view-body.fit-width CSS rules; consider switching this condition to PageWidth (and/or introducing a separate class for height) so the toolbar state matches the actual fit mode.
  • The JS init/event logic appears inconsistent with the new FitMode parameter: init sends FitMode (an enum) but addEventListener still references options.isFitToPage and then assigns pdfViewer.currentScaleValue = fitMode, where fitMode and options.fitMode are undefined/incorrect casing; update the JS options shape and use the enum's description string so the initial scale is applied correctly.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `ViewBodyString`, the `fit-width` CSS class is applied when `FitMode == PdfReaderFitMode.PageHeight`, which looks inverted relative to the intent and the `.bb-view-body.fit-width` CSS rules; consider switching this condition to `PageWidth` (and/or introducing a separate class for height) so the toolbar state matches the actual fit mode.
- The JS init/event logic appears inconsistent with the new `FitMode` parameter: `init` sends `FitMode` (an enum) but `addEventListener` still references `options.isFitToPage` and then assigns `pdfViewer.currentScaleValue = fitMode`, where `fitMode` and `options.fitMode` are undefined/incorrect casing; update the JS options shape and use the enum's description string so the initial scale is applied correctly.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs:128` </location>
<code_context>

     private string? ViewBodyString => CssBuilder.Default("bb-view-body")
-        .AddClass("fit-page", IsFitToPage)
+        .AddClass("fit-width", FitMode == PdfReaderFitMode.PageHeight)
         .Build();

</code_context>

<issue_to_address>
**issue (bug_risk):** The `fit-width` CSS class is tied to `PageHeight` instead of `PageWidth`, which looks inverted.

This will mark the body as `fit-width` when `FitMode == PdfReaderFitMode.PageHeight`, so the toolbar state and CSS selectors (e.g. `.bb-view-body.fit-width .bb-view-fit-height`) won’t match the actual fit mode. Please change the condition to `FitMode == PdfReaderFitMode.PageWidth`, or use a different class if this is intended to represent height instead.
</issue_to_address>

### Comment 2
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:114-115` </location>
<code_context>
-        }
-        else {
-            pdfViewer.currentScaleValue = "page-actual";
+        if (options.fitMode) {
+            pdfViewer.currentScaleValue = fitMode;
         }

</code_context>

<issue_to_address>
**issue (bug_risk):** `fitMode` is referenced but never defined; `options.fitMode` is likely intended.

This will throw a `ReferenceError` at runtime because `fitMode` is not in scope here. Use `options.fitMode` (or a value derived from it) when setting `pdfViewer.currentScaleValue` so the intended fit behavior works correctly.
</issue_to_address>

### Comment 3
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs:263` </location>
<code_context>
     {
         Url,
-        IsFitToPage,
+        FitMode,
         EnableThumbnails,
         TriggerPagesInit = OnPagesInitAsync != null,
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Passing the raw `PdfReaderFitMode` enum to JS may not match the string values expected by `pdfViewer.currentScaleValue`.

Because `FitMode` is an enum, Blazor will serialize it as a number in the JS options, but `pdfViewer.currentScaleValue` expects string values like `"page-width"` / `"page-height"`. `setScaleValue` already uses `_fitMode.ToDescriptionString()` to produce those strings. For consistency and to avoid an incorrect initial scale, pass `FitMode.ToDescriptionString()` (or an equivalent string) into JS and have the JS use that string instead of the raw enum value.

Suggested implementation:

```csharp
    protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new
    {
        Url,
        FitMode = FitMode.ToDescriptionString(),
        EnableThumbnails,
        TriggerPagesInit = OnPagesInitAsync != null,
        TriggerPagesLoaded = OnPagesLoadedAsync != null,

```

On the JavaScript side (where the `init` interop call is handled), adjust the code so that it treats the `FitMode` option as a string that is directly usable with `pdfViewer.currentScaleValue` / `setScaleValue`. For example, if it currently assumes a numeric enum and maps it to a string, remove that mapping and instead use the provided string value directly (e.g., `"page-width"`, `"page-height"`, etc.).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ArgoZhang ArgoZhang merged commit bb3597b into master Nov 27, 2025
2 checks passed
@ArgoZhang ArgoZhang deleted the dev-page branch November 27, 2025 03:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new ShowPrint parameter to control the visibility of the print button and refactors the PDF fit mode functionality from a boolean IsFitToPage parameter to a more flexible enum-based FitMode parameter. Additionally, it refactors the "more options" dropdown from a custom Dropdown component to native Bootstrap dropdown markup.

Key Changes

  • Added ShowPrint parameter to control print button visibility (default: true)
  • Replaced boolean IsFitToPage with enum PdfReaderFitMode supporting multiple fit modes (PageWidth, PageHeight, PageActual, PageFit, Auto)
  • Refactored toolbar UI to use Bootstrap split button dropdown for fit mode selection

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
PdfReaderFitMode.cs New enum defining document fit modes with description attributes for JavaScript interop
PdfReader.razor.js Refactored fit mode logic to use a single setScaleValue method instead of separate fitToWidth/fitToPage methods
PdfReader.razor.css Updated CSS classes from fit-page to fit-width, adjusted spacing and added styles for split button dropdown
PdfReader.razor.cs Added ShowPrint parameter, replaced IsFitToPage boolean with FitMode enum, renamed ShowTwoPagesOneViewButton to ShowTwoPagesOneView
PdfReader.razor Added conditional rendering for print button, replaced custom Dropdown component with native Bootstrap dropdown, added split button UI for fit mode selection

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -277,12 +278,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
/// <summary>
/// 适应页面宽度
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 documentation comment "适应页面宽度" (Fit to page width) is misleading. This method now sets any fit mode via parameter, not just page width. The comment should be updated to reflect the actual functionality, e.g., "设置文档适配模式" (Set document fit mode).

Suggested change
/// 适应页面宽度
/// 设置文档适配模式

Copilot uses AI. Check for mistakes.
@@ -59,13 +65,13 @@ public partial class PdfReader
/// 获得/设置 是否适配当前页面宽度 默认 false
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 documentation comment "获得/设置 是否适配当前页面宽度 默认 false" (Get/Set whether to fit current page width, default false) is outdated. The parameter type changed from bool IsFitToPage to PdfReaderFitMode FitMode, which accepts multiple fit modes. The comment should be updated to reflect this, e.g., "获得/设置 文档适配模式 默认 Auto" (Get/Set document fit mode, default Auto).

Suggested change
/// 获得/设置 是否适配当前页面宽度 默认 false
/// 获得/设置 文档适配模式 默认 Auto

Copilot uses AI. Check for mistakes.
else {
pdfViewer.currentScaleValue = "page-actual";
if (options.fitMode) {
pdfViewer.currentScaleValue = fitMode;
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 variable fitMode is undefined. It should be options.fitMode to match the condition check on line 114.

Suggested change
pdfViewer.currentScaleValue = fitMode;
pdfViewer.currentScaleValue = options.fitMode;

Copilot uses AI. Check for mistakes.
{
Url,
IsFitToPage,
FitMode,
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 FitMode enum value is being passed directly to JavaScript, but it needs to be converted to its description string value (e.g., "page-width", "page-height"). It should be FitMode.ToDescriptionString() or a similar conversion, similar to what's done on line 232.

Suggested change
FitMode,
FitMode = FitMode.ToDescriptionString(),

Copilot uses AI. Check for mistakes.
/// <summary>
/// PdfReader 文档适配模式
/// </summary>
public enum PdfReaderFitMode
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 enum name PdfReaderFitMode is inconsistent with the naming convention used for other enums in this component. Other enums in the PdfReader component use the "Enum" prefix (e.g., EnumPageMode, EnumZoomMode). Consider renaming to EnumFitMode for consistency.

Suggested change
public enum PdfReaderFitMode
public enum EnumFitMode

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +43
/// <summary>
/// PdfReader 文档适配模式
/// </summary>
public enum PdfReaderFitMode
{
/// <summary>
/// 页面宽度
/// </summary>
[Description("page-width")]
PageWidth,

/// <summary>
/// 实际大小
/// </summary>
[Description("page-actual")]
PageActual,

/// <summary>
/// 页面高度
/// </summary>
[Description("page-height")]
PageHeight,

/// <summary>
/// 自适应宽高
/// </summary>
[Description("page-fit")]
PageFit,

/// <summary>
/// 自动
/// </summary>
[Description("auto")]
Auto
}
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.

This enum duplicates functionality already present in EnumZoomMode which has the same values: Auto, PageActual, PageFit, PageWidth, and PageHeight with identical Description attributes. Consider reusing EnumZoomMode instead of creating a new enum to avoid code duplication and maintain consistency across the codebase.

Suggested change
/// <summary>
/// PdfReader 文档适配模式
/// </summary>
public enum PdfReaderFitMode
{
/// <summary>
/// 页面宽度
/// </summary>
[Description("page-width")]
PageWidth,
/// <summary>
/// 实际大小
/// </summary>
[Description("page-actual")]
PageActual,
/// <summary>
/// 页面高度
/// </summary>
[Description("page-height")]
PageHeight,
/// <summary>
/// 自适应宽高
/// </summary>
[Description("page-fit")]
PageFit,
/// <summary>
/// 自动
/// </summary>
[Description("auto")]
Auto
}

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +33
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageActual)">page-actual</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageWidth)">page-width</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageHeight)">page-height</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageFit)">page-fit</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.Auto)">auto</div>
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 dropdown items display raw technical values (e.g., "page-actual", "page-width") which are not user-friendly. Consider using localized or human-readable labels instead, similar to how the enum descriptions are used in Chinese comments (e.g., "实际大小" for PageActual, "页面宽度" for PageWidth).

Suggested change
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageActual)">page-actual</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageWidth)">page-width</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageHeight)">page-height</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageFit)">page-fit</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.Auto)">auto</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageActual)">实际大小</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageWidth)">页面宽度</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageHeight)">页面高度</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.PageFit)">适合页面</div>
<div class="dropdown-item" @onclick="() => SetFitMode(PdfReaderFitMode.Auto)">自动</div>

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(PdfReader): add ShowPrint parameter

2 participants