Skip to content

feat(PdfReader): add EnableThumbnails parameter#739

Merged
ArgoZhang merged 2 commits intomasterfrom
dev-thumb
Nov 28, 2025
Merged

feat(PdfReader): add EnableThumbnails parameter#739
ArgoZhang merged 2 commits intomasterfrom
dev-thumb

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Nov 28, 2025

Link issues

fixes #738

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 thumbnail sidebar support to the PdfReader component and adjust its UI interactions accordingly.

New Features:

  • Introduce an EnableThumbnails parameter on PdfReader to allow toggling the thumbnail sidebar visibility at runtime.

Enhancements:

  • Update the PdfReader toolbar so the sidebar toggle button is only rendered when thumbnails are enabled.
  • Adjust thumbnail toggle event handling to be attached via the view title container for better control and cleanup when disposing the component.
  • Add JS interop support to reset thumbnails when the EnableThumbnails setting is turned back on.

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

sourcery-ai Bot commented Nov 28, 2025

Reviewer's Guide

Adds a configurable EnableThumbnails option to PdfReader that controls whether the thumbnails sidebar is available and ensures the JS viewer correctly initializes, toggles, and resets thumbnail state when the option changes.

Sequence diagram for updating thumbnails when EnableThumbnails changes

sequenceDiagram
    actor User
    participant ParentComponent
    participant PdfReader
    participant JsRuntime
    participant PdfReaderRazorJs as PdfReader_razor_js

    User ->> ParentComponent: Change thumbnail setting in UI
    ParentComponent ->> PdfReader: Render with EnableThumbnails = value
    PdfReader ->> PdfReader: OnAfterRenderAsync(firstRender = false)
    PdfReader ->> PdfReader: Detect _enableThumbnails != EnableThumbnails
    PdfReader ->> PdfReader: _enableThumbnails = EnableThumbnails
    alt EnableThumbnails is true
        PdfReader ->> JsRuntime: InvokeVoidAsync(resetThumbnails, Id)
        JsRuntime ->> PdfReaderRazorJs: resetThumbnails(Id)
        PdfReaderRazorJs ->> PdfReaderRazorJs: Data.get(Id)
        PdfReaderRazorJs ->> PdfReaderRazorJs: resetThumbnailsView(el, pdfViewer)
        PdfReaderRazorJs ->> User: Thumbnails sidebar reset and shown correctly
    else EnableThumbnails is false
        PdfReader ->> User: Thumbnails disabled, no JS reset
    end
Loading

Class diagram for updated PdfReader thumbnail configuration

classDiagram
    class PdfReader {
        string~?~ _url
        string~?~ _currentScale
        string~?~ _dropdownItemCheckIcon
        string~?~ _dropdownItemDefaultIcon
        bool _enableThumbnails
        bool EnableThumbnails
        Task OnAfterRenderAsync(bool firstRender)
        ValueTask InvokeVoidAsync(string identifier, string id)
    }

    class PdfReaderRazorJs {
        void init(string id, bool enableThumbnails)
        void scale(string id, string scale)
        void resetThumbnails(string id)
        void dispose(string id)
        void addEventListener(Element el, object pdfViewer, object eventBus, Delegate invoke, PdfReaderOptions options)
    }

    class PdfReaderOptions {
        bool fitMode
        bool enableThumbnails
    }

    PdfReader --> PdfReaderRazorJs : uses_JS_interop
    PdfReader --> PdfReaderOptions : passes
    PdfReaderOptions ..> PdfReaderRazorJs : configures_behavior
Loading

File-Level Changes

Change Details Files
Wire a new EnableThumbnails parameter into the PdfReader lifecycle and trigger thumbnail reset when it changes.
  • Introduced a private backing field _enableThumbnails with default true to track the last applied thumbnails state.
  • Synchronized _enableThumbnails with the public EnableThumbnails parameter during the initial render.
  • On subsequent renders, detect changes to EnableThumbnails and, when it is turned on, invoke a new JS interop method resetThumbnails to reinitialize the thumbnails view.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Conditionally render and rewire the thumbnails toggle UI so it only appears and works when thumbnails are enabled.
  • Made the sidebar toggle button (.bb-view-bar) render only when EnableThumbnails is true inside the toolbar title section.
  • Changed the thumbnails toggle click handling to delegate from the .bb-view-title container to the .bb-view-bar element instead of binding directly to the bar element.
  • Updated disposal logic to detach the click handler from the title container instead of the bar element.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Expose and implement a JS-side resetThumbnails function and harden thumbnail-related event handling against missing configuration.
  • Added a resetThumbnails(id) export that retrieves the PdfReader instance and calls resetThumbnailsView with the element and pdfViewer when present.
  • Adjusted page change handling to check (options.enableThumbnails

Assessment against linked issues

Issue Objective Addressed Explanation
#738 Introduce an EnableThumbnails parameter on PdfReader that controls whether the PDF thumbnails sidebar (including its toggle UI and behavior) is shown and kept in sync when the parameter 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

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 - here's some feedback:

  • In addEventListener, the if (options.enableThumbnails || false) check is effectively the same as if (options.enableThumbnails) and adds noise; consider dropping the || false or normalizing options.enableThumbnails earlier if you need a strict boolean.
  • When EnableThumbnails is toggled from true to false, the JS side doesn’t proactively hide or reset the thumbnail sidebar (only the toolbar button disappears); consider also collapsing or resetting the thumbnails container in this path to avoid leaving an open, now-unsupported sidebar visible.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `addEventListener`, the `if (options.enableThumbnails || false)` check is effectively the same as `if (options.enableThumbnails)` and adds noise; consider dropping the `|| false` or normalizing `options.enableThumbnails` earlier if you need a strict boolean.
- When `EnableThumbnails` is toggled from true to false, the JS side doesn’t proactively hide or reset the thumbnail sidebar (only the toolbar button disappears); consider also collapsing or resetting the thumbnails container in this path to avoid leaving an open, now-unsupported sidebar visible.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs:246-251` </location>
<code_context>
             _currentScale = CurrentScale;
             await InvokeVoidAsync("scale", Id, _currentScale);
         }
+        if (_enableThumbnails != EnableThumbnails)
+        {
+            _enableThumbnails = EnableThumbnails;
+            if (_enableThumbnails)
+            {
+                await InvokeVoidAsync("resetThumbnails", Id);
+            }
+        }
</code_context>

<issue_to_address>
**suggestion (bug_risk):** When thumbnails are disabled, the UI state of the sidebar may remain visible and inconsistent.

This logic only reacts when `EnableThumbnails` becomes `true`. When it changes from `true` to `false`, no JS runs, so an open thumbnails sidebar (with `show` class) can remain visible even though the icon is gone. Please also hide/reset the thumbnails panel on disable (e.g., via JS interop that removes `show`) to keep the UI consistent with `EnableThumbnails`.

Suggested implementation:

```csharp
        if (_enableThumbnails != EnableThumbnails)
        {
            _enableThumbnails = EnableThumbnails;

            if (_enableThumbnails)
            {
                // Thumbnails enabled: ensure sidebar is in a clean, visible state.
                await InvokeVoidAsync("resetThumbnails", Id);
            }
            else
            {
                // Thumbnails disabled: ensure any open sidebar is hidden to keep UI consistent.
                await InvokeVoidAsync("hideThumbnails", Id);
            }
        }

```

To fully implement this behavior, you will also need to:
1. Add a `hideThumbnails` JavaScript function in the corresponding JS file used by `PdfReader` (where `resetThumbnails` is defined). That function should:
   - Locate the thumbnails sidebar element.
   - Remove any `show` (or equivalent) class.
   - Ensure it is visually hidden/closed.
2. Verify that `hideThumbnails` is correctly exported/available under the same JS interop namespace used by `resetThumbnails`, so `InvokeVoidAsync("hideThumbnails", Id)` successfully resolves.
</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 thread src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
@ArgoZhang ArgoZhang merged commit 993e6bb into master Nov 28, 2025
2 checks passed
@ArgoZhang ArgoZhang deleted the dev-thumb branch November 28, 2025 00:35
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 support for dynamically enabling/disabling PDF thumbnails in the PdfReader component by making the EnableThumbnails parameter reactive to runtime changes.

Key Changes:

  • Added runtime detection and handling of EnableThumbnails parameter changes in C# code
  • Introduced a new resetThumbnails JavaScript function to re-initialize thumbnails when enabled
  • Modified event handlers to use event delegation pattern for better flexibility
  • Made thumbnail sidebar toggle button conditionally render based on EnableThumbnails state

Reviewed changes

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

File Description
PdfReader.razor.cs Added _enableThumbnails field and logic in OnAfterRenderAsync to detect parameter changes and call resetThumbnails when thumbnails are enabled
PdfReader.razor.js Added resetThumbnails export function, changed event handler from direct attachment to event delegation pattern, and added redundant `
PdfReader.razor Made the thumbnail toggle button (.bb-view-bar) conditionally render only when EnableThumbnails is true
Comments suppressed due to low confidence (1)

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

  • Potential null reference error. When options.enableThumbnails is truthy and thumbnailsContainer exists but has no element with the .active class, line 153 will throw a "Cannot read property 'classList' of null" error because active is not checked for null before calling classList.remove(). This should be guarded with a null check: if (active) { active.classList.remove('active'); }.
                const active = thumbnailsContainer.querySelector('.active');
                active.classList.remove('active');

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

}

if (options.enableThumbnails) {
if (options.enableThumbnails || false) {
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

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

The expression options.enableThumbnails || false is redundant. Since options.enableThumbnails is already a boolean, the || false doesn't change the behavior. If enableThumbnails is true, it returns true; if it's false, the expression evaluates to false. This should be simplified to just options.enableThumbnails.

Suggested change
if (options.enableThumbnails || false) {
if (options.enableThumbnails) {

Copilot uses AI. Check for mistakes.
if (titleEl) {
EventHandler.on(titleEl, "click", '.bb-view-bar', e => {
const thumbnailsEl = el.querySelector(".bb-view-thumbnails");
thumbnailsEl.classList.toggle("show");
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

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

Missing null check for thumbnailsEl. The code queries for .bb-view-thumbnails but doesn't verify it exists before calling classList.toggle(). While the event delegation pattern ensures this handler only fires when .bb-view-bar is clicked, there's a timing issue: during dynamic state changes (e.g., when EnableThumbnails transitions from true to false), the .bb-view-bar element might still exist briefly while .bb-view-thumbnails is already removed, leading to a null reference error. Add a null check: if (thumbnailsEl) { thumbnailsEl.classList.toggle("show"); }.

Suggested change
thumbnailsEl.classList.toggle("show");
if (thumbnailsEl) {
thumbnailsEl.classList.toggle("show");
}

Copilot uses AI. Check for mistakes.

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

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

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

Missing null check for el parameter. The function retrieves el from Data.get(id) but only checks if pdfViewer exists before calling resetThumbnailsView(el, pdfViewer). If el is null or undefined, it will be passed to resetThumbnailsView, which will fail when trying to call el.querySelector() at line 206. Add a check: if (el && pdfViewer) { ... }.

Suggested change
if (pdfViewer) {
if (el && pdfViewer) {

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

2 participants