refine functionality of UI so far

This commit is contained in:
Alex
2025-08-28 22:54:00 -07:00
parent 5c6e144e8a
commit 6138c693bf
3 changed files with 39 additions and 28 deletions
+2 -2
View File
@@ -76,8 +76,8 @@ public class Song
e.Reading = Rubi; e.Reading = Rubi;
e.Artist = Artist; e.Artist = Artist;
e.BpmMessage = BpmMessage; e.BpmMessage = BpmMessage;
e.PreviewBegin = PreviewTime; e.PreviewBegin = PreviewTime*1000f;
e.PreviewLength = PreviewLen; e.PreviewLength = PreviewLen*1000f;
e.ClearThreshold = clearThreshold; e.ClearThreshold = clearThreshold;
e.Difficulty = diff; e.Difficulty = diff;
e.Level = l.Value.Item1; e.Level = l.Value.Item1;
+1 -1
View File
@@ -88,7 +88,7 @@ public class Exporter
/// JACKET /// /// JACKET ///
if (song.Jacket != null) if (song.Jacket != null)
File.Copy(song.Jacket, Path.Combine(exportSongPath, "jacket.png")); File.Copy(song.Jacket, Path.Combine(exportSongPath, "jacket.png"), true);
return new ExportResult { status = ExportResult.Status.Failed, message = "Unimplemented" }; return new ExportResult { status = ExportResult.Status.Failed, message = "Unimplemented" };
} }
+36 -25
View File
@@ -30,7 +30,6 @@ public partial class ExportRow : ObservableObject
{ {
private static Dictionary<ExportStatus, IImage?> StatusImgs = new() private static Dictionary<ExportStatus, IImage?> StatusImgs = new()
{ {
{ ExportStatus.NotStarted, null },
{ ExportStatus.Working, new Bitmap(Utils.AssetPath("imgs/status/indeterminate_spinner.png")) }, { ExportStatus.Working, new Bitmap(Utils.AssetPath("imgs/status/indeterminate_spinner.png")) },
{ ExportStatus.Error, new Bitmap(Utils.AssetPath("imgs/status/task_error.png")) }, { ExportStatus.Error, new Bitmap(Utils.AssetPath("imgs/status/task_error.png")) },
{ ExportStatus.Finished, new Bitmap(Utils.AssetPath("imgs/status/task_complete.png")) }, { ExportStatus.Finished, new Bitmap(Utils.AssetPath("imgs/status/task_complete.png")) },
@@ -40,16 +39,31 @@ public partial class ExportRow : ObservableObject
[ObservableProperty] [ObservableProperty]
private IImage? statusImg = null; private IImage? statusImg = null;
public required Song Song { get; set; } public required Song Song { get; set; }
public void SetStatus(ExportStatus status) public ExportStatus Status { set => StatusImg = StatusImgs.GetValueOrDefault(value, null); }
{
StatusImg = StatusImgs[status];
}
} }
public partial class Export : Panel public partial class Export : Panel
{ {
public ObservableCollection<ExportRow> Rows { get; } = new(); public ObservableCollection<ExportRow> Rows { get; } = new();
private bool _exporting = false;
private bool Exporting
{
get => _exporting;
set
{
_exporting = value;
Dispatcher.UIThread.Invoke(() =>
{
BtnExport.IsEnabled = !value;
ExportOptionsPane.IsEnabled = !value;
MainWindow.Instance!.TabSelection.IsEnabled = !value;
ExportSelectionPane.IsEnabled = !value;
});
}
}
public Export() public Export()
{ {
InitializeComponent(); InitializeComponent();
@@ -98,6 +112,8 @@ public partial class Export : Panel
private void UpdateRows() private void UpdateRows()
{ {
if (Exporting) return;
Console.WriteLine("Updating rows!"); Console.WriteLine("Updating rows!");
Rows.Clear(); Rows.Clear();
@@ -118,6 +134,8 @@ public partial class Export : Panel
/// </summary> /// </summary>
private void UpdateUIConditions() private void UpdateUIConditions()
{ {
if (Exporting) return;
ListSelectAudioConvertFormat.IsEnabled = (bool)RadioShouldAudioConvert.IsChecked!; ListSelectAudioConvertFormat.IsEnabled = (bool)RadioShouldAudioConvert.IsChecked!;
BtnExport.IsEnabled = BtnExport.IsEnabled =
@@ -134,7 +152,6 @@ public partial class Export : Panel
); );
var ffmpegAvail = Utils.IsFFMpegAvailable(); var ffmpegAvail = Utils.IsFFMpegAvailable();
Console.WriteLine($"FFMpeg available: {ffmpegAvail}");
if (!ffmpegAvail) if (!ffmpegAvail)
RadioLeaveAudioWAV.IsChecked = true; RadioLeaveAudioWAV.IsChecked = true;
RadioLeaveAudioWAV.IsEnabled = ffmpegAvail; RadioLeaveAudioWAV.IsEnabled = ffmpegAvail;
@@ -142,25 +159,13 @@ public partial class Export : Panel
NoFFMpegMessage.IsVisible = !ffmpegAvail; NoFFMpegMessage.IsVisible = !ffmpegAvail;
} }
private void UIExportingMode(bool isExporting)
{
Dispatcher.UIThread.Invoke(() =>
{
BtnExport.IsEnabled = !isExporting;
ExportOptionsPane.IsEnabled = !isExporting;
MainWindow.Instance!.TabSelection.IsEnabled = !isExporting;
ExportSelectionPane.IsEnabled = !isExporting;
});
}
private async void ExportFlow() private async void ExportFlow()
{ {
UIExportingMode(true); Exporting = true;
var path = await Utils.BeginDirSelection("Choose your export path...", Settings.I!.ExportPath); var path = await Utils.BeginDirSelection("Choose your export path...", Settings.I!.ExportPath);
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
{ {
UIExportingMode(false); Exporting = false;
return; return;
} }
Settings.I!.ExportPath = path; Settings.I!.ExportPath = path;
@@ -182,18 +187,24 @@ public partial class Export : Panel
}; };
}); });
// Reset statuses
Dispatcher.UIThread.Invoke(() => Rows.ToList().ForEach(row => row.Status = ExportStatus.NotStarted));
// process each song in parallel (for audio conversion) // process each song in parallel (for audio conversion)
Parallel.ForEach( // TODO: cancellable?
await Parallel.ForEachAsync(
Rows, Rows,
new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Settings.I!.ConcurrentExports) }, new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Settings.I!.ConcurrentExports) },
async row => async (row, cancelToken) =>
{ {
await Dispatcher.UIThread.InvokeAsync(() => row.SetStatus(ExportStatus.Working)); if (cancelToken.IsCancellationRequested) return;
await Dispatcher.UIThread.InvokeAsync(() => row.Status = ExportStatus.Working);
Exporter.Run(path, row.Song, options); Exporter.Run(path, row.Song, options);
await Dispatcher.UIThread.InvokeAsync(() => row.SetStatus(ExportStatus.Finished)); await Dispatcher.UIThread.InvokeAsync(() => row.Status = ExportStatus.Finished);
} }
); );
UIExportingMode(false); Exporting = false;
} }
} }