mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
Setup support for live themes (#1162)
Co-authored-by: Alexandru Macocian <amacocian@microsoft.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using Daybreak.Shared.Services.Themes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using static Daybreak.Shared.Models.Theme;
|
||||
using static Daybreak.Shared.Models.Themes.Theme;
|
||||
|
||||
namespace Daybreak.Shared.Models;
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Daybreak.Shared.Models.Themes;
|
||||
|
||||
public sealed class EmbedBackground(string embedCode)
|
||||
: IAppBackground
|
||||
{
|
||||
public string EmbedCode { get; } = embedCode;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Daybreak.Shared.Models.Themes;
|
||||
|
||||
/// <summary>
|
||||
/// Tells the app how to display the background.
|
||||
/// Implemented in <see cref="StaticBackground"/> and <see cref="EmbedBackground"/>
|
||||
/// </summary>
|
||||
public interface IAppBackground
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Daybreak.Shared.Models.Themes;
|
||||
|
||||
public sealed class StaticBackground(string backdropImage)
|
||||
: IAppBackground
|
||||
{
|
||||
public string BackdropImage { get; } = backdropImage;
|
||||
}
|
||||
@@ -2,9 +2,14 @@
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Shared.Models;
|
||||
namespace Daybreak.Shared.Models.Themes;
|
||||
[JsonConverter(typeof(ThemeJsonConverter))]
|
||||
public class Theme(string name, AccentColor accentColor, string backdrop, Theme.LightDarkMode mode, string filter)
|
||||
public class Theme(
|
||||
string name,
|
||||
AccentColor accentColor,
|
||||
IAppBackground background,
|
||||
Theme.LightDarkMode mode,
|
||||
string filter)
|
||||
{
|
||||
public enum LightDarkMode
|
||||
{
|
||||
@@ -15,7 +20,7 @@ public class Theme(string name, AccentColor accentColor, string backdrop, Theme.
|
||||
|
||||
public string Name { get; init; } = name;
|
||||
public AccentColor AccentColor { get; internal set; } = accentColor;
|
||||
public string Backdrop { get; internal set; } = backdrop;
|
||||
public IAppBackground Background { get; internal set; } = background;
|
||||
public LightDarkMode Mode { get; internal set; } = mode;
|
||||
public string Filter { get; internal set; } = filter;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using Daybreak.Shared.Services.Screenshots;
|
||||
using System.Windows.Extensions.Services;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Daybreak.Shared.Services.Themes;
|
||||
public sealed class GameScreenshotsTheme(
|
||||
IThemeManager themeManager,
|
||||
IScreenshotService screenshotService)
|
||||
: Theme(ThemeName, AccentColor.Orange, string.Empty, LightDarkMode.SystemSynchronized, string.Empty), IApplicationLifetimeService
|
||||
: Theme(ThemeName, AccentColor.Orange, new StaticBackground(string.Empty), LightDarkMode.SystemSynchronized, string.Empty), IApplicationLifetimeService
|
||||
{
|
||||
public const string ThemeName = "Dynamic Screenshots";
|
||||
|
||||
@@ -37,7 +37,7 @@ public sealed class GameScreenshotsTheme(
|
||||
}
|
||||
|
||||
this.AccentColor = entry.AccentColor;
|
||||
this.Backdrop = entry.FilePath;
|
||||
this.Background = new StaticBackground(entry.FilePath);
|
||||
this.Mode = entry.LightDarkMode;
|
||||
this.Filter = entry.LightDarkMode is LightDarkMode.Light
|
||||
? "blur(3px) brightness(1.3) sepia(0.2) saturate(1.2)"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
|
||||
namespace Daybreak.Shared.Services.Themes;
|
||||
public interface IThemeManager
|
||||
@@ -12,7 +12,8 @@ public interface IThemeManager
|
||||
string AccentBaseColorHex { get; }
|
||||
string NeutralBaseColorHex { get; }
|
||||
float BaseLayerLuminance { get; }
|
||||
string BackdropImage { get; }
|
||||
string? BackdropImage { get; }
|
||||
string? BackdropEmbed { get; }
|
||||
double UIScale { get; }
|
||||
double XXSmallFontSize { get; }
|
||||
double XSmallFontSize { get; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
|
||||
namespace Daybreak.Shared.Services.Themes;
|
||||
public interface IThemeProducer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Daybreak.Shared.Attributes;
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
public sealed class DaybreakThemeOptionsAttribute : OptionValuesFactoryAttribute
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Shared.Attributes;
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using Daybreak.Themes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
@@ -447,12 +447,10 @@ public class ProjectConfiguration : PluginConfigurationBase
|
||||
public override void RegisterThemes(IThemeProducer themeProducer)
|
||||
{
|
||||
themeProducer.ThrowIfNull();
|
||||
foreach (var theme in CoreThemes.Themes)
|
||||
{
|
||||
themeProducer.RegisterTheme(theme);
|
||||
}
|
||||
|
||||
foreach (var theme in HeroThemes.Themes)
|
||||
var themes = CoreThemes.Themes
|
||||
.Concat(HeroThemes.Themes)
|
||||
.Concat(LiveThemes.Themes);
|
||||
foreach (var theme in themes)
|
||||
{
|
||||
themeProducer.RegisterTheme(theme);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using Daybreak.Themes;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.ComponentModel;
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.IO;
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Services.Screenshots;
|
||||
using static Daybreak.Shared.Models.Theme;
|
||||
using static Daybreak.Shared.Models.Themes.Theme;
|
||||
|
||||
namespace Daybreak.Services.Screenshots;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using Daybreak.Shared.Services.Options;
|
||||
using Daybreak.Shared.Services.Themes;
|
||||
using Daybreak.Themes;
|
||||
@@ -39,7 +39,8 @@ public class BlazorThemeInteropService(
|
||||
public BackgroundColor NeutralBaseColor { get; private set; } = BackgroundColor.Gray40;
|
||||
public string AccentBaseColorHex { get; private set; } = string.Empty;
|
||||
public string NeutralBaseColorHex { get; private set; } = string.Empty;
|
||||
public string BackdropImage { get; private set; } = string.Empty;
|
||||
public string? BackdropImage { get; private set; }
|
||||
public string? BackdropEmbed { get; private set; }
|
||||
public float BaseLayerLuminance { get; private set; } = 0.0f;
|
||||
public double UIScale { get; private set; } = 1.0;
|
||||
public double XXSmallFontSize { get; private set; } = XXSmallFontSizeValue;
|
||||
@@ -83,7 +84,8 @@ public class BlazorThemeInteropService(
|
||||
var backgroundColor = lightMode ? BackgroundColor.Gray40 : BackgroundColor.Gray210;
|
||||
var baseLayerLuminance = lightMode ? 0.98f : 0.23f;
|
||||
this.CurrentTheme = theme;
|
||||
this.BackdropImage = theme.Backdrop;
|
||||
this.BackdropImage = theme.Background is StaticBackground staticBackground ? staticBackground.BackdropImage : default;
|
||||
this.BackdropEmbed = theme.Background is EmbedBackground embeddedBackground ? embeddedBackground.EmbedCode : default;
|
||||
this.IsLightMode = lightMode;
|
||||
this.AccentBaseColor = accentColor;
|
||||
this.AccentBaseColorHex = accentColor.Hex;
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using static Daybreak.Shared.Models.Theme;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using static Daybreak.Shared.Models.Themes.Theme;
|
||||
|
||||
namespace Daybreak.Themes;
|
||||
public static class CoreThemes
|
||||
{
|
||||
public static readonly Theme Daybreak = new("Daybreak", AccentColor.Yellow, "img/backdrops/daybreak.png", LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Nightfall = new("Nightfall", AccentColor.DarkGreen, "img/backdrops/nightfall.png", LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme WhiteMantle = new("White Mantle", AccentColor.Red, "img/backdrops/whitemantle.png", LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme ShiningBlade = new("Shining Blade", AccentColor.DarkGreen, "img/backdrops/shiningblade.png", LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme Jade = new("Jade", AccentColor.LightTeal, "img/backdrops/jade.png", LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme HarbingerOfTheDeceiver = new("Harbinger of the Deceiver", AccentColor.DarkPurple, "img/backdrops/harbinger.png", LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme Daybreak = new("Daybreak", AccentColor.Yellow, new StaticBackground("img/backdrops/daybreak.png"), LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Nightfall = new("Nightfall", AccentColor.DarkGreen, new StaticBackground("img/backdrops/nightfall.png"), LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme WhiteMantle = new("White Mantle", AccentColor.Red, new StaticBackground("img/backdrops/whitemantle.png"), LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme ShiningBlade = new("Shining Blade", AccentColor.DarkGreen, new StaticBackground("img/backdrops/shiningblade.png"), LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme Jade = new("Jade", AccentColor.LightTeal, new StaticBackground("img/backdrops/jade.png"), LightDarkMode.Light, string.Empty);
|
||||
|
||||
public static readonly IReadOnlyList<Theme> Themes = [
|
||||
Daybreak,
|
||||
Nightfall,
|
||||
WhiteMantle,
|
||||
ShiningBlade,
|
||||
Jade
|
||||
Jade,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Daybreak.Themes;
|
||||
|
||||
public static class EmbeddedBackgrounds
|
||||
{
|
||||
public const string EyeOfTheNorth = @"<video style=""object-fit: cover; width: 100%; height: 100%;"" autoplay muted loop playsinline><source src=""video/login_eotn.mp4"" type=""video/mp4"" /></video>";
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
using Daybreak.Shared.Models;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using static Daybreak.Shared.Models.Theme;
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using static Daybreak.Shared.Models.Themes.Theme;
|
||||
|
||||
namespace Daybreak.Themes;
|
||||
public static class HeroThemes
|
||||
{
|
||||
public static readonly Theme Abaddon = new("Abaddon", AccentColor.OrangeLight, "img/backdrops/abaddon.png", LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme Gwen = new("Gwen", AccentColor.Purple, "img/backdrops/gwen2.png", LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme ZeiRi = new("Zei Ri", AccentColor.DarkTeal, "img/backdrops/zei-ri.png", LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Livia = new("Livia", AccentColor.DarkRed, "img/backdrops/livia.png", LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Razah = new("Razah", AccentColor.LightBlue, "img/backdrops/razah.png", LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Abaddon = new("Abaddon", AccentColor.OrangeLight, new StaticBackground("img/backdrops/abaddon.png"), LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme Gwen = new("Gwen", AccentColor.Purple, new StaticBackground("img/backdrops/gwen.png"), LightDarkMode.Dark, string.Empty);
|
||||
public static readonly Theme ZeiRi = new("Zei Ri", AccentColor.DarkTeal, new StaticBackground("img/backdrops/zei-ri.png"), LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Livia = new("Livia", AccentColor.DarkRed, new StaticBackground("img/backdrops/livia.png"), LightDarkMode.Light, string.Empty);
|
||||
public static readonly Theme Razah = new("Razah", AccentColor.LightBlue, new StaticBackground("img/backdrops/razah.png"), LightDarkMode.Light, string.Empty);
|
||||
|
||||
public static readonly IReadOnlyList<Theme> Themes = [
|
||||
Abaddon,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Shared.Models.ColorPalette;
|
||||
using Daybreak.Shared.Models.Themes;
|
||||
using static Daybreak.Shared.Models.Themes.Theme;
|
||||
|
||||
namespace Daybreak.Themes;
|
||||
|
||||
public static class LiveThemes
|
||||
{
|
||||
public static readonly Theme EotN = new("Eye of the North", AccentColor.LightBlue, new EmbedBackground(EmbeddedBackgrounds.EyeOfTheNorth), LightDarkMode.Light, string.Empty);
|
||||
|
||||
public static readonly IReadOnlyList<Theme> Themes = [
|
||||
EotN,
|
||||
];
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
BaseLayerLuminance="@this.ViewModel.BaseLayerLuminace">
|
||||
<ErrorLoggingBoundary>
|
||||
<div class="app-container @(this.ViewModel.WindowState == WindowState.Maximized ? "maximized" : "")"
|
||||
style="--backdrop-image: @this.ViewModel.BackdropImage;
|
||||
--backdrop-image-filter: @this.ViewModel.BackdropImageFilter;
|
||||
style="@(string.IsNullOrWhiteSpace(this.ViewModel.BackdropImage) is false ? $"--backdrop-image: {this.ViewModel.BackdropImage}; --backdrop-image-filter: {this.ViewModel.BackdropImageFilter};" : string.Empty)
|
||||
--ui-scale: @(this.ViewModel.UIScale);
|
||||
--font-size-xx-small: @(this.ViewModel.XXSmallFontSize)rem;
|
||||
--font-size-x-small: @(this.ViewModel.XSmallFontSize)rem;
|
||||
@@ -16,6 +15,12 @@
|
||||
--font-size-x-large: @(this.ViewModel.XLargeFontSize)rem;
|
||||
--font-size-xx-large: @(this.ViewModel.XXLargeFontSize)rem;
|
||||
@(string.Join(";\n", AccentColor.Accents.Select(c => $"--accent-{c.Name.ToString().ToLower()}: {c.Hex}")))">
|
||||
@if (!string.IsNullOrWhiteSpace(this.ViewModel.BackdropEmbed))
|
||||
{
|
||||
<div id="video-background">
|
||||
@((MarkupString)this.ViewModel.BackdropEmbed)
|
||||
</div>
|
||||
}
|
||||
<WindowBorders OnResize="@this.ViewModel.StartResize" />
|
||||
|
||||
<WindowTitlebar WindowState="@this.ViewModel.WindowState"
|
||||
|
||||
@@ -59,8 +59,9 @@ public sealed class AppViewModel
|
||||
public string AccentBaseColor { get; set; } = string.Empty;
|
||||
public string NeutralBaseColor { get; set; } = string.Empty;
|
||||
public float BaseLayerLuminace { get; set; } = 0.0f;
|
||||
public string BackdropImage { get; set; } = string.Empty;
|
||||
public string BackdropImageFilter { get; set; } = string.Empty;
|
||||
public string? BackdropImage { get; set; } = string.Empty;
|
||||
public string? BackdropImageFilter { get; set; } = string.Empty;
|
||||
public string? BackdropEmbed { get; set; } = string.Empty;
|
||||
|
||||
public double UIScale { get; set; }
|
||||
public double XXSmallFontSize { get; set; }
|
||||
@@ -280,7 +281,9 @@ public sealed class AppViewModel
|
||||
|
||||
private void OnThemeChange()
|
||||
{
|
||||
this.BackdropImage = this.GetBackdropImageUrl(this.themeManager.BackdropImage);
|
||||
this.BackdropImage = !string.IsNullOrWhiteSpace(this.themeManager.BackdropImage) ? this.GetBackdropImageUrl(this.themeManager.BackdropImage) : default;
|
||||
this.BackdropEmbed = !string.IsNullOrWhiteSpace(this.themeManager.BackdropEmbed) ? this.themeManager.BackdropEmbed : default;
|
||||
this.BackdropImageFilter = this.themeManager.CurrentTheme?.Filter ?? string.Empty;
|
||||
this.BaseLayerLuminace = this.themeManager.BaseLayerLuminance;
|
||||
this.AccentBaseColor = this.themeManager.AccentBaseColorHex;
|
||||
this.NeutralBaseColor = this.themeManager.NeutralBaseColorHex;
|
||||
@@ -292,7 +295,6 @@ public sealed class AppViewModel
|
||||
this.XLargeFontSize = this.themeManager.XLargeFontSize;
|
||||
this.XXLargeFontSize = this.themeManager.XXLargeFontSize;
|
||||
this.UIScale = this.themeManager.UIScale;
|
||||
this.BackdropImageFilter = this.themeManager.CurrentTheme?.Filter ?? string.Empty;
|
||||
this.RedrawRequested?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,4 +25,28 @@
|
||||
overflow: hidden;
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Video Background */
|
||||
#video-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: -2;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#video-background video {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
transform: translate(-50%, -50%);
|
||||
object-fit: cover;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 MiB After Width: | Height: | Size: 3.3 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 MiB |
Binary file not shown.
Reference in New Issue
Block a user