Skip to content

fix(DockView): correctness fixes for group delete/re-insert, float and dock-back#1046

Closed
zhaijunlei955 wants to merge 4 commits into
masterfrom
fix-dockview-group
Closed

fix(DockView): correctness fixes for group delete/re-insert, float and dock-back#1046
zhaijunlei955 wants to merge 4 commits into
masterfrom
fix-dockview-group

Conversation

@zhaijunlei955

@zhaijunlei955 zhaijunlei955 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

A set of related fixes for the group lifecycle (delete → re-insert → float → dock).

Fixes

  • Re-insert into an emptied group: defer action-button state while a placeholder
    group is empty (avoids [].every() showing wrong buttons that stick), and restore
    the pre-delete width instead of collapsing to the ~100px minimum.
  • Dock a floating group back to grid: re-render the origin group's action buttons,
    which were deferred while it sat empty as a placeholder.
  • Floating group close / re-insert: closing a floating group now closes its panels
    individually, so external panel buttons stay highlight-synced; a re-added floating
    group gets its active panel set (no blank), and a hidden→re-inserted floating group
    keeps its last size & position (offset-based capture, immune to style:auto).
  • Width after re-open + float/dock-back: clear the stale _pendingSize left by the
    width restore, so a group resized after re-opening no longer snaps back to its old
    width on dock-back.

Scope

DockView only, 3 JS files (dockview-group.js, dockview-extensions.js,
dockview-panel.js). Only the delete/re-insert/float/dock paths are touched; adding a
tab to an existing group and all non-floating paths are unchanged.

Summary by Sourcery

Improve DockView group lifecycle handling across delete, re-insert, float, and dock-back flows to preserve layout, state, and actions.

Bug Fixes:

  • Preserve and restore pre-delete group width when re-inserting into an emptied grid group instead of collapsing to the minimum width.
  • Ensure floating groups retain their last size and position when hidden and re-inserted by preferring stored currentPosition over rect and using offset-based coordinates.
  • Prevent incorrect action button visibility on empty placeholder groups by deferring action state computation until panels are present.
  • Re-render origin group action buttons when docking a floating group back so that deferred actions are correctly shown.
  • Ensure newly created floating groups have an active panel selected so they do not appear blank.
  • Align floating group close behavior with grid groups by closing panels individually so visibility-change hooks and external button highlights stay in sync.
  • Clear stale pending size values after restoring width so subsequent visibility toggles do not snap groups back to outdated sizes.
  • Avoid losing floating group position when removing panels by using offsetTop/offsetLeft instead of style-based coordinates that can be 'auto'.

@sourcery-ai

sourcery-ai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adjusts DockView group lifecycle behavior for delete → re-insert → float → dock flows, ensuring placeholder groups defer action states, floating groups preserve size/position, origin groups restore width and action buttons correctly, and floating-group closes propagate per-panel visibility updates.

Sequence diagram for DockView group delete → re-insert → float → dock lifecycle

sequenceDiagram
    actor User
    participant DockviewComponent
    participant Group
    participant Panel
    participant dockview_group_js as addPanelWidthGroupId
    participant dockview_extensions_js as DockviewComponent_removeGroup
    participant dockview_panel_js as onRemovePanel
    participant DockFunction as dock
    participant ActionStates as reRenderActionStates

    User->>DockviewComponent: removeGroup(group)
    DockviewComponent->>DockviewComponent_removeGroup: DockviewComponent.prototype.removeGroup
    DockviewComponent_removeGroup->>Group: type == floating
    DockviewComponent_removeGroup->>Group: removeDrawerBtn
    alt floating group has panels
        DockviewComponent_removeGroup->>Group: [...group.panels]
        loop each panel
            DockviewComponent_removeGroup->>Panel: panel.api.close()
            Panel->>dockview_panel_js: onRemovePanel
            dockview_panel_js->>Panel: set panel.params.currentPosition
        end
    else no panels
        DockviewComponent_removeGroup->>DockviewComponent: removeGroup.apply(this, args)
    end

    User->>dockview_group_js: addPanelWidthGroupId(dockview, panel, index)
    dockview_group_js->>Group: dockview.api.getGroup(panel.groupId)
    alt reused empty group
        dockview_group_js->>dockview_group_js: reusedEmptyGroup = true
        dockview_group_js->>dockview_group_js: restoreWidth = panel.params.currentPosition.width
    else new floating group
        dockview_group_js->>dockview_group_js: isNewFloatingGroup = true
        dockview_group_js->>dockview_group_js: floatingGroupRect from currentPosition or rect
    end
    dockview_group_js->>DockviewComponent: dockview.addPanel({ initialWidth })
    alt new floating group
        dockview_group_js->>Panel: panel.api.setActive()
    end
    alt reused empty grid group
        dockview_group_js->>ActionStates: reRenderActionStates(group)
        dockview_group_js->>Group: group.api._pendingSize = undefined
    end

    User->>DockFunction: dock(group, floatType)
    DockFunction->>DockviewComponent: moveGroupOrPanel
    DockFunction->>Group: originGroup
    DockFunction->>ActionStates: reRenderActionStates(originGroup)
    DockFunction->>DockviewComponent: saveConfig
Loading

File-Level Changes

Change Details Files
Handle re-insert into emptied placeholder groups without incorrect action buttons or collapsed widths.
  • Detect reused empty groups and compute a restoreWidth for grid groups based on saved currentPosition width.
  • Pass initialWidth when adding a panel to restore pre-delete width instead of using the minimum width.
  • Skip resetActionStates when a group is empty to avoid vacuous [].every() enabling all actions by default.
  • Add reRenderActionStates helper and call it when a placeholder group gains a panel to recompute action button visibility and states.
  • Ensure bb-show-lock still applies lock state even when the lock button is hidden.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
Ensure floating group creation, positioning, and activation use persisted size/position and never render blank.
  • Introduce reusedEmptyGroup and isNewFloatingGroup flags to distinguish placeholder reuse from new floating groups.
  • Prefer panel.params.currentPosition (captured on hide) over rect when computing floatingGroupRect so hidden→re-inserted groups keep last size/position.
  • After addPanel, activate the new panel in newly created floating groups to avoid blank floating windows.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
Clear stale pending size to avoid width snapping after re-open and dock-back.
  • After restoring width via initialWidth, clear group.api._pendingSize so later visibility changes (float→dock) do not replay an outdated width.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
Re-render action buttons when docking a floating group back to its origin placeholder.
  • Call reRenderActionStates(originGroup) at the end of dock() so the origin group's deferred action buttons reflect the now-filled state.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
Align floating-group close behavior with grid groups so panel visibility events fire correctly and the group is removed.
  • Intercept floating-group removal in DockviewComponent.removeGroup for type 'floating'.
  • Close each panel via panel.api.close() so each triggers _panelVisibleChanged and the final close re-enters the empty path that removes the group.
  • Fallback to the original removeGroup when there are no panels.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js
Capture floating group position using offset-based measurements to survive style.top/left='auto'.
  • In onRemovePanel, record currentPosition.top/left using offsetTop/offsetLeft instead of parsing style.top/left, avoiding NaN when style is 'auto' and preserving position on re-insert.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js

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

@bb-auto

bb-auto Bot commented Jun 24, 2026

Copy link
Copy Markdown

Thanks for your PR, @zhaijunlei955. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@bb-auto bb-auto Bot requested a review from ArgoZhang June 24, 2026 09:18

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

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:

  • Directly assigning to group.api._pendingSize in addPanelWidthGroupId couples this fix to an internal/private field on the Dockview API; consider tracking pending sizes in your own metadata or via a public Dockview API to avoid breakage if upstream internals change.
  • In DockviewComponent.prototype.removeGroup for floating groups, the method now always returns undefined after closing panels (since removeGroup.apply is only called when there are no panels); if callers rely on the original return value, consider capturing and returning the result of the last panel.api.close() or explicitly documenting/standardizing the new behavior.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Directly assigning to `group.api._pendingSize` in `addPanelWidthGroupId` couples this fix to an internal/private field on the Dockview API; consider tracking pending sizes in your own metadata or via a public Dockview API to avoid breakage if upstream internals change.
- In `DockviewComponent.prototype.removeGroup` for floating groups, the method now always returns `undefined` after closing panels (since `removeGroup.apply` is only called when there are no panels); if callers rely on the original return value, consider capturing and returning the result of the last `panel.api.close()` or explicitly documenting/standardizing the new behavior.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant