@using Microsoft.AspNetCore.Components.Forms
Tracks
@if (AllowNewTracks)
{
}
@if (Tracks.Count == 0)
{
No tracks added yet.
}
else
{
@for (var i = 0; i < Tracks.Count; i++)
{
var index = i;
var row = Tracks[index];
SelectRow(index)">
@(index + 1).@row.TrackName
@StatusChip(row)
@* Replace audio: existing (persisted) rows only. New rows still pick their WAV
via the file input above, so a replace control there would be redundant. A
native
@if (row.Status == BatchRowStatus.Uploading)
{
}
}
}
@code {
[Parameter] public List Tracks { get; set; } = new();
[Parameter] public int SelectedIndex { get; set; }
[Parameter] public EventCallback SelectedIndexChanged { get; set; }
[Parameter] public bool Disabled { get; set; }
[Parameter] public bool AllowNewTracks { get; set; } = true;
///
/// Count of existing (persisted, Id-bearing) tracks in the list. When this is 1, the remove
/// control on the sole persisted row is suppressed so a release cannot be track-deleted to zero
/// (replace + release-level delete remain). New unsaved rows are excluded from this count.
///
[Parameter] public int ExistingTrackCount { get; set; }
[Parameter] public EventCallback> OnWavFilesSelected { get; set; }
[Parameter] public EventCallback OnMoveUp { get; set; }
[Parameter] public EventCallback OnMoveDown { get; set; }
[Parameter] public EventCallback OnRemove { get; set; }
///
/// Raised when the admin picks a replacement WAV for an existing row, carrying the list index and
/// the chosen file. Only fired for persisted (Id-bearing) rows.
///
[Parameter] public EventCallback<(int Index, IBrowserFile File)> OnReplaceFileSelected { get; set; }
// Stable per-row DOM id linking the swap-icon to its hidden InputFile.
private static string ReplaceInputId(int index) => $"replace-audio-input-{index}";
private const int MaxFilesPerPick = 50;
private Task SelectRow(int index) => SelectedIndexChanged.InvokeAsync(index);
private Task HandleWavFilesSelected(InputFileChangeEventArgs e) =>
OnWavFilesSelected.InvokeAsync(e.GetMultipleFiles(MaxFilesPerPick));
private string RowStyle(int index)
{
const string baseStyle = "cursor: pointer; border-radius: 4px;";
return index == SelectedIndex
? $"{baseStyle} background-color: var(--mud-palette-action-default-hover);"
: baseStyle;
}
private RenderFragment StatusChip(BatchRowModel row) => row.Status switch
{
BatchRowStatus.Uploading => @Uploading,
BatchRowStatus.Done => @Done,
BatchRowStatus.Failed => @Failed,
_ => @Queued
};
}