Skip to content

feat(PdfReader): add OnPageChangedAsync parameter#715

Merged
ArgoZhang merged 2 commits intomasterfrom
dev-pdf-page
Nov 25, 2025
Merged

feat(PdfReader): add OnPageChangedAsync parameter#715
ArgoZhang merged 2 commits intomasterfrom
dev-pdf-page

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Nov 25, 2025

Link issues

fixes #714

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

Introduce a configurable options model for the PdfReader component and enhance its page navigation and toolbar behavior.

New Features:

  • Add PdfReaderOptions to centralize PdfReader configuration including URL, view height, current page, toolbar visibility, and fit-to-page behavior.
  • Expose async callbacks for PDF initialization and page change events via OnInitAsync and OnPageChangedAsync options.
  • Support two-way interaction with the current page through the toolbar input and programmatic navigation, including reacting to URL and page changes.

Enhancements:

  • Refine PdfReader initialization and rendering logic to react to option changes such as URL, fit mode, and current page without recreating the component.
  • Update the PdfReader toolbar to optionally display, show dynamic page counts, and delay toolbar content visibility until pages are initialized.
  • Move PdfReader CSS into a component-scoped stylesheet and adjust initialization to load the pdf_viewer styles directly from JavaScript.

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

sourcery-ai Bot commented Nov 25, 2025

Reviewer's Guide

Refactors PdfReader to use a new PdfReaderOptions configuration object, adds async callbacks for initialization and page changes, and wires the Blazor component, JS interop, and styling to support current-page binding, optional toolbar, and event-based updates from pdf.js.

Sequence diagram for PdfReader initialization with options and OnInitAsync

sequenceDiagram
    actor User
    participant AppComponent
    participant PdfReader
    participant DotNetRuntime
    participant PdfReaderJs
    participant PdfJsViewer

    User ->> AppComponent: NavigateToPageWithPdf()
    AppComponent ->> PdfReader: Render with Options(Url, IsFitToPage, OnInitAsync, OnPageChangedAsync)
    activate PdfReader
    PdfReader ->> PdfReader: OnParametersSet()
    PdfReader ->> PdfReader: Options ??= new PdfReaderOptions()
    PdfReader ->> PdfReader: Ensure Options.CurrentPage >= 1
    PdfReader ->> PdfReader: _docTitle = Path.GetFileName(Options.Url)
    deactivate PdfReader

    loop FirstRender
        PdfReader ->> PdfReader: OnAfterRenderAsync(firstRender = true)
        activate PdfReader
        PdfReader ->> PdfReader: _isFitToPage = Options.IsFitToPage
        PdfReader ->> PdfReader: _currentPage = Options.CurrentPage
        PdfReader ->> PdfReader: _url = Options.Url
        PdfReader ->> PdfReader: InvokeInitAsync()
        PdfReader ->> DotNetRuntime: InvokeVoidAsync init(Id, Interop, { Url, IsFitToPage, TriggerPagesInit, TriggerPageChanged })
        deactivate PdfReader

        DotNetRuntime ->> PdfReaderJs: init(id, invoke, options)
        activate PdfReaderJs
        PdfReaderJs ->> PdfReaderJs: addLink css pdf_viewer.css
        PdfReaderJs ->> PdfReaderJs: Check options.url not null
        PdfReaderJs ->> PdfJsViewer: pdfjsLib.getDocument(options)
        PdfJsViewer -->> PdfReaderJs: loadingTask.promise resolved
        PdfReaderJs ->> PdfJsViewer: setDocument(pdfDocument)
        PdfReaderJs ->> PdfReaderJs: addEventListener(pdfViewer, eventBus, invoke, options)

        PdfJsViewer ->> PdfReaderJs: pagesinit event
        PdfReaderJs ->> PdfReaderJs: Set scale based on options.isFitToPage
        PdfReaderJs ->> PdfReaderJs: Update toolbar DOM (pagesCount, remove init)
        alt options.triggerPagesInit is true
            PdfReaderJs ->> DotNetRuntime: invokeMethodAsync pagesInit(numPages)
            DotNetRuntime ->> PdfReader: PagesInit(int pagesCount)
            activate PdfReader
            PdfReader ->> PdfReader: if Options.OnInitAsync != null
            PdfReader ->> AppComponent: await Options.OnInitAsync(pagesCount)
            deactivate PdfReader
        end
        deactivate PdfReaderJs
    end
Loading

Sequence diagram for page change flow with OnPageChangedAsync and CurrentPage binding

sequenceDiagram
    actor User
    participant AppComponent
    participant PdfReader
    participant DotNetRuntime
    participant PdfReaderJs
    participant PdfJsViewer

    rect rgb(230,230,250)
    note over User,PdfJsViewer: User driven page change in viewer
    User ->> PdfJsViewer: Scroll or navigate to another page
    PdfJsViewer ->> PdfReaderJs: pagechanging event
    activate PdfReaderJs
    PdfReaderJs ->> PdfReaderJs: Update bb-view-num input value
    alt options.triggerPageChanged is true
        PdfReaderJs ->> DotNetRuntime: invokeMethodAsync pageChanged(page)
        DotNetRuntime ->> PdfReader: PageChanged(uint pageIndex)
        activate PdfReader
        PdfReader ->> PdfReader: _currentPage = pageIndex
        PdfReader ->> PdfReader: Options.CurrentPage = pageIndex
        alt Options.OnPageChangedAsync != null
            PdfReader ->> AppComponent: await Options.OnPageChangedAsync(pageIndex)
        end
        deactivate PdfReader
    end
    deactivate PdfReaderJs
    end

    rect rgb(220,245,220)
    note over AppComponent,PdfReaderJs: App component changes page programmatically
    AppComponent ->> PdfReader: NavigateToPageAsync(newPage)
    activate PdfReader
    PdfReader ->> DotNetRuntime: InvokeVoidAsync navigateToPage(Id, newPage)
    deactivate PdfReader
    DotNetRuntime ->> PdfReaderJs: navigateToPage(id, pageNumber)
    activate PdfReaderJs
    PdfReaderJs ->> PdfJsViewer: Navigate to specified page
    deactivate PdfReaderJs
    end
Loading

Class diagram for updated PdfReader and new PdfReaderOptions

classDiagram
    class PdfReader {
        +PdfReaderOptions Options
        -string ClassString
        -string StyleString
        -string ViewBodyString
        -string _docTitle
        -bool _isFitToPage
        -uint _currentPage
        -string _url
        +string CurrentPageString
        +OnParametersSet()
        +OnAfterRenderAsync(bool firstRender)
        +InvokeInitAsync() Task
        +NavigateToPageAsync(uint pageNumber) Task
        +FitToPage() void
        +FitToWidth() void
        +RotateLeft() Task
        +RotateRight() Task
        +PagesInit(int pagesCount) Task
        +PageChanged(uint pageIndex) Task
    }

    class PdfReaderOptions {
        +bool ShowToolbar
        +string Url
        +string ViewHeight
        +uint CurrentPage
        +bool IsFitToPage
        +Func~int,Task~ OnInitAsync
        +Func~uint,Task~ OnPageChangedAsync
    }

    PdfReader --> PdfReaderOptions : uses
Loading

File-Level Changes

Change Details Files
Refactor PdfReader parameters into a single PdfReaderOptions configuration object and track URL, fit mode, and current page reactively.
  • Replace individual Url, ViewHeight, and IsFitToPage parameters with a required PdfReaderOptions parameter.
  • Update computed CSS class and style builders to read height and fit-to-page state from the options object.
  • Initialize options in OnParametersSet, including defaulting CurrentPage to 1 and deriving the document title from the configured Url.
  • Track previous Url, IsFitToPage, and CurrentPage in private fields and, in OnAfterRenderAsync, re-init the viewer when Url changes, trigger fit operations when IsFitToPage changes, and navigate when CurrentPage changes.
  • Expose CurrentPageString with invariant-culture parsing to bind the toolbar page number input to the numeric CurrentPage option.
  • Change NavigateToPageAsync to use uint and update FitToPage/FitToWidth methods to mutate Options.IsFitToPage.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Add async callbacks for pages initialization and page-changed events, and propagate them through JS interop.
  • Extend InvokeInitAsync to pass url, isFitToPage, and boolean flags indicating whether to trigger pages-init and page-changed callbacks based on options.
  • Change JSInvokable PagesInit and PageChanging methods to async methods PagesInit(int pagesCount) and PageChanged(uint pageIndex) that update Options state and invoke OnInitAsync/OnPageChangedAsync if provided.
  • Wire pdf.js eventBus pagesinit and pagechanging events in JavaScript to update toolbar UI, set scale, and call the corresponding .NET methods when the trigger flags are true.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Enhance the PdfReader toolbar markup and behavior, including optional visibility, binding to current page, and initial hidden state styling.
  • Wrap the toolbar markup in an Options.ShowToolbar conditional and add an 'init' CSS class for initial hidden state.
  • Bind the page number input to CurrentPageString and replace the hard-coded pages count element with a dynamically updated container.
  • Keep existing toolbar controls (zoom, fit, rotate, draw, download, print, home) but wire them to the updated methods where applicable.
  • Move component-specific CSS into PdfReader.razor.css and add a rule to hide toolbar contents until initialization completes.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css
Adjust JavaScript initialization to support null URLs, separate viewer CSS loading, and centralized event wiring.
  • Load pdf_viewer.css explicitly in the init function instead of via CSS @import, and stop initializing if the container element or options.url are null.
  • Refactor eventBus wiring into a dedicated addEventListener helper that sets initial scale, updates page count and input fields, manages toolbar visibility, and conditionally invokes .NET callbacks.
  • Simplify PDF loading by awaiting loadingTask.promise and setting the document on the viewer, tracking the viewer in Data for later operations.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Introduce PdfReaderOptions to encapsulate PdfReader configuration and callbacks.
  • Create PdfReaderOptions class with ShowToolbar, Url, ViewHeight, CurrentPage, and IsFitToPage properties.
  • Add async callback delegates OnInitAsync (pages count) and OnPageChangedAsync (current page) to enable consumers to respond to lifecycle events.
  • Set sensible defaults such as ShowToolbar = true and leave other properties nullable or value-typed for consumer control.
src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#714 Add an asynchronous page-changed callback parameter (OnPageChangedAsync) to the PdfReader component and wire it so it is invoked when the current page changes.

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 d33b0d4 into master Nov 25, 2025
6 of 7 checks passed
@ArgoZhang ArgoZhang deleted the dev-pdf-page branch November 25, 2025 02:24
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.

Blocking issues:

  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a countEl.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)

General comments:

  • The JS interop callbacks appear to be mismatched: JavaScript calls invoke.invokeMethodAsync("pagesInit", ...) and invoke.invokeMethodAsync("pageChanged", ...) but the C# methods are [JSInvokable] public async Task PagesInit(...) and PageChanged(...), so either the JS names or the [JSInvokable] identifiers should be aligned to avoid runtime failures.
  • The Options parameter is treated as non-null in members like StyleString, ViewBodyString, and CurrentPageString but is only defaulted in OnParametersSet, so consider making it non-nullable with a default instance or guarding all usages to avoid potential null-reference issues during initial render or misuse by consumers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The JS interop callbacks appear to be mismatched: JavaScript calls `invoke.invokeMethodAsync("pagesInit", ...)` and `invoke.invokeMethodAsync("pageChanged", ...)` but the C# methods are `[JSInvokable] public async Task PagesInit(...)` and `PageChanged(...)`, so either the JS names or the `[JSInvokable]` identifiers should be aligned to avoid runtime failures.
- The `Options` parameter is treated as non-null in members like `StyleString`, `ViewBodyString`, and `CurrentPageString` but is only defaulted in `OnParametersSet`, so consider making it non-nullable with a default instance or guarding all usages to avoid potential null-reference issues during initial render or misuse by consumers.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:81-90` </location>
<code_context>
+    eventBus.on("pagesinit", async () => {
</code_context>

<issue_to_address>
**issue (bug_risk):** JSInvokable method names in JS don’t match the C# method names, which will break interop calls.

The JS currently calls `invoke.invokeMethodAsync(
</issue_to_address>

### Comment 2
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs:122` </location>
<code_context>
     /// <param name="pageNumber"></param>
     /// <returns></returns>
-    public Task NavigateToPageAsync(int pageNumber) => InvokeVoidAsync("navigateToPage", Id, pageNumber);
+    public Task NavigateToPageAsync(uint pageNumber) => InvokeVoidAsync("navigateToPage", Id, pageNumber);

     /// <summary>
</code_context>

<issue_to_address>
**suggestion (bug_risk):** CurrentPage/initial page support is only applied after changes, so the initial page value on first load is effectively ignored.

Because `_currentPage` is set from `Options.CurrentPage` only on first render and no navigation is triggered then, the viewer never actually jumps to a non-default initial page. To honor an initial `CurrentPage`, either pass it to JS and set `pdfViewer.currentPageNumber` in `pagesinit`, or, once initialization completes, call `NavigateToPageAsync(Options.CurrentPage)` when `Options.CurrentPage > 1`.

Suggested implementation:

```csharp
        TriggerPagesInit = Options.OnInitAsync != null,
        TriggerPageChanged = Options.OnPageChangedAsync != null
    });

    // Honor an initial non-default CurrentPage by navigating after initialization completes
    if (Options is not null && Options.CurrentPage > 1)
    {
        await NavigateToPageAsync((uint)Options.CurrentPage);
    }

```

I assumed this block is inside an async initialization method (likely OnAfterRenderAsync or a similar lifecycle/initialization method) where:
- "InvokeVoidAsync" initializes the JS PDF viewer, and
- "Options.CurrentPage" is an int or similar numeric type.

You may need to:
1) Ensure the enclosing method is async and can await the new NavigateToPageAsync call.
2) Adjust the cast to uint if Options.CurrentPage is already an unsigned type.
3) If the initialization can be called multiple times, consider guarding this navigation with a "firstRender" or similar flag so the initial navigation only happens once.
4) If you prefer the "pass to JS and handle in pagesinit" approach instead, add "InitialPage = Options.CurrentPage" to the object passed to JS here and then update the JS side to set "pdfViewer.currentPageNumber" in the "pagesinit" handler using that value.
</issue_to_address>

### Comment 3
<location> `src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs:38-45` </location>
<code_context>
+    public bool IsFitToPage { get; set; }
+
+    /// <summary>
+    /// 页面初始化回调方法
+    /// </summary>
+    public Func<int, Task>? OnInitAsync { get; set; }
+
+    /// <summary>
+    /// 页面初始化回调方法
+    /// </summary>
+    public Func<uint, Task>? OnPageChangedAsync { get; set; }
+}
</code_context>

<issue_to_address>
**nitpick:** The summary for OnPageChangedAsync doesn’t reflect that it is a page-changed callback.

The XML comment for `OnPageChangedAsync` is copied from `OnInitAsync` but this delegate is called on page changes, not initialization. Please update the description (e.g., to “页面变更回调方法”) so its behavior is accurately documented for consumers.
</issue_to_address>

### Comment 4
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:93` </location>
<code_context>
            countEl.innerHTML = numPages;
</code_context>

<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 5
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:93` </location>
<code_context>
            countEl.innerHTML = numPages;
</code_context>

<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `countEl.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</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.

/// <param name="pageNumber"></param>
/// <returns></returns>
public Task NavigateToPageAsync(int pageNumber) => InvokeVoidAsync("navigateToPage", Id, pageNumber);
public Task NavigateToPageAsync(uint pageNumber) => InvokeVoidAsync("navigateToPage", Id, pageNumber);
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): CurrentPage/initial page support is only applied after changes, so the initial page value on first load is effectively ignored.

Because _currentPage is set from Options.CurrentPage only on first render and no navigation is triggered then, the viewer never actually jumps to a non-default initial page. To honor an initial CurrentPage, either pass it to JS and set pdfViewer.currentPageNumber in pagesinit, or, once initialization completes, call NavigateToPageAsync(Options.CurrentPage) when Options.CurrentPage > 1.

Suggested implementation:

        TriggerPagesInit = Options.OnInitAsync != null,
        TriggerPageChanged = Options.OnPageChangedAsync != null
    });

    // Honor an initial non-default CurrentPage by navigating after initialization completes
    if (Options is not null && Options.CurrentPage > 1)
    {
        await NavigateToPageAsync((uint)Options.CurrentPage);
    }

I assumed this block is inside an async initialization method (likely OnAfterRenderAsync or a similar lifecycle/initialization method) where:

  • "InvokeVoidAsync" initializes the JS PDF viewer, and
  • "Options.CurrentPage" is an int or similar numeric type.

You may need to:

  1. Ensure the enclosing method is async and can await the new NavigateToPageAsync call.
  2. Adjust the cast to uint if Options.CurrentPage is already an unsigned type.
  3. If the initialization can be called multiple times, consider guarding this navigation with a "firstRender" or similar flag so the initial navigation only happens once.
  4. If you prefer the "pass to JS and handle in pagesinit" approach instead, add "InitialPage = Options.CurrentPage" to the object passed to JS here and then update the JS side to set "pdfViewer.currentPageNumber" in the "pagesinit" handler using that value.

const numPages = pdfViewer.pagesCount;
const countEl = el.querySelector(".bb-view-pagesCount");
if (countEl) {
countEl.innerHTML = numPages;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

const numPages = pdfViewer.pagesCount;
const countEl = el.querySelector(".bb-view-pagesCount");
if (countEl) {
countEl.innerHTML = numPages;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security (javascript.browser.security.insecure-innerhtml): User controlled data in a countEl.innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

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 the OnPageChangedAsync callback parameter to the PdfReader component and refactors the component's parameter structure by introducing a PdfReaderOptions class. The refactoring consolidates individual parameters (Url, ViewHeight, IsFitToPage) into a single options object for better maintainability and adds support for both initialization and page change callbacks.

Key Changes:

  • Introduced PdfReaderOptions class to encapsulate all PdfReader configuration properties
  • Added OnPageChangedAsync and OnInitAsync callback parameters to enable component event handling
  • Refactored component to use options pattern instead of individual parameters

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
PdfReaderOptions.cs New options class containing all PdfReader configuration properties including the new OnPageChangedAsync callback
PdfReader.razor.cs Refactored to use PdfReaderOptions parameter; added callback method implementations (PagesInit, PageChanged) and state management for URL, page, and fit mode changes
PdfReader.razor.js Moved CSS import earlier in initialization; extracted event listener setup into separate function; added callbacks for page initialization and page changes
PdfReader.razor Updated template to conditionally render toolbar and bind current page input to new CurrentPageString property
PdfReader.razor.css Removed CSS import (moved to JavaScript); added styling for toolbar initialization state
Comments suppressed due to low confidence (1)

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

  • Unused class Pdf.
class Pdf {

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

Comment on lines +98 to 102
if (_currentPage != Options.CurrentPage)
{
_currentPage = Options.CurrentPage;
await NavigateToPageAsync(_currentPage);
}
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

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

There's a potential race condition here. If NavigateToPageAsync is called while the JavaScript pageChanged callback is executing, the page state could become inconsistent. Consider adding a flag to prevent updating _currentPage and Options.CurrentPage in the PageChanged method when the navigation was triggered from C# code rather than user interaction.

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +53
private void SetCurrentPage(string value)
{
if (uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num))
{
Options.CurrentPage = num;
}
}
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

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

The SetCurrentPage method silently ignores invalid input without providing feedback. Consider adding validation error handling or at least logging when the parse fails, so developers and users understand why page navigation might not work as expected.

Copilot uses AI. Check for mistakes.
public Func<int, Task>? OnInitAsync { get; set; }

/// <summary>
/// 页面初始化回调方法
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

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

The documentation comment is incorrect. This describes "页面初始化回调方法" (page initialization callback method), but it should describe "页面切换回调方法" (page changed callback method) or similar, to differentiate it from the OnInitAsync property above.

Suggested change
/// 页面初始化回调方法
/// 页面切换回调方法

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 OnPageChangedAsync parameter

2 participants