Finished the Pandoc integration (#487)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2025-05-30 22:39:16 +02:00
1 parent 5b685193ef
commit 437da0fd9b
30 files changed
+1600 -349

No files matched your search

@@ -1,19 +1,32 @@
using AIStudio.Tools.Services;
using System.Reflection;
using AIStudio.Components;
using AIStudio.Tools.Metadata;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
using SharedTools;
namespace AIStudio.Dialogs;
public partial class PandocDialog : ComponentBase
public partial class PandocDialog : MSGComponentBase
{
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
[Parameter]
public bool ShowInstallationPage { get; set; }
[Parameter]
public bool ShowInitialResultInSnackbar { get; set; } = true;
[Inject]
private HttpClient HttpClient { get; set; } = null!;
[Inject]
private RustService RustService { get; init; } = null!;
[Inject]
protected IJSRuntime JsRuntime { get; init; } = null!;
[Inject]
private IDialogService DialogService { get; init; } = null!;
@@ -21,107 +34,98 @@ public partial class PandocDialog : ComponentBase
private IMudDialogInstance MudDialog { get; set; } = null!;
private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger("PandocDialog");
private static readonly string LICENCE_URI = "https://raw.githubusercontent.com/jgm/pandoc/master/COPYRIGHT";
private static string PANDOC_VERSION = "1.0.0";
private static readonly string LICENCE_URI = "https://raw.githubusercontent.com/jgm/pandoc/refs/heads/main/COPYING.md";
private static string LATEST_PANDOC_VERSION = string.Empty;
private bool isPandocAvailable;
private bool showSkeleton;
private bool showInstallPage;
private PandocInstallation pandocInstallation;
private string? licenseText;
private bool isLoading;
private bool isLoadingLicence;
private bool isInstallationInProgress;
private int selectedInstallerIndex = SelectInstallerIndex();
private int selectedArchiveIndex = SelectArchiveIndex();
private string downloadUrlArchive = string.Empty;
private string downloadUrlInstaller = string.Empty;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
this.showSkeleton = true;
await this.CheckPandocAvailabilityAsync();
PANDOC_VERSION = await Pandoc.FetchLatestVersionAsync();
LATEST_PANDOC_VERSION = await Pandoc.FetchLatestVersionAsync();
await this.CheckPandocAvailabilityAsync(this.ShowInitialResultInSnackbar);
}
#endregion
private void Cancel() => this.MudDialog.Cancel();
private async Task CheckPandocAvailabilityAsync()
private async Task CheckPandocAvailabilityAsync(bool useSnackbar)
{
this.isPandocAvailable = await Pandoc.CheckAvailabilityAsync(this.RustService);
this.showSkeleton = false;
this.pandocInstallation = await Pandoc.CheckAvailabilityAsync(this.RustService, useSnackbar);
await this.InvokeAsync(this.StateHasChanged);
}
private async Task InstallPandocAsync()
{
this.isInstallationInProgress = true;
this.StateHasChanged();
await Pandoc.InstallAsync(this.RustService);
this.isInstallationInProgress = false;
this.MudDialog.Close(DialogResult.Ok(true));
await this.DialogService.ShowAsync<PandocDialog>("pandoc dialog");
await this.DialogService.ShowAsync<PandocDialog>("Pandoc Installation", DialogOptions.FULLSCREEN);
}
private void ProceedToInstallation() => this.showInstallPage = true;
private async Task GetInstaller()
{
var uri = await Pandoc.GenerateInstallerUriAsync();
var filename = this.FilenameFromUri(uri);
await this.JsRuntime.InvokeVoidAsync("triggerDownload", uri, filename);
}
private async Task GetArchive()
{
var uri = await Pandoc.GenerateUriAsync();
var filename = this.FilenameFromUri(uri);
await this.JsRuntime.InvokeVoidAsync("triggerDownload", uri, filename);
}
private void ProceedToInstallation() => this.ShowInstallationPage = true;
private async Task RejectLicense()
{
var message = "Pandoc is open-source and free of charge, but if you reject Pandoc's license, it can not be installed and some of AIStudios data retrieval features will be disabled (e.g. using Office files like Word)." +
"This decision can be revoked at any time. Are you sure you want to reject the license?";
var message = T("Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license?");
var dialogParameters = new DialogParameters
{
{ "Message", message },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Reject Pandoc's licence", dialogParameters, DialogOptions.FULLSCREEN);
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Reject Pandoc's Licence"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
dialogReference.Close();
else
this.Cancel();
}
private string FilenameFromUri(string uri)
private async Task WhenExpandingManualInstallation(bool isExpanded)
{
var index = uri.LastIndexOf('/');
return uri[(index + 1)..];
if(string.IsNullOrWhiteSpace(this.downloadUrlArchive))
this.downloadUrlArchive = await Pandoc.GenerateArchiveUriAsync();
if(string.IsNullOrWhiteSpace(this.downloadUrlInstaller))
this.downloadUrlInstaller = await Pandoc.GenerateInstallerUriAsync();
}
private async Task OnExpandedChanged(bool isExpanded)
private async Task WhenExpandingLicence(bool isExpanded)
{
if (isExpanded)
{
this.isLoading = true;
this.isLoadingLicence = true;
try
{
await Task.Delay(600);
this.licenseText = await this.LoadLicenseTextAsync();
}
catch (Exception ex)
{
this.licenseText = "Error loading license text, please consider following the links to read the GPL.";
LOG.LogError("Error loading GPL license text:\n{ErrorMessage}", ex.Message);
this.licenseText = T("Error loading license text, please consider following the links to read the GPL.");
LOG.LogError("Error loading GPL license text: {ErrorMessage}", ex.Message);
}
finally
{
this.isLoading = false;
this.isLoadingLicence = false;
}
}
else
{
await Task.Delay(350);
this.licenseText = string.Empty;
}
}
@@ -130,7 +134,34 @@ public partial class PandocDialog : ComponentBase
{
var response = await this.HttpClient.GetAsync(LICENCE_URI);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return content;
return await response.Content.ReadAsStringAsync();
}
// ReSharper disable RedundantSwitchExpressionArms
private static int SelectInstallerIndex() => CPU_ARCHITECTURE switch
{
RID.OSX_ARM64 => 1,
RID.OSX_X64 => 2,
RID.WIN_ARM64 => 0,
RID.WIN_X64 => 0,
_ => 0,
};
private static int SelectArchiveIndex() => CPU_ARCHITECTURE switch
{
RID.OSX_ARM64 => 1,
RID.OSX_X64 => 1,
RID.WIN_ARM64 => 0,
RID.WIN_X64 => 0,
RID.LINUX_ARM64 => 2,
RID.LINUX_X64 => 2,
_ => 0,
};
// ReSharper restore RedundantSwitchExpressionArms
}