From 27173104b5f0a05c4f3184def7076fe1df790d86 Mon Sep 17 00:00:00 2001 From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:19:42 +0100 Subject: [PATCH 1/3] remove sections --- .../Model/AudioCuesheet/Cuesheet.cs | 38 --- .../Model/IO/Export/CuesheetSection.cs | 217 ------------------ .../Model/Options/ExportOptions.cs | 2 +- .../Services/IO/CuesheetExportService.cs | 88 +++---- .../Services/IO/ExportfileGenerator.cs | 92 +++----- .../Services/IO/ImportManager.cs | 7 - AudioCuesheetEditor/Services/Result.cs | 117 ++++++++++ .../Shared/Cuesheet/EditSections.de.resx | 150 ------------ .../Shared/Cuesheet/EditSections.razor | 154 ------------- .../Shared/Cuesheet/EditSections.resx | 150 ------------ .../Dialogs/GenerateCuesheetDialog.razor | 37 +-- .../Dialogs/GenerateExportDialog.de.resx | 16 +- .../Shared/Dialogs/GenerateExportDialog.razor | 65 ++---- .../Shared/Dialogs/GenerateExportDialog.resx | 16 +- .../Shared/TrackList/TrackList.de.resx | 6 - .../Shared/TrackList/TrackList.razor | 6 - .../Shared/TrackList/TrackList.resx | 6 - .../Shared/ViewModes/ViewModeFull.de.resx | 3 - .../Shared/ViewModes/ViewModeFull.razor | 9 - .../Shared/ViewModes/ViewModeFull.resx | 3 - 20 files changed, 223 insertions(+), 959 deletions(-) delete mode 100644 AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs create mode 100644 AudioCuesheetEditor/Services/Result.cs delete mode 100644 AudioCuesheetEditor/Shared/Cuesheet/EditSections.de.resx delete mode 100644 AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor delete mode 100644 AudioCuesheetEditor/Shared/Cuesheet/EditSections.resx diff --git a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs index c0501fdf..d4c73211 100644 --- a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs +++ b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs @@ -15,7 +15,6 @@ //. using AudioCuesheetEditor.Model.Entity; using AudioCuesheetEditor.Model.IO.Audio; -using AudioCuesheetEditor.Model.IO.Export; using AudioCuesheetEditor.Model.UI; using System.Text.Json.Serialization; @@ -43,7 +42,6 @@ public class Cuesheet() : Validateable, ITraceable, ICuesheet private CDTextfile? cDTextfile; private String? catalogueNumber; private readonly List> currentlyHandlingLinkedTrackPropertyChange = []; - private List sections = []; public event EventHandler? TraceablePropertyChanged; public event EventHandler? IsRecordingChanged; @@ -151,42 +149,6 @@ public IEnumerable IsRecordingPossible [JsonIgnore] public Boolean IsImporting { get; set; } - - [JsonInclude] - public IReadOnlyCollection Sections - { - get => sections; - private set - { - foreach(var section in value.Where(x => x.Cuesheet != this)) - { - section.Cuesheet = this; - } - sections = [.. value]; - } - } - - public CuesheetSection AddSection() - { - var previousValue = new List(sections); - var section = new CuesheetSection(this); - sections.Add(section); - OnTraceablePropertyChanged(previousValue, nameof(Sections)); - return section; - } - - public void RemoveSections(IEnumerable sectionsToRemove) - { - var previousValue = new List(sections); - var intersection = sections.Intersect(sectionsToRemove); - sections = [.. sections.Except(intersection)]; - OnTraceablePropertyChanged(previousValue, nameof(Sections)); - } - - public CuesheetSection? GetSection(Track track) - { - return Sections?.FirstOrDefault(x => track.Begin <= x.Begin && track.End >= x.Begin); - } /// /// Get the previous linked track of a track object diff --git a/AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs b/AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs deleted file mode 100644 index 534b65d3..00000000 --- a/AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs +++ /dev/null @@ -1,217 +0,0 @@ -//This file is part of AudioCuesheetEditor. - -//AudioCuesheetEditor is free software: you can redistribute it and/or modify -//it under the terms of the GNU General Public License as published by -//the Free Software Foundation, either version 3 of the License, or -//(at your option) any later version. - -//AudioCuesheetEditor is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. - -//You should have received a copy of the GNU General Public License -//along with Foobar. If not, see -//. -using AudioCuesheetEditor.Model.AudioCuesheet; -using AudioCuesheetEditor.Model.Entity; -using AudioCuesheetEditor.Model.UI; -using System.Text.Json.Serialization; - -namespace AudioCuesheetEditor.Model.IO.Export -{ - public class CuesheetSection : Validateable, ITraceable - { - private Cuesheet? cuesheet; - private TimeSpan? begin; - private TimeSpan? end; - private String? artist; - private String? title; - private String? audiofileName; - - public event EventHandler? TraceablePropertyChanged; - - public CuesheetSection(Cuesheet cuesheet) - { - Cuesheet = cuesheet; - artist = Cuesheet.Artist; - title = Cuesheet.Title; - audiofileName = Cuesheet.Audiofile?.Name; - //Try to set begin - begin = Cuesheet.Sections?.LastOrDefault()?.End; - if (Begin.HasValue == false) - { - begin = Cuesheet.Tracks.Min(x => x.Begin); - } - end = Cuesheet.Tracks.Max(x => x.End); - } - - [JsonConstructor] - public CuesheetSection() { } - public Cuesheet? Cuesheet - { - get => cuesheet; - set - { - if (cuesheet == null) - { - cuesheet = value; - } - else - { - throw new InvalidOperationException(); - } - } - } - - public String? Artist - { - get => artist; - set - { - var previousValue = artist; - artist = value; - OnValidateablePropertyChanged(nameof(Artist)); - OnTraceablePropertyChanged(previousValue, nameof(Artist)); - } - } - - public String? Title - { - get => title; - set - { - var previousValue = title; - title = value; - OnValidateablePropertyChanged(nameof(Title)); - OnTraceablePropertyChanged(previousValue, nameof(Title)); - } - } - - public TimeSpan? Begin - { - get => begin; - set - { - var previousValue = begin; - begin = value; - OnValidateablePropertyChanged(nameof(Begin)); - OnTraceablePropertyChanged(previousValue, nameof(Begin)); - } - } - - public TimeSpan? End - { - get => end; - set - { - var previousValue = end; - end = value; - OnValidateablePropertyChanged(nameof(End)); - OnTraceablePropertyChanged(previousValue, nameof(End)); - } - } - - public String? AudiofileName - { - get => audiofileName; - set - { - var previousValue = audiofileName; - audiofileName = value; - OnValidateablePropertyChanged(nameof(AudiofileName)); - OnTraceablePropertyChanged(previousValue, nameof(AudiofileName)); - } - } - - public void CopyValues(CuesheetSection splitPoint) - { - Artist = splitPoint.Artist; - Title = splitPoint.Title; - Begin = splitPoint.Begin; - } - - public override ValidationResult Validate(string property) - { - ValidationStatus validationStatus = ValidationStatus.NoValidation; - List? validationMessages = null; - switch (property) - { - case nameof(Begin): - validationStatus = ValidationStatus.Success; - if (Begin == null) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(Begin))); - } - else - { - var minBegin = Cuesheet?.Tracks.Min(x => x.Begin); - if (Begin < minBegin) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} should be greater than or equal '{1}'!", nameof(Begin), minBegin)); - } - if (Begin > End) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} should be less than or equal '{1}'!", nameof(Begin), End)); - } - } - break; - case nameof(End): - validationStatus = ValidationStatus.Success; - if (End == null) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(End))); - } - else - { - var maxEnd = Cuesheet?.Tracks.Max(x => x.End); - if (End > maxEnd) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} should be less than or equal '{1}'!", nameof(End), maxEnd)); - } - if (End < Begin) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} should be greater than or equal '{1}'!", nameof(End), Begin)); - } - } - break; - case nameof(Artist): - validationStatus = ValidationStatus.Success; - if (String.IsNullOrEmpty(Artist)) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(Artist))); - } - break; - case nameof(Title): - validationStatus = ValidationStatus.Success; - if (String.IsNullOrEmpty(Title)) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(Title))); - } - break; - case nameof(AudiofileName): - validationStatus = ValidationStatus.Success; - if (String.IsNullOrEmpty(AudiofileName)) - { - validationMessages ??= []; - validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(AudiofileName))); - } - break; - } - return ValidationResult.Create(validationStatus, validationMessages); - } - - private void OnTraceablePropertyChanged(object? previousValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") - { - TraceablePropertyChanged?.Invoke(this, new TraceablePropertiesChangedEventArgs(new TraceableChange(previousValue, propertyName))); - } - } -} diff --git a/AudioCuesheetEditor/Model/Options/ExportOptions.cs b/AudioCuesheetEditor/Model/Options/ExportOptions.cs index dfa267a2..3f8457ac 100644 --- a/AudioCuesheetEditor/Model/Options/ExportOptions.cs +++ b/AudioCuesheetEditor/Model/Options/ExportOptions.cs @@ -60,7 +60,7 @@ public ExportOptions() public ExportOptions(ICollection exportProfiles, Guid? selectedProfileId = null) { ExportProfiles = exportProfiles; - SelectedProfileId = selectedProfileId ?? ExportProfiles.First().Id; + SelectedProfileId = selectedProfileId ?? ExportProfiles.FirstOrDefault()?.Id; } public ICollection ExportProfiles { get; set; } [JsonIgnore] diff --git a/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs b/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs index 835cad77..eefeac07 100644 --- a/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs +++ b/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs @@ -17,16 +17,19 @@ using AudioCuesheetEditor.Model.Entity; using AudioCuesheetEditor.Model.IO; using AudioCuesheetEditor.Model.IO.Export; +using AudioCuesheetEditor.Model.IO.Import; using AudioCuesheetEditor.Services.UI; +using Microsoft.Extensions.Localization; using System.Text; namespace AudioCuesheetEditor.Services.IO { - public class CuesheetExportService(ISessionStateContainer sessionStateContainer) + public class CuesheetExportService(ISessionStateContainer sessionStateContainer, IStringLocalizer localizer) { private readonly ISessionStateContainer _sessionStateContainer = sessionStateContainer; + private readonly IStringLocalizer _localizer = localizer; - public IEnumerable CanGenerateExportfiles(string? filename) + public Result CanGenerateExportfile(string? filename) { List validationMessages = []; var extension = Path.GetExtension(filename); @@ -37,52 +40,36 @@ public IEnumerable CanGenerateExportfiles(string? filename) } validationMessages.AddRange(_sessionStateContainer.Cuesheet.Validate().ValidationMessages); validationMessages.AddRange(_sessionStateContainer.Cuesheet.Tracks.Select(x => x.Validate()).SelectMany(x => x.ValidationMessages)); - return validationMessages; + if (validationMessages.Count != 0) + { + return Result.Failure(new Error(ErrorType.ValidationFailed, string.Join(Environment.NewLine, validationMessages.Select(x => x.GetMessageLocalized(_localizer))))); + } + return Result.Success(); } - public IReadOnlyCollection GenerateExportfiles(string? filename) + public Result GenerateExportfile(string? filename) { - List exportfiles = []; - if (!CanGenerateExportfiles(filename).Any()) + var validationResult = CanGenerateExportfile(filename); + if (validationResult.IsSuccess == false) { - if (_sessionStateContainer.Cuesheet.Sections.Count != 0) - { - var counter = 1; - string? content = null; - string? audioFileName = null; - foreach (var section in _sessionStateContainer.Cuesheet.Sections.OrderBy(x => x.Begin)) - { - audioFileName = section.AudiofileName; - if (section.Validate().Status == ValidationStatus.Success) - { - content = WriteCuesheet(audioFileName, section); - var name = string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(filename), counter, FileExtensions.Cuesheet); - exportfiles.Add(new Exportfile() { Name = name, Content = content, Begin = section.Begin, End = section.End }); - counter++; - } - } - } - else - { - string? content = null; - var extension = Path.GetExtension(filename); - if (extension?.Equals(FileExtensions.Cuesheet, StringComparison.OrdinalIgnoreCase) == false) - { - filename = $"{filename}{FileExtensions.Cuesheet}"; - } - if (_sessionStateContainer.Cuesheet.Audiofile != null) - { - content = WriteCuesheet(_sessionStateContainer.Cuesheet.Audiofile.Name); - } - var begin = _sessionStateContainer.Cuesheet.Tracks.Min(x => x.Begin); - var end = _sessionStateContainer.Cuesheet.Tracks.Max(x => x.End); - exportfiles.Add(new Exportfile() { Name = filename!, Content = content, Begin = begin, End = end }); - } + return Result.Failure(new Error(ErrorType.ValidationFailed, validationResult.Error!.Message)); + } + string? content = null; + var extension = Path.GetExtension(filename); + if (extension?.Equals(FileExtensions.Cuesheet, StringComparison.OrdinalIgnoreCase) == false) + { + filename = $"{filename}{FileExtensions.Cuesheet}"; + } + if (_sessionStateContainer.Cuesheet.Audiofile != null) + { + content = WriteCuesheet(_sessionStateContainer.Cuesheet.Audiofile.Name); } - return exportfiles; + var begin = _sessionStateContainer.Cuesheet.Tracks.Min(x => x.Begin); + var end = _sessionStateContainer.Cuesheet.Tracks.Max(x => x.End); + return Result.Success(new Exportfile() { Name = filename!, Content = content, Begin = begin, End = end }); } - private string WriteCuesheet(string? audiofileName, CuesheetSection? section = null) + private string WriteCuesheet(string? audiofileName) { var builder = new StringBuilder(); if (string.IsNullOrEmpty(_sessionStateContainer.Cuesheet.Cataloguenumber) == false) @@ -93,14 +80,10 @@ private string WriteCuesheet(string? audiofileName, CuesheetSection? section = n { builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetCDTextfile, _sessionStateContainer.Cuesheet.CDTextfile.Name)); } - builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, section != null ? section.Title : _sessionStateContainer.Cuesheet.Title)); - builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, section != null ? section.Artist : _sessionStateContainer.Cuesheet.Artist)); + builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, _sessionStateContainer.Cuesheet.Title)); + builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, _sessionStateContainer.Cuesheet.Artist)); builder.AppendLine(string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, audiofileName, _sessionStateContainer.Cuesheet.Audiofile?.AudioFileType)); IEnumerable tracks = _sessionStateContainer.Cuesheet.Tracks.OrderBy(x => x.Position); - if (section != null) - { - tracks = _sessionStateContainer.Cuesheet.Tracks.Where(x => x.Begin <= section.End && x.End >= section.Begin).OrderBy(x => x.Position); - } if (tracks.Any()) { //Position and begin should always start from 0 even with splitpoints @@ -121,17 +104,6 @@ private string WriteCuesheet(string? audiofileName, CuesheetSection? section = n if (track.Begin.HasValue) { var begin = track.Begin.Value; - if (section != null && section.Begin.HasValue) - { - if (section.Begin >= track.Begin) - { - begin = TimeSpan.Zero; - } - else - { - begin = track.Begin.Value - section.Begin.Value; - } - } builder.AppendLine(string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(begin.TotalMinutes), begin.Seconds, begin.Milliseconds * 75 / 1000)); } else diff --git a/AudioCuesheetEditor/Services/IO/ExportfileGenerator.cs b/AudioCuesheetEditor/Services/IO/ExportfileGenerator.cs index b6f3656b..3b2901fa 100644 --- a/AudioCuesheetEditor/Services/IO/ExportfileGenerator.cs +++ b/AudioCuesheetEditor/Services/IO/ExportfileGenerator.cs @@ -17,77 +17,55 @@ using AudioCuesheetEditor.Model.Entity; using AudioCuesheetEditor.Model.IO.Export; using AudioCuesheetEditor.Services.UI; +using Microsoft.Extensions.Localization; using System.Data; using System.Text; namespace AudioCuesheetEditor.Services.IO { - public class ExportfileGenerator(ISessionStateContainer sessionStateContainer) + public class ExportfileGenerator(ISessionStateContainer sessionStateContainer, IStringLocalizer localizer) { private readonly ISessionStateContainer _sessionStateContainer = sessionStateContainer; + private readonly IStringLocalizer _localizer = localizer; - public IEnumerable CanGenerateExportfiles(Exportprofile? exportprofile) + public Result CanGenerateExportfile(Exportprofile exportprofile) { List validationMessages = []; - if (exportprofile != null) - { - validationMessages.AddRange(exportprofile.Validate().ValidationMessages); - } - else - { - validationMessages.Add(new ValidationMessage("No exportprofile selected!")); - } + validationMessages.AddRange(exportprofile.Validate().ValidationMessages); validationMessages.AddRange(_sessionStateContainer.Cuesheet.Validate().ValidationMessages); validationMessages.AddRange(_sessionStateContainer.Cuesheet.Tracks.Select(x => x.Validate()).SelectMany(x => x.ValidationMessages)); - return validationMessages; + if (validationMessages.Count != 0) + { + return Result.Failure(new Error(ErrorType.ValidationFailed, string.Join(Environment.NewLine, validationMessages.Select(x => x.GetMessageLocalized(_localizer))))); + } + return Result.Success(); } - public IReadOnlyCollection GenerateExportfiles(Exportprofile? exportprofile) + public Result GenerateExportfile(Exportprofile exportprofile) { - List exportfiles = []; - if ((!CanGenerateExportfiles(exportprofile).Any()) && (exportprofile != null)) + var validationResult = CanGenerateExportfile(exportprofile); + if (validationResult.IsSuccess == false) { - if (_sessionStateContainer.Cuesheet.Sections.Count != 0) - { - var counter = 1; - string? content = null; - string filename = string.Empty; - string? audioFileName = null; - foreach (var section in _sessionStateContainer.Cuesheet.Sections.OrderBy(x => x.Begin)) - { - audioFileName = section.AudiofileName; - if (section.Validate().Status == ValidationStatus.Success) - { - content = WriteExport(exportprofile, audioFileName, section); - filename = string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(exportprofile.Filename), counter, Path.GetExtension(exportprofile.Filename)); - exportfiles.Add(new Exportfile() { Name = filename, Content = content, Begin = section.Begin, End = section.End }); - counter++; - } - } - } - else - { - string? content = null; - if (_sessionStateContainer.Cuesheet.Audiofile != null) - { - content = WriteExport(exportprofile, _sessionStateContainer.Cuesheet.Audiofile.Name); - } - var begin = _sessionStateContainer.Cuesheet.Tracks.Min(x => x.Begin); - var end = _sessionStateContainer.Cuesheet.Tracks.Max(x => x.End); - exportfiles.Add(new Exportfile() { Name = exportprofile.Filename, Content = content, Begin = begin, End = end }); - } + return Result.Failure(new Error(ErrorType.ValidationFailed, validationResult.Error!.Message)); + } + string? content = null; + if (_sessionStateContainer.Cuesheet.Audiofile != null) + { + content = WriteExport(exportprofile, _sessionStateContainer.Cuesheet.Audiofile.Name); } - return exportfiles; + var begin = _sessionStateContainer.Cuesheet.Tracks.Min(x => x.Begin); + var end = _sessionStateContainer.Cuesheet.Tracks.Max(x => x.End); + return Result.Success(new Exportfile() { Name = exportprofile.Filename, Content = content, Begin = begin, End = end }); } - private string WriteExport(Exportprofile exportprofile, string? audiofileName, CuesheetSection? section = null) + private string WriteExport(Exportprofile exportprofile, string? audiofileName) { var builder = new StringBuilder(); if (exportprofile != null) { var header = exportprofile.SchemeHead - .Replace(Exportprofile.SchemeCuesheetArtist, section != null ? section.Artist : _sessionStateContainer.Cuesheet.Artist) - .Replace(Exportprofile.SchemeCuesheetTitle, section != null ? section.Title : _sessionStateContainer.Cuesheet.Title) + .Replace(Exportprofile.SchemeCuesheetArtist, _sessionStateContainer.Cuesheet.Artist) + .Replace(Exportprofile.SchemeCuesheetTitle, _sessionStateContainer.Cuesheet.Title) .Replace(Exportprofile.SchemeCuesheetAudiofile, audiofileName) .Replace(Exportprofile.SchemeCuesheetCDTextfile, _sessionStateContainer.Cuesheet.CDTextfile?.Name) .Replace(Exportprofile.SchemeCuesheetCatalogueNumber, _sessionStateContainer.Cuesheet.Cataloguenumber) @@ -96,10 +74,6 @@ private string WriteExport(Exportprofile exportprofile, string? audiofileName, C .Replace(Exportprofile.SchemeTime, DateTime.Now.ToLongTimeString()); builder.AppendLine(header); IEnumerable tracks = _sessionStateContainer.Cuesheet.Tracks.OrderBy(x => x.Position); - if (section != null) - { - tracks = _sessionStateContainer.Cuesheet.Tracks.Where(x => x.Begin <= section.End && x.End >= section.Begin).OrderBy(x => x.Position); - } if (tracks.Any()) { //Position, Begin and End should always start from 0 even with splitpoints @@ -111,18 +85,6 @@ private string WriteExport(Exportprofile exportprofile, string? audiofileName, C if (track.Begin.HasValue) { begin = track.Begin.Value; - if (section?.Begin != null) - { - if (section.Begin >= track.Begin) - { - begin = TimeSpan.Zero; - } - else - { - begin = track.Begin.Value - section.Begin.Value; - } - end = track.End - section.Begin.Value; - } } else { @@ -145,8 +107,8 @@ private string WriteExport(Exportprofile exportprofile, string? audiofileName, C } } var footer = exportprofile.SchemeFooter - .Replace(Exportprofile.SchemeCuesheetArtist, section != null ? section.Artist : _sessionStateContainer.Cuesheet.Artist) - .Replace(Exportprofile.SchemeCuesheetTitle, section != null ? section.Title : _sessionStateContainer.Cuesheet.Title) + .Replace(Exportprofile.SchemeCuesheetArtist, _sessionStateContainer.Cuesheet.Artist) + .Replace(Exportprofile.SchemeCuesheetTitle, _sessionStateContainer.Cuesheet.Title) .Replace(Exportprofile.SchemeCuesheetAudiofile, audiofileName) .Replace(Exportprofile.SchemeCuesheetCDTextfile, _sessionStateContainer.Cuesheet.CDTextfile?.Name) .Replace(Exportprofile.SchemeCuesheetCatalogueNumber, _sessionStateContainer.Cuesheet.Cataloguenumber) diff --git a/AudioCuesheetEditor/Services/IO/ImportManager.cs b/AudioCuesheetEditor/Services/IO/ImportManager.cs index 6817670f..adeabb5e 100644 --- a/AudioCuesheetEditor/Services/IO/ImportManager.cs +++ b/AudioCuesheetEditor/Services/IO/ImportManager.cs @@ -19,7 +19,6 @@ using AudioCuesheetEditor.Model.IO.Audio; using AudioCuesheetEditor.Model.IO.Import; using AudioCuesheetEditor.Services.UI; -using Microsoft.AspNetCore.Components.Forms; using System.Diagnostics; namespace AudioCuesheetEditor.Services.IO @@ -188,12 +187,6 @@ private static void CopyCuesheet(Cuesheet target, ICuesheet cuesheetToCopy) if (cuesheetToCopy is Cuesheet originCuesheet) { tracks = originCuesheet.Tracks; - // Copy sections - foreach (var section in originCuesheet.Sections) - { - var newSplitPoint = target.AddSection(); - newSplitPoint.CopyValues(section); - } target.Audiofile = originCuesheet.Audiofile; target.CDTextfile = originCuesheet.CDTextfile; target.Cataloguenumber = originCuesheet.Cataloguenumber; diff --git a/AudioCuesheetEditor/Services/Result.cs b/AudioCuesheetEditor/Services/Result.cs new file mode 100644 index 00000000..da870084 --- /dev/null +++ b/AudioCuesheetEditor/Services/Result.cs @@ -0,0 +1,117 @@ +//This file is part of AudioCuesheetEditor. + +//AudioCuesheetEditor is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. + +//AudioCuesheetEditor is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. + +//You should have received a copy of the GNU General Public License +//along with Foobar. If not, see +//. +namespace AudioCuesheetEditor.Services +{ + /// + /// Defines types of errors + /// + public enum ErrorType + { + /// + /// Validation failed with error + /// + ValidationFailed + } + + /// + /// Represents an error of an service + /// + public class Error(ErrorType type, string message) + { + /// + /// Type of error + /// + public ErrorType Type { get; } = type; + /// + /// The error message + /// + public string Message { get; } = message; + } + + /// + /// Indicates a service result + /// + public class Result + { + /// + /// Indicates if the result was successful + /// + public bool IsSuccess { get; } + /// + /// The error if one occurred + /// + public Error? Error { get; } + + /// + /// Private constructor + /// + protected Result() + { + IsSuccess = true; + } + + /// + /// Private constructor + /// + protected Result(Error error) + { + IsSuccess = false; + Error = error; + } + /// + /// Creates a success result + /// + /// + public static Result Success() => new(); + /// + /// Creates a failure result + /// + /// + /// + public static Result Failure(Error error) => new(error); + } + + /// + /// Represent the result of a service + /// + /// + public class Result : Result + { + /// + /// The result value + /// + public T? Value { get; } + + private Result(T value) : base() + { + Value = value; + } + + private Result(Error error) : base(error) { } + /// + /// Creates a success result + /// + /// + /// + public static Result Success(T value) => new(value); + /// + /// Creates a failure result + /// + /// + /// + public static new Result Failure(Error error) => new(error); + } +} diff --git a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.de.resx b/AudioCuesheetEditor/Shared/Cuesheet/EditSections.de.resx deleted file mode 100644 index e7321fc5..00000000 --- a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.de.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Neue Sektion hinzufügen - - - Sind Sie sicher, dass Sie alle Abschnitte entfernen möchten? - - - Audiodatei - - - Start - - - Bestätigen - - - Cuesheet Künstler - - - Cuesheet Titel - - - Alle Abschnitte löschen - - - Ausgewählte Abschnitte löschen - - - Ende - - \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor b/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor deleted file mode 100644 index 2c998de5..00000000 --- a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor +++ /dev/null @@ -1,154 +0,0 @@ - -@inherits BaseLocalizedComponent - -@inject IStringLocalizer _localizer -@inject ApplicationOptionsTimeSpanParser _applicationOptionsTimeSpanParser -@inject ValidationService _validationService -@inject IDialogService _dialogService -@inject IFileInputManager _fileInputManager -@inject ISessionStateContainer _sessionStateContainer - - - - - - - - @_localizer["Delete selected sections"] - - - - - - - - @_localizer["Delete all sections"] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x.MimeType))" - DisplayMenu="false" /> - - - - - -@code { - HashSet selectedSections = new(); - - [CascadingParameter] - public ViewMode CurrentViewMode { get; set; } - - public Cuesheet? Cuesheet - { - get - { - if (CurrentViewMode == ViewMode.ImportView) - { - return _sessionStateContainer.ImportCuesheet; - } - return _sessionStateContainer.Cuesheet; - } - } - - void AddSectionClicked() - { - if (Cuesheet != null) - { - var section = Cuesheet.AddSection(); - TraceChangeManager.TraceChanges(section); - } - } - - String? GetValidationErrorMessage(object model, string propertyName) - { - String? validationErrorMessage = null; - var validationMessages = _validationService.Validate(model, propertyName); - if (validationMessages.Count() > 0) - { - validationErrorMessage = String.Join(Environment.NewLine, validationMessages); - } - return validationErrorMessage; - } - - void DeleteSelectedSections() - { - Cuesheet?.RemoveSections(selectedSections); - selectedSections.Clear(); - } - - async Task DeleteAllSections() - { - var parameters = new DialogParameters - { - { x => x.ConfirmText, _localizer["Are you sure you want to remove all sections?"] }, - }; - var dialog = await _dialogService.ShowAsync(_localizer["Confirm"], parameters); - var result = await dialog.Result; - if (result?.Canceled == false) - { - Cuesheet?.RemoveSections(Cuesheet.Sections); - selectedSections.Clear(); - } - } - - void AudiofileSelected(CuesheetSection section, IBrowserFile? browserFile) - { - if ((browserFile != null) && (_fileInputManager.IsValidAudiofile(browserFile.ContentType, browserFile.Name) == true)) - { - section.AudiofileName = browserFile?.Name; - } - else - { - section.AudiofileName = null; - } - } -} diff --git a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.resx b/AudioCuesheetEditor/Shared/Cuesheet/EditSections.resx deleted file mode 100644 index c8ddb59e..00000000 --- a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.resx +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Add new section - - - Are you sure you want to remove all sections? - - - Audio file - - - Begin - - - Confirm - - - Cuesheet artist - - - Cuesheet title - - - Delete all sections - - - Delete selected sections - - - End - - \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/Dialogs/GenerateCuesheetDialog.razor b/AudioCuesheetEditor/Shared/Dialogs/GenerateCuesheetDialog.razor index bf701eee..4dd21bab 100644 --- a/AudioCuesheetEditor/Shared/Dialogs/GenerateCuesheetDialog.razor +++ b/AudioCuesheetEditor/Shared/Dialogs/GenerateCuesheetDialog.razor @@ -18,7 +18,6 @@ along with Foobar. If not, see @inherits BaseLocalizedComponent @inject IStringLocalizer _localizer -@inject IStringLocalizer _validationMessageLocalizer @inject ValidationService _validationService @inject IBlazorDownloadFileService _blazorDownloadFileService @inject CuesheetExportService _cuesheetExportService @@ -32,10 +31,10 @@ along with Foobar. If not, see @((MarkupString)GetGenerationValidationMessages()!) } -
- + @_localizer["Name"] @_localizer["Begin"] @@ -57,15 +56,21 @@ along with Foobar. If not, see @code { - IEnumerable exportfiles = []; - DownloadOptions? options; + //TODO: Get validation messages only once during rendering and use the reference for better performance + //TODO: Will be a single file when #548 gets done + IEnumerable _exportfiles = []; + DownloadOptions? _options; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - options = await base.LocalStorageOptionsProvider.GetOptionsAsync(); + _options = await base.LocalStorageOptionsProvider.GetOptionsAsync(); base.LocalStorageOptionsProvider.OptionSaved += LocalStorageOptionsProvider_OptionSaved; - exportfiles = _cuesheetExportService.GenerateExportfiles(options?.CuesheetFilename); + var result = _cuesheetExportService.GenerateExportfile(_options?.CuesheetFilename); + if (result.IsSuccess) + { + _exportfiles = [result.Value!]; + } } protected override void Dispose(bool disposing) @@ -77,9 +82,9 @@ along with Foobar. If not, see String? GetValidationErrorMessage() { String? validationErrorMessage = null; - if (options != null) + if (_options != null) { - var validationMessages = _validationService.Validate(options, nameof(DownloadOptions.CuesheetFilename)); + var validationMessages = _validationService.Validate(_options, nameof(DownloadOptions.CuesheetFilename)); if (validationMessages.Count() > 0) { validationErrorMessage = String.Join(Environment.NewLine, validationMessages); @@ -91,10 +96,10 @@ along with Foobar. If not, see String? GetGenerationValidationMessages() { String? validationErrorMessage = null; - var messages = _cuesheetExportService.CanGenerateExportfiles(options?.CuesheetFilename); - if (messages.Count() > 0) + var result = _cuesheetExportService.CanGenerateExportfile(_options?.CuesheetFilename); + if (result.IsSuccess == false) { - validationErrorMessage = String.Join("
", messages.Select(x => x.GetMessageLocalized(_validationMessageLocalizer))); + validationErrorMessage = result.Error?.Message.Replace(Environment.NewLine, "
"); } return validationErrorMessage; } @@ -102,14 +107,18 @@ along with Foobar. If not, see async Task CuesheetFilenameChanged(string newFilename) { await LocalStorageOptionsProvider.SaveOptionsValueAsync(x => x.CuesheetFilename, newFilename); - exportfiles = _cuesheetExportService.GenerateExportfiles(options?.CuesheetFilename); + var result = _cuesheetExportService.GenerateExportfile(_options?.CuesheetFilename); + if (result.IsSuccess) + { + _exportfiles = [result.Value!]; + } } void LocalStorageOptionsProvider_OptionSaved(object? sender, IOptions option) { if (option is DownloadOptions downloadOptions) { - options = downloadOptions; + _options = downloadOptions; StateHasChanged(); } } diff --git a/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.de.resx b/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.de.resx index 29747256..13c2296c 100644 --- a/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.de.resx +++ b/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.de.resx @@ -132,9 +132,6 @@ Ausgewähltes Exportprofil löschen - - Name - Geben Sie hier den Namen für dieses Profil ein @@ -168,15 +165,6 @@ Export herunterladen - - Beginn - - - Ende - - - Inhalt - Künstler @@ -216,7 +204,7 @@ Nachlücke - - Inhalt anzeigen + + Kein Exportprofil ausgewählt! \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.razor b/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.razor index c8d8da7f..7444765e 100644 --- a/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.razor +++ b/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.razor @@ -18,7 +18,6 @@ along with Foobar. If not, see @inherits BaseLocalizedComponent @inject IStringLocalizer _localizer -@inject IStringLocalizer _validationMessageLocalizer @inject ValidationService _validationService @inject ExportfileGenerator _exportfileGenerator @inject IBlazorDownloadFileService _blazorDownloadFileService @@ -121,42 +120,7 @@ along with Foobar. If not, see - @if (_exportFiles.Count() == 1) - { - var exportFile = _exportFiles.Single(); - - } - else - { - - - @_localizer["Name"] - @_localizer["Begin"] - @_localizer["End"] - @_localizer["Content"] - - - @context.Name - @context.Begin - @context.End - @{ - var ariaLabelDownload = $"Download-{context.Name}"; - var ariaLabelDialog = $"Dialog-{context.Name}"; - var dialogVisible = _displayContentDialogVisible.GetValueOrDefault(context); - - @_localizer["Display content"] - - - - - - - - - } - - - } + @@ -165,7 +129,7 @@ along with Foobar. If not, see @code { ExportOptions? _exportOptions; - IEnumerable _exportFiles = []; + Exportfile? _exportFile; Boolean _configureExportCompleted = false; MudMenu? _schemeHeadMenu, _schemeTracksMenu, _schemeFooterMenu; Dictionary _displayContentDialogVisible = new(); @@ -218,10 +182,18 @@ along with Foobar. If not, see String? GetGenerationValidationMessages() { String? validationErrorMessage = null; - var messages = _exportfileGenerator.CanGenerateExportfiles(_exportOptions?.SelectedExportProfile); - if (messages.Count() > 0) + var selectedExportProfile = _exportOptions?.SelectedExportProfile; + if (selectedExportProfile != null) + { + var result = _exportfileGenerator.CanGenerateExportfile(selectedExportProfile); + if (result.IsSuccess == false) + { + validationErrorMessage = result.Error?.Message.Replace(Environment.NewLine, "
"); + } + } + else { - validationErrorMessage = String.Join("
", messages.Select(x => x.GetMessageLocalized(_validationMessageLocalizer))); + validationErrorMessage = _localizer["No export profile selected!"]; } return validationErrorMessage; } @@ -237,10 +209,15 @@ along with Foobar. If not, see void ActiveIndexChanged(int newIndex) { - if (newIndex == 1) + if (newIndex == 1) { - _exportFiles = _exportfileGenerator.GenerateExportfiles(_exportOptions?.SelectedExportProfile); - _configureExportCompleted = _exportFiles.Any(); + var selectedExportProfile = _exportOptions?.SelectedExportProfile; + if (selectedExportProfile != null) + { + var result = _exportfileGenerator.GenerateExportfile(selectedExportProfile); + _exportFile = result.Value; + _configureExportCompleted = result.IsSuccess; + } } } diff --git a/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.resx b/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.resx index b44b5523..d3274d80 100644 --- a/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.resx +++ b/AudioCuesheetEditor/Shared/Dialogs/GenerateExportDialog.resx @@ -132,9 +132,6 @@ Delete selected export profile - - Name - Enter the name for this profile here @@ -168,15 +165,6 @@ Download export - - Begin - - - End - - - Content - Artist @@ -216,7 +204,7 @@ PostGap - - Display content + + No export profile selected! \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx b/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx index c780f878..241c5171 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx @@ -138,9 +138,6 @@ Länge - - Ein Abschnitt beginnt innerhalb dieses Titels - Wiedergabe dieses Titel starten @@ -156,9 +153,6 @@ Status - - Abschnitt - Track von vorherigem abkoppeln diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor index a445f42b..912fc315 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor @@ -110,12 +110,6 @@ along with Foobar. If not, see