Added theming support. Added import/export
Missing: API Server save
This commit is contained in:
83
Moonlight.Client/UI/Components/ThemeColorSelector.razor
Normal file
83
Moonlight.Client/UI/Components/ThemeColorSelector.razor
Normal file
@@ -0,0 +1,83 @@
|
||||
@using System.Drawing
|
||||
@using MoonCore.Helpers
|
||||
|
||||
<div class="card card-body py-2 px-4 flex flex-row items-center justify-between">
|
||||
<span>
|
||||
@PrettyIdentifier
|
||||
</span>
|
||||
<div class="flex flex-row items-center gap-x-1">
|
||||
@{
|
||||
var currentValue = Value ?? DefaultValue;
|
||||
var currentHex = ColorToHex(currentValue);
|
||||
var elementId = $"colorSelect{GetHashCode()}";
|
||||
}
|
||||
|
||||
<input id="@elementId" @onchange="OnColorChanged" type="color" hidden="" value="@(currentHex)"/>
|
||||
<label for="@elementId" class="btn w-32 justify-between" style="background-color: @(currentHex)">
|
||||
<i class="icon-palette mix-blend-exclusion"></i>
|
||||
<span class="ms-2 mix-blend-exclusion">@(currentHex)</span>
|
||||
</label>
|
||||
<button @onclick="Reset" class="btn btn-danger">
|
||||
<i class="icon-rotate-ccw"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
[Parameter] public string? Value { get; set; }
|
||||
[Parameter] public string Identifier { get; set; }
|
||||
[Parameter] public string DefaultValue { get; set; }
|
||||
[Parameter] public Func<string, Task> OnChanged { get; set; }
|
||||
|
||||
private string PrettyIdentifier;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
var parts = Identifier
|
||||
.Split("-")
|
||||
.Select(Formatter.CapitalizeFirstCharacter);
|
||||
|
||||
PrettyIdentifier = string.Join(" ", parts);
|
||||
}
|
||||
|
||||
private async Task Save()
|
||||
{
|
||||
await OnChanged.Invoke(Value ?? DefaultValue);
|
||||
}
|
||||
|
||||
private async Task Reset()
|
||||
{
|
||||
Value = DefaultValue;
|
||||
await Save();
|
||||
}
|
||||
|
||||
private async Task OnColorChanged(ChangeEventArgs eventArgs)
|
||||
{
|
||||
var strVal = eventArgs.Value?.ToString() ?? null;
|
||||
|
||||
if (strVal == null)
|
||||
Value = DefaultValue;
|
||||
else
|
||||
Value = HexToColor(strVal);
|
||||
|
||||
await Save();
|
||||
}
|
||||
|
||||
private string ColorToHex(string str)
|
||||
{
|
||||
var colorParts = str.Split(" ");
|
||||
|
||||
var r = int.Parse(colorParts[0]);
|
||||
var g = int.Parse(colorParts[1]);
|
||||
var b = int.Parse(colorParts[2]);
|
||||
|
||||
return ColorTranslator.ToHtml(Color.FromArgb(r, g, b));
|
||||
}
|
||||
|
||||
private string HexToColor(string str)
|
||||
{
|
||||
var color = ColorTranslator.FromHtml(str);
|
||||
return $"{color.R} {color.G} {color.B}";
|
||||
}
|
||||
}
|
||||
43
Moonlight.Client/UI/Components/ThemeLoader.razor
Normal file
43
Moonlight.Client/UI/Components/ThemeLoader.razor
Normal file
@@ -0,0 +1,43 @@
|
||||
@using Moonlight.Client.Services
|
||||
|
||||
@inject ThemeService ThemeService
|
||||
|
||||
@implements IDisposable
|
||||
|
||||
<style>
|
||||
:root {
|
||||
@Css
|
||||
}
|
||||
</style>
|
||||
|
||||
@code
|
||||
{
|
||||
private string Css = "";
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
GenerateCss();
|
||||
|
||||
ThemeService.OnRefresh += OnRefresh;
|
||||
}
|
||||
|
||||
private async Task OnRefresh()
|
||||
{
|
||||
GenerateCss();
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void GenerateCss()
|
||||
{
|
||||
Css = "";
|
||||
|
||||
foreach (var variable in ThemeService.Variables)
|
||||
Css += $"--color-{variable.Key}: {variable.Value};\n";
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ThemeService.OnRefresh -= OnRefresh;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user