feat(themes): seed example custom theme on first start
This commit is contained in:
@@ -75,6 +75,9 @@
|
||||
<EmbeddedResource Include="Resources\HellionFont-OFL.txt">
|
||||
<LogicalName>HellionFont-OFL.txt</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Themes\Builtin\example-theme.json">
|
||||
<LogicalName>HellionChat.Themes.Builtin.example-theme.json</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user