feat(themes): optional chat channel colors in theme schema

This commit is contained in:
2026-05-05 14:44:59 +02:00
parent fcbbd174b6
commit 53952717c0
4 changed files with 47 additions and 2 deletions
+2 -1
View File
@@ -8,5 +8,6 @@ public sealed record Theme(
ThemeColors Colors, ThemeColors Colors,
ThemeLayout Layout, ThemeLayout Layout,
ThemeTypography Typography, ThemeTypography Typography,
bool IsBuiltIn bool IsBuiltIn,
ThemeChatColors? ChatColors = null
); );
+11
View File
@@ -0,0 +1,11 @@
using HellionChat.Code;
namespace HellionChat.Themes;
// Optional pro Theme. Wenn ein Theme ChatColors mitliefert, kann der
// User sie per Klick im Themes-Tab auf Configuration.ChatColours anwenden.
// Ein Theme ohne ChatColors (z.B. chat2-classic) lässt die User-Channel-
// Farben unverändert.
public sealed record ThemeChatColors(
IReadOnlyDictionary<ChatType, uint> Channels
);
+26 -1
View File
@@ -32,10 +32,35 @@ internal static class ThemeJsonLoader
var colors = ReadColors(root.GetProperty("colors")); var colors = ReadColors(root.GetProperty("colors"));
var layout = ReadLayout(root.GetProperty("layout")); var layout = ReadLayout(root.GetProperty("layout"));
return new Theme(slug, name, author, description, colors, layout, new ThemeTypography(), IsBuiltIn: false); ThemeChatColors? chatColors = null;
if (root.TryGetProperty("chatChannels", out var ch) && ch.ValueKind == JsonValueKind.Object)
chatColors = ReadChatColors(ch);
return new Theme(slug, name, author, description, colors, layout, new ThemeTypography(), IsBuiltIn: false, ChatColors: chatColors);
} }
} }
private static ThemeChatColors ReadChatColors(JsonElement el)
{
var dict = new Dictionary<HellionChat.Code.ChatType, uint>();
foreach (var prop in el.EnumerateObject())
{
// Property-Name ist der ChatType-Name als String (z.B. "Say", "Tell"),
// Value ist Hex wie bei den Theme-Colors. Unbekannte Channel-Names
// werden still übersprungen — Forward-Compat falls SE neue Channels
// einführt.
if (!Enum.TryParse<HellionChat.Code.ChatType>(prop.Name, ignoreCase: true, out var channel))
continue;
if (prop.Value.ValueKind != JsonValueKind.String)
continue;
var hex = prop.Value.GetString();
if (string.IsNullOrWhiteSpace(hex))
continue;
dict[channel] = HellionChat.Util.ColourUtil.HexToRgba(hex);
}
return new ThemeChatColors(dict);
}
public static Theme LoadFromFile(string path) public static Theme LoadFromFile(string path)
{ {
var json = File.ReadAllText(path); var json = File.ReadAllText(path);
+8
View File
@@ -52,6 +52,14 @@ internal static class ThemeJsonWriter
writer.WriteNumber("frameBorderSize", theme.Layout.FrameBorderSize); writer.WriteNumber("frameBorderSize", theme.Layout.FrameBorderSize);
writer.WriteEndObject(); writer.WriteEndObject();
if (theme.ChatColors is { Channels.Count: > 0 } cc)
{
writer.WriteStartObject("chatChannels");
foreach (var kvp in cc.Channels)
writer.WriteString(kvp.Key.ToString(), $"#{kvp.Value:X8}");
writer.WriteEndObject();
}
writer.WriteEndObject(); writer.WriteEndObject();
} }