Finished dialog and download of installers and archives

This commit is contained in:
nilsk 2025-05-27 01:11:54 +02:00
parent cecf777827
commit 012b28da27
5 changed files with 115 additions and 52 deletions

View File

@ -1,4 +1,4 @@
<MudTabs @bind-ActivePanelIndex="selectedIndex" PanelClass="code-block" MinimumTabWidth="30px">
<MudTabs @bind-ActivePanelIndex="selectedIndex" PanelClass="code-block" MinimumTabWidth="30px" Class="mt-2">
@foreach (var block in blocks)
{
<MudTabPanel Text="@block.Title">

View File

@ -33,39 +33,44 @@
</MudExpansionPanels>
</div>
<MudExpansionPanels Class="mb-3" MultiExpansion="@false" Outlined="false" Elevation="0">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.AutoFixHigh" HeaderText="Automatic Installation" IsExpanded="true">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.AutoFixHigh" HeaderText="Automatic installation" IsExpanded="true">
<MudText Typo="Typo.caption">
Pandoc is distributed under the
<MudLink Typo="Typo.caption" Href="https://github.com/jgm/pandoc/blob/main/COPYRIGHT"
Target="_blank">GNU General Public License v2 (GPL)
</MudLink>
.
<MudLink Typo="Typo.caption" Href="https://github.com/jgm/pandoc/blob/main/COPYRIGHT" Target="_blank">GNU General Public License v2 (GPL)</MudLink>.
By clicking "Accept GPL and Install", you agree to the terms of the GPL license <br/> and Pandoc
will be installed automatically for you.<br/>
</MudText>
<MudButton Color="Color.Primary" Class="mt-4" Variant="Variant.Filled" Size="Size.Small"
StartIcon="@Icons.Material.Filled.InstallDesktop">Accept GPL and Install
<MudButton OnClick="InstallPandocAsync" Color="Color.Primary" Class="mt-4" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.InstallDesktop">
Accept GPL and Install
</MudButton>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Build" HeaderText="Manual Installation">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Build" HeaderText="Manual installation">
<MudText Class="mb-2">
If you prefer to install Pandoc yourself, please follow one of these two guides. Installers are only available for Windows and Mac.
</MudText>
<MudExpansionPanels Outlined="false" Elevation="0">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.AppRegistration" HeaderText="Download with Installer" IsExpanded="true">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.AppRegistration" HeaderText="Download with installer" IsExpanded="true">
<MudList T="string">
<MudListItem T="string" Class="mb-4">
Accept the terms of the GPL license and download the latest installer with the download button below.
Eventually you need to allow the download of the installer in the download window.
<CodeTabs>
<CodeBlock Title="Windows">pandoc-3.7.0-windows-x86_64.msi</CodeBlock>
<CodeBlock Title="Mac OS x86">pandoc-3.7.0.1-x86_64-macOS.pkg</CodeBlock>
<CodeBlock Title="Mac OS ARM">pandoc-3.7.0.1-arm64-macOS.pkg</CodeBlock>
<CodeBlock Title="Windows">pandoc-@(PANDOC_VERSION)-windows-x86_64.msi</CodeBlock>
<CodeBlock Title="Mac OS x86">pandoc-@(PANDOC_VERSION)-x86_64-macOS.pkg</CodeBlock>
<CodeBlock Title="Mac OS ARM">pandoc-@(PANDOC_VERSION)-arm64-macOS.pkg</CodeBlock>
</CodeTabs>
</MudListItem>
<MudListItem T="string">
Execute the installer and follow the instructions.
</MudListItem>
</MudList>
<MudText Class="mb-3" Typo="Typo.caption">
Pandoc is distributed under the <MudLink Typo="Typo.caption" Href="https://github.com/jgm/pandoc/blob/main/COPYRIGHT" Target="_blank">GNU General Public License v2 (GPL)</MudLink>.
By clicking "Accept GPL and download installer", you agree to the terms of the GPL license.<br/>
</MudText>
<MudButton OnClick="@this.GetInstaller" Color="Color.Secondary" Class="mt-4" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Downloading">
Accept GPL and download installer
</MudButton>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Outlined.Archive" HeaderText="Download with archive">
<MudList T="string">
@ -81,36 +86,31 @@
</CodeTabs>
</MudListItem>
<MudListItem T="string" Class="mb-4">
Open the folder and copy the full path to the <code>pandoc.exe</code> file into you
Open the folder and copy the full path to the <CodeBlock IsInline="@true">pandoc.exe</CodeBlock> file into your
clipboard.
<CodeTabs>
<CodeBlock Title="Windows">C:\Users\%USERNAME%\pandoc\pandoc-3.7.0-windows-x86_64\pandoc-3.7.0</CodeBlock>
<CodeBlock Title="Mac OS">/usr/local/bin/pandoc/pandoc-3.7.0-x86_64-macOS/pandoc-3.7.0</CodeBlock>
<CodeBlock Title="Linux">/usr/local/bin/pandoc/pandoc-3.7.0-linux-amd64/pandoc-3.7.0</CodeBlock>
<CodeBlock Title="Windows">C:\Users\%USERNAME%\pandoc\pandoc-@(PANDOC_VERSION)</CodeBlock>
<CodeBlock Title="Mac OS">/usr/local/bin/pandoc/pandoc-@(PANDOC_VERSION)</CodeBlock>
<CodeBlock Title="Linux">/usr/local/bin/pandoc/pandoc-@(PANDOC_VERSION)</CodeBlock>
</CodeTabs>
</MudListItem>
<MudListItem T="string">
Add the copied path to your systems environment variables and check the installation
by typing
<CodeBlock IsInline="@true">pandoc --version</CodeBlock>
by typing <br/><CodeBlock IsInline="@true">pandoc --version</CodeBlock>
into your command line interface.
<CodeTabs>
<CodeBlock Title="Windows">> pandoc.exe --version<br/>> pandoc.exe 3.7.0</CodeBlock>
<CodeBlock Title="Mac OS">> pandoc --version<br/>> pandoc.exe 3.7.0</CodeBlock>
<CodeBlock Title="Linux">> pandoc --version<br/>> pandoc.exe 3.7.0</CodeBlock>
<CodeBlock Title="Windows">> pandoc.exe --version<br/>> pandoc.exe @(PANDOC_VERSION)</CodeBlock>
<CodeBlock Title="Mac OS">> pandoc --version<br/>> pandoc.exe @(PANDOC_VERSION)</CodeBlock>
<CodeBlock Title="Linux">> pandoc --version<br/>> pandoc.exe @(PANDOC_VERSION)</CodeBlock>
</CodeTabs>
</MudListItem>
</MudList>
<MudText Class="mb-3" Typo="Typo.caption">
Pandoc is distributed under the
<MudLink Typo="Typo.caption" Href="https://github.com/jgm/pandoc/blob/main/COPYRIGHT"
Target="_blank">GNU General Public License v2 (GPL)
</MudLink>
.
By clicking "Accept GPL and Download", you agree to the terms of the GPL license.
Pandoc is distributed under the <MudLink Typo="Typo.caption" Href="https://github.com/jgm/pandoc/blob/main/COPYRIGHT" Target="_blank">GNU General Public License v2 (GPL)</MudLink>.
By clicking "Accept GPL and archive", you agree to the terms of the GPL license.<br/>
</MudText>
<MudButton Color="Color.Secondary" Class="mt-4" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Downloading">
Accept GPL and Download
<MudButton OnClick="@this.GetArchive" Color="Color.Secondary" Class="mt-4" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Downloading">
Accept GPL and download archive
</MudButton>
</ExpansionPanel>
</MudExpansionPanels>
@ -122,8 +122,7 @@
}
else
{
<MudItem Class="pa-6"
Style="height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;">
<MudItem Class="px-8 py-2" Style="height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;">
@if (showSkeleton)
{
<MudSkeleton SkeletonType="SkeletonType.Circle" Animation="Animation.Pulse" Class="mb-4"
@ -141,14 +140,12 @@
}
else
{
<MudIcon Class="mb-2" Style="width: 2.5em; height: 2.5em;" Icon="@Icons.Material.Filled.Error"
Color="Color.Error"/>
<MudText Class="mb-2" Typo="Typo.subtitle1" Align="Align.Center">
<MudIcon Class="mb-2" Style="width: 3.5em; height: 3.5em;" Icon="@Icons.Material.Filled.Error" Color="Color.Error"/>
<MudText Class="mb-6" Typo="Typo.subtitle1" Align="Align.Center">
Pandoc ist auf Ihrem System nicht verfügbar
</MudText>
<MudButton Color="Color.Primary" OnClick="@this.ProceedToInstallation" Variant="Variant.Filled">
Proceed
to installation
Proceed to installation
</MudButton>
}
</MudItem>

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Dialogs;
@ -7,10 +8,17 @@ public partial class PandocDialog : ComponentBase
[Inject]
private HttpClient HttpClient { get; set; } = null!;
[Inject]
private RustService RustService { get; init; } = null!;
[Inject]
protected IJSRuntime JsRuntime { get; init; } = null!;
[CascadingParameter]
private IMudDialogInstance MudDialog { get; set; } = null!;
private static readonly string LICENCE_URI = "https://raw.githubusercontent.com/jgm/pandoc/master/COPYRIGHT";
private static string PANDOC_VERSION = "1.0.0";
private bool isPandocAvailable;
private bool showSkeleton;
@ -25,6 +33,7 @@ public partial class PandocDialog : ComponentBase
await base.OnInitializedAsync();
this.showSkeleton = true;
await this.CheckPandocAvailabilityAsync();
PANDOC_VERSION = await Pandoc.FetchLatestVersionAsync();
}
#endregion
@ -33,13 +42,36 @@ public partial class PandocDialog : ComponentBase
private async Task CheckPandocAvailabilityAsync()
{
this.isPandocAvailable = await Pandoc.CheckAvailabilityAsync();
this.isPandocAvailable = await Pandoc.CheckAvailabilityAsync(false);
this.showSkeleton = false;
await this.InvokeAsync(this.StateHasChanged);
}
private async Task InstallPandocAsync() => await Pandoc.InstallAsync(this.RustService);
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 string FilenameFromUri(string uri)
{
var index = uri.LastIndexOf('/');
return uri[(index + 1)..];
}
private async Task OnExpandedChanged(bool newVal)
{
if (newVal)
@ -53,8 +85,7 @@ public partial class PandocDialog : ComponentBase
}
catch (Exception ex)
{
Console.WriteLine($"Fehler beim Laden des Lizenztexts: {ex.Message}");
this.licenseText = "Fehler beim Laden des Lizenztexts.";
this.licenseText = "Error loading license text, please consider following the links to the GPL.";
}
finally
{

View File

@ -10,7 +10,7 @@ namespace AIStudio.Tools;
public static partial class Pandoc
{
private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger("PluginFactory");
private static readonly string DOWNLOAD_URL = "https://github.com/jgm/pandoc/releases/download/";
private static readonly string DOWNLOAD_URL = "https://github.com/jgm/pandoc/releases/download";
private static readonly string LATEST_URL = "https://github.com/jgm/pandoc/releases/latest";
private static readonly Version MINIMUM_REQUIRED_VERSION = new (3, 6);
private static readonly Version FALLBACK_VERSION = new (3, 6, 4);
@ -20,7 +20,7 @@ public static partial class Pandoc
/// Checks if pandoc is available on the system and can be started as a process
/// </summary>
/// <returns>True, if pandoc is available and the minimum required version is met, else False.</returns>
public static async Task<bool> CheckAvailabilityAsync()
public static async Task<bool> CheckAvailabilityAsync(bool showMessages = true)
{
try
{
@ -35,6 +35,7 @@ public static partial class Pandoc
using var process = Process.Start(startInfo);
if (process == null)
{
if (showMessages)
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Help, "The pandoc process could not be started."));
LOG.LogInformation("The pandoc process was not started, it was null");
return false;
@ -44,6 +45,7 @@ public static partial class Pandoc
await process.WaitForExitAsync();
if (process.ExitCode != 0)
{
if (showMessages)
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, $"The pandoc process exited unexpectedly."));
LOG.LogError("The pandoc process was exited with code {ProcessExitCode}", process.ExitCode);
return false;
@ -52,6 +54,7 @@ public static partial class Pandoc
var versionMatch = PandocRegex().Match(output);
if (!versionMatch.Success)
{
if (showMessages)
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"pandoc --version returned an invalid format."));
LOG.LogError("pandoc --version returned an invalid format:\n {Output}", output);
return false;
@ -63,10 +66,12 @@ public static partial class Pandoc
if (installedVersion >= MINIMUM_REQUIRED_VERSION)
{
if (showMessages)
await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, $"Pandoc {installedVersion.ToString()} is installed."));
return true;
}
if (showMessages)
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Build, $"Pandoc {installedVersion.ToString()} is installed, but it doesn't match the required version ({MINIMUM_REQUIRED_VERSION.ToString()})."));
LOG.LogInformation("Pandoc {Installed} is installed, but it does not match the required version ({Requirement})", installedVersion.ToString(), MINIMUM_REQUIRED_VERSION.ToString());
return false;
@ -74,6 +79,7 @@ public static partial class Pandoc
}
catch (Exception e)
{
if (showMessages)
await MessageBus.INSTANCE.SendError(new (@Icons.Material.Filled.AppsOutage, "Pandoc is not installed."));
LOG.LogError("Pandoc is not installed and threw an exception:\n {Message}", e.Message);
return false;
@ -177,7 +183,7 @@ public static partial class Pandoc
}
// win arm not available
private static async Task<string> GenerateUriAsync()
public static async Task<string> GenerateUriAsync()
{
var version = await FetchLatestVersionAsync();
var baseUri = $"{DOWNLOAD_URL}/{version}/pandoc-{version}-";
@ -192,6 +198,25 @@ public static partial class Pandoc
};
}
public static async Task<string> GenerateInstallerUriAsync()
{
var version = await FetchLatestVersionAsync();
var baseUri = $"{DOWNLOAD_URL}/{version}/pandoc-{version}-";
switch (CPU_ARCHITECTURE)
{
case "win-x64":
return $"{baseUri}windows-x86_64.msi";
case "osx-x64":
return $"{baseUri}x86_64-macOS.pkg";
case "osx-arm64":
return $"{baseUri}arm64-macOS.pkg\n";
default:
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"Installers are not available on {CPU_ARCHITECTURE} systems."));
return string.Empty;
}
}
/// <summary>
/// Returns the name of the pandoc executable based on the running operating system
/// </summary>
@ -200,6 +225,6 @@ public static partial class Pandoc
[GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+)")]
private static partial Regex PandocRegex();
[GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+\.[0-9]+)")]
[GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+\.[0-9]+(?:\.[0-9]+)?)")]
private static partial Regex VersionRegex();
}

View File

@ -26,3 +26,13 @@ window.clearDiv = function (divName) {
window.scrollToBottom = function(element) {
element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
}
window.triggerDownload = function(url, filename) {
const a = document.createElement('a');
a.href = url;
a.setAttribute('download', filename);
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}