Skip to content

feat(PdfReader): add TwoPagesOnView function#721

Merged
ArgoZhang merged 8 commits intomasterfrom
dev-view
Nov 26, 2025
Merged

feat(PdfReader): add TwoPagesOnView function#721
ArgoZhang merged 8 commits intomasterfrom
dev-view

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Nov 26, 2025

Link issues

fixes #720

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 two-pages-on-view mode and overflow menu to the PdfReader toolbar, including state synchronization with the underlying PDF viewer.

New Features:

  • Introduce a two-pages-on-view display mode for the PdfReader, including a toolbar control to toggle it and a corresponding JavaScript bridge.
  • Allow consumers to show or hide the two-pages-on-view button and to react via an OnTwoPagesOneViewAsync callback.
  • Add a customizable "more" button icon and dropdown menu with additional document-related actions in the PdfReader toolbar.

Enhancements:

  • Use named scale presets (e.g., page-actual) instead of fixed numeric scale on initialization, and harden event unsubscription and button styling in the PdfReader toolbar.

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

sourcery-ai Bot commented Nov 26, 2025

Reviewer's Guide

Adds support for a two-pages-on-view mode to the PdfReader component, including UI, options, JS interop wiring, and safer event handling, while adjusting default scale behavior.

Sequence diagram for toggling two-pages-on-view mode

sequenceDiagram
    actor User
    participant PdfReader as PdfReader_component
    participant Dropdown as Toolbar_dropdown
    participant JSRuntime as Blazor_JSRuntime
    participant PdfJs as PdfReader_razor_js
    participant Viewer as PdfViewer_instance

    User->>Dropdown: click dropdown-item-pages
    Dropdown->>PdfReader: invoke OnToggleTwoPagesOneView
    PdfReader->>PdfReader: _enableTwoPagesOneView = !_enableTwoPagesOneView
    PdfReader->>PdfReader: Options.EnableTwoPagesOnView = _enableTwoPagesOneView
    PdfReader->>PdfReader: _twoPagesOneViewIcon based on _enableTwoPagesOneView
    PdfReader-->>User: re-render toolbar with updated icon

    PdfReader->>JSRuntime: InvokeVoidAsync setPages(Id, _enableTwoPagesOneView)
    JSRuntime->>PdfJs: setPages(id, enableTowPagesOnView)
    PdfJs->>Viewer: set pdfViewer.spreadMode (1 or 0)
    Viewer-->>PdfJs: pages re-layout in two-page or single-page
    PdfJs-->>User: updated PDF layout displayed
Loading

Sequence diagram for initial PdfReader render with two-pages-on-view option

sequenceDiagram
    participant App as Parent_component
    participant PdfReader as PdfReader_component
    participant JSRuntime as Blazor_JSRuntime
    participant PdfJs as PdfReader_razor_js
    participant Viewer as PdfViewer_instance

    App->>PdfReader: set Options (EnableTwoPagesOnView, ShowTwoPagesOnViewButton, Url, CurrentScale)
    PdfReader->>PdfReader: OnParametersSet
    PdfReader->>PdfReader: set _docTitle from Options.Url
    PdfReader->>PdfReader: MoreButtonIcon default if null
    PdfReader->>PdfReader: _twoPagesOneViewIcon default if null

    PdfReader->>PdfReader: OnAfterRenderAsync(firstRender = true)
    PdfReader->>PdfReader: cache _currentPage, _url, _currentScale, _enableTwoPagesOneView
    PdfReader->>JSRuntime: initPdfReaderCore with TriggerTowPagesOnViewChanged
    JSRuntime->>PdfJs: initialize pdf viewer
    PdfJs->>Viewer: create PdfViewer with options

    PdfReader->>JSRuntime: InvokeVoidAsync scale(Id, _currentScale)
    JSRuntime->>PdfJs: scale(id, scale)
    PdfJs->>Viewer: set currentScaleValue

    alt _enableTwoPagesOneView true
        PdfReader->>JSRuntime: InvokeVoidAsync setPages(Id, _enableTwoPagesOneView)
        JSRuntime->>PdfJs: setPages(id, enableTowPagesOnView)
        PdfJs->>Viewer: set spreadMode = 1
    else _enableTwoPagesOneView false
        PdfJs->>Viewer: default spreadMode = 0
    end
Loading

Class diagram for updated PdfReader and PdfReaderOptions

classDiagram
    class PdfReaderOptions {
        bool IsFitToPage
        bool ShowTwoPagesOnViewButton
        bool EnableTwoPagesOnView
        Func_uint_Task OnInitAsync
        Func_uint_Task OnPageChangedAsync
        Func_bool_Task OnTwoPagesOneViewAsync
    }

    class PdfReader {
        +PdfReaderOptions Options
        +string MoreButtonIcon
        string ClassString
        string DocumentTitleString
        uint _currentPage
        string _url
        string _currentScale
        bool _enableTwoPagesOneView
        string _twoPagesOneViewIcon
        HashSet_string_ AllowedScaleValues
        void SetCurrentScale(string value)
        void OnToggleTwoPagesOneView()
        void OnParametersSet()
        Task OnAfterRenderAsync(bool firstRender)
        Task InitPdfReaderCore(PdfReaderOptions options)
    }

    PdfReader --> PdfReaderOptions : uses
Loading

File-Level Changes

Change Details Files
Introduce JS hook and UI event wiring to toggle PDF viewer spread (two-pages-on-view) mode and adjust default scale behavior.
  • Add setPages(id, enableTowPagesOnView) to update pdfViewer.spreadMode via JS interop
  • Wire a toolbar dropdown item click handler to toggle pdfViewer.spreadMode between single- and two-page modes
  • Change default non-fit scale from numeric 1.0 to "page-actual"
  • Tighten updateScale step filtering comparison spacing for readability
  • Harden dispose() by null-checking toolbar buttons before detaching click handlers and unbinding the new two-pages-on-view handler
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Extend PdfReader component state and lifecycle to support configurable two-pages-on-view behavior and a customizable "more" button icon.
  • Add MoreButtonIcon parameter for customizing the toolbar overflow/more icon
  • Track _enableTwoPagesOneView and associated icon state in the component backing class
  • Provide OnToggleTwoPagesOneView handler to flip the mode, sync to Options.EnableTwoPagesOnView, and update icon CSS classes
  • Initialize MoreButtonIcon and two-pages-on-view icon defaults during OnParametersSet
  • Sync _enableTwoPagesOneView from Options in OnAfterRenderAsync and invoke JS setPages when the mode changes
  • Include TriggerTowPagesOnViewChanged flag in JS init options based on OnTwoPagesOneViewAsync callback presence
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Expose configuration and callback hooks for two-pages-on-view behavior on PdfReaderOptions.
  • Add ShowTwoPagesOnViewButton option to control visibility of the two-pages-on-view toolbar button
  • Add EnableTwoPagesOnView option to set initial mode for two-pages-on-view
  • Add OnTwoPagesOneViewAsync callback for reacting to mode changes
src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs
Update PdfReader toolbar markup and styling to use a dropdown-based overflow menu that contains the two-pages-on-view control.
  • Replace previous trailing toolbar icons with a Dropdown menu using MoreButtonIcon as the trigger icon
  • Render a conditional dropdown item for toggling two-pages-on-view, bound to OnToggleTwoPagesOneView and showing an icon reflecting current state
  • Add a static dropdown item for document properties below a Divider
  • Adjust toolbar CSS so dropdown buttons match existing toolbar color scheme and hide the default dropdown caret
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css

Assessment against linked issues

Issue Objective Addressed Explanation
#720 Add a TwoPagesOnView feature to PdfReader, including an option/parameter to enable it, UI control to toggle it, and underlying JS logic to switch the PDF viewer into two-page spread mode.

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

@ArgoZhang ArgoZhang merged commit 492184f into master Nov 26, 2025
3 of 4 checks passed
@ArgoZhang ArgoZhang deleted the dev-view branch November 26, 2025 02:07
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.

  • There are several inconsistent spellings of the two‑page mode across JS/C# (TwoPagesOnView vs TowPagesOnView, e.g. setPages parameter and TriggerTowPagesOnViewChanged), which will be confusing and make future refactoring/error searching harder; consider standardizing all public and internal names to a single, correctly spelled form.
  • The two‑pages toggle currently has both a Blazor @onclick handler and a JS EventHandler.on(..., "click", ...) on .dropdown-item-pages; this double binding makes the behavior harder to reason about and may surprise future maintainers, so it would be better to centralize the toggle in one place (either JS or Blazor) and keep the other side purely in sync.
  • In setPages, Data.get(id) is used without checking for a missing entry, and the el binding is unused; consider removing the unused el destructuring and adding a null/undefined guard for the Data.get result to avoid potential runtime errors if the viewer is disposed or not initialized.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- There are several inconsistent spellings of the two‑page mode across JS/C# (`TwoPagesOnView` vs `TowPagesOnView`, e.g. `setPages` parameter and `TriggerTowPagesOnViewChanged`), which will be confusing and make future refactoring/error searching harder; consider standardizing all public and internal names to a single, correctly spelled form.
- The two‑pages toggle currently has both a Blazor `@onclick` handler and a JS `EventHandler.on(..., "click", ...)` on `.dropdown-item-pages`; this double binding makes the behavior harder to reason about and may surprise future maintainers, so it would be better to centralize the toggle in one place (either JS or Blazor) and keep the other side purely in sync.
- In `setPages`, `Data.get(id)` is used without checking for a missing entry, and the `el` binding is unused; consider removing the unused `el` destructuring and adding a null/undefined guard for the `Data.get` result to avoid potential runtime errors if the viewer is disposed or not initialized.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:105-114` </location>
<code_context>
     }
 }

+export function setPages(id, enableTowPagesOnView) {
+    const { el, pdfViewer } = Data.get(id);
+    if (pdfViewer) {
</code_context>

<issue_to_address>
**suggestion (typo):** Align naming ("Two" vs "Tow") for the two-pages-on-view feature across JS and C#.

The parameter `enableTowPagesOnView`, local `towPagesOneView`, and C# flag `TriggerTowPagesOnViewChanged` all use `Tow` instead of `Two`. Please rename them to `enableTwoPagesOnView` / `twoPagesOneView` / `TriggerTwoPagesOnViewChanged` to match `EnableTwoPagesOnView` / `ShowTwoPagesOnViewButton` and the UI text, and to keep the feature easy to search for and reason about.

Suggested implementation:

```javascript
export function setPages(id, enableTwoPagesOnView) {
    const { el, pdfViewer } = Data.get(id);
    if (pdfViewer) {
        if (enableTwoPagesOnView) {
            pdfViewer.spreadMode = 1;
        }
        else {
            pdfViewer.spreadMode = 0;
        }
    }
}

```

```javascript
twoPagesOneView

```

To fully align the naming across the codebase, you should also:

1. In the corresponding C# files (likely in the PdfReader component and any related event args or services), rename:
   - `TriggerTowPagesOnViewChanged``TriggerTwoPagesOnViewChanged`
   - Any other `TowPagesOnView` occurrences → `TwoPagesOnView`.
2. Update any JS interop calls that reference `setPages` so that they pass the parameter named `enableTwoPagesOnView` instead of `enableTowPagesOnView`.
3. Search the entire repository for `TowPagesOnView` and `towPagesOneView` to ensure all usages are consistently renamed.
</issue_to_address>

### Comment 2
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs:159-162` </location>
<code_context>
             _currentScale = Options.CurrentScale;
             await InvokeVoidAsync("scale", Id, _currentScale);
         }
+        if (_enableTwoPagesOneView != Options.EnableTwoPagesOnView)
+        {
+            _currentScale = Options.CurrentScale;
+            await InvokeVoidAsync("setPages", Id, _enableTwoPagesOneView);
+        }
     }
</code_context>

<issue_to_address>
**issue (bug_risk):** The two-page view sync block likely uses the wrong value and never updates local state, causing external changes to be reverted.

Here you compare `_enableTwoPagesOneView` with `Options.EnableTwoPagesOnView`, but then call `setPages` with the stale `_enableTwoPagesOneView` and never update it.

If a parent changes `Options.EnableTwoPagesOnView` from `false` to `true` without calling `OnToggleTwoPagesOneView`, this block will fire but still pass `false` to `setPages`, undoing the parent’s change on the JS side.

Consider instead:
```csharp
if (_enableTwoPagesOneView != Options.EnableTwoPagesOnView)
{
    _enableTwoPagesOneView = Options.EnableTwoPagesOnView;
    await InvokeVoidAsync("setPages", Id, _enableTwoPagesOneView);
}
```
(or pass `Options.EnableTwoPagesOnView` directly and then sync `_enableTwoPagesOneView`.)
</issue_to_address>

### Comment 3
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs:98` </location>
<code_context>
+        _enableTwoPagesOneView = !_enableTwoPagesOneView;
+        Options.EnableTwoPagesOnView = _enableTwoPagesOneView;
+
+        _twoPagesOneViewIcon = _enableTwoPagesOneView ? "fa-solid fa-fw fa-check" : "fa-solid fa-fw";
+    }
+
</code_context>

<issue_to_address>
**suggestion (bug_risk):** The icon state for two-page view is only updated via the local toggle method, not when Options is changed externally.

Because `_twoPagesOneViewIcon` is only set in `OnToggleTwoPagesOneView`, but `_enableTwoPagesOneView` is also updated from `Options.EnableTwoPagesOnView` in `OnAfterRenderAsync`, a parent updating `Options.EnableTwoPagesOnView` directly can leave the icon out of sync with the actual state.

To avoid this, either recompute `_twoPagesOneViewIcon` whenever `_enableTwoPagesOneView` is updated from `Options`, or derive the icon directly from `_enableTwoPagesOneView` instead of keeping a separate field.

Suggested implementation:

```csharp
    private void OnToggleTwoPagesOneView()
    {
        _enableTwoPagesOneView = !_enableTwoPagesOneView;
        Options.EnableTwoPagesOnView = _enableTwoPagesOneView;
    }

```

```csharp
    private uint _currentPage;

    private string TwoPagesOneViewIcon => _enableTwoPagesOneView ? "fa-solid fa-fw fa-check" : "fa-solid fa-fw";

```

1. Remove the `_twoPagesOneViewIcon` field declaration from this file, e.g.:
   - `private string _twoPagesOneViewIcon = "fa-solid fa-fw";`
2. In `PdfReader.razor` (the markup file), replace usages of `_twoPagesOneViewIcon` with `TwoPagesOneViewIcon`, for example:
   - `class="@_twoPagesOneViewIcon"``class="@TwoPagesOneViewIcon"`.
3. Ensure any other references to `_twoPagesOneViewIcon` (if present elsewhere in the code-behind) are updated or removed in favor of the `TwoPagesOneViewIcon` property.
</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.

Comment on lines +159 to +162
if (_enableTwoPagesOneView != Options.EnableTwoPagesOnView)
{
_currentScale = Options.CurrentScale;
await InvokeVoidAsync("setPages", Id, _enableTwoPagesOneView);
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 two-page view sync block likely uses the wrong value and never updates local state, causing external changes to be reverted.

Here you compare _enableTwoPagesOneView with Options.EnableTwoPagesOnView, but then call setPages with the stale _enableTwoPagesOneView and never update it.

If a parent changes Options.EnableTwoPagesOnView from false to true without calling OnToggleTwoPagesOneView, this block will fire but still pass false to setPages, undoing the parent’s change on the JS side.

Consider instead:

if (_enableTwoPagesOneView != Options.EnableTwoPagesOnView)
{
    _enableTwoPagesOneView = Options.EnableTwoPagesOnView;
    await InvokeVoidAsync("setPages", Id, _enableTwoPagesOneView);
}

(or pass Options.EnableTwoPagesOnView directly and then sync _enableTwoPagesOneView.)

_enableTwoPagesOneView = !_enableTwoPagesOneView;
Options.EnableTwoPagesOnView = _enableTwoPagesOneView;

_twoPagesOneViewIcon = _enableTwoPagesOneView ? "fa-solid fa-fw fa-check" : "fa-solid fa-fw";
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 (bug_risk): The icon state for two-page view is only updated via the local toggle method, not when Options is changed externally.

Because _twoPagesOneViewIcon is only set in OnToggleTwoPagesOneView, but _enableTwoPagesOneView is also updated from Options.EnableTwoPagesOnView in OnAfterRenderAsync, a parent updating Options.EnableTwoPagesOnView directly can leave the icon out of sync with the actual state.

To avoid this, either recompute _twoPagesOneViewIcon whenever _enableTwoPagesOneView is updated from Options, or derive the icon directly from _enableTwoPagesOneView instead of keeping a separate field.

Suggested implementation:

    private void OnToggleTwoPagesOneView()
    {
        _enableTwoPagesOneView = !_enableTwoPagesOneView;
        Options.EnableTwoPagesOnView = _enableTwoPagesOneView;
    }
    private uint _currentPage;

    private string TwoPagesOneViewIcon => _enableTwoPagesOneView ? "fa-solid fa-fw fa-check" : "fa-solid fa-fw";
  1. Remove the _twoPagesOneViewIcon field declaration from this file, e.g.:
    • private string _twoPagesOneViewIcon = "fa-solid fa-fw";
  2. In PdfReader.razor (the markup file), replace usages of _twoPagesOneViewIcon with TwoPagesOneViewIcon, for example:
    • class="@_twoPagesOneViewIcon"class="@TwoPagesOneViewIcon".
  3. Ensure any other references to _twoPagesOneViewIcon (if present elsewhere in the code-behind) are updated or removed in favor of the TwoPagesOneViewIcon property.

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 "Two Pages on View" feature to the PdfReader component, allowing users to toggle between single-page and two-page spread modes. The implementation includes UI controls, JavaScript interop, and configuration options for the new viewing mode.

Key Changes:

  • Added configuration options for showing/enabling the two-pages-on-view button and mode
  • Implemented JavaScript functionality to toggle PDF spread mode
  • Added dropdown menu with "More" button to house the new feature

Reviewed changes

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

Show a summary per file
File Description
PdfReaderOptions.cs Added properties to control two-pages-on-view button visibility, mode state, and callback
PdfReader.razor.js Implemented setPages function and click handlers for toggling spread mode
PdfReader.razor.css Added CSS styling for the new toolbar button and dropdown
PdfReader.razor.cs Added backend logic to manage two-pages-on-view state and synchronization
PdfReader.razor Updated UI to include dropdown menu with two-pages-on-view toggle option
BootstrapBlazor.PdfReader.csproj Version bump and ItemGroup reorganization
Comments suppressed due to low confidence (1)

src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:160

  • Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
    })

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

Comment on lines +105 to +108
export function setPages(id, enableTowPagesOnView) {
const { el, pdfViewer } = Data.get(id);
if (pdfViewer) {
if (enableTowPagesOnView) {
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'Tow' to 'Two' in parameter name 'enableTowPagesOnView'.

Suggested change
export function setPages(id, enableTowPagesOnView) {
const { el, pdfViewer } = Data.get(id);
if (pdfViewer) {
if (enableTowPagesOnView) {
export function setPages(id, enableTwoPagesOnView) {
const { el, pdfViewer } = Data.get(id);
if (pdfViewer) {
if (enableTwoPagesOnView) {

Copilot uses AI. Check for mistakes.
EventHandler.on(minus, "click", e => updateScale(pdfViewer, e.target, -1));
EventHandler.on(plus, "click", e => updateScale(pdfViewer, e.target, 1));

const towPagesOneView = el.querySelector(".dropdown-item-pages");
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'tow' to 'two' in variable name 'towPagesOneView'.

Copilot uses AI. Check for mistakes.
EventHandler.off(plus, "click");
}

const towPagesOneView = el.querySelector(".dropdown-item-pages");
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'tow' to 'two' in variable name 'towPagesOneView'.

Copilot uses AI. Check for mistakes.
Comment on lines +63 to +65
/// 设置双页单视图模式回调方法
/// </summary>
public Func<bool, Task>? OnTwoPagesOneViewAsync { get; set; }
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

The callback property name 'OnTwoPagesOneViewAsync' is inconsistent with the feature name used elsewhere ('TwoPagesOnView'). Consider renaming to 'OnTwoPagesOnViewChangedAsync' to match the naming pattern of other callbacks like 'OnPageChangedAsync' and align with 'ShowTwoPagesOnViewButton' and 'EnableTwoPagesOnView'.

Suggested change
/// 设置双页单视图模式回调方法
/// </summary>
public Func<bool, Task>? OnTwoPagesOneViewAsync { get; set; }
/// 双页单视图模式变更回调方法
/// </summary>
public Func<bool, Task>? OnTwoPagesOnViewChangedAsync { get; set; }

Copilot uses AI. Check for mistakes.
TriggerPagesInit = Options.OnInitAsync != null,
TriggerPageChanged = Options.OnPageChangedAsync != null
TriggerPageChanged = Options.OnPageChangedAsync != null,
TriggerTowPagesOnViewChanged = Options.OnTwoPagesOneViewAsync != null
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'Tow' to 'Two' in property name 'TriggerTowPagesOnViewChanged'.

Suggested change
TriggerTowPagesOnViewChanged = Options.OnTwoPagesOneViewAsync != null
TriggerTwoPagesOnViewChanged = Options.OnTwoPagesOneViewAsync != null

Copilot uses AI. Check for mistakes.
Comment on lines +167 to +173
EventHandler.on(towPagesOneView, "click", e => {
if (pdfViewer.spreadMode === 0) {
pdfViewer.spreadMode = 1;
}
else {
pdfViewer.spreadMode = 0;
}
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

The click handler in addEventListener toggles the spreadMode but doesn't invoke the C# callback 'OnTwoPagesOneViewAsync' even though 'TriggerTowPagesOnViewChanged' is passed in options. If the callback should be triggered, add an async invocation similar to other event handlers (e.g., pageChanged). If the callback is not needed, remove the unused 'TriggerTowPagesOnViewChanged' property from options.

Suggested change
EventHandler.on(towPagesOneView, "click", e => {
if (pdfViewer.spreadMode === 0) {
pdfViewer.spreadMode = 1;
}
else {
pdfViewer.spreadMode = 0;
}
EventHandler.on(towPagesOneView, "click", async e => {
if (pdfViewer.spreadMode === 0) {
pdfViewer.spreadMode = 1;
}
else {
pdfViewer.spreadMode = 0;
}
if (options.TriggerTowPagesOnViewChanged === true) {
await invoke.invokeMethodAsync("OnTwoPagesOneViewAsync", pdfViewer.spreadMode);
}

Copilot uses AI. Check for mistakes.
}
if (_enableTwoPagesOneView != Options.EnableTwoPagesOnView)
{
_currentScale = Options.CurrentScale;
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

The JavaScript function is called with the old value '_enableTwoPagesOneView' before it's updated. The assignment should be '_enableTwoPagesOneView = Options.EnableTwoPagesOnView;' and then pass the updated value to 'setPages'.

Suggested change
_currentScale = Options.CurrentScale;
_enableTwoPagesOneView = Options.EnableTwoPagesOnView;

Copilot uses AI. Check for mistakes.
<ItemsTemplate>
@if (Options.ShowTwoPagesOnViewButton)
{
<div class="dropdown-item dropdown-item-pages" @onclick="OnToggleTwoPagesOneView"><i class="@_twoPagesOneViewIcon"></i><span>Two pages on view</span></div>
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

[nitpick] The text 'Two pages on view' is hardcoded in English while other component strings appear to support Chinese (based on C# comments). Consider localizing this string for consistency with the rest of the component, especially since the codebase uses Chinese documentation.

Copilot uses AI. Check for mistakes.
}

export function setPages(id, enableTowPagesOnView) {
const { el, pdfViewer } = Data.get(id);
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

Unused variable el.

Suggested change
const { el, pdfViewer } = Data.get(id);
const { pdfViewer } = Data.get(id);

Copilot uses AI. Check for mistakes.
const step = [25, 33, 50, 67, 75, 80, 90, 100, 110, 125, 150, 175, 200, 250, 300, 400, 500];
const findValues = step.filter(s => rate > 0 ? current < s : current > s);
const findValues = step.filter(s => rate > 0 ? current < s : current > s);
let v = 100;
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

The initial value of v is unused, since it is always overwritten.

Suggested change
let v = 100;
let v;

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 TwoPagesOnView function

2 participants