From 2f52cbb7d4340e3e23a187971c6dd9a96b5dbc44 Mon Sep 17 00:00:00 2001 From: JonKazama-Hellion Date: Tue, 5 May 2026 14:17:22 +0200 Subject: [PATCH] feat(themes): seed example custom theme on first start --- HellionChat/HellionChat.csproj | 3 ++ HellionChat/Plugin.cs | 34 +++++++++++++++ HellionChat/Themes/Builtin/example-theme.json | 41 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 HellionChat/Themes/Builtin/example-theme.json diff --git a/HellionChat/HellionChat.csproj b/HellionChat/HellionChat.csproj index 0d048e8..cfe8103 100644 --- a/HellionChat/HellionChat.csproj +++ b/HellionChat/HellionChat.csproj @@ -75,6 +75,9 @@ HellionFont-OFL.txt + + HellionChat.Themes.Builtin.example-theme.json + diff --git a/HellionChat/Plugin.cs b/HellionChat/Plugin.cs index e5e7770..6cb47f5 100755 --- a/HellionChat/Plugin.cs +++ b/HellionChat/Plugin.cs @@ -291,6 +291,8 @@ public sealed class Plugin : IDalamudPlugin // v1.1.0 — Theme-Engine init. Custom-Themes liegen in // pluginConfigs/HellionChat/themes/, lazy geladen beim ersten Get. var customThemesDir = Path.Combine(Interface.ConfigDirectory.FullName, "themes"); + Directory.CreateDirectory(customThemesDir); + SeedExampleThemeIfEmpty(customThemesDir); ThemeRegistry = new Themes.ThemeRegistry(customThemesDir); ThemeRegistry.Switch(Config.Theme); @@ -675,4 +677,36 @@ public sealed class Plugin : IDalamudPlugin public static bool InBattle => Condition[ConditionFlag.InCombat]; public static bool GposeActive => Condition[ConditionFlag.WatchingCutscene]; public static bool CutsceneActive => Condition[ConditionFlag.OccupiedInCutSceneEvent] || Condition[ConditionFlag.WatchingCutscene78]; + + // v1.1.0 — wenn der themes/-Ordner leer ist, schreiben wir die embedded + // example-theme.json als Vorlage rein. Bestehende User-Customs werden + // nicht angefasst (existing JSONs lassen den Block überspringen). + private static void SeedExampleThemeIfEmpty(string dir) + { + if (Directory.EnumerateFiles(dir, "*.json").Any()) + return; + + var examplePath = Path.Combine(dir, "example-theme.json"); + var resourceStream = typeof(Plugin).Assembly.GetManifestResourceStream("HellionChat.Themes.Builtin.example-theme.json"); + if (resourceStream is null) + { + Log.Warning("Themes example template not found in assembly resources; skipping seed."); + return; + } + + try + { + using var fileStream = File.Create(examplePath); + resourceStream.CopyTo(fileStream); + Log.Information($"Seeded example-theme.json into {dir}"); + } + catch (IOException ex) + { + Log.Warning(ex, "Failed to seed example-theme.json; user can create custom themes manually."); + } + finally + { + resourceStream.Dispose(); + } + } } diff --git a/HellionChat/Themes/Builtin/example-theme.json b/HellionChat/Themes/Builtin/example-theme.json new file mode 100644 index 0000000..1f547f7 --- /dev/null +++ b/HellionChat/Themes/Builtin/example-theme.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "slug": "example-custom", + "name": "Example Custom", + "author": "You", + "description": "Starting template — duplicate, rename, edit colors and reload.", + "colors": { + "primaryDark": "#0097A7", + "primary": "#00BED2", + "primaryLight": "#4DD9E8", + "primaryGlow": "#00BED299", + "accentDark": "#E85D04", + "accent": "#F97316", + "accentLight": "#FB923C", + "identity": "#0097A7", + "windowBg": "#070B12", + "childBg": "#0C1220", + "frameBg": "#141E30", + "surface": "#1A2538", + "surfaceHover": "#22303F", + "border": "#00BED266", + "textPrimary": "#E6F4F1", + "textMuted": "#8FA3B5", + "textDim": "#566273", + "statusSuccess": "#5CB85C", + "statusDanger": "#D9534F", + "statusWarning": "#F0AD4E", + "statusInfo": "#00BED2" + }, + "layout": { + "windowRounding": 4, + "childRounding": 3, + "popupRounding": 3, + "frameRounding": 2, + "grabRounding": 2, + "tabRounding": 2, + "scrollbarRounding": 2, + "windowBorderSize": 1, + "frameBorderSize": 1 + } +}