From 1ca9547756638203cc80f4798ede3c40da5656bf Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 13:36:52 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20ThemeChangedAs?= =?UTF-8?q?ync=20=E5=9B=9E=E8=B0=83=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/DefaultThemeProvider.cs | 10 ++++++++++ src/BootstrapBlazor/Services/IThemeProvider.cs | 15 +++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/BootstrapBlazor/Services/DefaultThemeProvider.cs b/src/BootstrapBlazor/Services/DefaultThemeProvider.cs index 9fddf9c6bd6..397a7b4800a 100644 --- a/src/BootstrapBlazor/Services/DefaultThemeProvider.cs +++ b/src/BootstrapBlazor/Services/DefaultThemeProvider.cs @@ -7,6 +7,11 @@ namespace BootstrapBlazor.Components; class DefaultThemeProvider(IJSRuntime jsRuntime) : IThemeProvider { + /// + /// + /// + public Func? ThemeChangedAsync { get; set; } + /// /// /// @@ -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); + } } /// diff --git a/src/BootstrapBlazor/Services/IThemeProvider.cs b/src/BootstrapBlazor/Services/IThemeProvider.cs index f2c0fc03bba..070c9040cdb 100644 --- a/src/BootstrapBlazor/Services/IThemeProvider.cs +++ b/src/BootstrapBlazor/Services/IThemeProvider.cs @@ -6,18 +6,25 @@ namespace BootstrapBlazor.Components; /// -/// 主题提供器接口 +/// Interface for theme provider /// public interface IThemeProvider { /// - /// 设置主题方法 + /// Sets the theme asynchronously. /// - /// + /// The name of the theme to set. + /// A representing the asynchronous operation. ValueTask SetThemeAsync(string themeName); /// - /// 获得当前主题方法 + /// Gets the current theme asynchronously. /// + /// A representing the asynchronous operation, with the current theme name as the result. ValueTask GetThemeAsync(); + + /// + /// The callback when theme changed + /// + Func? ThemeChangedAsync { get; set; } } From 07b8dc3325e9424bf90abe9629a3584033d25756 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 18:46:44 +0800 Subject: [PATCH 2/8] =?UTF-8?q?doc:=20=E5=A2=9E=E5=8A=A0=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Components/ThemeMode.razor | 2 +- .../Components/Components/ThemeMode.razor.cs | 19 +++++++++++++++++++ .../Components/Components/ThemeMode.razor.js | 3 ++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor b/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor index a1b658e6549..3021f368488 100644 --- a/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor +++ b/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor @@ -1,5 +1,5 @@ @inherits WebSiteModuleComponentBase -@attribute [JSModuleAutoLoader("Components/ThemeMode.razor.js")] +@attribute [JSModuleAutoLoader("Components/ThemeMode.razor.js", JSObjectReference = true)]
diff --git a/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.cs b/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.cs index f996d2122dd..783caf74ba2 100644 --- a/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone +using Microsoft.JSInterop; + namespace BootstrapBlazor.Server.Components.Components; /// @@ -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(); @@ -35,4 +41,17 @@ protected override void OnInitialized() _darkModeIcon ??= IconTheme.GetIconByKey(ComponentIcons.ThemeProviderDarkModeIcon); _lightModeIcon ??= IconTheme.GetIconByKey(ComponentIcons.ThemeProviderLightModeIcon); } + + /// + /// + /// + protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(OnThemeChanged)); + + /// + /// The callback when theme changed + /// + /// + /// + [JSInvokable] + public ValueTask OnThemeChanged(string themeName) => ThemeProvider.SetThemeAsync(themeName); } diff --git a/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.js b/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.js index f0a7962ba3b..ce6ed515de3 100644 --- a/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.js +++ b/src/BootstrapBlazor.Server/Components/Components/ThemeMode.razor.js @@ -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 => { @@ -15,6 +15,7 @@ export function init(id) { const rect = calcCenterPosition(el); switchTheme(theme, rect.x, rect.y); + invoke.invokeMethodAsync(method, theme); }); } } From 0219f00a8e38e7193548617aaec3f26c722235de Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 18:53:10 +0800 Subject: [PATCH 3/8] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=20IThemeProv?= =?UTF-8?q?ider=20=E8=81=94=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/ThemeProvider/ThemeProvider.razor.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/BootstrapBlazor/Components/ThemeProvider/ThemeProvider.razor.cs b/src/BootstrapBlazor/Components/ThemeProvider/ThemeProvider.razor.cs index a94776499fe..01a0592f605 100644 --- a/src/BootstrapBlazor/Components/ThemeProvider/ThemeProvider.razor.cs +++ b/src/BootstrapBlazor/Components/ThemeProvider/ThemeProvider.razor.cs @@ -90,6 +90,10 @@ public partial class ThemeProvider [Inject, NotNull] private IStringLocalizer? Localizer { get; set; } + [Inject] + [NotNull] + private IThemeProvider? ThemeProviderService { get; set; } + private string? ClassString => CssBuilder.Default("dropdown bb-theme-mode") .AddClassFromAttributes(AdditionalAttributes) .Build(); @@ -139,5 +143,6 @@ public async Task OnThemeChanged(ThemeValue name) { await OnThemeChangedAsync(name); } + await ThemeProviderService.SetThemeAsync(name.ToDescriptionString()); } } From 35bff676d810f9b6380eda58d99ad720a261ecc2 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 18:55:52 +0800 Subject: [PATCH 4/8] =?UTF-8?q?doc:=20=E5=A2=9E=E5=8A=A0=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/ThemeProvider/ThemeValue.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/BootstrapBlazor/Components/ThemeProvider/ThemeValue.cs b/src/BootstrapBlazor/Components/ThemeProvider/ThemeValue.cs index 3276c2354dd..5305bcfc357 100644 --- a/src/BootstrapBlazor/Components/ThemeProvider/ThemeValue.cs +++ b/src/BootstrapBlazor/Components/ThemeProvider/ThemeValue.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone +using System.ComponentModel; + namespace BootstrapBlazor.Components; /// @@ -14,20 +16,24 @@ public enum ThemeValue /// /// 自动 /// + [Description("auto")] Auto, /// /// 明亮主题 /// + [Description("light")] Light, /// /// 暗黑主题 /// + [Description("dark")] Dark, /// /// 使用本地保存选项 /// + [Description("useLocalStorage")] UseLocalStorage, } From 7c5c1b57eeb8bf239c6234a1f600b15ba51f550c Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 18:58:26 +0800 Subject: [PATCH 5/8] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20Pre=20=E7=BB=84=E4=BB=B6=E4=B8=BB=E9=A2=98=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=8F=90=E9=AB=98=E5=8F=AF=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Components/Header.razor | 2 +- .../Components/Components/Header.razor.cs | 2 -- .../Components/Components/Header.razor.js | 7 +------ 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/BootstrapBlazor.Server/Components/Components/Header.razor b/src/BootstrapBlazor.Server/Components/Components/Header.razor index abf04151a31..5a2200b9615 100644 --- a/src/BootstrapBlazor.Server/Components/Components/Header.razor +++ b/src/BootstrapBlazor.Server/Components/Components/Header.razor @@ -48,5 +48,5 @@ @DownloadText - + diff --git a/src/BootstrapBlazor.Server/Components/Components/Header.razor.cs b/src/BootstrapBlazor.Server/Components/Components/Header.razor.cs index 42252c1801e..3ffe421f37e 100644 --- a/src/BootstrapBlazor.Server/Components/Components/Header.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Components/Header.razor.cs @@ -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); } diff --git a/src/BootstrapBlazor.Server/Components/Components/Header.razor.js b/src/BootstrapBlazor.Server/Components/Components/Header.razor.js index 204e7bbeda6..f678cd30842 100644 --- a/src/BootstrapBlazor.Server/Components/Components/Header.razor.js +++ b/src/BootstrapBlazor.Server/Components/Components/Header.razor.js @@ -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 @@ -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'); } From d567baaf8a0c5a29bd81a6fb0707b1bc30ff713f Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 19:06:49 +0800 Subject: [PATCH 6/8] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E8=81=94=E5=8A=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Components/Pre.razor.cs | 22 +++++++++++++++++++ .../Components/Components/Pre.razor.js | 10 ++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/BootstrapBlazor.Server/Components/Components/Pre.razor.cs b/src/BootstrapBlazor.Server/Components/Components/Pre.razor.cs index 7077a5f9adc..90133402d80 100644 --- a/src/BootstrapBlazor.Server/Components/Components/Pre.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Components/Pre.razor.cs @@ -29,6 +29,10 @@ public partial class Pre [NotNull] private CodeSnippetService? CodeSnippetService { get; set; } + [Inject] + [NotNull] + private IThemeProvider? ThemeProviderService { get; set; } + /// /// 获得/设置 子组件 CodeFile 为空时生效 /// @@ -67,6 +71,16 @@ public partial class Pre private string? CopiedText { get; set; } + /// + /// + /// + protected override void OnInitialized() + { + base.OnInitialized(); + + ThemeProviderService.ThemeChangedAsync += OnThemeChanged; + } + /// /// /// @@ -189,4 +203,12 @@ private string FindCodeSnippetByName(string code) [GeneratedRegex(@"[\s\S]*?")] private static partial Regex TipsRegex(); + + private async Task OnThemeChanged(string themeName) + { + if (themeName == "light" || themeName == "dark") + { + await InvokeVoidAsync("switchTheme", themeName); + } + } } diff --git a/src/BootstrapBlazor.Server/Components/Components/Pre.razor.js b/src/BootstrapBlazor.Server/Components/Components/Pre.razor.js index 35247026b4e..54d82b2be68 100644 --- a/src/BootstrapBlazor.Server/Components/Components/Pre.razor.js +++ b/src/BootstrapBlazor.Server/Components/Components/Pre.razor.js @@ -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`); } } From 1a3b1f6424546ef9b419e4f28151d44b308701aa Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 24 Mar 2025 19:40:27 +0800 Subject: [PATCH 7/8] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=20DockView=20?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=E5=88=87=E6=8D=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.Server.csproj | 2 +- .../Samples/DockViews2/BaseDockView.cs | 27 +++++++++++++++++++ .../Samples/DockViews2/DockViewCol.razor | 2 +- .../Samples/DockViews2/DockViewComplex.razor | 2 +- .../Samples/DockViews2/DockViewGroup.razor | 2 +- .../Samples/DockViews2/DockViewLayout.razor | 2 +- .../Samples/DockViews2/DockViewLock.razor | 2 +- .../Samples/DockViews2/DockViewNest.razor | 6 ++--- .../Samples/DockViews2/DockViewNest.razor.cs | 2 -- .../Samples/DockViews2/DockViewRow.razor | 2 +- .../Samples/DockViews2/DockViewTitle.razor | 2 +- .../Samples/DockViews2/DockViewVisible.razor | 2 +- 12 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj index acf0224f659..fb6f05ea55d 100644 --- a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj +++ b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj @@ -31,7 +31,7 @@ - + diff --git a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/BaseDockView.cs b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/BaseDockView.cs index b43fb66ad7d..ca40bad886f 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/BaseDockView.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/BaseDockView.cs @@ -22,6 +22,10 @@ public abstract class BaseDockView : ComponentBase [NotNull] private MockDataTableDynamicService? DataTableDynamicService { get; set; } + [Inject] + [NotNull] + private IThemeProvider? ThemeProviderService { get; set; } + /// /// 获得/设置 数据集合 /// @@ -39,6 +43,11 @@ public abstract class BaseDockView : ComponentBase /// protected DataTableDynamicContext? DataTableDynamicContext { get; set; } + /// + /// Gets or sets the theme + /// + protected DockViewTheme Theme { get; set; } = DockViewTheme.Light; + /// /// 获得 实例方法 /// @@ -51,6 +60,8 @@ public abstract class BaseDockView : ComponentBase /// protected override void OnInitialized() { + base.OnInitialized(); + Items = Foo.GenerateFoo(LocalizerFoo, 50); // 模拟数据从数据库中获得 @@ -63,6 +74,22 @@ protected override void OnInitialized() TreeItems.AddRange(TreeFoo.GenerateFoos(LocalizerFoo, 3, 101, 1010)); DataTableDynamicContext = DataTableDynamicService.CreateContext(); + + ThemeProviderService.ThemeChangedAsync += OnThemeChanged; + } + + private Task OnThemeChanged(string themeName) + { + if (themeName == "dark") + { + Theme = DockViewTheme.Dark; + } + else + { + Theme = DockViewTheme.Light; + } + StateHasChanged(); + return Task.CompletedTask; } /// diff --git a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewCol.razor b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewCol.razor index 422522d84ad..38632f3419e 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewCol.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewCol.razor @@ -5,7 +5,7 @@

@((MarkupString)Localizer["DockViewColIntro"].Value)

- + @((MarkupString)Localizer["DockViewComplexIntro"].Value) - + diff --git a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewGroup.razor b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewGroup.razor index 891e1af7d83..3e5e85ad94b 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewGroup.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewGroup.razor @@ -5,7 +5,7 @@

@((MarkupString)Localizer["DockViewGroupIntro"].Value)

- + diff --git a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewLayout.razor b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewLayout.razor index 08fffe29a95..8d469704886 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewLayout.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewLayout.razor @@ -12,7 +12,7 @@ - +
- +
@((MarkupString)Localizer["DockViewNestIntro"].Value) - + - +
- +
? Localizer { get; set; } - - private DockViewTheme _theme; } diff --git a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewRow.razor b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewRow.razor index e5bb196c9e9..e53c5225a57 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewRow.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/DockViews2/DockViewRow.razor @@ -5,7 +5,7 @@

@((MarkupString)Localizer["DockViewRowIntro"].Value)

- +
@((MarkupString)Localizer["DockViewTitleIntro"].Value) - +
- +
Date: Mon, 24 Mar 2025 20:11:26 +0800 Subject: [PATCH 8/8] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Services/ThemeProviderTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/UnitTest/Services/ThemeProviderTest.cs b/test/UnitTest/Services/ThemeProviderTest.cs index 3b219a2dae5..0f09ed404db 100644 --- a/test/UnitTest/Services/ThemeProviderTest.cs +++ b/test/UnitTest/Services/ThemeProviderTest.cs @@ -10,8 +10,15 @@ public class ThemeProviderTest : BootstrapBlazorTestBase [Fact] public async Task SetTheme_Ok() { + var themeName = ""; var themeProviderService = Context.Services.GetRequiredService(); + themeProviderService.ThemeChangedAsync = async theme => + { + themeName = theme; + await Task.CompletedTask; + }; await themeProviderService.SetThemeAsync("light"); + Assert.Equal("light", themeName); } [Fact]