Files
AI-Studio/app/MindWork AI Studio/Components/SelectFile.razor.cs
T

108 lines
3.2 KiB
C#

using AIStudio.Tools.Rust;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
public partial class SelectFile : MSGComponentBase
{
[Parameter]
public string File { get; set; } = string.Empty;
[Parameter]
public EventCallback<string> FileChanged { get; set; }
[Parameter]
public bool Disabled { get; set; }
[Parameter]
public string Label { get; set; } = string.Empty;
[Parameter]
public string FileDialogTitle { get; set; } = "Select File";
[Parameter]
public FileTypeFilter[]? Filter { get; set; }
[Parameter]
public Func<string, string?> Validation { get; set; } = _ => null;
/// <summary>
/// When true, the file can also be chosen by dropping it onto this component.
/// </summary>
[Parameter]
public bool EnableDragDrop { get; set; }
/// <summary>
/// Makes this component the default target of its area, meaning of its page, assistant, or
/// dialog: it then also takes the drops which land anywhere in that area without hitting a zone
/// of their own.
/// </summary>
[Parameter]
public bool CatchAllDocuments { get; set; }
[Inject]
public RustService RustService { get; set; } = null!;
[Inject]
protected ILogger<SelectFile> Logger { get; init; } = null!;
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
private bool isFileDialogOpen;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
// Configure the spellchecking for the instance name input:
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
await base.OnInitializedAsync();
}
#endregion
private void InternalFileChanged(string file)
{
this.File = file;
this.FileChanged.InvokeAsync(file);
}
private async Task OpenFileDialog()
{
if (this.isFileDialogOpen)
return;
this.isFileDialogOpen = true;
try
{
var response = await this.RustService.SelectFile(this.FileDialogTitle, this.Filter, string.IsNullOrWhiteSpace(this.File) ? null : this.File);
this.Logger.LogInformation("The user selected the file '{SelectedFilePath}'.", response.SelectedFilePath);
if (!response.UserCancelled)
this.InternalFileChanged(response.SelectedFilePath);
}
finally
{
this.isFileDialogOpen = false;
}
}
/// <summary>
/// Takes the first dropped path which leads to a usable file.
/// </summary>
/// <param name="paths">The dropped paths.</param>
private async Task PathsDropped(List<string> paths)
{
var path = DroppedFile.FirstUsable(paths, this.Filter);
if (path is null)
{
this.Logger.LogWarning("None of the {Count} dropped path(s) could be used as a file.", paths.Count);
await this.MessageBus.SendWarning(new(Icons.Material.Filled.Warning, DroppedFile.WarningFor(paths)));
return;
}
this.Logger.LogInformation("The user dropped the file '{DroppedFilePath}'.", path);
this.InternalFileChanged(path);
}
}