diff --git a/AudioCuesheetEditor.Tests/Services/AudioCuesheet/CuesheetManagerTests.cs b/AudioCuesheetEditor.Tests/Services/AudioCuesheet/CuesheetManagerTests.cs index 12368caa..dea190de 100644 --- a/AudioCuesheetEditor.Tests/Services/AudioCuesheet/CuesheetManagerTests.cs +++ b/AudioCuesheetEditor.Tests/Services/AudioCuesheet/CuesheetManagerTests.cs @@ -706,6 +706,75 @@ public void MoveUp_TracksAbove_ReturnsSuccess() _traceChangeManager.VerifySet(x => x.BulkEdit = false, Times.Once); } + [TestMethod] + public void MoveUp_Move2Positions_ReturnsSuccess() + { + // Arrange + var track1End = new TimeSpan(0, 3, 12); + var track1 = new Track() + { + Position = 1, + Begin = TimeSpan.Zero, + End = track1End, + IsLinkedToPreviousTrack = true + }; + var track2End = new TimeSpan(0, 7, 34); + var track2 = new Track() + { + Position = 2, + Begin = track1End, + End = track2End, + IsLinkedToPreviousTrack = true + }; + var track3End = new TimeSpan(0, 10, 4); + var track3 = new Track() + { + Position = 3, + Begin = track2End, + End = track3End, + IsLinkedToPreviousTrack = true + }; + var track4 = new Track() + { + Position = 4, + Begin = track3End, + End = new TimeSpan(0, 13, 45), + IsLinkedToPreviousTrack = true + }; + var cuesheet = new Cuesheet() + { + Audiofiles = [ + new() { + Tracks = [track4, track3, track2, track1] + } + ], + }; + track1.Cuesheet = cuesheet; + track2.Cuesheet = cuesheet; + track3.Cuesheet = cuesheet; + track4.Cuesheet = cuesheet; + track1.Audiofile = cuesheet.Audiofiles.First(); + track2.Audiofile = cuesheet.Audiofiles.First(); + track3.Audiofile = cuesheet.Audiofiles.First(); + track4.Audiofile = cuesheet.Audiofiles.First(); + _sessionStateContainer.Setup(x => x.ActiveCuesheet).Returns(cuesheet); + // Act + var result = _cuesheetManager.MoveUp([track2, track3], 2); + // Assert + Assert.IsTrue(result.IsSuccess); + Assert.AreEqual((ushort?)1, track2.Position); + Assert.AreEqual(TimeSpan.Zero, track2.Begin); + Assert.AreEqual(track1End, track2.End); + Assert.AreEqual((ushort?)2, track3.Position); + Assert.AreEqual(track1End, track3.Begin); + Assert.AreEqual(track2End, track3.End); + Assert.AreEqual((ushort?)3, track1.Position); + Assert.AreEqual(track2End, track1.Begin); + _traceChangeManager.Verify(x => x.AddChange(It.Is(y => y.TraceableObject == cuesheet.Audiofiles.First() && y.TraceableChange.PropertyName == nameof(Audiofile.Tracks))), Times.Never); + _traceChangeManager.VerifySet(x => x.BulkEdit = true, Times.Once); + _traceChangeManager.VerifySet(x => x.BulkEdit = false, Times.Once); + } + [TestMethod] public void MoveUp_NoTracksAbove_ReturnsFailure() { @@ -1060,6 +1129,78 @@ public void MoveDown_TracksBelow_ReturnsSuccess() _traceChangeManager.VerifySet(x => x.BulkEdit = false, Times.Once); } + [TestMethod] + public void MoveDown_Move2Positions_ReturnsSuccess() + { + // Arrange + var track1End = new TimeSpan(0, 3, 12); + var track1 = new Track() + { + Position = 1, + Begin = TimeSpan.Zero, + End = track1End, + IsLinkedToPreviousTrack = true + }; + var track2End = new TimeSpan(0, 7, 34); + var track2 = new Track() + { + Position = 2, + Begin = track1End, + End = track2End, + IsLinkedToPreviousTrack = true + }; + var track3End = new TimeSpan(0, 10, 4); + var track3 = new Track() + { + Position = 3, + Begin = track2End, + End = track3End, + IsLinkedToPreviousTrack = true + }; + var track4 = new Track() + { + Position = 4, + Begin = track3End, + End = new TimeSpan(0, 13, 45), + IsLinkedToPreviousTrack = true + }; + var cuesheet = new Cuesheet() + { + Audiofiles = [ + new() { + Tracks = [track4, track3, track2, track1] + } + ] + }; + track1.Cuesheet = cuesheet; + track2.Cuesheet = cuesheet; + track3.Cuesheet = cuesheet; + track4.Cuesheet = cuesheet; + track1.Audiofile = cuesheet.Audiofiles.First(); + track2.Audiofile = cuesheet.Audiofiles.First(); + track3.Audiofile = cuesheet.Audiofiles.First(); + track4.Audiofile = cuesheet.Audiofiles.First(); + _sessionStateContainer.Setup(x => x.ActiveCuesheet).Returns(cuesheet); + // Act + var result = _cuesheetManager.MoveDown([track2, track1], 2); + // Assert + Assert.IsTrue(result.IsSuccess); + Assert.AreEqual((ushort?)1, track3.Position); + Assert.AreEqual(TimeSpan.Zero, track3.Begin); + Assert.AreEqual(track1End, track3.End); + Assert.AreEqual((ushort?)2, track4.Position); + Assert.AreEqual(track1End, track4.Begin); + Assert.AreEqual(track2End, track4.End); + Assert.AreEqual((ushort?)3, track1.Position); + Assert.AreEqual(track2End, track1.Begin); + Assert.AreEqual(track3End, track1.End); + Assert.AreEqual((ushort?)4, track2.Position); + Assert.AreEqual(track3End, track2.Begin); + _traceChangeManager.Verify(x => x.AddChange(It.Is(y => y.TraceableObject == cuesheet.Audiofiles.First() && y.TraceableChange.PropertyName == nameof(Audiofile.Tracks))), Times.Never); + _traceChangeManager.VerifySet(x => x.BulkEdit = true, Times.Once); + _traceChangeManager.VerifySet(x => x.BulkEdit = false, Times.Once); + } + [TestMethod] public void MoveDown_NoTracksBelow_ReturnsFailure() { diff --git a/AudioCuesheetEditor.Tests/Services/UI/TraceChangeManagerTests.cs b/AudioCuesheetEditor.Tests/Services/UI/TraceChangeManagerTests.cs index 06613a8b..f1eeef6f 100644 --- a/AudioCuesheetEditor.Tests/Services/UI/TraceChangeManagerTests.cs +++ b/AudioCuesheetEditor.Tests/Services/UI/TraceChangeManagerTests.cs @@ -19,6 +19,7 @@ using AudioCuesheetEditor.Tests.Utility; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; +using System.Collections.Generic; using System.Linq; namespace AudioCuesheetEditor.Tests.Services.UI @@ -112,6 +113,40 @@ public void BulkEdit_AlreadyEnabledBulkEdit_DoesntDropPreviousEdits() Assert.IsTrue(_traceChangeManager.CanRedo); } + + [TestMethod()] + public void BulkEditFalse_AfterBulkEditAndUndo_ResetsRedoStack() + { + // Arrange + var audiofile = new Audiofile(); + var track1 = new Track(); + var track2 = new Track(); + var track3 = new Track(); + _traceChangeManager.BulkEdit = true; + _traceChangeManager.AddChange(new(audiofile, new(new List() { track1 }, nameof(Audiofile.Tracks)))); + track1.Audiofile = audiofile; + _traceChangeManager.BulkEdit = false; + _traceChangeManager.BulkEdit = true; + _traceChangeManager.AddChange(new(audiofile, new(new List() { track1, track2 }, nameof(Audiofile.Tracks)))); + track1.Audiofile = audiofile; + track2.Audiofile = audiofile; + _traceChangeManager.BulkEdit = false; + _traceChangeManager.Undo(); + _traceChangeManager.BulkEdit = true; + _traceChangeManager.AddChange(new(audiofile, new(new List() { track1, track2, track3 }, nameof(Audiofile.Tracks)))); + track1.Audiofile = audiofile; + track2.Audiofile = audiofile; + track3.Audiofile = audiofile; + _traceChangeManager.BulkEdit = false; + _traceChangeManager.BulkEdit = true; + _traceChangeManager.AddChange(new(track2, new("Testartist", nameof(Track.Artist)))); + // Act + _traceChangeManager.BulkEdit = false; + // Assert + Assert.IsTrue(_traceChangeManager.CanUndo); + Assert.IsFalse(_traceChangeManager.CanRedo); + } + [TestMethod()] public void Undo_SingleChange_UndoesChange() { diff --git a/AudioCuesheetEditor/Services/AudioCuesheet/CuesheetManager.cs b/AudioCuesheetEditor/Services/AudioCuesheet/CuesheetManager.cs index 3b635a50..6333479a 100644 --- a/AudioCuesheetEditor/Services/AudioCuesheet/CuesheetManager.cs +++ b/AudioCuesheetEditor/Services/AudioCuesheet/CuesheetManager.cs @@ -141,41 +141,50 @@ public bool IsMoveDownPossible(HashSet selectedAudiofiles) } /// - public Result MoveUp(HashSet selectedTracks) + public Result MoveUp(HashSet selectedTracks, uint positions = 1) { if (IsMoveUpPossible(selectedTracks) == false) { return Result.Failure(new Error(ErrorType.NotPossible, "Moving tracks up is not possible!")); } _traceChangeManager.BulkEdit = true; - var cuesheet = _sessionStateContainer.ActiveCuesheet; - foreach (var selectedTrack in selectedTracks.OrderBy(x => x.Position)) + while (positions > 0) { - var previousTrack = cuesheet?.Audiofiles.SelectMany(x => x.Tracks).FirstOrDefault(x => x.Position == selectedTrack.Position - 1); - if (previousTrack?.Audiofile != null && previousTrack.Audiofile != selectedTrack.Audiofile) + if (IsMoveUpPossible(selectedTracks) == false) { - SwitchAudiofile(selectedTrack, previousTrack.Audiofile); + positions = 0; + break; } - else + var cuesheet = _sessionStateContainer.ActiveCuesheet; + foreach (var selectedTrack in selectedTracks.OrderBy(x => x.Position)) { - var newBegin = previousTrack?.Begin; - var newEnd = previousTrack?.End; - if (previousTrack != null) + var previousTrack = cuesheet?.Audiofiles.SelectMany(x => x.Tracks).FirstOrDefault(x => x.Position == selectedTrack.Position - 1); + if (previousTrack?.Audiofile != null && previousTrack.Audiofile != selectedTrack.Audiofile) + { + SwitchAudiofile(selectedTrack, previousTrack.Audiofile); + } + else { - _trackManager.SetProperty(previousTrack, x => x.Position, selectedTrack.Position); - _trackManager.SetProperty(previousTrack, x => x.Begin, selectedTrack.Begin); - _trackManager.SetProperty(previousTrack, x => x.End, selectedTrack.End); + var newBegin = previousTrack?.Begin; + var newEnd = previousTrack?.End; + if (previousTrack != null) + { + _trackManager.SetProperty(previousTrack, x => x.Position, selectedTrack.Position); + _trackManager.SetProperty(previousTrack, x => x.Begin, selectedTrack.Begin); + _trackManager.SetProperty(previousTrack, x => x.End, selectedTrack.End); + } + _trackManager.SetProperty(selectedTrack, x => x.Position, (ushort?)(selectedTrack.Position - 1)); + _trackManager.SetProperty(selectedTrack, x => x.Begin, newBegin); + _trackManager.SetProperty(selectedTrack, x => x.End, newEnd); } - _trackManager.SetProperty(selectedTrack, x => x.Position, (ushort?)(selectedTrack.Position - 1)); - _trackManager.SetProperty(selectedTrack, x => x.Begin, newBegin); - _trackManager.SetProperty(selectedTrack, x => x.End, newEnd); + } - - } - foreach (var audiofile in cuesheet!.Audiofiles) - { - var orderedTracks = audiofile.Tracks.OrderBy(x => x.Position).ToList(); - _audiofileManager.SetProperty(audiofile, x => x.Tracks, orderedTracks); + foreach (var audiofile in cuesheet!.Audiofiles) + { + var orderedTracks = audiofile.Tracks.OrderBy(x => x.Position).ToList(); + _audiofileManager.SetProperty(audiofile, x => x.Tracks, orderedTracks); + } + positions--; } _traceChangeManager.BulkEdit = false; return Result.Success(); @@ -216,40 +225,49 @@ public Result MoveUp(HashSet selectedAudiofiles) } /// - public Result MoveDown(HashSet selectedTracks) + public Result MoveDown(HashSet selectedTracks, uint positions = 1) { if (IsMoveDownPossible(selectedTracks) == false) { return Result.Failure(new Error(ErrorType.NotPossible, "Moving tracks down is not possible!")); } _traceChangeManager.BulkEdit = true; - var cuesheet = _sessionStateContainer.ActiveCuesheet; - foreach (var selectedTrack in selectedTracks.OrderByDescending(x => x.Position)) + while (positions > 0) { - var nextTrack = cuesheet?.Audiofiles.SelectMany(x => x.Tracks).FirstOrDefault(x => x.Position == selectedTrack.Position + 1); - if (nextTrack?.Audiofile != null && nextTrack.Audiofile != selectedTrack.Audiofile) + if (IsMoveDownPossible(selectedTracks) == false) { - SwitchAudiofile(selectedTrack, nextTrack.Audiofile); + positions = 0; + break; } - else + var cuesheet = _sessionStateContainer.ActiveCuesheet; + foreach (var selectedTrack in selectedTracks.OrderByDescending(x => x.Position)) { - var newBegin = nextTrack?.Begin; - var newEnd = nextTrack?.End; - if (nextTrack != null) + var nextTrack = cuesheet?.Audiofiles.SelectMany(x => x.Tracks).FirstOrDefault(x => x.Position == selectedTrack.Position + 1); + if (nextTrack?.Audiofile != null && nextTrack.Audiofile != selectedTrack.Audiofile) + { + SwitchAudiofile(selectedTrack, nextTrack.Audiofile); + } + else { - _trackManager.SetProperty(nextTrack, x => x.Position, selectedTrack.Position); - _trackManager.SetProperty(nextTrack, x => x.Begin, selectedTrack.Begin); - _trackManager.SetProperty(nextTrack, x => x.End, selectedTrack.End); + var newBegin = nextTrack?.Begin; + var newEnd = nextTrack?.End; + if (nextTrack != null) + { + _trackManager.SetProperty(nextTrack, x => x.Position, selectedTrack.Position); + _trackManager.SetProperty(nextTrack, x => x.Begin, selectedTrack.Begin); + _trackManager.SetProperty(nextTrack, x => x.End, selectedTrack.End); + } + _trackManager.SetProperty(selectedTrack, x => x.Position, (ushort?)(selectedTrack.Position + 1)); + _trackManager.SetProperty(selectedTrack, x => x.Begin, newBegin); + _trackManager.SetProperty(selectedTrack, x => x.End, newEnd); } - _trackManager.SetProperty(selectedTrack, x => x.Position, (ushort?)(selectedTrack.Position + 1)); - _trackManager.SetProperty(selectedTrack, x => x.Begin, newBegin); - _trackManager.SetProperty(selectedTrack, x => x.End, newEnd); } - } - foreach (var audiofile in cuesheet!.Audiofiles) - { - var orderedTracks = audiofile.Tracks.OrderBy(x => x.Position).ToList(); - _audiofileManager.SetProperty(audiofile, x => x.Tracks, orderedTracks); + foreach (var audiofile in cuesheet!.Audiofiles) + { + var orderedTracks = audiofile.Tracks.OrderBy(x => x.Position).ToList(); + _audiofileManager.SetProperty(audiofile, x => x.Tracks, orderedTracks); + } + positions--; } _traceChangeManager.BulkEdit = false; return Result.Success(); diff --git a/AudioCuesheetEditor/Services/AudioCuesheet/ICuesheetManager.cs b/AudioCuesheetEditor/Services/AudioCuesheet/ICuesheetManager.cs index bb4daed6..66631da8 100644 --- a/AudioCuesheetEditor/Services/AudioCuesheet/ICuesheetManager.cs +++ b/AudioCuesheetEditor/Services/AudioCuesheet/ICuesheetManager.cs @@ -78,7 +78,9 @@ public interface ICuesheetManager /// Moves selected tracks up /// /// - Result MoveUp(HashSet selectedTracks); + /// + /// + Result MoveUp(HashSet selectedTracks, uint positions = 1); /// /// Moves selected audiofiles up /// @@ -89,8 +91,9 @@ public interface ICuesheetManager /// Moves selected tracks down /// /// + /// /// - Result MoveDown(HashSet selectedTracks); + Result MoveDown(HashSet selectedTracks, uint positions = 1); /// /// Moves selected audiofiles down /// diff --git a/AudioCuesheetEditor/Services/Result.cs b/AudioCuesheetEditor/Services/Result.cs index fac41830..565b1fe0 100644 --- a/AudioCuesheetEditor/Services/Result.cs +++ b/AudioCuesheetEditor/Services/Result.cs @@ -31,7 +31,11 @@ public enum ErrorType /// /// Current action is not possible /// - NotPossible + NotPossible, + /// + /// Action was aborted + /// + Aborted, } /// diff --git a/AudioCuesheetEditor/Services/UI/DialogManager.cs b/AudioCuesheetEditor/Services/UI/DialogManager.cs index bf33908a..f8712578 100644 --- a/AudioCuesheetEditor/Services/UI/DialogManager.cs +++ b/AudioCuesheetEditor/Services/UI/DialogManager.cs @@ -227,5 +227,30 @@ public async Task ShowImportAudiofilesDialogAsync() } return canceled; } + + /// + public async Task> ShowInputDialogAsync(string? title, string? placeholder, string? label, T initialValue, string? OkText = "Ok", string? OkButtonStartIcon = null) + { + var parameters = new DialogParameters> + { + { x => x.Placeholder, placeholder }, + { x => x.Label, label }, + { x => x.InitialValue, initialValue }, + { x => x.OkText, OkText }, + { x => x.OkButtonStartIcon, OkButtonStartIcon } + }; + var options = new DialogOptions() { CloseOnEscapeKey = true, BackdropClick = false, FullWidth = true, CloseButton = true }; + var dialog = await _dialogService.ShowAsync>(title, parameters, options); + var result = await dialog.Result; + if (result?.Canceled == false) + { + var value = (T)result.Data!; + return Result.Success(value); + } + else + { + return Result.Failure(new Error(ErrorType.Aborted, "User canceled the input dialog.")); + } + } } } diff --git a/AudioCuesheetEditor/Services/UI/IDialogManager.cs b/AudioCuesheetEditor/Services/UI/IDialogManager.cs index b996a6b1..1394af97 100644 --- a/AudioCuesheetEditor/Services/UI/IDialogManager.cs +++ b/AudioCuesheetEditor/Services/UI/IDialogManager.cs @@ -24,5 +24,17 @@ public interface IDialogManager Task ShowAndHandleModalEditDialogAsync(IEnumerable tracks); Task ShowImportAudiofilesDialogAsync(); Task ShowLoadingDialogAsync(); + /// + /// Show input dialog and wait for user input. + /// + /// + /// + /// + /// + /// + /// + /// + /// + Task> ShowInputDialogAsync(string? title, string? placeholder, string? label, T initialValue, string? OkText = "Ok", string? OkButtonStartIcon = null); } } \ No newline at end of file diff --git a/AudioCuesheetEditor/Services/UI/TraceChangeManager.cs b/AudioCuesheetEditor/Services/UI/TraceChangeManager.cs index 79a53ef1..192c3866 100644 --- a/AudioCuesheetEditor/Services/UI/TraceChangeManager.cs +++ b/AudioCuesheetEditor/Services/UI/TraceChangeManager.cs @@ -175,6 +175,7 @@ public bool BulkEdit if (_bulkEditTracedChanges?.Count > 0) { _undoStack.Add(new TracedChanges(_bulkEditTracedChanges)); + _redoStack.Clear(); TracedObjectHistoryChanged?.Invoke(this, EventArgs.Empty); } _bulkEditTracedChanges = null; diff --git a/AudioCuesheetEditor/Shared/AppBar.razor b/AudioCuesheetEditor/Shared/AppBar.razor index 5c8c03f6..4fad7e10 100644 --- a/AudioCuesheetEditor/Shared/AppBar.razor +++ b/AudioCuesheetEditor/Shared/AppBar.razor @@ -37,10 +37,10 @@ along with Foobar. If not, see { - + - + } @@ -97,8 +97,8 @@ along with Foobar. If not, see { base.OnInitialized(); _hotKeysContext = _hotKeys.CreateContext() - .Add(ModKey.Ctrl, Key.z, () => TraceChangeManager.Undo()) - .Add(ModKey.Ctrl, Key.y, () => TraceChangeManager.Redo()) + .Add(ModKey.Ctrl, Key.z, TraceChangeManager.Undo) + .Add(ModKey.Ctrl, Key.y, TraceChangeManager.Redo) .Add(ModKey.Ctrl, Key.s, DownloadProjectfileClicked) .Add(ModKey.Ctrl, Key.e, DownloadExportClicked) .Add(ModKey.Ctrl, Key.u, DownloadCuesheetClicked) diff --git a/AudioCuesheetEditor/Shared/Cuesheet/Audiofiles.razor b/AudioCuesheetEditor/Shared/Cuesheet/Audiofiles.razor index d16cc16f..ddf19bd9 100644 --- a/AudioCuesheetEditor/Shared/Cuesheet/Audiofiles.razor +++ b/AudioCuesheetEditor/Shared/Cuesheet/Audiofiles.razor @@ -20,7 +20,7 @@ along with Foobar. If not, see @inject IStringLocalizer _localizer @inject IStringLocalizer _validationMessageLocalizer @inject IAudiofileManager _audiofileManager -@inject IDialogService _dialogService +@inject IDialogManager _dialogManager @switch (CurrentViewMode) { @@ -77,34 +77,15 @@ along with Foobar. If not, see [Parameter] public EventCallback> SelectedFilesChanged { get; set; } - async Task ShowInputDialog(string? initialValue) - { - var parameters = new DialogParameters - { - { x => x.Placeholder, _localizer["Enter the new file name here"] }, - { x => x.Label, _localizer["New file name"] }, - { x => x.InitialValue, initialValue } - }; - var options = new DialogOptions() { CloseOnEscapeKey = true, BackdropClick = false, FullWidth = true, CloseButton = true }; - var dialog = await _dialogService.ShowAsync(_localizer["Change file name"], parameters, options); - var result = await dialog.Result; - var newFileName = result?.Data as string; - if ((result?.Canceled == false) && (String.IsNullOrEmpty(newFileName) == false)) - { - return newFileName; - } - else - { - return null; - } - } - async Task FileRenameClicked(Audiofile audiofile) { - var newFileName = await ShowInputDialog(audiofile.Name); - if (String.IsNullOrEmpty(newFileName) == false) + var result = await _dialogManager.ShowInputDialogAsync(_localizer["Change file name"], _localizer["Enter the new file name here"], _localizer["New file name"], audiofile.Name); + if (result.IsSuccess) { - _audiofileManager.SetProperty(audiofile, x => x.Name, newFileName); + if (String.IsNullOrEmpty(result.Value) == false) + { + _audiofileManager.SetProperty(audiofile, x => x.Name, result.Value); + } } } diff --git a/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor b/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor index f42de74b..07df226a 100644 --- a/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor +++ b/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor @@ -20,7 +20,7 @@ along with Foobar. If not, see @inject IStringLocalizer _localizer @inject ValidationService _validationService @inject IFileInputManager _fileInputManager -@inject IDialogService _dialogService +@inject IDialogManager _dialogManager @inject ISessionStateContainer _sessionStateContainer @inject ICuesheetManager _cuesheetManager @@ -93,39 +93,20 @@ along with Foobar. If not, see async Task CDTextFileRename() { - var newFileName = await ShowInputDialog(Cuesheet?.CDTextfile?.Name); - if (String.IsNullOrEmpty(newFileName) == false) + var result = await _dialogManager.ShowInputDialogAsync(_localizer["Change file name"], _localizer["Enter the new file name here"], _localizer["New file name"], Cuesheet?.CDTextfile?.Name); + if (result.IsSuccess) { - var cdTextFile = Cuesheet?.CDTextfile; - if (cdTextFile != null) + if (String.IsNullOrEmpty(result.Value) == false) { - cdTextFile.Name = newFileName; + var cdTextFile = Cuesheet?.CDTextfile; + if (cdTextFile != null) + { + cdTextFile.Name = result.Value; + } } } } - async Task ShowInputDialog(string? initialValue) - { - var parameters = new DialogParameters - { - { x => x.Placeholder, _localizer["Enter the new file name here"] }, - { x => x.Label, _localizer["New file name"] }, - { x => x.InitialValue, initialValue } - }; - var options = new DialogOptions() { CloseOnEscapeKey = true, BackdropClick = false, FullWidth = true, CloseButton = true }; - var dialog = await _dialogService.ShowAsync(_localizer["Change file name"], parameters, options); - var result = await dialog.Result; - var newFileName = result?.Data as string; - if ((result?.Canceled == false) && (String.IsNullOrEmpty(newFileName) == false)) - { - return newFileName; - } - else - { - return null; - } - } - void CataloguenumberOnBlur() { var newValue = _catalogueNumber?.Replace(" ", string.Empty); diff --git a/AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.de.resx b/AudioCuesheetEditor/Shared/Dialogs/InputDialog.de.resx similarity index 100% rename from AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.de.resx rename to AudioCuesheetEditor/Shared/Dialogs/InputDialog.de.resx diff --git a/AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.razor b/AudioCuesheetEditor/Shared/Dialogs/InputDialog.razor similarity index 60% rename from AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.razor rename to AudioCuesheetEditor/Shared/Dialogs/InputDialog.razor index 6eddbfcb..b835ed40 100644 --- a/AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.razor +++ b/AudioCuesheetEditor/Shared/Dialogs/InputDialog.razor @@ -15,26 +15,34 @@ You should have received a copy of the GNU General Public License along with Foobar. If not, see . --> +@typeparam T @inherits BaseLocalizedComponent -@inject IStringLocalizer _localizer +@inject IStringLocalizer> _localizer @inject HotKeys _hotKeys - + @if (IsNumericType) + { + + } + else + { + + } - @_localizer["Ok"] + @OkText @code { HotKeysContext? _hotKeysContext; - string? _inputValue; + T? _value; - [CascadingParameter] - private IMudDialogInstance? MudDialog { get; set; } + [Parameter] + public T? InitialValue { get; set; } [Parameter] public string? Label { get; set; } @@ -43,7 +51,16 @@ along with Foobar. If not, see public string? Placeholder { get; set; } [Parameter] - public string? InitialValue { get; set; } + public string? OkText { get; set; } + + [Parameter] + public string? OkButtonStartIcon { get; set; } + + [CascadingParameter] + private IMudDialogInstance? MudDialog { get; set; } + + bool IsNumericType => typeof(T) == typeof(short) || typeof(T) == typeof(ushort) || typeof(T) == typeof(int) || typeof(T) == typeof(uint) || typeof(T) == typeof(long) + || typeof(T) == typeof(ulong) || typeof(T) == typeof(float) || typeof(T) == typeof(double) || typeof(T) == typeof(decimal); protected override void OnInitialized() { @@ -51,19 +68,23 @@ along with Foobar. If not, see _hotKeysContext = _hotKeys.CreateContext().Add(ModKey.None, Key.Enter, CloseDialogOk); } - protected override void Dispose(bool disposing) + protected override void OnParametersSet() { - base.Dispose(disposing); - _hotKeysContext?.DisposeAsync(); + base.OnParametersSet(); + _value = InitialValue; + if (String.IsNullOrEmpty(OkText)) + { + OkText = _localizer["Ok"]; + } } - protected override void OnParametersSet() + protected override void Dispose(bool disposing) { - base.OnParametersSet(); - _inputValue = InitialValue; + base.Dispose(disposing); + _hotKeysContext?.DisposeAsync(); } - void TextFieldKeyDown(KeyboardEventArgs args) + void OnKeyDown(KeyboardEventArgs args) { if (args.Key == "Enter") { @@ -74,6 +95,6 @@ along with Foobar. If not, see void CloseDialogOk(object? state = null) { - MudDialog?.Close(_inputValue); + MudDialog?.Close(_value); } } diff --git a/AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.resx b/AudioCuesheetEditor/Shared/Dialogs/InputDialog.resx similarity index 100% rename from AudioCuesheetEditor/Shared/Dialogs/InputTextDialog.resx rename to AudioCuesheetEditor/Shared/Dialogs/InputDialog.resx diff --git a/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.de.resx b/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.de.resx deleted file mode 100644 index 2128b9f9..00000000 --- a/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.de.resx +++ /dev/null @@ -1,132 +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 - - - Aufnahmecountdown in Sekunden - - - Sekunden bis die Aufnahme startet - - - Countdown starten - - - Aufnahmecountdown starten - - \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.razor b/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.razor deleted file mode 100644 index 1bccb8c9..00000000 --- a/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.razor +++ /dev/null @@ -1,62 +0,0 @@ - -@inherits BaseLocalizedComponent - -@inject IStringLocalizer _localizer - - - - @_localizer["Start record countdown timer"] - - - - - - @_localizer["Start countdown"] - - - -@code { - RecordOptions? options; - - [CascadingParameter] - private IMudDialogInstance? MudDialog { get; set; } - - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - options = await base.LocalStorageOptionsProvider.GetOptionsAsync(); - base.LocalStorageOptionsProvider.OptionSaved += LocalStorageOptionsProvider_OptionSaved; - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - base.LocalStorageOptionsProvider.OptionSaved -= LocalStorageOptionsProvider_OptionSaved; - } - - void LocalStorageOptionsProvider_OptionSaved(object? sender, IOptions option) - { - if (option is RecordOptions recordOptions) - { - options = recordOptions; - StateHasChanged(); - } - } -} diff --git a/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.resx b/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.resx deleted file mode 100644 index d829f469..00000000 --- a/AudioCuesheetEditor/Shared/Dialogs/StartRecordCountdownDialog.resx +++ /dev/null @@ -1,132 +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 - - - Record countdown in sconds - - - Seconds till record starts - - - Start countdown - - - Start record countdown timer - - \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/Record/ControlRecording.de.resx b/AudioCuesheetEditor/Shared/Record/ControlRecording.de.resx index 400150ef..4bdfe9f0 100644 --- a/AudioCuesheetEditor/Shared/Record/ControlRecording.de.resx +++ b/AudioCuesheetEditor/Shared/Record/ControlRecording.de.resx @@ -126,6 +126,9 @@ Countdowntimer angeben + + Aufnahmecountdown in Sekunden + Die Aufnahme läuft bereits! @@ -138,6 +141,15 @@ Aufnahme aktiv! + + Sekunden bis die Aufnahme startet + + + Countdown starten + + + Aufnahmecountdown starten + Aufnahme starten diff --git a/AudioCuesheetEditor/Shared/Record/ControlRecording.razor b/AudioCuesheetEditor/Shared/Record/ControlRecording.razor index dfeef283..e98af628 100644 --- a/AudioCuesheetEditor/Shared/Record/ControlRecording.razor +++ b/AudioCuesheetEditor/Shared/Record/ControlRecording.razor @@ -18,7 +18,7 @@ along with Foobar. If not, see @inherits BaseLocalizedComponent @inject IStringLocalizer _localizer -@inject IDialogService _dialogService +@inject IDialogManager _dialogManager @inject ISessionStateContainer _sessionStateContainer @inject ICuesheetManager _cuesheetManager @@ -146,13 +146,12 @@ along with Foobar. If not, see async Task DisplayStartCountdownDialog() { - var options = new DialogOptions() { CloseOnEscapeKey = true, BackdropClick = false, CloseButton = true }; - var dialog = await _dialogService.ShowAsync(options); - var result = await dialog.Result; - var recordCountdownTimer = result?.Data as uint?; - if ((result?.Canceled == false) && (recordCountdownTimer.HasValue)) + var recordOptions = await LocalStorageOptionsProvider.GetOptionsAsync(); + var result = await _dialogManager.ShowInputDialogAsync(@_localizer["Start record countdown timer"], @_localizer["Seconds till record starts"], @_localizer["Record countdown in sconds"], recordOptions.RecordCountdownTimer, @_localizer["Start countdown"], @Icons.Material.Outlined.Timer); + if (result.IsSuccess) { - _startRecordTimer = new Timer(recordCountdownTimer.Value * 1000); + await LocalStorageOptionsProvider.SaveOptionsValueAsync(x => x.RecordCountdownTimer, result.Value); + _startRecordTimer = new Timer(result.Value * 1000); _startRecordTimer.Elapsed += delegate { StartRecording(); diff --git a/AudioCuesheetEditor/Shared/Record/ControlRecording.resx b/AudioCuesheetEditor/Shared/Record/ControlRecording.resx index d407ec4e..c69d68a6 100644 --- a/AudioCuesheetEditor/Shared/Record/ControlRecording.resx +++ b/AudioCuesheetEditor/Shared/Record/ControlRecording.resx @@ -126,6 +126,9 @@ Enter countdown timer + + Record countdown in sconds + Record is already running! @@ -138,6 +141,15 @@ Recording! + + Seconds till record starts + + + Start countdown + + + Start record countdown timer + Start recording diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx b/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx index 241c5171..40d84338 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.de.resx @@ -159,4 +159,22 @@ Track mit vorherigem verknüpfen + + Titel nach oben bewegen + + + Anzahl der Positionen die nach oben bewegt werden soll + + + Anzahl der Positionen angeben + + + Titel nach unten bewegen + + + Anzahl der Positionen die nach unten bewegt werden soll + + + Anzahl der Positionen angeben + \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor index 60c33574..ea5c8c95 100644 --- a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor @@ -25,6 +25,7 @@ along with Foobar. If not, see @inject ValidationService _validationService @inject PlaybackService _playbackService @inject IDialogService _dialogService +@inject IDialogManager _dialogManager @inject ITrackManager _trackManager @inject ICuesheetManager _cuesheetManager @inject ITraceChangeManager _traceChangeManager @@ -37,24 +38,25 @@ along with Foobar. If not, see
+ FixedHeader="_fixedTableHeader" FixedHeaderClicked="() => _fixedTableHeader = !_fixedTableHeader" MoveTracksUpSeveralClicked="MoveTracksUpSeveralClicked" + MoveTracksDownSeveralClicked="MoveTracksDownSeveralClicked" />
break; } -