From 77f5bb227ee8e1c7b18ff3fdee28c68f0802619d Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Tue, 29 Aug 2023 13:54:31 +0200 Subject: [PATCH] Theme setting updates --- BTCPayApp.Server/Pages/_Host.cshtml | 1 + BTCPayApp.UI/Features/UIState.cs | 29 ++++++++++++++--- BTCPayApp.UI/Pages/SettingsPage.razor | 10 +----- BTCPayApp.UI/Shared/MainLayout.razor | 23 ++++++++------ BTCPayApp.UI/Shared/SimpleLayout.razor | 25 ++++++++++----- .../wwwroot/css/mudblazor-overrides.css | 9 +----- BTCPayApp.UI/wwwroot/css/site.css | 31 +------------------ BTCPayApp.UI/wwwroot/index.html | 1 + BTCPayApp.UI/wwwroot/js/site.js | 11 +++++++ 9 files changed, 73 insertions(+), 67 deletions(-) create mode 100644 BTCPayApp.UI/wwwroot/js/site.js diff --git a/BTCPayApp.Server/Pages/_Host.cshtml b/BTCPayApp.Server/Pages/_Host.cshtml index 9511ed6..fbee1a5 100644 --- a/BTCPayApp.Server/Pages/_Host.cshtml +++ b/BTCPayApp.Server/Pages/_Host.cshtml @@ -12,6 +12,7 @@ + diff --git a/BTCPayApp.UI/Features/UIState.cs b/BTCPayApp.UI/Features/UIState.cs index f987a4a..a55e575 100644 --- a/BTCPayApp.UI/Features/UIState.cs +++ b/BTCPayApp.UI/Features/UIState.cs @@ -1,4 +1,5 @@ using Fluxor; +using Microsoft.JSInterop; namespace BTCPayApp.UI.Features; @@ -9,11 +10,12 @@ public class UIState private string SystemTheme { get; init; } = Constants.LightTheme; public bool IsDarkMode { get; set; } - public record ApplySystemPreference(string Theme); - public record ApplyTheme(string Theme); + public record ApplyUserTheme(string Theme); + public record SetSystemPreference(string Theme); + public record SetUserTheme(string Theme); [ReducerMethod] - public static UIState Reduce(UIState state, ApplySystemPreference action) + public static UIState Reduce(UIState state, SetSystemPreference action) { var effectiveTheme = state.SelectedTheme == Constants.SystemTheme ? action.Theme : state.SelectedTheme; return new UIState @@ -25,7 +27,7 @@ public class UIState } [ReducerMethod] - public static UIState Reduce(UIState state, ApplyTheme action) + public static UIState Reduce(UIState state, SetUserTheme action) { var effectiveTheme = action.Theme == Constants.SystemTheme ? state.SystemTheme : action.Theme; return new UIState @@ -35,4 +37,23 @@ public class UIState IsDarkMode = effectiveTheme == Constants.DarkTheme }; } + + public class UIEffects + { + private readonly IJSRuntime _jsRuntime; + + public UIEffects(IJSRuntime jsRuntime) + { + _jsRuntime = jsRuntime; + } + + [EffectMethod] + public async Task ApplyUserThemeEffect(ApplyUserTheme action, IDispatcher dispatcher) + { + // store + dispatcher.Dispatch(new SetUserTheme(action.Theme)); + // ui + await _jsRuntime.InvokeVoidAsync("setTheme", action.Theme); + } + } } diff --git a/BTCPayApp.UI/Pages/SettingsPage.razor b/BTCPayApp.UI/Pages/SettingsPage.razor index a41935f..3453b83 100644 --- a/BTCPayApp.UI/Pages/SettingsPage.razor +++ b/BTCPayApp.UI/Pages/SettingsPage.razor @@ -8,13 +8,5 @@ Settings - - -@code { - private Task SetTheme(string theme) - { - Dispatcher.Dispatch(new UIState.ApplyTheme(theme)); - return Task.CompletedTask; - } -} + diff --git a/BTCPayApp.UI/Shared/MainLayout.razor b/BTCPayApp.UI/Shared/MainLayout.razor index 0e2526b..86a2020 100644 --- a/BTCPayApp.UI/Shared/MainLayout.razor +++ b/BTCPayApp.UI/Shared/MainLayout.razor @@ -17,8 +17,10 @@ - - BTCPay Server + + + BTCPay Server + @@ -29,7 +31,7 @@ - + @Body @@ -52,16 +54,19 @@ { LoadingStateSelection.Select(state => state.Loading); DarkModeStateSelection.Select(state => state.IsDarkMode); - if (_darkMode is null && !Store.Initialized.IsCompleted) + var state = await ConfigProvider.Get(StateMiddleware.UiStateConfigKey); + if (state != null) { - var state = await ConfigProvider.Get(StateMiddleware.UiStateConfigKey); - if (state != null) + if (_darkMode is null && !Store.Initialized.IsCompleted) { _darkMode = state.IsDarkMode; - _ = Store.Initialized.ContinueWith(task => _darkMode = null); + _ = Store.Initialized.ContinueWith(_ => _darkMode = null); + } + if (!string.IsNullOrEmpty(state.SelectedTheme)) + { + Dispatcher.Dispatch(new UIState.ApplyUserTheme(state.SelectedTheme)); } } - await base.OnInitializedAsync(); } @@ -79,6 +84,6 @@ private void ApplySystemPreference(object? sender, bool isDarkMode) { var systemTheme = isDarkMode ? Constants.DarkTheme : Constants.LightTheme; - Dispatcher.Dispatch(new UIState.ApplySystemPreference(systemTheme)); + Dispatcher.Dispatch(new UIState.SetSystemPreference(systemTheme)); } } diff --git a/BTCPayApp.UI/Shared/SimpleLayout.razor b/BTCPayApp.UI/Shared/SimpleLayout.razor index 29f4d4e..a7395a2 100644 --- a/BTCPayApp.UI/Shared/SimpleLayout.razor +++ b/BTCPayApp.UI/Shared/SimpleLayout.razor @@ -3,6 +3,7 @@ @inherits Fluxor.Blazor.Web.Components.FluxorLayout @inject IStateSelection> LoadingStateSelection @inject IStateSelection DarkModeStateSelection +@inject IDispatcher Dispatcher @inject IConfigProvider ConfigProvider @inject ISystemThemeProvider SystemThemeProvider @inject IStore Store @@ -13,7 +14,7 @@ - + @Body @@ -28,26 +29,36 @@ { LoadingStateSelection.Select(state => state.Loading); DarkModeStateSelection.Select(state => state.IsDarkMode); - if (_darkMode is null && !Store.Initialized.IsCompleted) + var state = await ConfigProvider.Get(StateMiddleware.UiStateConfigKey); + if (state != null) { - var state = await ConfigProvider.Get(StateMiddleware.UiStateConfigKey); - if (state != null) + if (_darkMode is null && !Store.Initialized.IsCompleted) { _darkMode = state.IsDarkMode; _ = Store.Initialized.ContinueWith(_ => _darkMode = null); } + if (!string.IsNullOrEmpty(state.SelectedTheme)) + { + Dispatcher.Dispatch(new UIState.ApplyUserTheme(state.SelectedTheme)); + } } - await base.OnInitializedAsync(); } - protected override Task OnAfterRenderAsync(bool firstRender) + protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { if (SystemThemeProvider is MudBlazorThemeProvider mudThemeProvider) mudThemeProvider.MudThemeProvider = _mudThemeProvider; + ApplySystemPreference(this, await _mudThemeProvider.GetSystemPreference()); + SystemThemeProvider.SystemThemeChanged += ApplySystemPreference; } - return Task.CompletedTask; + } + + private void ApplySystemPreference(object? sender, bool isDarkMode) + { + var theme = isDarkMode ? Constants.DarkTheme : Constants.LightTheme; + Dispatcher.Dispatch(new UIState.SetSystemPreference(theme)); } } diff --git a/BTCPayApp.UI/wwwroot/css/mudblazor-overrides.css b/BTCPayApp.UI/wwwroot/css/mudblazor-overrides.css index f1cafcb..c619302 100644 --- a/BTCPayApp.UI/wwwroot/css/mudblazor-overrides.css +++ b/BTCPayApp.UI/wwwroot/css/mudblazor-overrides.css @@ -1,7 +1,6 @@ :root { } -.mud-icon-button, .mud-button-text { --btcpay-btn-disabled-opacity: 0.65; @@ -12,16 +11,13 @@ padding: var(--btcpay-btn-padding-y) var(--btcpay-btn-padding-x) !important; } -.mud-icon-button:hover, .mud-button-text:hover, -.mud-icon-button:focus-visible, .mud-button-text:focus-visible { color: var(--btcpay-btn-hover-color) !important; background-color: var(--btcpay-btn-hover-bg) !important; border-color: var(--btcpay-btn-hover-border-color) !important; } -.mud-icon-button:disabled, .mud-button-text:disabled { color: var(--btcpay-btn-disabled-color) !important; background-color: var(--btcpay-btn-disabled-bg) !important; @@ -45,7 +41,7 @@ --btcpay-btn-disabled-bg: var(--btcpay-primary); --btcpay-btn-disabled-border-color: var(--btcpay-primary-border); } -.mud-icon-button.mud-button-outlined, + .mud-button-text-default, .mud-button-text-secondary, .mud-button-filled-secondary { @@ -64,7 +60,6 @@ --btcpay-btn-disabled-border-color: var(--btcpay-secondary-border); } -.mud-icon-button-size-large, .mud-button-text-size-large { --btcpay-btn-padding-y: 1rem; --btcpay-btn-padding-x: 2rem; @@ -72,7 +67,6 @@ --btcpay-btn-border-radius: var(--btcpay-border-radius-l); } -.mud-icon-button-size-medium, .mud-button-text-size-medium { --btcpay-btn-padding-x: 1.5rem; --btcpay-btn-padding-y: 0.5rem; @@ -80,7 +74,6 @@ --btcpay-btn-border-radius: var(--btcpay-border-radius); } -.mud-icon-button-size-small, .mud-button-text-size-small { --btcpay-btn-padding-y: 0.5rem; --btcpay-btn-padding-x: 1.5rem; diff --git a/BTCPayApp.UI/wwwroot/css/site.css b/BTCPayApp.UI/wwwroot/css/site.css index e260f96..c7ae6e6 100644 --- a/BTCPayApp.UI/wwwroot/css/site.css +++ b/BTCPayApp.UI/wwwroot/css/site.css @@ -1,33 +1,4 @@ -#blazor-error-ui { - background: lightyellow; - bottom: 0; - box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); - display: none; - left: 0; - padding: 0.6rem 1.25rem 0.7rem 1.25rem; - position: fixed; - width: 100%; - z-index: 1000; -} - -#blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; -} - -.blazor-error-boundary { - background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; - padding: 1rem 1rem 1rem 3.7rem; - color: white; -} - -.blazor-error-boundary::after { - content: "An error has occurred." -} - -@media (min-width: 0px) { +@media (min-width: 0px) { #OnboardingCarousel { min-height: 430px; } diff --git a/BTCPayApp.UI/wwwroot/index.html b/BTCPayApp.UI/wwwroot/index.html index dc0ab42..fb4bd9d 100644 --- a/BTCPayApp.UI/wwwroot/index.html +++ b/BTCPayApp.UI/wwwroot/index.html @@ -7,6 +7,7 @@ BTCPay Server + diff --git a/BTCPayApp.UI/wwwroot/js/site.js b/BTCPayApp.UI/wwwroot/js/site.js new file mode 100644 index 0000000..0d19083 --- /dev/null +++ b/BTCPayApp.UI/wwwroot/js/site.js @@ -0,0 +1,11 @@ +// Theme Switch +const THEMES = ['light', 'dark'] +const THEME_ATTR = 'data-btcpay-theme' +const systemColorMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? THEMES[1] : THEMES[0] +function setTheme(mode) { + if (THEMES.includes(mode) && mode !== systemColorMode) { + document.documentElement.setAttribute(THEME_ATTR, mode) + } else { + document.documentElement.removeAttribute(THEME_ATTR) + } +}