Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@ namespace BootstrapBlazor.Components;
/// </summary>
public partial class DockViewV2
{
/// <summary>
/// <para lang="zh">获得/设置 DockView 名称,默认为 null,用于本地存储标识</para>
/// <para lang="en">Gets or sets the DockView name. Default is null and it is used for local storage identification</para>
/// </summary>
[Parameter]
[EditorRequired]
[NotNull]
public string? Name { get; set; }

/// <summary>
/// <para lang="zh">获得/设置 布局配置</para>
/// <para lang="en">Gets or sets the layout configuration</para>
Expand Down Expand Up @@ -128,6 +119,14 @@ public partial class DockViewV2
[Parameter]
public string? Version { get; set; }

/// <summary>
/// <para lang="zh">获得/设置 DockView 名称,默认为 null,用于本地存储标识</para>
/// <para lang="en">Gets or sets the DockView name. Default is null and it is used for local storage identification</para>
/// </summary>
[Parameter]
[NotNull]
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

Name is declared as nullable (string?) and is intentionally optional now (only required when local storage is enabled), but it is still annotated with [NotNull]. That attribute communicates to the nullability analyzer that the property getter never returns null, which is no longer true and can lead to incorrect flow analysis. Consider removing [NotNull] (or making Name non-nullable again if it must always be supplied).

Suggested change
[NotNull]

Copilot uses AI. Check for mistakes.
public string? Name { get; set; }

/// <summary>
/// <para lang="zh">获得/设置 是否启用本地存储布局,默认为 null</para>
/// <para lang="en">Gets or sets whether local storage layout is enabled. Default is null</para>
Expand Down Expand Up @@ -186,6 +185,20 @@ protected override void OnInitialized()
ThemeProviderService.ThemeChangedAsync += OnThemeChangedAsync;
}

/// <summary>
/// <inheritdoc/>
/// </summary>
protected override void OnParametersSet()
{
base.OnParametersSet();

// 开启本体存储未提供 Name 时抛出异常提示
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

Typo in the comment: it says “本体存储” but the code and docs refer to “本地存储”. This should be corrected to avoid confusion.

Suggested change
// 开启本体存储未提供 Name 时抛出异常提示
// 开启本地存储未提供 Name 时抛出异常提示

Copilot uses AI. Check for mistakes.
if (IsEnableLocalStorage && string.IsNullOrEmpty(Name))
{
throw new InvalidOperationException("Name must be provided when local storage is enabled.");
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The thrown InvalidOperationException message could be more actionable for consumers. Consider including the component/parameter names via nameof(Name)/nameof(EnableLocalStorage) and clarifying that local storage may be enabled either via the parameter or global DockViewOptions, so users know what to change.

Suggested change
throw new InvalidOperationException("Name must be provided when local storage is enabled.");
throw new InvalidOperationException($"{nameof(Name)} must be provided when local storage is enabled. Local storage can be enabled either by the {nameof(EnableLocalStorage)} parameter or by global {nameof(DockViewOptions)} configuration.");

Copilot uses AI. Check for mistakes.
}
}

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand All @@ -196,19 +209,19 @@ protected override async Task OnAfterRenderAsync(bool firstRender)

if (!firstRender)
{
await InvokeVoidAsync("update", Id, GetOptions());
await InvokeVoidAsync("update", Id, GetDockViewConfig());
}
}

/// <summary>
/// <inheritdoc />
/// </summary>
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, GetOptions());
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, GetDockViewConfig());

private DockViewConfig GetOptions() => new()
private DockViewConfig GetDockViewConfig() => new()
{
EnableLocalStorage = EnableLocalStorage ?? _options.EnableLocalStorage ?? false,
LocalStorageKey = $"{GetPrefixKey()}-{Name}-{GetVersion()}",
EnableLocalStorage = IsEnableLocalStorage,
LocalStorageKey = LocalStorageKey,
IsLock = IsLock,
ShowLock = ShowLock,
IsFloating = IsFloating,
Expand All @@ -227,6 +240,10 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
LoadTabs = nameof(LoadTabs)
};

private bool IsEnableLocalStorage => EnableLocalStorage ?? _options.EnableLocalStorage ?? false;

private string? LocalStorageKey => IsEnableLocalStorage ? $"{GetPrefixKey()}-{Name}-{GetVersion()}" : null;
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

LocalStorageKey is now null when local storage is disabled, but some JS code (e.g. dockview-utils.js) reads options.localStorageKey outside the enableLocalStorage guard. This can cause unexpected access to localStorage keys like null-panels/undefined-panels, and potentially JSON parse errors if those keys exist. Consider always providing a stable non-null key, or updating the JS side to only access localStorageKey when enableLocalStorage is true.

Suggested change
private string? LocalStorageKey => IsEnableLocalStorage ? $"{GetPrefixKey()}-{Name}-{GetVersion()}" : null;
private string LocalStorageKey => $"{GetPrefixKey()}-{Name}-{GetVersion()}";

Copilot uses AI. Check for mistakes.

private string GetVersion() => Version ?? _options.Version ?? "v1";

private string GetPrefixKey() => LocalStoragePrefix ?? _options.LocalStoragePrefix ?? "bb-dockview";
Expand All @@ -237,7 +254,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
/// </summary>
public async Task Reset(string? layoutConfig = null)
{
var options = GetOptions();
var options = GetDockViewConfig();
if (layoutConfig != null)
{
options.LayoutConfig = layoutConfig;
Expand Down
Loading