Skip to content

feat(DockView): add onPanelVisibleChanged event#980

Open
ArgoZhang wants to merge 7 commits intomasterfrom
dev-only-visible
Open

feat(DockView): add onPanelVisibleChanged event#980
ArgoZhang wants to merge 7 commits intomasterfrom
dev-only-visible

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Apr 20, 2026

Link issues

fixes #979

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

Handle DockView panel visibility changes uniformly and improve panel lifecycle robustness.

Bug Fixes:

  • Prevent initialization and visibility handlers from running after the dockview has been disposed to avoid runtime errors.

Enhancements:

  • Unify panel visibility handling to trigger configuration saving, visible tab loading, and drawer title updates based on visibility instead of active state.
  • Guard asynchronous dockview initialization and visibility callbacks against disposed instances to avoid operations on destroyed views.
  • Ensure panel removal from the internal panels list uses key-based lookup for correctness when panel references differ.
  • Allow toggling components to merge new panel options into existing panels without overwriting defined values with undefined.
  • Mark newly added panels as inactive when creating or adding them to groups to control their initial state.
  • Simplify and tighten panel close behavior when moving content back to templates, avoiding redundant checks and logs.
  • Make DockView click handlers and DOM queries resilient to missing elements and reduce initialization delay for faster setup.

Copilot AI review requested due to automatic review settings April 20, 2026 06:10
@bb-auto bb-auto bot added the enhancement New feature or request label Apr 20, 2026
@bb-auto bb-auto bot added this to the v9.2.0 milestone Apr 20, 2026
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 20, 2026

Reviewer's Guide

Implements a new panel visibility change handling flow for DockView, improves panel lifecycle and toggle logic, and hardens initialization and cleanup against disposed instances and missing DOM, while adding minor behavioral tweaks like inactive panel creation and safer panel deletion.

Sequence diagram for the updated panel visibility change handling

sequenceDiagram
    participant Panel
    participant PanelApi
    participant Group
    participant Dockview
    participant LoadTabsEvent

    Panel->>PanelApi: onDidVisibilityChange callback(isVisible)
    activate PanelApi
    PanelApi->>Dockview: get accessor
    Note over Dockview: dockview._isDisposed?
    alt Dockview is disposed
        PanelApi-->>Panel: return
    else Dockview is not disposed
        PanelApi->>Dockview: read params.options.renderer
        Note over Dockview: renderer === onlyWhenVisible && dockview._inited?
        alt onlyWhenVisible and inited
            alt isVisible
                PanelApi->>Dockview: saveConfig(dockview)
                PanelApi->>Dockview: collect visible panels from groups
                Dockview-->>LoadTabsEvent: _loadTabs.fire(visiblePanelKeys)
            else not isVisible
                PanelApi->>Panel: appendTemplatePanelEle(panel)
            end
        end
        Note over Group: group.getParams().floatType == drawer?
        alt isVisible and floatType drawer
            PanelApi->>Group: setDrawerTitle(group)
        end
        PanelApi->>PanelApi: setTimeout(0)
        Note over PanelApi: after timeout
        PanelApi->>Dockview: check dockview._isDisposed
        alt Dockview is disposed
            PanelApi-->>Panel: return
        else Dockview is not disposed
            PanelApi->>Panel: moveAlwaysRenderPanel(panel)
        end
    end
    deactivate PanelApi
Loading

Updated class diagram for Dockview panel lifecycle and extensions

classDiagram
    class Dockview {
        +any params
        +array~DockviewGroup~ groups
        +array~DockviewPanel~ panels
        +HTMLElement element
        +boolean _inited
        +boolean _isDisposed
        +any _loadTabs
        +any gridview
        +addPanel(id, title, inactive, renderer, component, position, params)
    }

    class DockviewGroup {
        +array~DockviewPanel~ panels
        +getParams()
    }

    class DockviewPanel {
        +any api
        +any accessor
        +any group
        +any params
        +string renderer
        +string component
        +string id
        +string title
    }

    class DockviewGroupPanel {
        +array~DockviewPanel~ panels
        +any accessor
        +getParams()
        +setParams(data)
    }

    class DockviewGroupPanelModel {
        +any accessor
        +closePanel(panel, triggerVisibleChange, moveToTemplate)
    }

    class DockviewUtils {
        +initDockview(dockview, options, template)
        +toggleComponent(dockview, options)
        +cleanUndefined(obj)
    }

    Dockview "1" o-- "many" DockviewGroup : groups
    Dockview "1" o-- "many" DockviewPanel : panels
    DockviewGroup "1" o-- "many" DockviewPanel : panels
    DockviewGroupPanel "1" o-- "many" DockviewPanel : panels
    DockviewGroupPanelModel "1" o-- "1" DockviewGroupPanel : controls

    class PanelVisibilityObserver {
        +observePanelActiveChange(panel)
    }

    PanelVisibilityObserver ..> DockviewPanel : observes
    PanelVisibilityObserver ..> Dockview : uses accessor

    class InitFlow {
        +savePanel(dockview, panel)
        +deletePanel(dockview, panel)
        +setWidth(target, dockview)
        +addPanelWidthGroupId(dockview, panel, index)
        +addPanelWidthCreatGroup(dockview, panel, panels)
    }

    InitFlow ..> Dockview : manages panels

    %% Key behavioral updates
    %% - DockviewPanel.api.onDidVisibilityChange now drives visibility logic
    %% - Dockview.panels deletion uses key-based findIndex
    %% - initDockview guards against disposed dockview and missing DOM
    %% - toggleComponent merges panels with cleanUndefined
    %% - addPanel* helpers mark new panels as inactive at creation
Loading

Flow diagram for the updated toggleComponent panel merge logic

flowchart TD
    A[Start toggleComponent] --> B[getPanelsFromOptions options]
    B --> C[Filter panels where params.visible is true]
    C --> D[Get panels from dockview.params.panels as localPanels]
    D --> E[For each visible options panel p]

    E --> F{Exists in localPanels?}
    F -- Yes --> G[Use local panel instance pan]
    G --> H[Update group and index based on panels and parentId]

    F -- No --> I[Find existingPanel in dockview.params.panels matching key]
    I --> J{existingPanel found?}

    J -- Yes --> K[Create merged panel object]
    K --> L[Merge top-level fields using cleanUndefined]
    L --> M[Merge params using cleanUndefined]
    M --> H

    J -- No --> N[Use new panel definition p]
    N --> H

    H --> O[Insert or move panel into group at computed index]
    O --> P[Continue for next visible panel]
    P --> Q[End toggleComponent]

    subgraph "cleanUndefined behavior"
        R[Input object] --> S[Remove entries with null or undefined values]
        S --> T[Return cleaned object]
    end
Loading

File-Level Changes

Change Details Files
Unify panel visibility/active handling and ensure config saving, tab loading, drawer title updates, and always-render moves all react to visibility changes safely.
  • Replace onDidActiveChange usage with onDidVisibilityChange so visibility drives saveConfig, loadTabs firing, drawer title updates, and always-render panel movement.
  • Guard visibility handler logic with dockview disposal checks and renderer/initialization conditions to avoid acting on disposed or uninitialized instances.
  • Fire _loadTabs only when a panel becomes visible and, on hide, move template panels back via appendTemplatePanelEle instead of relying on a separate visibility listener.
  • Ensure drawer title updates are tied to panel visibility and debounce moveAlwaysRenderPanel via a zero-delay timeout while safely clearing the handler.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js
Harden dockview initialization, toggle logic, and panel deletion to better handle disposed instances, missing DOM nodes, and partial option updates.
  • In initDockview, short-circuit initialization if dockview has been disposed, null out the reference, and make DOM query selectors and node lists null-safe with optional chaining.
  • Reduce the post-initialization timeout from 100ms to immediate (0ms) while keeping the deferred setup behavior.
  • Change deletePanel to identify panels by params.key instead of object identity when removing from dockview.params.panels.
  • Introduce a cleanUndefined helper to strip null/undefined properties before merging toggleComponent options onto existing panels, and adjust the merge strategy to preserve existing panel structure while overlaying provided params.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js
Tighten group panel extension behavior by removing debugging noise and simplifying closePanel template movement.
  • Remove a stray console.log from DockviewGroupPanel.setParams to avoid noisy logs.
  • Simplify closePanel template movement logic by checking panel.view.content.element first and then conditionally appending titleMenuEle and the content element to the template when moveToTemplate is true.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js
Adjust group panel creation to mark new panels as initially inactive when adding to an existing or new group.
  • When adding a panel to an existing group, include inactive: true in the addPanel options so it does not auto-activate on creation.
  • Similarly, when creating a new group for a panel, mark the new panel as inactive on add to avoid unintended activation.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js

Assessment against linked issues

Issue Objective Addressed Explanation
#979 Add an onPanelVisibleChanged event to DockView that fires when a panel’s visibility 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 - I've left some high level feedback:

  • The helper cleanUndefined currently filters out both undefined and null values (v != null); if the intent is truly only to ignore undefined while preserving explicit nulls, adjust the predicate or rename the function to better reflect the semantics.
  • observePanelActiveChange is now wired to onDidVisibilityChange and no longer uses the panel active state; consider renaming this function (and any related identifiers) to reflect visibility-based behavior to keep the lifecycle logic easier to follow.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The helper `cleanUndefined` currently filters out both `undefined` and `null` values (`v != null`); if the intent is truly only to ignore `undefined` while preserving explicit `null`s, adjust the predicate or rename the function to better reflect the semantics.
- `observePanelActiveChange` is now wired to `onDidVisibilityChange` and no longer uses the panel active state; consider renaming this function (and any related identifiers) to reflect visibility-based behavior to keep the lifecycle logic easier to follow.

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.

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

Adds support for a panelVisibleChanged event in DockView (fixes #979), and adjusts panel/group initialization and visibility handling to better align UI state with saved/localStorage state.

Changes:

  • Fire panelVisibleChanged events during layout restore and when panels are closed.
  • Refactor panel visibility handling to drive tab loading and template DOM placement from onDidVisibilityChange.
  • Adjust panel creation/merge behavior (avoid overwriting stored values with undefined/null, add inactive flag when adding panels).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js Adds disposed-guarding during post-layout init; introduces cleanUndefined and changes panel merge behavior; minor event wiring robustness tweaks.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js Consolidates behavior into onDidVisibilityChange to save config/load tabs and move DOM nodes based on visibility; improves panel deletion matching by key.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js Adds inactive: true when adding panels to avoid auto-activation.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js Removes debug logging; simplifies closePanel template move logic; ensures close triggers panelVisibleChanged(false).
Comments suppressed due to low confidence (2)

src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js:84

  • Passing inactive: true to dockview.addPanel prevents Dockview from setting the new panel (and possibly the group) active. When this code creates a brand-new group (e.g. when group didn’t exist yet), this can leave the group with no active panel/content rendered until something else activates it. Consider only setting inactive: true when adding into an already-active group (to avoid stealing focus), or explicitly activating the first panel after creation when the group has no active panel.
    dockview.addPanel({
        id: panel.id,
        title: panel.title,
        inactive: true,
        renderer: panel.renderer,
        component: panel.component,
        position: { referenceGroup: group, index: index || 0 },
        params: { ...panel.params, rect, packup, visible: true }
    })

src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js:121

  • inactive: true here changes the behavior of adding a panel so it won’t become the active/visible panel. If this path is used to show a newly-visible panel (e.g. via toggleComponent), the UI may not switch to it and may even render an empty group if no other panel is active. If the intent is “don’t steal focus”, consider making this conditional (only when the target group already has an active panel) or activating the panel based on panel.params.isActive/index after insertion.
    let option = {
        id: panel.id,
        title: panel.title,
        inactive: true,
        renderer: panel.renderer,
        component: panel.component,
        position: { referenceGroup: group },
        params: { ...panel.params, isPackup, packupHeight, isMaximized, position }
    }

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

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(DockView): add onPanelVisibleChanged event

3 participants