Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.0" />
<PackageReference Include="BootstrapBlazor.CherryMarkdown" Version="9.0.0" />
<PackageReference Include="BootstrapBlazor.Dock" Version="9.0.0" />
<PackageReference Include="BootstrapBlazor.DockView" Version="9.1.5" />
<PackageReference Include="BootstrapBlazor.DockView" Version="9.1.7" />
<PackageReference Include="BootstrapBlazor.DriverJs" Version="9.0.3" />
<PackageReference Include="BootstrapBlazor.ElementIcon" Version="9.0.3" />
<PackageReference Include="BootstrapBlazor.FileViewer" Version="9.0.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@
</ul>
<a class="btn btn-bd-download d-none d-lg-block mb-3 mb-md-0 ms-md-3" target="_blank" href="@DownloadUrl">@DownloadText</a>
<div class="navbar-version ms-2">@_versionString</div>
<ThemeProvider class="ms-2 d-none d-lg-block" OnThemeChangedAsync="OnThemeChangedAsync"></ThemeProvider>
<ThemeProvider class="ms-2 d-none d-lg-block"></ThemeProvider>
</header>
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,4 @@ protected override void OnInitialized()
TutorialsText ??= Localizer[nameof(TutorialsText)];
_versionString = $"v{PackageVersionService.Version}";
}

private Task OnThemeChangedAsync(ThemeValue themeName) => InvokeVoidAsync("updateTheme", themeName, WebsiteOption.CurrentValue.AssetRootPath);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { switchTheme as syncTheme } from "./Pre.razor.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"

export function init(id) {
const scrollTop = () => (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop
Expand All @@ -17,10 +16,6 @@ export function init(id) {
});
}

export async function updateTheme(theme, assetPath) {
await syncTheme(theme, assetPath);
}

export function dispose(id) {
EventHandler.off(document, 'scroll');
}
22 changes: 22 additions & 0 deletions src/BootstrapBlazor.Server/Components/Components/Pre.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public partial class Pre
[NotNull]
private CodeSnippetService? CodeSnippetService { get; set; }

[Inject]
[NotNull]
private IThemeProvider? ThemeProviderService { get; set; }

/// <summary>
/// 获得/设置 子组件 CodeFile 为空时生效
/// </summary>
Expand Down Expand Up @@ -67,6 +71,16 @@ public partial class Pre

private string? CopiedText { get; set; }

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

ThemeProviderService.ThemeChangedAsync += OnThemeChanged;
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Manage event subscription lifecycle in Pre component.

Just as in other components, ensure that the event handler registered to ThemeProviderService.ThemeChangedAsync is removed when the component is disposed. This helps avoid unintended behavior and memory retention.

Suggested implementation:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        ThemeProviderService.ThemeChangedAsync -= OnThemeChanged;
    }
    base.Dispose(disposing);
}

Ensure that the method OnThemeChanged exists in the component. If not, implement it accordingly.

}

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand Down Expand Up @@ -189,4 +203,12 @@ private string FindCodeSnippetByName(string code)

[GeneratedRegex(@"<Tips[\s\S]*>[\s\S]*?</Tips>")]
private static partial Regex TipsRegex();

private async Task OnThemeChanged(string themeName)
{
if (themeName == "light" || themeName == "dark")
{
await InvokeVoidAsync("switchTheme", themeName);
}
}
}
10 changes: 5 additions & 5 deletions src/BootstrapBlazor.Server/Components/Components/Pre.razor.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ export async function highlight(id) {
}
}

export async function switchTheme(theme, assetPath) {
export async function switchTheme(theme) {
if (theme === 'dark') {
removeLink(`${assetPath}lib/highlight/vs.min.css`);
await addLink(`${assetPath}lib/highlight/vs2015.min.css`);
removeLink(`./lib/highlight/vs.min.css`);
await addLink(`./lib/highlight/vs2015.min.css`);
}
else {
removeLink(`${assetPath}lib/highlight/vs2015.min.css`);
await addLink(`${assetPath}lib/highlight/vs.min.css`);
removeLink(`./lib/highlight/vs2015.min.css`);
await addLink(`./lib/highlight/vs.min.css`);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@inherits WebSiteModuleComponentBase
@attribute [JSModuleAutoLoader("Components/ThemeMode.razor.js")]
@attribute [JSModuleAutoLoader("Components/ThemeMode.razor.js", JSObjectReference = true)]

<div id="@Id" class="btn btn-circle btn-fade btn-theme-mode icon-theme d-flex" @onclick:stopPropagation>
<i class="@GetLightIconClassString"></i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

using Microsoft.JSInterop;

namespace BootstrapBlazor.Server.Components.Components;

/// <summary>
Expand All @@ -13,6 +15,10 @@ public partial class ThemeMode
[Inject, NotNull]
private IIconTheme? IconTheme { get; set; }

[Inject]
[NotNull]
private IThemeProvider? ThemeProvider { get; set; }

private string? GetLightIconClassString => CssBuilder.Default("icon-light")
.AddClass(_lightModeIcon)
.Build();
Expand All @@ -35,4 +41,17 @@ protected override void OnInitialized()
_darkModeIcon ??= IconTheme.GetIconByKey(ComponentIcons.ThemeProviderDarkModeIcon);
_lightModeIcon ??= IconTheme.GetIconByKey(ComponentIcons.ThemeProviderLightModeIcon);
}

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

/// <summary>
/// The callback when theme changed
/// </summary>
/// <param name="themeName"></param>
/// <returns></returns>
[JSInvokable]
public ValueTask OnThemeChanged(string themeName) => ThemeProvider.SetThemeAsync(themeName);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getTheme, switchTheme, calcCenterPosition } from "../../_content/BootstrapBlazor/modules/utility.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"

export function init(id) {
export function init(id, invoke, method) {
const el = document.getElementById(id);
if (el) {
EventHandler.on(el, 'click', e => {
Expand All @@ -15,6 +15,7 @@ export function init(id) {

const rect = calcCenterPosition(el);
switchTheme(theme, rect.x, rect.y);
invoke.invokeMethodAsync(method, theme);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public abstract class BaseDockView : ComponentBase
[NotNull]
private MockDataTableDynamicService? DataTableDynamicService { get; set; }

[Inject]
[NotNull]
private IThemeProvider? ThemeProviderService { get; set; }

/// <summary>
/// 获得/设置 数据集合
/// </summary>
Expand All @@ -39,6 +43,11 @@ public abstract class BaseDockView : ComponentBase
/// </summary>
protected DataTableDynamicContext? DataTableDynamicContext { get; set; }

/// <summary>
/// Gets or sets the theme
/// </summary>
protected DockViewTheme Theme { get; set; } = DockViewTheme.Light;

/// <summary>
/// 获得 <see cref="DynamicObjectContext"/> 实例方法
/// </summary>
Expand All @@ -51,6 +60,8 @@ public abstract class BaseDockView : ComponentBase
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();

Items = Foo.GenerateFoo(LocalizerFoo, 50);

// 模拟数据从数据库中获得
Expand All @@ -63,6 +74,22 @@ protected override void OnInitialized()
TreeItems.AddRange(TreeFoo.GenerateFoos(LocalizerFoo, 3, 101, 1010));

DataTableDynamicContext = DataTableDynamicService.CreateContext();

ThemeProviderService.ThemeChangedAsync += OnThemeChanged;
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Unsubscribe from ThemeChangedAsync to prevent potential memory leaks.

Since the component registers for theme change notifications during OnInitialized, consider unsubscribing in Dispose to ensure that disposed instances do not remain referenced through the delegate.

Suggested implementation:

        base.OnInitialized();

        ThemeProviderService.ThemeChangedAsync += OnThemeChanged;
    // Unsubscribe from the ThemeChangedAsync event to avoid memory leaks
    public void Dispose()
    {
        if (ThemeProviderService != null)
        {
            ThemeProviderService.ThemeChangedAsync -= OnThemeChanged;
        }
        GC.SuppressFinalize(this);
    }

If your class already overrides a Dispose(bool disposing) method, then incorporate the unsubscription logic there instead of creating a new Dispose() method. Additionally, ensure that the class implements IDisposable if it isn’t already.

}

private Task OnThemeChanged(string themeName)
{
if (themeName == "dark")
{
Theme = DockViewTheme.Dark;
}
else
{
Theme = DockViewTheme.Light;
}
StateHasChanged();
return Task.CompletedTask;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<h4>@((MarkupString)Localizer["DockViewColIntro"].Value)</h4>

<DockViewV2 Name="DockViewV2LayoutColumn" class="dockview-demo">
<DockViewV2 Name="DockViewV2LayoutColumn" Theme="@Theme" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Column">
<DockViewComponent Key="tab1" Title="标签一" Height="33">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<h4>@((MarkupString)Localizer["DockViewComplexIntro"].Value)</h4>

<DockViewV2 Name="DockViewV2LayoutComplex" class="dockview-demo">
<DockViewV2 Name="DockViewV2LayoutComplex" Theme="@Theme" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Row">
<DockViewContent Type="DockViewContentType.Column">
<DockViewComponent Key="tab1" Title="标签一">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<h4>@((MarkupString)Localizer["DockViewGroupIntro"].Value)</h4>

<DockViewV2 Name="DockViewV2LayoutGroup" class="dockview-demo">
<DockViewV2 Name="DockViewV2LayoutGroup" Theme="@Theme" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Row">
<DockViewContent Type="DockViewContentType.Group">
<DockViewComponent Key="tab1" Title="标签一">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<Button OnClickWithoutRender="Reset" Text="复位"></Button>
</GroupBox>

<DockViewV2 @ref="DockView" Name="DockViewLayout" LayoutConfig="@LayoutConfig" class="dock-layout-demo">
<DockViewV2 @ref="DockView" Name="DockViewLayout" Theme="@Theme" LayoutConfig="@LayoutConfig" class="dock-layout-demo">
<DockViewContent Type="DockViewContentType.Column">
<DockViewComponent Key="tab1" Title="标签一">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<Button OnClick="OnToggleLock" Text="@LockText"></Button>

<DockViewV2 Name="DockViewLock" OnLockChangedCallbackAsync="OnLockChangedCallbackAsync" IsLock="IsLock" class="dock-lock-demo">
<DockViewV2 Name="DockViewLock" Theme="@Theme" OnLockChangedCallbackAsync="OnLockChangedCallbackAsync" IsLock="IsLock" class="dock-lock-demo">
<DockViewContent Type="DockViewContentType.Row">
<DockViewComponent Key="tab1" Title="标签一" Width="18">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

<h4>@((MarkupString)Localizer["DockViewNestIntro"].Value)</h4>

<Select @bind-Value="@_theme"></Select>
<Select @bind-Value="@Theme"></Select>

<DockViewV2 Name="DockViewNest" Theme="_theme" class="dockview-demo">
<DockViewV2 Name="DockViewNest" Theme="Theme" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Row">
<DockViewComponent Key="tab1" Title="标签一">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down Expand Up @@ -40,7 +40,7 @@
</Table>
</DockViewComponent>
<DockViewComponent Key="tab3" Title="嵌套布局" ShowHeader="false">
<DockViewV2 Name="DockViewInnerNest" Theme="_theme">
<DockViewV2 Name="DockViewInnerNest" Theme="Theme">
<DockViewContent Type="DockViewContentType.Column">
<DockViewComponent Key="tab31" Title="内嵌标签一">
<Table TItem="TreeFoo" IsBordered="true" IsStriped="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,4 @@ public partial class DockViewNest
[Inject]
[NotNull]
private IStringLocalizer<DockViewNest>? Localizer { get; set; }

private DockViewTheme _theme;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<h4>@((MarkupString)Localizer["DockViewRowIntro"].Value)</h4>

<DockViewV2 Name="DockViewV2LayoutRow" class="dockview-demo">
<DockViewV2 Name="DockViewV2LayoutRow" Theme="@Theme" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Row">
<DockViewComponent Key="tab1" Title="标签一" ShowClose="false" Width="14">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<h4>@((MarkupString)Localizer["DockViewTitleIntro"].Value)</h4>

<DockViewV2 Name="DockViewV2LayoutColumn" class="dockview-demo">
<DockViewV2 Name="DockViewV2LayoutColumn" Theme="@Theme" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Column">
<DockViewComponent Key="tab1" Title="标签一" ShowTitleBar="true" OnClickTitleBarCallback="OnClickTitleBarCallback" Height="33">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<Button OnClick="OnToggleVisible" Text="切换标签一"></Button>

<DockViewV2 Name="DockViewVisible" OnVisibleStateChangedAsync="OnVisibleStateChangedAsync" class="dockview-demo">
<DockViewV2 Name="DockViewVisible" Theme="@Theme" OnVisibleStateChangedAsync="OnVisibleStateChangedAsync" class="dockview-demo">
<DockViewContent Type="DockViewContentType.Column">
<DockViewComponent Key="tab1" Title="标签一" Visible="Visible">
<Table TItem="DynamicObject" DynamicContext="DataTableDynamicContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public partial class ThemeProvider
[Inject, NotNull]
private IStringLocalizer<ThemeProvider>? Localizer { get; set; }

[Inject]
[NotNull]
private IThemeProvider? ThemeProviderService { get; set; }

private string? ClassString => CssBuilder.Default("dropdown bb-theme-mode")
.AddClassFromAttributes(AdditionalAttributes)
.Build();
Expand Down Expand Up @@ -139,5 +143,6 @@ public async Task OnThemeChanged(ThemeValue name)
{
await OnThemeChangedAsync(name);
}
await ThemeProviderService.SetThemeAsync(name.ToDescriptionString());
}
}
6 changes: 6 additions & 0 deletions src/BootstrapBlazor/Components/ThemeProvider/ThemeValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

using System.ComponentModel;

namespace BootstrapBlazor.Components;

/// <summary>
Expand All @@ -14,20 +16,24 @@ public enum ThemeValue
/// <summary>
/// 自动
/// </summary>
[Description("auto")]
Auto,

/// <summary>
/// 明亮主题
/// </summary>
[Description("light")]
Light,

/// <summary>
/// 暗黑主题
/// </summary>
[Description("dark")]
Dark,

/// <summary>
/// 使用本地保存选项
/// </summary>
[Description("useLocalStorage")]
UseLocalStorage,
}
10 changes: 10 additions & 0 deletions src/BootstrapBlazor/Services/DefaultThemeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ namespace BootstrapBlazor.Components;

class DefaultThemeProvider(IJSRuntime jsRuntime) : IThemeProvider
{
/// <summary>
/// <inheritdoc/>
/// </summary>
public Func<string, Task>? ThemeChangedAsync { get; set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
Expand All @@ -15,6 +20,11 @@ public async ValueTask SetThemeAsync(string themeName)
{
var module = await jsRuntime.LoadUtility();
await module.SetThemeAsync(themeName);

if (ThemeChangedAsync is not null)
{
await ThemeChangedAsync(themeName);
}
}

/// <summary>
Expand Down
Loading