feat(ui): constrain decimal input and add stacked timed toasts with uniform actions

This commit is contained in:
2026-11-02 19:19:07 +01:00
parent 22e509d982
commit 86a73b862a
24 changed files with 315 additions and 103 deletions
@@ -1,40 +1,19 @@
@inject ToastService Toasts
@inject IFileSaveService FileSaveService
@if (Result != null)
{
<div class="alert @(Result.Status == FileOperationStatus.Error ? "alert-danger" : Result.Status == FileOperationStatus.Success ? "alert-success" : "alert-info")" role="status" aria-live="polite" aria-atomic="true">
<p>@Result.Message</p>
@if (Result.Path != null)
{
<p class="text-break">@Result.Path</p>
<button class="btn btn-outline-secondary" disabled="@busy" @onclick="OpenFolder">Ordner öffnen</button>
}
@if (Result.Details != null)
{
<details><summary>Technische Details</summary><p class="text-break">@Result.Details</p></details>
}
@if (openResult != null)
{
<p role="alert">@openResult.Message</p>
@if (openResult.Details != null) { <details><summary>Technische Details</summary>@openResult.Details</details> }
}
</div>
}
@code {
[Parameter] public FileOperationResult? Result { get; set; }
private FileOperationResult? openResult;
private FileOperationResult? previous;
private bool busy;
protected override void OnParametersSet()
{
if (previous != Result) { openResult = null; previous = Result; }
}
private async Task OpenFolder()
{
if (busy || Result?.Path == null) return;
busy = true;
try { openResult = await FileSaveService.OpenFolderAsync(Result.Path); }
finally { busy = false; }
if (Result == null || ReferenceEquals(previous, Result)) return;
previous = Result;
var result = Result;
Toasts.Show(result.Message + (result.Path != null ? " " + result.Path : ""),
result.Status == FileOperationStatus.Error ? ToastKind.Error : result.Status == FileOperationStatus.Success ? ToastKind.Success : ToastKind.Info,
result.Details, result.Path != null ? "Ordner öffnen" : null,
result.Path != null ? async () => {
var opened = await FileSaveService.OpenFolderAsync(result.Path);
Toasts.Show(opened.Message, opened.Status == FileOperationStatus.Error ? ToastKind.Error : ToastKind.Info, opened.Details);
} : null);
}
}