From 953c1c1dd8b839d702c6b5e7ea1097e4f2c868f6 Mon Sep 17 00:00:00 2001 From: Nils Kruthoff Date: Wed, 29 Jul 2026 13:31:00 +0200 Subject: [PATCH] refactored the ExportDocument method to support pandoc and plain file export --- .../Chat/ContentBlockComponent.razor.cs | 17 +++++- .../Tools/PlainFileExport.cs | 59 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 app/MindWork AI Studio/Tools/PlainFileExport.cs diff --git a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs index 9021cc1d..f7896444 100644 --- a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs +++ b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs @@ -552,7 +552,22 @@ public partial class ContentBlockComponent : MSGComponentBase, IAsyncDisposable { try { - await PandocExport.ToDocument(this.RustService, this.DialogService, format, this.Content); + switch (format) + { + case FileExportFormat.MARKDOWN: + await PlainFileExport.ToFile(this.RustService, format, this.Content); + break; + + case FileExportFormat.MICROSOFT_WORD: + case FileExportFormat.OPEN_DOCUMENT_TEXT: + case FileExportFormat.HTML: + await PandocExport.ToDocument(this.RustService, this.DialogService, format, this.Content); + break; + + default: + LOGGER.LogError($"No exporter is registered for {format}."); + return; + } } catch (ArgumentOutOfRangeException e) { diff --git a/app/MindWork AI Studio/Tools/PlainFileExport.cs b/app/MindWork AI Studio/Tools/PlainFileExport.cs new file mode 100644 index 00000000..fce357fb --- /dev/null +++ b/app/MindWork AI Studio/Tools/PlainFileExport.cs @@ -0,0 +1,59 @@ +using System.Diagnostics; +using AIStudio.Chat; +using AIStudio.Dialogs; +using AIStudio.Tools.PluginSystem; +using AIStudio.Tools.Rust; +using AIStudio.Tools.Services; +using DialogOptions = MudBlazor.DialogOptions; + +namespace AIStudio.Tools; + +public static class PlainFileExport +{ + private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(nameof(PlainFileExport)); + + private sealed record ExportTarget(string DisplayName, FileTypeFilter FileType); + + private static readonly ExportTarget MARKDOWN = new("Markdown (.md)", FileTypes.MARKDOWN); + + private static string TB(string fallbackEn) => I18N.I.T(fallbackEn, typeof(PlainFileExport).Namespace, nameof(PlainFileExport)); + + public static async Task ToFile(RustService rustService, FileExportFormat format, IContent markdownContent) + { + var exportTarget = format switch + { + FileExportFormat.MARKDOWN => MARKDOWN, + _ => throw new ArgumentOutOfRangeException(nameof(format), format, null), + }; + + var response = await rustService.SaveFile(TB("Export chat"), [exportTarget.FileType]); + if (response.UserCancelled) + { + LOGGER.LogInformation("User cancelled the save dialog."); + return false; + } + + LOGGER.LogInformation($"The user chose the path '{response.SaveFilePath}' for the {exportTarget.DisplayName} export."); + + try + { + var markdownText = markdownContent switch + { + ContentText text => text.Text, + ContentImage _ => "Image export is not yet possible.", + _ => "Unknown content type. Cannot export document." + }; + + await File.WriteAllTextAsync(response.SaveFilePath, markdownText); + await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, TB("Document export successful"))); + + return true; + } + catch (Exception ex) + { + LOGGER.LogError(ex, $"Error during {exportTarget.DisplayName} export."); + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Cancel, TB("Error during document export"))); + return false; + } + } +}