Skip to content

feat(DockView): bump version 10.0.10#989

Merged
ArgoZhang merged 10 commits into
masterfrom
fix-dockview
May 8, 2026
Merged

feat(DockView): bump version 10.0.10#989
ArgoZhang merged 10 commits into
masterfrom
fix-dockview

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented May 8, 2026

Link issues

fixes #988

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

Improve DockView layout initialization and rendering behavior while cleaning up obsolete configuration utilities.

New Features:

  • Add fallback layout initialization from content when stored or provided configuration is invalid.

Bug Fixes:

  • Prevent errors when loading malformed or outdated layout configurations by wrapping initialization in error handling and falling back to content-based configuration.
  • Avoid triggering panel visibility rendering while groups are being maximized by tracking a temporary maximizing state.
  • Preserve panel ids and avoid removing empty root branches without a parent when renewing layout configs.

Enhancements:

  • Simplify configuration handling by removing the dockview-fix helper and related mutation logic, relying on renewed configuration data instead.
  • Default the renderer option to 'onlyWhenVisible' on updates and remove unconditional eager tab loading.

Build:

  • Update DockView project metadata, including the package version bump to 10.0.10.

Copilot AI review requested due to automatic review settings May 8, 2026 02:11
@bb-auto bb-auto Bot added the enhancement New feature or request label May 8, 2026
@bb-auto bb-auto Bot added this to the v9.2.0 milestone May 8, 2026
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 8, 2026

Reviewer's Guide

Refactors DockView configuration and initialization to remove the legacy fixObject helper, make layout config reconstruction more robust, add a fallback path when stored/layout configs are invalid, and adjust rendering/maximize behavior to avoid unnecessary or incorrect panel loading; also exports new helpers and minorly updates group/panel logic.

Sequence diagram for Dockview initialization with config fallbacks

sequenceDiagram
    participant Init as initDockview
    participant Dockview as DockviewComponent
    participant Config as dockview_config
    participant Options as DockviewOptions

    Init->>Dockview: set init()
    activate Dockview
    Dockview->>Config: getConfig(Options)
    activate Config
    alt getConfig throws
        Config-->>Dockview: error
        Dockview->>Config: getConfigFromContent(Options)
        Config-->>Dockview: configFromContent
    else getConfig succeeds
        Config-->>Dockview: config
    end
    deactivate Config

    Dockview->>Dockview: fromJSON(config)
    alt fromJSON throws
        Dockview-->>Dockview: error logged
        Dockview->>Config: getConfigFromContent(Options)
        activate Config
        Config-->>Dockview: configFromContent
        deactivate Config
        Dockview->>Dockview: fromJSON(configFromContent)
    else fromJSON succeeds
        Dockview-->>Dockview: layout initialized
    end

    Dockview->>Dockview: params.floatingGroups = config.floatingGroups || []
    deactivate Dockview
Loading

Sequence diagram for panel visibility during group maximization

sequenceDiagram
    actor User
    participant Group as DockviewGroup
    participant Toggle as toggleFull
    participant Panel as DockviewPanel

    User->>Group: click maximize button
    Group->>Toggle: toggleFull(group, actionContainer, maximize)
    activate Toggle
    Toggle->>Group: group.api.accessor.maximizing = true
    alt grid group
        Toggle->>Group: group.api.maximize() or exitMaximized()
    else floating group
        Toggle->>Group: floatingMaximize(group) or floatingExitMaximized(group)
    end
    Toggle->>Group: group.api.accessor.maximizing = false
    deactivate Toggle

    Note over Panel,Group: Later, panel visibility changes
    Panel->>Panel: onDidVisibilityChange(event)
    Panel->>Panel: if dockview._isDisposed or dockview.maximizing return
    Panel->>Panel: else handle renderer onlyWhenVisible
Loading

Updated class diagram for Dockview modules and config helpers

classDiagram

    class DockviewComponent {
        +any params
        +any panels
        +any floatingGroups
        +boolean _isDisposed
        +boolean _inited
        +void fromJSON(config)
        +void updateTheme()
        +void init()
        +void update(options)
    }

    class DockviewParams {
        +DockviewOptions options
        +any observer
        +any floatingGroups
        +any theme
    }

    class DockviewOptions {
        +string localStorageKey
        +string layoutConfig
        +string renderer
        +boolean lock
        +string theme
        +any content
        +number width
        +number height
    }

    class DockviewGroup {
        +any api
        +any model
        +any header
        +any panels
        +HTMLElement element
    }

    class DockviewGroupApiAccessor {
        +boolean maximizing
    }

    class DockviewPanel {
        +any api
        +any accessor
        +any params
        +void onDidVisibilityChange(handler)
    }

    class DockviewConfigModule {
        +any getConfig(options)
        +any getConfigFromStorage(options)
        +any getConfigFromOptions(options)
        +any getConfigFromLayoutString(options)
        +any getConfigFromContent(options)
        +any renewConfigFromOptions(config, options)
        +any reloadFromConfig(dockview, options)
        +void saveConfig(dockview)
        +void loadPanelsFromLocalstorage(dockview)
    }

    class ConfigRoot {
        +string activeGroup
        +ConfigGrid grid
        +ConfigPanels panels
    }

    class ConfigGrid {
        +number width
        +number height
        +string orientation
        +ConfigBranch root
    }

    class ConfigBranch {
        +string type
        +any data
        +any position
    }

    class ConfigPanel {
        +string id
        +any params
    }

    DockviewComponent o-- DockviewParams
    DockviewParams o-- DockviewOptions

    DockviewComponent "*" o-- DockviewGroup
    DockviewGroup o-- DockviewGroupApiAccessor : accessor

    DockviewComponent "*" o-- DockviewPanel
    DockviewPanel --> DockviewComponent : accessor

    DockviewConfigModule --> ConfigRoot
    ConfigRoot o-- ConfigGrid
    ConfigRoot "*" o-- ConfigPanels
    ConfigGrid o-- ConfigBranch
    ConfigBranch "*" o-- ConfigBranch : data
    ConfigPanels "*" o-- ConfigPanel

    class ConfigPanels {
    }

    class ObservePanelActiveChange {
        +void observePanelActiveChange(panel)
    }

    ObservePanelActiveChange ..> DockviewPanel : uses
    ObservePanelActiveChange ..> DockviewOptions : reads renderer

    class ToggleFullHelper {
        +void toggleFull(group, actionContainer, maximize)
    }

    ToggleFullHelper ..> DockviewGroup
    ToggleFullHelper ..> DockviewGroupApiAccessor : sets maximizing

    class DockviewUtilsModule {
        +void initDockview(dockview, options, template)
        +void update(dockview, options)
    }

    DockviewUtilsModule ..> DockviewComponent
    DockviewUtilsModule ..> DockviewConfigModule : getConfig, getConfigFromContent
    DockviewUtilsModule ..> ToggleFullHelper
    DockviewUtilsModule ..> ObservePanelActiveChange
Loading

Flow diagram for Dockview config reconstruction without fixObject

flowchart TD
    A[Start getConfig] --> B[Has options.layoutConfig?]
    B -->|Yes| C[Parse layoutConfig JSON]
    C --> D[renewConfigFromOptions config and options]
    D --> E[Final config]

    B -->|No| F[loadPanelsFromLocalstorage]
    F --> G[Has stored layout?]
    G -->|Yes| H[Parse stored JSON]
    H --> I[renewConfigFromOptions config and options]
    I --> E
    G -->|No| J[getConfigFromContent options]
    J --> E

    E --> K[Return config]

    subgraph renewConfigFromOptions
        R1[Iterate panels in config]
        R1 --> R2[Find optionPanel by id]
        R2 -->|Found| R3[Merge params and visible]
        R3 --> R4[Set optionPanel.id = panel.id]
        R4 --> R5[Replace config panels by panel id]
        R2 -->|Not found| R6[Remove panel from config]
    end
Loading

File-Level Changes

Change Details Files
Make dockview initialization resilient to invalid saved/layout configuration and support rebuilding config directly from content when needed.
  • Extend dockview-utils imports to include getConfigFromContent from dockview-config
  • Wrap getConfig(options) in a try/catch; on error, log and fall back to getConfigFromContent(options)
  • Wrap dockview.fromJSON(config) in a try/catch; on error, log and rebuild state via dockview.fromJSON(getConfigFromContent(options))
  • Ensure dockview.params.floatingGroups is derived from the resolved config’s floatingGroups or an empty array
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-config.js
Simplify and harden configuration building by removing fixObject usage, improving config renewal from options/storage/layout, and exporting getConfigFromContent.
  • Remove dependency on dockview-fix.js and the fixObject helper throughout dockview-config
  • Change getConfigFromStorage and getConfigFromLayoutString to return configs passed through renewConfigFromOptions instead of fixObject
  • Update renewConfigFromOptions to always copy panel ids from option panels to config panels
  • Guard branch cleanup in removePanel so empty branches are removed only when a parent exists
  • Return a plain object from getConfigFromContent instead of wrapping it with fixObject
  • Export getConfigFromContent from dockview-config
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-config.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-fix.js
Adjust dockview update and visibility behavior to rely on options state and avoid mass preloading, and prevent visibility side effects during maximize operations.
  • In dockview.update, snapshot old options, then replace dockview.params.options with the new options merged with a default renderer of 'onlyWhenVisible' when not provided
  • Compare lock changes using oldOptions.lock and call toggleGroupLock only when it changes
  • Compare theme changes using oldOptions.theme.className; on change, call dockview.updateTheme instead of directly mutating theme.className
  • Remove the eager load of all panels when renderer === 'always', relying instead on visibility-driven loading
  • Stop forcing the active panel when observing a group, removing the loop that calls panel.api.setActive on the first active panel
  • In observePanelActiveChange, bail out when the accessor is disposed or currently maximizing so maximize transitions don’t trigger load/unload
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
Track maximize operations on groups to coordinate with panel visibility logic and avoid inconsistent state.
  • In toggleFull, mark group.api.accessor.maximizing as true before calling maximize/exitMaximized or floating maximize helpers
  • Reset group.api.accessor.maximizing to false after maximize operations complete
  • Use the maximizing flag in panel visibility observers to skip load/unload events fired during maximize
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js

Assessment against linked issues

Issue Objective Addressed Explanation
#988 Update the BootstrapBlazor.DockView component/package version to 10.0.10.

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 4432834 into master May 8, 2026
4 checks passed
@ArgoZhang ArgoZhang deleted the fix-dockview branch May 8, 2026 02:12
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 found 2 issues, and left some high level feedback:

  • In dockview-config.js, getConfigFromLayoutString now calls renewConfigFromOptions(config) without passing options, but renewConfigFromOptions still expects and uses options, so this will result in options being undefined at runtime and likely break layout renewal.
  • The new maximizing flag in toggleFull is set before and cleared after the maximize operation, but not in a try/finally; if an exception occurs during maximize/exitMaximized, maximizing could remain true and suppress visibility handling unexpectedly.
  • In dockview.update, the theme change check now compares oldOptions.theme.className to options.theme but no longer updates dockview.options.theme.className (or another target) to the new value, so updateTheme() may run with stale theme data unless the theme is being set elsewhere.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `dockview-config.js`, `getConfigFromLayoutString` now calls `renewConfigFromOptions(config)` without passing `options`, but `renewConfigFromOptions` still expects and uses `options`, so this will result in `options` being `undefined` at runtime and likely break layout renewal.
- The new `maximizing` flag in `toggleFull` is set before and cleared after the maximize operation, but not in a `try/finally`; if an exception occurs during maximize/exitMaximized, `maximizing` could remain `true` and suppress visibility handling unexpectedly.
- In `dockview.update`, the theme change check now compares `oldOptions.theme.className` to `options.theme` but no longer updates `dockview.options.theme.className` (or another target) to the new value, so `updateTheme()` may run with stale theme data unless the theme is being set elsewhere.

## Individual Comments

### Comment 1
<location path="src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js" line_range="451-454" />
<code_context>
 }

 const toggleFull = (group, actionContainer, maximize) => {
+    group.api.accessor.maximizing = true;
     const type = group.model.location.type;
     if (type === 'grid') {
</code_context>
<issue_to_address>
**issue (bug_risk):** maximizing flag should be reset even if maximizing/exitMaximized throws, to avoid leaving the dockview in a bad state.

If any of the maximize/exitMaximized variants (`maximize`, `exitMaximized`, `floatingMaximize`, `floatingExitMaximized`) throws, `group.api.accessor.maximizing` will remain `true` and `observePanelActiveChange`’s visibility handling will never run again. Consider wrapping the relevant calls in `try { ... } finally { group.api.accessor.maximizing = false; }` to guarantee the flag is reset.
</issue_to_address>

### Comment 2
<location path="src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js" line_range="61-64" />
<code_context>
+        const oldOptions = dockview.params.options;
+        dockview.params.options = {...options, renderer: options.renderer || 'onlyWhenVisible' };
+
+        if (oldOptions.lock !== options.lock) {
             toggleGroupLock(dockview, options);
         }
-        if (dockview.options.theme.className !== options.theme) {
-            dockview.options.theme.className = options.theme;
+        if (oldOptions.theme.className !== options.theme) {
             dockview.updateTheme();
         }
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Using oldOptions for theme comparison may be fragile if the theme shape changes or is not an object.

The previous code compared `dockview.options.theme.className` to `options.theme` and then updated `dockview.options.theme.className`. Now it compares `oldOptions.theme.className` to `options.theme` without updating the dockview theme object. If `options.theme` is a string or `oldOptions.theme` is absent/non-object, this can throw or fail to detect theme changes. Consider normalizing `options.theme` to a consistent shape (e.g., an object with `className`) and updating the dockview theme’s source of truth before calling `updateTheme()`.

Suggested implementation:

```javascript
    dockview.update = options => {
        const oldOptions = dockview.params.options || {};

        // normalize theme to a consistent shape
        const nextTheme =
            typeof options.theme === 'string'
                ? { className: options.theme }
                : (options.theme || {});

        dockview.params.options = {
            ...options,
            theme: nextTheme,
            renderer: options.renderer || 'onlyWhenVisible',
        };

        // toggle lock state if it changed
        if (oldOptions.lock !== options.lock) {
            toggleGroupLock(dockview, options);
        }

        // safely compare previous theme to new theme and update dockview theme source of truth
        const previousTheme = oldOptions.theme;
        const previousClassName =
            previousTheme && typeof previousTheme === 'object'
                ? previousTheme.className
                : previousTheme;

        if (previousClassName !== nextTheme.className) {
            if (!dockview.options) {
                dockview.options = {};
            }

            dockview.options.theme = nextTheme;
            dockview.updateTheme();
        }

        try {

```

If other parts of the codebase assume `dockview.params.options.theme` is a string, you should update those usages to expect an object with a `className` property, or adjust the normalization logic to keep both forms (e.g., store the string separately while still providing an object to `dockview.options.theme`).
</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 +451 to 454
group.api.accessor.maximizing = true;
const type = group.model.location.type;
if (type === 'grid') {
maximize ? group.api.exitMaximized() : group.api.maximize();
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): maximizing flag should be reset even if maximizing/exitMaximized throws, to avoid leaving the dockview in a bad state.

If any of the maximize/exitMaximized variants (maximize, exitMaximized, floatingMaximize, floatingExitMaximized) throws, group.api.accessor.maximizing will remain true and observePanelActiveChange’s visibility handling will never run again. Consider wrapping the relevant calls in try { ... } finally { group.api.accessor.maximizing = false; } to guarantee the flag is reset.

Comment on lines +61 to +64
if (oldOptions.lock !== options.lock) {
toggleGroupLock(dockview, options);
}
if (dockview.options.theme.className !== options.theme) {
dockview.options.theme.className = options.theme;
if (oldOptions.theme.className !== options.theme) {
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): Using oldOptions for theme comparison may be fragile if the theme shape changes or is not an object.

The previous code compared dockview.options.theme.className to options.theme and then updated dockview.options.theme.className. Now it compares oldOptions.theme.className to options.theme without updating the dockview theme object. If options.theme is a string or oldOptions.theme is absent/non-object, this can throw or fail to detect theme changes. Consider normalizing options.theme to a consistent shape (e.g., an object with className) and updating the dockview theme’s source of truth before calling updateTheme().

Suggested implementation:

    dockview.update = options => {
        const oldOptions = dockview.params.options || {};

        // normalize theme to a consistent shape
        const nextTheme =
            typeof options.theme === 'string'
                ? { className: options.theme }
                : (options.theme || {});

        dockview.params.options = {
            ...options,
            theme: nextTheme,
            renderer: options.renderer || 'onlyWhenVisible',
        };

        // toggle lock state if it changed
        if (oldOptions.lock !== options.lock) {
            toggleGroupLock(dockview, options);
        }

        // safely compare previous theme to new theme and update dockview theme source of truth
        const previousTheme = oldOptions.theme;
        const previousClassName =
            previousTheme && typeof previousTheme === 'object'
                ? previousTheme.className
                : previousTheme;

        if (previousClassName !== nextTheme.className) {
            if (!dockview.options) {
                dockview.options = {};
            }

            dockview.options.theme = nextTheme;
            dockview.updateTheme();
        }

        try {

If other parts of the codebase assume dockview.params.options.theme is a string, you should update those usages to expect an object with a className property, or adjust the normalization logic to keep both forms (e.g., store the string separately while still providing an object to dockview.options.theme).

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

Updates the BootstrapBlazor.DockView package to v10.0.10 while also adjusting DockView client-side (JS) layout/config loading and some runtime behaviors (maximize/visibility handling, theme/update flow).

Changes:

  • Bumped BootstrapBlazor.DockView package version from 10.0.9 to 10.0.10.
  • Updated DockView JS config loading (fallback to content-derived config) and removed the unused dockview-fix.js.
  • Adjusted panel visibility handling during maximize and tweaked update logic for renderer/theme.

Reviewed changes

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

Show a summary per file
File Description
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js Adds config-loading fallbacks and changes update/theme handling + tab loading behavior.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js Skips visibility-change handling while maximizing.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js Sets a maximizing flag during maximize/restore operations.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-fix.js Removes the file entirely.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js Removes an unused import from config module.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-config.js Refactors config renewal and exports (now exports getConfigFromContent).
src/components/BootstrapBlazor.DockView/BootstrapBlazor.DockView.csproj Version bump to 10.0.10.

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

}
});
return fixObject(config);
return renewConfigFromOptions(config);
dockview.fromJSON(config);
} catch (error) {
console.error(error);
dockview.fromJSON(getConfigFromContent(options));
Comment on lines 46 to 47
dockview.params.floatingGroups = config.floatingGroups || []
dockview.fromJSON(config);
}
}
if (dockview.options.theme.className !== options.theme) {
dockview.options.theme.className = options.theme;
if (oldOptions.theme.className !== options.theme) {
Comment on lines 3 to 5
<PropertyGroup>
<Version>10.0.9</Version>
<Version>10.0.10</Version>
</PropertyGroup>
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): bump version 10.0.10

3 participants