From a2d8a9c223529f29f59eb571f40f860aa0f665f1 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Mon, 15 Jun 2026 16:28:34 +0200 Subject: [PATCH] feat(themes): add an export button for the active theme --- .../Settings/ThemeImportExportRow.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/HellionChat/Ui/Components/Settings/ThemeImportExportRow.cs b/HellionChat/Ui/Components/Settings/ThemeImportExportRow.cs index f76db1d..25045d3 100644 --- a/HellionChat/Ui/Components/Settings/ThemeImportExportRow.cs +++ b/HellionChat/Ui/Components/Settings/ThemeImportExportRow.cs @@ -37,6 +37,12 @@ internal sealed class ThemeImportExportRow OpenThemesFolder(); } + ImGui.SameLine(); + if (ImGui.Button("Export active theme…")) + { + ExportActive(); + } + ImGui.SetNextItemWidth(-1); ImGui.InputTextWithHint( "##theme-import-path", @@ -293,4 +299,43 @@ internal sealed class ThemeImportExportRow _logger.LogWarning(ex, "Could not open themes folder {Dir}", dir); } } + + private void ExportActive() + { + // Capture the active theme now, not in the async dialog callback — the user + // could switch themes while the dialog is open. + var theme = _themes.Active; + var defaultName = $"{theme.Slug}.json"; + + Plugin.FileDialogManager.SaveFileDialog( + "Export theme", + ".json", + defaultName, + ".json", + (ok, path) => + { + if (ok) + { + ExportTo(theme, path); + } + }, + null, + isModal: true + ); + } + + private void ExportTo(Theme theme, string path) + { + try + { + var json = ThemeJsonWriter.Serialize(theme); + File.WriteAllText(path, json); + _logger.LogInformation("Exported theme {Slug} to {Path}", theme.Slug, path); + } + catch (Exception ex) + when (ex is IOException or UnauthorizedAccessException or SecurityException) + { + _logger.LogWarning(ex, "Theme export to {Path} failed", path); + } + } }