mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-02-13 06:01:37 +00:00
Inject PandocAvailabilityService and refactor its usage
This commit is contained in:
parent
85e0d7dd6c
commit
bb843fa812
@ -82,8 +82,11 @@
|
||||
}
|
||||
|
||||
<ChatTemplateSelection CanChatThreadBeUsedForTemplate="@this.CanThreadBeSaved" CurrentChatThread="@this.ChatThread" CurrentChatTemplate="@this.currentChatTemplate" CurrentChatTemplateChanged="@this.ChatTemplateWasChanged"/>
|
||||
|
||||
<AttachDocuments Name="File Attachments" @bind-DocumentPaths="@this.chatDocumentPaths" CatchAllDocuments="true" UseSmallForm="true"/>
|
||||
|
||||
@if (this.isPandocAvailable)
|
||||
{
|
||||
<AttachDocuments Name="File Attachments" @bind-DocumentPaths="@this.chatDocumentPaths" CatchAllDocuments="true" UseSmallForm="true"/>
|
||||
}
|
||||
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
{
|
||||
|
||||
@ -3,6 +3,7 @@ using AIStudio.Dialogs;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
@ -33,9 +34,12 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
[Inject]
|
||||
private ILogger<ChatComponent> Logger { get; set; } = null!;
|
||||
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private PandocAvailabilityService PandocAvailabilityService { get; init; } = null!;
|
||||
|
||||
private const Placement TOOLBAR_TOOLTIP_PLACEMENT = Placement.Top;
|
||||
private static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
@ -58,6 +62,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
private Guid currentWorkspaceId = Guid.Empty;
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
private HashSet<string> chatDocumentPaths = [];
|
||||
private bool isPandocAvailable;
|
||||
|
||||
// Unfortunately, we need the input field reference to blur the focus away. Without
|
||||
// this, we cannot clear the input field.
|
||||
@ -198,6 +203,10 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
// Select the correct provider:
|
||||
await this.SelectProviderWhenLoadingChat();
|
||||
|
||||
// Check if Pandoc is available (no dialog or messages):
|
||||
this.isPandocAvailable = await this.PandocAvailabilityService.IsAvailableAsync();
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public partial class ReadFileContent : MSGComponentBase
|
||||
@ -21,12 +18,15 @@ public partial class ReadFileContent : MSGComponentBase
|
||||
|
||||
[Inject]
|
||||
private RustService RustService { get; init; } = null!;
|
||||
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
|
||||
[Inject]
|
||||
private ILogger<ReadFileContent> Logger { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private PandocAvailabilityService PandocAvailabilityService { get; init; } = null!;
|
||||
|
||||
private async Task SelectFile()
|
||||
{
|
||||
@ -57,24 +57,9 @@ public partial class ReadFileContent : MSGComponentBase
|
||||
}
|
||||
|
||||
// Ensure that Pandoc is installed and ready:
|
||||
var pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showSuccessMessage: false);
|
||||
if (!pandocState.IsAvailable)
|
||||
{
|
||||
var dialogParameters = new DialogParameters<PandocDialog>
|
||||
{
|
||||
{ x => x.ShowInitialResultInSnackbar, false },
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<PandocDialog>(T("Pandoc Installation"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||
await dialogReference.Result;
|
||||
|
||||
pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showSuccessMessage: true);
|
||||
if (!pandocState.IsAvailable)
|
||||
{
|
||||
this.Logger.LogError("Pandoc is not available after installation attempt.");
|
||||
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Cancel, T("Pandoc may be required for importing files.")));
|
||||
}
|
||||
}
|
||||
await this.PandocAvailabilityService.EnsureAvailabilityAsync(
|
||||
showSuccessMessage: false,
|
||||
showDialog: true);
|
||||
|
||||
var fileContent = await this.RustService.ReadArbitraryFileData(selectedFile.SelectedFilePath, int.MaxValue);
|
||||
await this.FileContentChanged.InvokeAsync(fileContent);
|
||||
|
||||
@ -126,6 +126,7 @@ internal sealed class Program
|
||||
builder.Services.AddSingleton<SettingsManager>();
|
||||
builder.Services.AddSingleton<ThreadSafeRandom>();
|
||||
builder.Services.AddSingleton<DataSourceService>();
|
||||
builder.Services.AddScoped<PandocAvailabilityService>();
|
||||
builder.Services.AddTransient<HTMLParser>();
|
||||
builder.Services.AddTransient<AgentDataSourceSelection>();
|
||||
builder.Services.AddTransient<AgentRetrievalContextValidation>();
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
|
||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||
|
||||
namespace AIStudio.Tools.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Service to check Pandoc availability and ensure installation.
|
||||
/// This service encapsulates the logic for checking if Pandoc is installed
|
||||
/// and showing the installation dialog if needed.
|
||||
/// </summary>
|
||||
public sealed class PandocAvailabilityService(RustService rustService, IDialogService dialogService, ILogger<PandocAvailabilityService> logger)
|
||||
{
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PandocAvailabilityService).Namespace, nameof(PandocAvailabilityService));
|
||||
|
||||
private RustService RustService => rustService;
|
||||
|
||||
private IDialogService DialogService => dialogService;
|
||||
|
||||
private ILogger<PandocAvailabilityService> Logger => logger;
|
||||
|
||||
private PandocInstallation? cachedInstallation;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if Pandoc is available and shows the installation dialog if needed.
|
||||
/// </summary>
|
||||
/// <param name="showSuccessMessage">Whether to show a success message if Pandoc is available.</param>
|
||||
/// <param name="showDialog">Whether to show the installation dialog if Pandoc is not available.</param>
|
||||
/// <returns>The Pandoc installation state.</returns>
|
||||
public async Task<PandocInstallation> EnsureAvailabilityAsync(bool showSuccessMessage = false, bool showDialog = true)
|
||||
{
|
||||
// Check if Pandoc is available:
|
||||
var pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showMessages: false, showSuccessMessage: showSuccessMessage);
|
||||
|
||||
// Cache the result:
|
||||
this.cachedInstallation = pandocState;
|
||||
|
||||
// If not available, show installation dialog:
|
||||
if (!pandocState.IsAvailable && showDialog)
|
||||
{
|
||||
var dialogParameters = new DialogParameters<PandocDialog>
|
||||
{
|
||||
{ x => x.ShowInitialResultInSnackbar, false },
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<PandocDialog>(TB("Pandoc Installation"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||
await dialogReference.Result;
|
||||
|
||||
// Re-check availability after dialog:
|
||||
pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showMessages: showSuccessMessage, showSuccessMessage: showSuccessMessage);
|
||||
this.cachedInstallation = pandocState;
|
||||
|
||||
if (!pandocState.IsAvailable)
|
||||
{
|
||||
this.Logger.LogError("Pandoc is not available after installation attempt.");
|
||||
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Cancel, TB("Pandoc may be required for importing files.")));
|
||||
}
|
||||
}
|
||||
|
||||
return pandocState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if Pandoc is available without showing any dialogs or messages.
|
||||
/// Uses cached result if available to avoid redundant checks.
|
||||
/// </summary>
|
||||
/// <returns>True if Pandoc is available, false otherwise.</returns>
|
||||
public async Task<bool> IsAvailableAsync()
|
||||
{
|
||||
if (this.cachedInstallation.HasValue)
|
||||
return this.cachedInstallation.Value.IsAvailable;
|
||||
|
||||
var pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showMessages: false, showSuccessMessage: false);
|
||||
this.cachedInstallation = pandocState;
|
||||
|
||||
return pandocState.IsAvailable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the cached Pandoc installation state.
|
||||
/// Useful when the installation state might have changed.
|
||||
/// </summary>
|
||||
public void ClearCache() => this.cachedInstallation = null;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user